从控制台创建密钥到Python请求、流式输出与生产级重试,给出可直接运行的DeepSeek API示例,覆盖参数配置、成本控制与常见错误处理。 DeepSeek API提供与OpenAI SDK习惯兼容的HTTP接口,开发者可以在不改变既有调用模式的前提下接入对话、推理与工具调用能力。本文以Python和openai官方SDK为主线,从密钥配置、首个请求、流式输出一直讲到生产环境的重试封装,示例代码可直接复制运行,同时标注容易出错的参数边界与安全事项。
1. 接入准备与密钥安全配置
接入DeepSeek API的第一步是在DeepSeek开放平台控制台创建API Key,并确认账户余额与可用模型。控制台生成的密钥通常只完整展示一次,丢失后只能重新创建,因此不要把密钥写入前端代码、Git仓库或聊天记录。工程上更稳妥的做法是通过环境变量或密钥管理服务注入,例如在服务端运行时读取DEEPSEEK_API_KEY,本地开发可以用.env文件配合python-dotenv加载,但.env必须加入.gitignore。对于团队协作,建议按环境拆分密钥,开发、测试、生产各用独立Key,并设置预算告警和定期轮换策略,一旦发现异常调用可以快速吊销。 Python侧需要安装openai SDK,版本应在1.x以上,因为旧版0.x的接口结构不同。安装后初始化客户端时传入api_key和base_url,DeepSeek的base_url使用,SDK会自动拼接聊天补全路径;也有文档示例使用,两种写法都能工作,但不要在同一个项目里混用。模型名称方面,通用对话使用deepseek-chat,推理模型使用deepseek-reasoner,后者会返回reasoning_content字段,适合需要展示思考过程的场景,但部分工具能力与通用模型存在差异,接入前应以控制台模型页和最新文档为准。 密钥安全不仅是“不要硬编码”,还包括调用链路的隔离。真实产品中应由后端服务代理DeepSeek请求,前端只调用自己的业务接口,避免浏览器直接持有API Key;日志系统要过滤Authorization头与用户隐私内容,只保留请求ID、模型名、token用量和耗时。对于AI指导老师类应用,课程助教、题库解析和代码评测可能共用同一账户,建议按业务维度打标签并统计usage,发现某类请求token异常增长时及时调整max_tokens或提示词,防止预算在短时间内被长上下文请求消耗。
2. 首个Chat Completions请求与完整代码
Chat Completions的请求体围绕messages展开,system消息用于设定角色和约束,user消息承载用户问题,assistant消息用于多轮历史。模型选择deepseek-chat时,temperature控制随机性,教学场景通常设置在0.2到0.5之间,既保留表达自然度又降低胡编概率;max_tokens限制输出长度,避免长答案拖高成本。需要特别注意的是,messages中的历史越长,输入token越多,多轮对话应做摘要或截断,而不是无限制追加。下面这段代码是可直接运行的最小完整示例,包含客户端初始化、消息构造、请求发送与用量打印。 “`python import os from openai import OpenAI
client = OpenAI( api_key=os.environ[“DEEPSEEK_API_KEY”], base_url=”https://api.deepseek.com”, )
messages = [ {“role”: “system”, “content”: “你是一位严谨的AI课程助教,回答要给出步骤和可验证的依据。”}, {“role”: “user”, “content”: “用三段话解释API限流的成因,并说明客户端重试时要注意什么。”}, ]
response = client.chat.completions.create( model=”deepseek-chat”, messages=messages, temperature=0.3, max_tokens=800, )
print(response.choices[0].message.content) print(“tokens:”, response.usage) “` 响应对象中choices[0].message.content是模型输出,usage记录输入、输出和总token数,生产环境应把它写入监控指标而不是只打印。常见错误包括把base_url误写成完整聊天补全地址导致路径重复、忘记安装openai 1.x导致OpenAI类不存在、以及把密钥直接写进代码后提交到仓库。若需要JSON结构化输出,可以在请求中加入response_format={“type”:”json_object”},但提示词必须明确要求返回JSON,并做好解析失败兜底;若使用deepseek-reasoner,输出结构会多出推理内容字段,展示层要区分“思考过程”和“最终答案”,不要把推理内容直接当作业务结果。
3. 流式输出、函数调用与参数调优
流式输出通过stream=True开启,服务端以SSE逐块返回增量内容,客户端循环读取chunk.choices[0].delta.content即可实现打字机效果。相比一次性返回,流式更适合课程问答、代码解释和长文生成,因为首token延迟明显降低,用户能更早看到反馈。下面示例在收到空choices时跳过,避免部分心跳块导致索引错误;如果使用推理模型,还需要同时处理delta.reasoning_content,把思考过程和最终回答分开展示。流式请求一旦中途断开,不能简单重放整个请求,否则前端可能出现重复文本,应结合finish_reason和业务层消息ID做断点处理。 “`python stream = client.chat.completions.create( model=”deepseek-chat”, messages=[{“role”: “user”, “content”: “写一个Python函数,校验环境变量中的API密钥是否为空,只输出代码。”}], temperature=0.2, stream=True, )
for chunk in stream: if not chunk.choices: continue delta = chunk.choices[0].delta if delta.content: print(delta.content, end=””, flush=True) print “` 参数调优要围绕业务目标而不是盲目堆配置。temperature和top_p通常只调整一个,教学答疑用较低temperature保证稳定,创意写作可以适当提高;presence_penalty和frequency_penalty用于抑制重复,但在代码生成中过强会导致变量名或注释被过度改写。函数调用通过tools传入JSON Schema定义,模型返回tool_calls后由业务代码执行本地函数,再把结果作为tool角色消息回传,适合课表查询、订单状态和题库检索。使用deepseek-reasoner时要关注其工具调用支持范围,复杂Agent流程优先在deepseek-chat上验证,再决定是否迁移。
4. 错误处理、限流与生产级封装
生产环境调用DeepSeek API不能只写一次try/except,而要区分可重试错误和不可重试错误。401通常意味着密钥无效或过期,400多为参数格式错误,这类错误重试没有意义;429表示触发限流,5xx表示服务端临时故障,网络超时和连接中断也属于可重试范畴。重试策略应采用指数退避加随机抖动,避免大量客户端在同一时刻再次冲击服务端;同时设置最大重试次数和总超时,防止请求在队列中堆积。对于流式请求,重试要更谨慎,因为已经输出的内容可能无法回滚,建议在业务层记录消息状态,必要时重新生成而不是静默拼接。 “`python import os import time import random import logging from openai import OpenAI, APIError, RateLimitError, APITimeoutError, APIConnectionError
logger = logging.getLogger(“deepseek_client”) client = OpenAI( api_key=os.environ[“DEEPSEEK_API_KEY”], base_url=”https://api.deepseek.com”, timeout=30.0, )
def chat_with_retry(messages, model=”deepseek-chat”, max_retries=4, kwargs): last_error = None for attempt in range(max_retries): try: response = client.chat.completions.create( model=model, messages=messages, kwargs ) logger.info(“usage=%s”, response.usage) return response except (RateLimitError, APITimeoutError, APIConnectionError) as exc: last_error = exc wait = min(2 attempt + random.random, 20) logger.warning(“retryable error=%s, wait=%.2fs”, type(exc).__name__, wait) time.sleep(wait) except APIError as exc: last_error = exc status = getattr(exc, “status_code”, None) if status is not None and status >= 500 and attempt < max_retries – 1: wait = min(2 attempt + random.random, 20) logger.warning(“server error status=%s, wait=%.2fs”, status, wait) time.sleep(wait) continue logger.exception(“non-retryable api error status=%s”, status) raise raise RuntimeError(“DeepSeek API retries exhausted”) from last_error “` 生产级封装还应加入并发控制和成本观测。并发方面可以用信号量限制同时在途请求数,避免突发流量把账户限流打满;成本方面按业务线记录usage中的prompt_tokens和completion_tokens,对长上下文课程材料做分段摘要和检索增强,减少无关历史进入请求。日志要脱敏,不记录完整密钥和用户隐私原文;对外暴露的错误信息要统一,不把上游状态码和内部堆栈直接返回给前端。对于AI指导老师场景,建议把模型调用封装在独立服务中,业务层只依赖一个稳定的chat接口,这样模型切换、参数调整和重试策略变更都不会影响课程侧代码。

