简介:面向 DeepSeek API 调用场景的 Python 入门示例包,专门服务于正在学习“DeepSeek API 如何调用”的开发者,定位清晰、使用门槛低;无论用于学习研究、快速尝试接口效果,还是作为后续二次开发的起始骨架都很合适。包内包含两个 Python 示例脚本,分别演示单次请求与循环调用两种典型形态,读者可先运行脚本观察请求返回结果与执行日志,再迁移到自己的项目中;同时开源配置文件与许可协议一并收录,便于合规使用并复用项目结构。压缩包共 4 个文件,整体仅 14KB,体量轻量,保留开源项目常见目录结构,下载后可快速对照源码进行动手调试,也能作为本地原型验证的极简基础。示例外围的通用调用要点进一步梳理了完整链路:先阅读官方文档确认接口规范,再申请并安全保存密钥,随后按要求构造请求方法与参数、解析响应数据,并针对网络异常、鉴权失败、限流等常见错误设计处理逻辑;将这些要点与包内脚本对照学习,可帮助读者建立从零到一的清晰调用思路,为后续在真实项目中使用 DeepSeek API 打下基础。目前已有 283 人学习下载,适合作为 DeepSeek API 入门阶段小而精的参考资料。
1. DeepSeek API 如何调用:先搞清楚这个 demo 包里有什么
很多刚接触 DeepSeek API 的人,第一件事就是去下载一个叫deepseek-demo-master.zip的压缩包。满怀期待地解压,然后对着里面的几十个文件发懵:哪个是入口?怎么跑起来?API Key 填在哪里?如果你也卡在这一步,这篇笔记就是给你写的。我要做的是把这个压缩包的用途、调用链路和踩坑点拆开,让你从「下了一个包」到「真正调通一次对话」,全程不超过半小时。这里适合三种人:想快速验证 DeepSeek 能力的开发者、要把 API 集成进自己项目的人,以及看了很多文档但始终没跑通的半新手。下面我们直接从鉴权开始,因为所有调用都绕不开它。
2. 获取 API Key 与鉴权方式:调用前必须迈过的一道门槛
调用任何大模型 API,第一件事不是写代码,而是拿到一把「钥匙」。DeepSeek 的调用方式和 OpenAI 兼容,这意味着你只需要一个 Key,就能用 HTTP 请求完成对话。但很多人在这个 demo 里卡住,是因为不清楚 Key 从哪来、怎么填、以及填错了会看到什么报错。
2.1 从开放平台拿 Key:注册、创建、充值三步
我一般会先打开 DeepSeek 开放平台页面,用手机号注册一个账号。这一步没什么门槛,但要注意:平台可能会要求实名认证,否则某些服务不可用。注册完成后,进入「API Keys」管理页面,点击创建新 Key,复制保存。这个 Key 只在创建时完整显示一次,关掉页面后就只能删了重建,所以我会立刻粘贴到一个临时文件里。
Key 拿到之后还有个现实问题:新账号通常有免费额度,但正式调用需要账户余额。在平台左侧找到「充值」入口,充个最低额度就能用。注意,DeepSeek 的计费是按 token 算的,不是按请求次数,所以哪怕调 1000 次短对话,可能也就几分钱。这里我踩过一次坑:以为 Key 创建成功就能无限调用,结果一直返回 402,查了才知道是余额不足。
提示:别把 Key 硬编码在 demo 的源码里,尤其当你打算把项目推到公开仓库时。后面我们会用环境变量来存。
2.2 鉴权头与请求体:看懂官方 SDK 之外的原始 HTTP 调用
这个 demo 包内部可能封装了 SDK,但你要明白底层发生了什么,否则出问题只能瞎猜。DeepSeek 的 REST API 端点是固定的,请求头里带Authorization: Bearer 你的Key,请求体是标准的 Chat Completion 格式。下面是一个最原始的curl调用,我建议你在跑 demo 前先执行一遍,能帮助快速确认 Key 是否有效。
curl https://api.deepseek.com/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $DEEPSEEK_API_KEY" \ -d '{ "model": "deepseek-chat", "messages": [ {"role": "system", "content": "你是一个简洁的助手"}, {"role": "user", "content": "用一句话介绍你自己"} ], "stream": false }'这段命令里,$DEEPSEEK_API_KEY是环境变量,如果没设置就直接替换成你的 Key 字符串。model字段指定模型,deepseek-chat是通用对话模型,某些新模型可能有单独的模型名,以文档为准。重点看messages数组的结构:每条消息必须有role和content,role只能是system、user、assistant三种。stream设为false表示一次性返回完整结果,调试时这样最直观。
执行后你会得到一大段 JSON,其中choices[0].message.content就是模型回答。如果返回 401,说明 Key 错了或过期;返回 402 是欠费;返回 400 大多是请求格式问题,比如messages缺字段。走通这一步,再回头看 demo 里的代码,你会觉得所有封装都不过是在拼这个请求。
3. 把 deepseek-demo-master.zip 跑起来:从解压到首次对话
下载下来的压缩包通常带着-master后缀,说明是某个仓库的主分支打包。解压后你可能会看到 Python 脚本、前端页面、配置文件混在一起。别慌,先摸清目录结构,再找到入口,然后跑通一次对话。
3.1 解压目录结构:先分清哪个是服务端、哪个是客户端
我习惯先执行tree -L 2看一眼整体布局,或者用文件管理器逐层展开。常见的 demo 包会包含这几类东西:main.py或app.py作为后端入口,requirements.txt是依赖清单,.env.example是环境变量模板,templates/或static/是前端资源,还有README.md。这里最容易翻车的是:有人直接双击index.html,以为打开页面就能调用 API,结果跨域报错——因为浏览器里的 JS 调用 API 会遇到 CORS 限制,必须通过后端转发。
我的建议是先把 README 完整读一遍,不要跳着看。很多 demo 的启动命令、Python 版本要求都写在里面。如果 README 写得太简略,就看requirements.txt里的依赖推断技术栈。比如里面有flask,那大概率是个 Web 服务;如果只有openai,说明是个纯脚本。下面是我处理这种 demo 的通用流程:
cd deepseek-demo-master python3 -m venv venv source venv/bin/activate pip install -r requirements.txt cp .env.example .env这段命令创建虚拟环境并安装依赖。注意,python3 -m venv venv需要 Python 3.8 以上,如果报错说明系统缺venv模块,可以用pip install virtualenv替代。cp .env.example .env这一步很关键,因为很多新手跳过它,直接运行程序,然后报错KeyError: DEEPSEEK_API_KEY。
3.2 配置环境变量:把 Key 写进 .env,而不是代码里
env.example文件里通常有一行DEEPSEEK_API_KEY=,你打开.env,把 Key 填在等号后面。注意不要加引号,也不要留空格。如果你不习惯用.env,也可以直接在终端里导出环境变量,但这只对当前终端会话有效。
# 在 .env 中配置(推荐) DEEPSEEK_API_KEY=sk-你的完整Key # 或者临时导出 export DEEPSEEK_API_KEY="sk-你的完整Key"有些 demo 会用python-dotenv自动加载.env文件,有些不会。如果你运行后发现KeyError,就手动在代码入口加上一行from dotenv import load_dotenv; load_dotenv()。这里也提醒一句:.env文件不要提交到 Git,否则等于公开 Key。我会在.gitignore里加上.env,并且删除从压缩包带出来的任何历史.env备份。
3.3 最小调用示例:用 Python 完成第一次对话
如果这个 demo 本身结构太乱,我建议先跳过它,自己写一个 20 行的脚本验证 API。这样能最快排除「项目问题」和「API 问题」。下面是我每次调试新环境都会用的最小示例:
# test_deepseek.py import os from openai import OpenAI client = OpenAI( api_key=os.getenv("DEEPSEEK_API_KEY"), base_url="https://api.deepseek.com" ) response = client.chat.completions.create( model="deepseek-chat", messages=[ {"role": "system", "content": "你是一个乐于助人的助手"}, {"role": "user", "content": "你好,请简单介绍 DeepSeek API 的调用方式"} ], stream=False, temperature=0.7 ) print(response.choices[0].message.content)用openaiSDK 是因为 DeepSeek 兼容这一协议,你不需要引入额外的包。关键参数有三个:base_url必须指向 DeepSeek 的地址,否则 SDK 默认会去别的地方;model决定模型版本;temperature控制随机性,0.7 是通用值,后面会细说。运行前确认环境变量已加载:
python test_deepseek.py如果看到输出文本,说明 API 调用成功。如果报错,百分之九十是环境变量没读进来,或在client初始化时少了base_url。这时候回到第 2 章用 curl 验证 Key 是否有效,能快速缩小问题范围。
4. 参数调优与上下文管理:让回答质量从「能用」到「好用」
跑通一次对话只是开始。实际使用中,你会发现同样的输入,参数设置不同,输出的质量和风格天差地别。这一章讲的是 demo 里通常会忽略但你必须学会的三个东西:temperature、top_p、max_tokens,以及多轮对话时消息数组该怎么维护。
4.1 temperature、top_p 与 max_tokens:三个参数决定回答风格
temperature控制随机性,取值范围一般是 0 到 2。调得越低,回答越确定、越保守,适合写代码、提取结构化信息;调得越高,回答越发散、越有创造性,适合头脑风暴。我自己的习惯是:日常问答用 0.7,代码生成用 0.2,文案创作用 1.0 以上。
top_p是核采样,作用类似,但机制不同。它按概率累计截断,比如top_p=0.9意味着只从累计概率达到 90% 的 token 里选择。官方建议是不要同时大幅调整这两个参数,保持一个为默认值、只调另一个,否则会互相干扰,导致输出难以预测。max_tokens限制单次回答的最大 token 数,不是字符数。一个中文字大约占 1 到 2 个 token,英文一个词约 1 个 token。如果回答经常被截断,就调大这个值,但注意它也会影响费用。
下面是一段对比代码,让你直观感受参数变化:
params = [ {"temperature": 0.2, "top_p": 0.5}, {"temperature": 1.2, "top_p": 0.9}, ] for p in params: resp = client.chat.completions.create( model="deepseek-chat", messages=[{"role": "user", "content": "写一句鼓励加班的话"}], temperature=p["temperature"], top_p=p["top_p"], max_tokens=100 ) print(p, resp.choices[0].message.content)你会发现低温时回答更像是「合理的劝说」,高温时可能变成反讽或冷幽默。这正好说明:调试时不要一上来就改代码逻辑,先试参数。很多「回答变笨了」的问题,其实是temperature被设成了 0,导致模型每次只选概率最高的答案,缺乏灵活性。
4.2 多轮对话与上下文窗口:system 消息和 history 怎么传
大模型本身是无状态的,每次请求都是独立的。所谓「多轮对话」,就是你手动把所有历史消息都放在messages里一起传过去。demo 里常见的错误是:用户在第二轮提问时,只传了当前问题,导致模型完全忘了前面说过什么。
正确做法是维护一个列表,把系统提示、用户消息、助手消息按顺序追加进去,每次请求都把整个列表传给 API。下面是伪代码结构:
messages = [{"role": "system", "content": "你是一个智能客服"}] messages.append({"role": "user", "content": "我想退货"}) # 第一次响应... messages.append({"role": "assistant", "content": "请提供订单号"}) messages.append({"role": "user", "content": "订单号是12345"}) # 第二次请求时,messages 已包含全部内容 response = client.chat.completions.create( model="deepseek-chat", messages=messages )这里有两个实际问题。第一,上下文窗口有上限,DeepSeek 的上下文长度取决于具体模型,通常足够长,但如果对话超过限制,最早的消息会被截断或直接报错。第二,system消息会影响全局风格,我一般把它放在第一位,并且只在开头设置一次,不要每轮都重复往里塞,否则模型可能被搞糊涂。
另外要注意:assistant消息里的content必须是模型上一次真正返回的内容,不要自己编。如果你重复传相同的assistant消息,模型可能陷入重复循环。如果想让模型忘记某些话题,直接把前面的消息从列表里删掉再请求即可,这相当于「手动清空记忆」。
5. DeepSeek API 调用避坑:5 个最容易翻车的点
这一章是我在实际调试中多次撞墙后的记录,每条都按现象、原因、解决三步写。希望你看完能少走弯路。
5.1 现象:返回 401 Unauthorized,Key 明明没错
原因有两个可能:一是 Key 复制时多了空格或换行;二是.env文件里的值包含了引号,比如DEEPSEEK_API_KEY="sk-xxx",系统会把引号也当成 Key 的一部分。解决方法是打印 Key 的前几个字符做检查:
python -c "import os; print(repr(os.getenv('DEEPSEEK_API_KEY')))"如果输出是'sk-abc123',正常;如果是'"sk-abc123"',说明引号被吃进去了。去.env里去掉引号。还有一个隐蔽情况:某些环境变量加载库会覆盖已有变量,如果系统里本来就有一个旧的DEEPSEEK_API_KEY,也会导致 401。
5.2 现象:请求成功但响应极慢,甚至超时
原因大多是stream设为false,而模型要在生成完整回答后才一次性返回。长回答可能耗时几十秒,如果你用了默认的短超时时间,就会报ReadTimeout。解决方法是开启流式输出,或者调大 HTTP 超时时间。我这个 demo 里建议直接用 stream:
response = client.chat.completions.create( model="deepseek-chat", messages=messages, stream=True # 边生成边返回 ) for chunk in response: delta = chunk.choices[0].delta if delta and delta.content: print(delta.content, end="", flush=True)这种流式方式不仅响应快,还能给用户一种「正在思考」的交互感。注意,流式模式下response变成一个生成器,不能像之前那样直接取choices[0].message.content,必须遍历。
5.3 现象:中文回答内容被截断得像机翻
原因通常是max_tokens设得太小,比如 50。因为模型要在有限 token 内完成回答,被迫用简洁的短句,很多上下文丢失。解决方法是先估算回答长度,再设置max_tokens。一个粗略的经验:中文字符数除以 1.5 约等于 token 数。如果你期望 300 字回答,max_tokens至少设 500。同时检查temperature是否过低,因为低温会让模型倾向于保守的短回答。
5.4 现象:把 Key 提交到了 Git,被人盗刷
这是我最心疼的一次翻车。原因是 demo 自带的.gitignore没包含.env,我顺手git add .就把 Key 推上去了。几个小时后,余额没了。解决方法是立即到平台删掉这个 Key,创建一个新 Key,然后检查仓库历史里是否有泄露。最好用git filter-repo清理历史,或者干脆把整个仓库设为私有。以后每次提交前我都用git status确认没有.env。
5.5 现象:同一段 prompt,两次调用结果完全一样,怀疑是缓存
原因是你把temperature设成了 0,模型退化为贪心解码,每次都生成概率最高的序列。某些情况下这很合理,比如提取 JSON 也要固定输出。但如果想要多样化的回答,把temperature调到 0.7 到 1.0,并且不要同时固定top_p和temperature。另外,官方可能对完全相同的请求做缓存,如果你需要测试不同效果,一定要在 prompt 里加一点随机变化,比如时间戳或序列号。
6. 进阶:把 demo 改造成你自己的命令行问答工具
到这里,你已经能调通 API、理解参数、避开大多数坑。最后这一步,我们把这套能力固化成一个可以日常使用的命令行工具,而不是每次写测试脚本。这个工具会读取.env里的 Key,在终端里进行多轮对话,并支持/reset指令清空上下文。
# cli_chat.py import os from openai import OpenAI from dotenv import load_dotenv load_dotenv() client = OpenAI(api_key=os.getenv("DEEPSEEK_API_KEY"), base_url="https://api.deepseek.com") messages = [{"role": "system", "content": "你是一个简洁、准确的中文助手"}] print("DeepSeek CLI 已启动,输入 /reset 清空记忆,输入 /quit 退出。") while True: user_input = input("\n你: ") if user_input.strip() == "/quit": break if user_input.strip() == "/reset": messages = [{"role": "system", "content": "你是一个简洁、准确的中文助手"}] print("[上下文已清空]") continue messages.append({"role": "user", "content": user_input}) stream = client.chat.completions.create( model="deepseek-chat", messages=messages, stream=True, temperature=0.6 ) print("\nDeepSeek: ", end="", flush=True) reply_parts = [] for chunk in stream: if chunk.choices[0].delta and chunk.choices[0].delta.content: content = chunk.choices[0].delta.content print(content, end="", flush=True) reply_parts.append(content) messages.append({"role": "assistant", "content": "".join(reply_parts)})这段代码最关键的两个设计:一是把assistant返回的内容拼接到messages里,保证下一轮对话有完整上下文;二是stream=True让回答逐字出现,体感流畅很多。/reset只是重置了内存里的消息列表,不会影响 Key 或配置,这个逻辑很简单但很实用。
我之前遇到一个奇怪问题:CLI 有时会重复回答最后一次内容。后来发现是我在拼reply_parts时把chunk里的delta.content重复添加了,因为流式返回最后一个 chunk 可能包含空字符串或结束标记。解决办法是加了if chunk.choices[0].delta and chunk.choices[0].delta.content:的判断。同样的思路,如果你在集成这个 demo 到 Web 服务时遇到回答中断,优先检查流式解析逻辑,而不是怀疑 API。
另外一个实用技巧:把temperature调成 0.6,并且给system消息加上「请分点回答」或「请给出代码示例」这样的约束,能明显提升代码相关问题的回答质量。这也是我长期使用的固定配置。希望这篇笔记能帮你节省几个小时,让 DeepSeek API 的调用从「玄学」变成「手脚架上的熟练活」。希望帮到你。
本文还有配套的精品资源,点击获取