Responses API
两套协议都出自 OpenAI,DeepSeek 是照着接的。
Chat Completions 定于 2023 年。再早的 Completions 只收一整段 prompt。换成对话以后,请求走 POST /chat/completions,用 messages 按 role 分开谁说的话。这套后来成了各家对齐的格式,DeepSeek 也实现了它,所以前面几篇的 curl 都打在这条路径上:messages 进去,choices 出来。
Responses 定于 2025 年,给要调用工具、连续行动的程序用。OpenAI 把它做成 Chat Completions 的下一代原语,并把 Assistants API 里的工具能力收进同一次请求:input 进去,output 里按条目返回。DeepSeek 为了让 Codex 这类已经说 Responses 的客户端能换 base_url,在 POST https://api.deepseek.com/responses 上按这套格式接了进来。
问的可以还是「你是谁」。下面只看报文差在哪。
一次调用
curl https://api.deepseek.com/responses \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
-d '{
"model": "deepseek-flash",
"instructions": "你是一个助手",
"input": "你是谁",
"stream": false
}'
input 和 instructions 至少要有一个。instructions 会被插成第一条 system 消息,干的是 System prompt 那件事。前面几篇的 deepseek-chat 用在 /chat/completions;这条路径的示例模型是 deepseek-flash。
回来的是一条 response,不是 chat completion:
{
"id": "resp_8f2a",
"object": "response",
"status": "completed",
"model": "deepseek-flash",
"store": false,
"output": [
{
"type": "message",
"role": "assistant",
"content": [
{
"type": "output_text",
"text": "我是 DeepSeek,由深度求索开发的智能助手。"
}
]
}
]
}
翻译成人话:
- 没有
choices。话在output里,这一条的type是message - 正文在
content[].text,type为output_text。官方 SDK 会把这些文字收成output_text status为completed,相当于那边的finish_reason: stopoutput是列表。普通回答是一条message;思考过程若有,是另一条reasoning;伸手则是一条function_call
多轮仍要自己贴
DeepSeek 这份 Responses 是无状态的。previous_response_id、conversation、store 都不生效,响应里 store 固定为 false。下一轮还是把已经说过的条目放进 input:
{
"model": "deepseek-flash",
"input": [
{"role": "user", "content": "你以后称呼自己为小K"},
{"role": "assistant", "content": "好的,我以后称呼自己为小K!"},
{"role": "user", "content": "你是谁"}
]
}
这和 Messages 是同一件事,只是字段叫 input。OpenAI 自己的 Responses 可以用 previous_response_id 让服务端续上一条。接到 DeepSeek 时,这个字段会被忽略。
工具换了条目
Tool 里的清单套在 tools[].function 下,点名挂在 message.tool_calls,观察是 role: tool。Responses 把这三样摊成条目。
清单:
{
"type": "function",
"name": "get_weekday",
"description": "按给定时区返回当前日期和星期几",
"parameters": {
"type": "object",
"properties": {
"timezone": {"type": "string", "description": "IANA 时区,例如 Asia/Shanghai"}
},
"required": ["timezone"]
}
}
模型点名时,output 里多一条:
{
"type": "function_call",
"call_id": "call_8f2a",
"name": "get_weekday",
"arguments": "{\"timezone\":\"Asia/Shanghai\"}"
}
运行时读完时钟,下一次 input 里接上:
{
"type": "function_call_output",
"call_id": "call_8f2a",
"output": "2026-10-08 星期四"
}
arguments 仍是 JSON 字符串。call_id 要对上,对不上这条观察就挂空。循环还是 Agent loop 那一圈:执行,写回,再请求。DeepSeek 这里只认 function 这种工具;web_search 一类内置工具会被忽略。
流也不用 [DONE]
stream: true 时,每条 SSE 都写 event,名字是协议规定的。正文增量、工具参数、结束各是一种事件。没有 data: [DONE]。事件表见 Responses SSE。
总结
/chat/completions用messages和choices;/responses用input、instructions和output条目- DeepSeek 的 Responses 仍无状态。多轮自己把条目贴进
input - 工具是
function_call配function_call_output,用call_id对上 - 流以
response.completed结束,没有[DONE]
参见
- 同一问法的另一套:Chatbot
- Messages · Tool · Agent loop · Streaming
- 下一篇:Responses SSE
- 官方:Using the Responses API · DeepSeek
- 动手:从 0 实现一个 Agent · 阶段一(聊天机器人)