你拿到了 DeepSeek V3 的 Key,想跑通第一条请求,结果卡在鉴权头怎么写、endpoint 填哪个、返回一直空。这篇不讲协议大道理,只给一条能跑通的路径:申请、首次调用、把超时和重试设成工程默认值、把日志字段记全,让后面排查有据可查。
你拿到了 DeepSeek V3 的 Key,想跑通第一条请求,结果卡在鉴权头怎么写、endpoint 填哪个、返回一直是空。这篇不讲协议大道理,只给一条能跑通的路径:申请、首次调用、把超时和重试设成工程默认值、把日志字段记全。
先明确一件事:密钥只放环境变量,本地用 .env,线上走密钥管理,别写进代码、更别塞进前端。调试阶段用非流式,好读好打断点;跑通之后再考虑流式和更复杂的参数。
先拿到 Key,再确认要打哪个地址
申请入口拿到 Key 之后,第一件事不是写业务代码,而是确认你要打哪个域。走官方域和走中转域,域名和鉴权头写法可能不一样,写错最常见的结果就是 401 或 404,别靠猜。中转站的可信度和连通性可以先到 /sites 看一圈再决定。
- Base URL
- 只写到版本层,比如 /v1 这种,不要把完整接口路径也拼进去
- 完整请求路径
- 由 SDK 或你手写拼在 Base URL 后面,改 Base URL 时不要重复拼
- 鉴权头
- 一般是 Authorization: Bearer,但中转域的实现可能不同,以对方文档为准
- 环境变量
- 本地 .env 加载,线上走密钥管理服务,代码里只读变量名
- 先把 Key 放进环境变量,代码里只出现变量名,不出现明文
- 确认走官方域还是中转域,再确认对应的鉴权头写法
- Base URL 与接口路径分开维护,只改一处
- 模型名先去模型库和价格页核对当前可用的写法,别把名字写死在代码里
- 把最终请求的完整 URL 和状态码打进日志,出问题时先看这两项
第一条请求怎么发:从最小可跑通到能进代码
第一条请求越短越好。body 里只留模型名、一条用户消息、一个很小的输出上限,先排除参数干扰。这时候你验证的不是效果好不好,而是链路通不通、返回结构对不对。
- 发一条最小请求命令行或脚本里发最短 body,拿到响应后打印完整 JSON,确认内容字段的路径在哪一层
- 决定流式还是非流式调试阶段先用非流式,返回一次到齐,好打断点好复制;确认结构之后再换流式
- 逐个加参数system 提示、温度、输出上限,一次只加一个,出问题能直接定位到是哪一项引起的
- 固化成 smoke test把这条请求写成一个能随时重跑的小函数,改配置或换域名后先跑它验证连通性
模型名和计费口径不要凭记忆写。去 /models 看当前可用的写法,再去 /price-watch 核对当时的计费规则。这类信息会变,写死在代码里迟早要返工。
# 最小请求示例:只保留必要字段,跑通之后再往上加
curl -sS $BASE_URL/chat/completions \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"<按模型库当前写法填写>","messages":[{"role":"user","content":"ping"}],"max_tokens":16}'超时、重试、并发:三个必须提前定的默认值
超时和重试是调试期最容易忽略、上线后最容易出事的两项。连接超时和读取超时要分开设;流式请求的读取超时按首字延迟给,不能直接套用非流式的值,否则首字还没来就被你掐断了。
| 场景 | 重试是否有意义 | 做法 |
|---|---|---|
| 连接超时、读取超时 | 是 | 指数退避加随机抖动,设最大次数上限 |
| 5xx 服务端错误 | 是 | 同上,但要观察是不是持续返回 |
| 429 限流 | 是 | 退避后重试,同时考虑降并发或排队 |
| 401 / 403 | 否 | 鉴权或权限问题,重试只会放大错误 |
| 400 参数错误 | 否 | 改参数,别重试 |
并发上限从低往高试。先跑一小批,看失败率和错误码分布,再决定要不要抬并发或者加排队。一上来开满很容易把限流错误误判成服务端问题。如果你同时打官方和多家中转,先定好切换条件和判断依据,别把一堆 if 散落在业务代码里。需要压测连通性和响应表现,可以用站内的 /tools/speed-test。
日志记哪几个字段,改完怎么判断变好没
排查能不能快,取决于你一开始记了哪些字段。建议一次请求至少落下面这些,缺一项后面就得靠猜。
- 请求 ID:跟服务商侧的日志对得上号的关键
- 模型名与 Base URL 标识:区分官方还是哪条线路
- 输入输出 token:核对用量和异常请求的第一手依据
- 首字耗时与总耗时:流式场景下这两个要分开看
- HTTP 状态码与原始错误码:原样记录,不要自己改写成中文描述
- 重试次数:知道这次结果是不是重试之后才拿到的
错误码原样记。自己包装成「请求失败」这种描述,跨天排查时跟服务商返回对不上号,等于白记。用量和成本定期核对一次,异常请求挑出来看,往往是某个调用点忘了设输出上限或者并发没管住。
改提示词或换模型之前,先准备一小批固定用例,改完跑同一批做对比,别凭感觉说变好了。只想快速看个效果,可以到 /tools 找在线调试类的工具先试,进代码之前先确认方向没跑偏。
下一步模型名、计费口径和各家中转的当前状态都会变,动手前先去模型库和价格追踪页核对当时的数字,再决定用哪条线路。→常见问题
DeepSeek V3 的接口和 OpenAI 的写法一样吗?
大部分调用代码可以复用,但字段支持和返回细节有差异,不能假定完全等价。建议先按官方文档的最小请求跑通,再对照站内 deepseek-openai-compat-integration 那篇看差异点,别直接复制一套 OpenAI 代码就上生产。
第一条请求一直返回鉴权失败,先查什么?
按顺序查三样:Key 是否带了多余空格或换行、鉴权头格式是否和当前域名匹配、请求打的是官方域还是中转域。三者对上还失败,就去站内 401 报错排查那篇按步骤走,先别急着换 Key。
要不要一开始就上流式输出?
调试阶段不建议。非流式返回好读、好打断点,能先把请求体和返回结构确认清楚。等逻辑跑通、需要首字响应体验时再切流式,同时把读取超时和断流处理补上,这两件事得一起做。