通过一些例子,介绍 OpenAI chat/response 与 Anthropic messages 协议,不陷于枯燥的接口参数介绍。
在正式介绍 OpenAI Chat / Responses 和 Anthropic Messages 协议之前,有一个概念需要先明确:大模型本身是无状态的。
从模型的视角看,一次调用就是一次独立的输入与输出过程:模型接收当前请求中的上下文,根据概率分布生成结果,然后这次推理就结束了。下一次请求到来时,模型并不会天然记得上一轮发生过什么。因此,无论是 OpenAI 还是 Anthropic,底层的一次次模型调用,本质上都是相互独立、无状态的。
但我们日常使用 ChatGPT、Claude 时,却明显会感觉对话是“有记忆”的。例如:
user:我叫张三。
assistant:你好,张三。
user:我叫什么?
assistant:张三。
模型能够回答“张三”,并不是因为模型在上一次请求结束后保存了某种会话状态,而是因为应用在发起新一轮请求时,把前面的对话历史一起重新提交给了模型。本质上通常是应用层模拟出来的“有状态”。模型调用是无状态的,而多轮对话是在应用层通过重复携带历史上下文,实现出来的“逻辑有状态”。
这种设计也带来了一个直接代价:历史对话会持续占用上下文窗口,逐渐挤占模型可用于新输入、工具结果和输出内容的上下文空间。
理解这一点之后,再去看 OpenAI Chat / Responses 和 Anthropic Messages 协议就会容易很多:这些协议很大一部分工作,其实都围绕着“如何描述当前这一次模型调用所需要的完整上下文”展开。
OpenAI Chat #
endpoint #
POST /v1/chat/completions
example #
关键点:每次请求携带之前对话的所有内容

请求:
{
"model": "deepseek-v4-pro",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "我叫张三"
},
{
"role": "assistant",
"content": "你好,张三!"
},
{
"role": "user",
"content": "我叫什么?"
}
]
}
响应:
{
"id": "chatcmpl-d3cd1541-e7f0-95e4-9b9b-53aaef0ad77a",
"model": "deepseek-v4-pro",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "你刚才说你叫张三。😊",
"role": "assistant",
"reasoning_content": "我们被问到:“我叫什么?”在前面的对话中,用户说“我叫张三”。所以答案是“张三”。需要直接回复。"
},
}
],
"usage": {
"completion_tokens": 36,
"prompt_tokens": 24,
"total_tokens": 60
}
}
关键点:模型产生调用工具意图,由客户端进行调用获取其他数据。MCP 和 Skill 都建立在 Tool Call 之上,可以自行想象下。

请求:
{
"model": "deepseek-v4-pro",
"messages": [
{
"role": "user",
"content": "What is my horoscope? I am an Aquarius."
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_horoscope",
"description": "Get today's horoscope for an astrological sign.",
"parameters": {
"type": "object",
"properties": {
"sign": {
"type": "string",
"description": "An astrological sign like Taurus or Aquarius"
}
},
"required": ["sign"]
}
}
}
],
"tool_choice": "auto"
}
响应:
{
"id": "chatcmpl-962bc15f-9701-9e3b-a0cf-bddb6afa16cd",
"model": "deepseek-v4-pro",
"choices": [
{
"finish_reason": "tool_calls",
"index": 0,
"message": {
"content": "",
"role": "assistant",
"tool_calls": [
{
"index": 0,
"function": {
"arguments": "{\"sign\": \"Aquarius\"}",
"name": "get_horoscope"
},
"id": "call_1aea02ba05b84673a6f81aa9",
"type": "function"
}
],
"reasoning_content": "The user is asking for their horoscope and they mention they are an Aquarius. I'll use the get_horoscope function to fetch their horoscope."
}
}
],
"usage": {
"completion_tokens": 79,
"prompt_tokens": 305,
"total_tokens": 384
}
}
第二次请求
{
"model": "deepseek-v4-pro",
"messages": [
{
"role": "user",
"content": "What is my horoscope? I am an Aquarius."
},
{
"role": "assistant",
"content": "",
"tool_calls": [
{
"id": "call_1aea02ba05b84673a6f81aa9",
"type": "function",
"function": {
"name": "get_horoscope",
"arguments": "{\"sign\":\"Aquarius\"}"
}
}
]
},
{
"role": "tool",
"tool_call_id": "call_1aea02ba05b84673a6f81aa9",
"content": "Aquarius: Next Tuesday you will befriend a baby otter."
}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_horoscope",
"description": "Get today's horoscope for an astrological sign.",
"parameters": {
"type": "object",
"properties": {
"sign": {
"type": "string"
}
},
"required": [
"sign"
]
}
}
}
]
}
第二次响应
{
"id": "chatcmpl-0e73e44a-a423-9847-959f-8628b068cc81",
"model": "deepseek-v4-pro",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "Here's your horoscope for today, Aquarius! ♒\n\n> **\"Next Tuesday you will befriend a baby otter.\"**\n\nHow delightful! It sounds like an adorable and unexpected encounter is on the horizon for you. Keep your eyes open next Tuesday — perhaps near a river, zoo, or aquarium? Either way, that's one charming friendship in the making! 🦦",
"role": "assistant",
"reasoning_content": "The tool returned the horoscope for Aquarius. Let me present this to the user."
}
}
],
"usage": {
"completion_tokens": 98,
"prompt_tokens": 363,
"total_tokens": 461
}
}
关键点:通过json_schema约束模型输出
请求:
{
"model": "glm-5.2",
"messages": [
{
"role": "user",
"content": "张三今年 28 岁,邮箱是 zhangsan@example.com。请提取用户信息。"
}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "user_info",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "integer"
},
"email": {
"type": "string"
}
},
"required": [
"name",
"age",
"email"
],
"additionalProperties": false
}
}
}
}
响应:
{
"id": "chatcmpl-8071dea7-3ad1-93ef-8600-46159b0a28cc",
"model": "glm-5.2",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "{\n \"age\": 28,\n \"email\": \"zhangsan@example.com\",\n \"name\": \"张三\"\n}",
"role": "assistant",
"reasoning_content": "1. **分析请求:**\n * 输入文本:“张三今年 28 岁,邮箱是 zhangsan@example.com。请提取用户信息。”(张三今年 28 岁,他的邮箱是 zhangsan@example.com。请提取用户信息。)\n * 任务:从输入文本中提取用户信息。\n\n2. **识别实体:**\n * 姓名:张三(张三)\n * 年龄:28(28)\n * 邮箱:zhangsan@example.com\n\n3. **格式化输出:**\n * 清晰地呈现提取的信息,可以使用 JSON 格式或结构化列表。结构化列表通常具有很好的可读性,但 JSON 格式在数据提取中非常标准。我们两者都提供,或者只提供一个清晰的列表。采用具有清晰标签的结构化列表:\n * 姓名:张三\n * 年龄:28岁\n * 邮箱:zhangsan@example.com\n\n4. **起草最终回复:**\n “提取到的用户信息如下:\n - 姓名:张三\n - 年龄:28 岁\n - 邮箱:zhangsan@example.com”\n (也可以为了完整性添加一个 JSON 代码块,但我们保持简单直接)。\n\n5. **对照约束条件审查:**\n * 我提取所有信息了吗?是的。\n * 准确吗?是的。\n\n6. **最终输出生成。**"
}
}
],
"usage": {
"completion_tokens": 344,
"prompt_tokens": 34,
"total_tokens": 378
}
}
随后客户端可以提取结构化信息
user = json.loads(response.choices[0].message.content)
print(user["name"])
print(user["age"])
print(user["email"])
关键点:服务端不会一次性返回完整 JSON,而是通过 SSE text/event-stream 持续发送多个 chunk
请求:
{
"model": "glm-5.2",
"stream": true,
"messages": [
{
"role": "user",
"content": "用一句话介绍北京。"
}
]
}
响应:
{
"id": "chatcmpl-2c979863-1421-9629-95bb-03aee6314f35",
"model": "glm-5.2",
"choices": [
{
"index": 0,
"delta": {
"reasoning_content": "",
"content": "",
"role": "assistant"
}
}
]
}
{
"id": "chatcmpl-2c979863-1421-9629-95bb-03aee6314f35",
"model": "glm-5.2",
"choices": [
{
"index": 0,
"delta": {
"reasoning_content": "1",
"content": ""
}
}
]
}
{
"id": "chatcmpl-2c979863-1421-9629-95bb-03aee6314f35",
"model": "glm-5.2",
"choices": [
{
"index": 0,
"delta": {
"reasoning_content": "",
"content": "历史与蓬勃现代活力完美交融的国际"
}
}
]
}
{
"id": "chatcmpl-2c979863-1421-9629-95bb-03aee6314f35",
"model": "glm-5.2",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"delta": {}
}
]
}
{
"id": "chatcmpl-2c979863-1421-9629-95bb-03aee6314f35",
"model": "glm-5.2",
"choices": [
{
"index": 0,
"delta": {}
}
],
"usage": {
"completion_tokens": 607,
"prompt_tokens": 17,
"total_tokens": 624
}
}
[DONE]
客户端对应的处理代码:
content = ""
reasoning_content = ""
for chunk in stream:
delta = chunk.choices[0].delta
if delta.reasoning_content:
reasoning_content += delta.reasoning_content
if delta.content:
content += delta.content
Anthropic Messages #
endpoint #
POST /v1/messages
example #
和OpenAI chat很相似
请求:
{
"model": "glm-5.2-anthropic",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "我叫张三"
},
{
"role": "assistant",
"content": "你好,张三!"
},
{
"role": "user",
"content": "我叫什么?"
}
]
}
响应:
{
"id": "chatcmpl-838d4b77-8f0c-9cc4-b479-eae65acfedb3",
"type": "message",
"role": "assistant",
"content": [
{
"type": "thinking",
"text": "",
"thinking": "1. **分析用户的输入**:用户正在询问“我叫什么?”(What is my name?)。\n2. **回顾对话历史**:\n * 用户:“我叫张三”(我的名字是张三)。\n * 机器人:“你好,张三!”(你好,张三!)。\n * 用户:“我叫什么?”(我叫什么?)。\n3. **识别核心实体**:用户在第一轮对话中已经说明了他们的名字叫“张三”(Zhang San)。\n4. **构建回复**:清楚地说明用户的名字叫张三,并保持礼貌和乐于助人的语气。\n5. **起草回复(内心独白/草稿)**:\n * *草稿1*:你叫张三。(太生硬)\n * *草稿2*:你刚才告诉我,你叫张三。(更好,符合语境)\n * *草稿3*:你叫张三呀。(友好,口语化)\n6. **选择最佳回复**:草稿2或3。让我们采用简单、直接的回答。“你叫张三呀,刚才你自己说的。”或者简单地说“你叫张三。”让我们使其友好些:“你叫张三呀!”\n\n*起草过程中的自我纠正*:用户可能在测试记忆。一个简单直接的“你叫张三。”就很完美。添加一个礼貌的短语:“你叫张三。”\n\n最终选择:“你叫张三。刚才你告诉我了。”(你是张三。你刚才告诉我了。) -> 缩短为“你叫张三呀。”(你是张三。) -> 保持简单:“你叫张三。”"
},
{
"type": "text",
"text": "你叫张三。刚才你告诉我了。"
}
],
"model": "glm-5.2-anthropic",
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 34,
"output_tokens": 360,
"total_tokens": 394
},
"error": null
}
第一次请求:
{
"model": "glm-5.2-anthropic",
"messages": [
{
"role": "user",
"content": "What is my horoscope? I am an Aquarius."
}
],
"tools": [
{
"name": "get_horoscope",
"description": "Get today's horoscope for an astrological sign.",
"input_schema": {
"type": "object",
"properties": {
"sign": {
"type": "string",
"description": "An astrological sign like Taurus or Aquarius"
}
},
"required": [
"sign"
]
}
}
],
"tool_choice": {
"type": "auto"
}
}
第一次响应:
{
"id": "chatcmpl-0092bb86-85eb-9114-ac64-7e63c9ccf444",
"type": "message",
"role": "assistant",
"content": [
{
"type": "thinking",
"text": "",
"thinking": "The user wants their horoscope and they are an Aquarius. Let me call the get_horoscope function with the sign \"Aquarius\"."
},
{
"type": "text",
"text": "Let me fetch your horoscope for Aquarius!"
},
{
"type": "tool_use",
"text": "",
"id": "call_0cad738fedeb4701b75335ff",
"name": "get_horoscope",
"input": {
"sign": "Aquarius"
}
}
],
"model": "glm-5.2-anthropic",
"stop_reason": "tool_use",
"stop_sequence": null,
"usage": {
"input_tokens": 186,
"output_tokens": 51,
"total_tokens": 237
},
"error": null
}
第二次请求:
{
"model": "glm-5.2-anthropic",
"messages": [
{
"role": "user",
"content": "What is my horoscope? I am an Aquarius."
},
{
"role": "assistant",
"content": [
{
"type": "thinking",
"text": "",
"thinking": "The user wants their horoscope and they are an Aquarius. Let me call the get_horoscope function with the sign \"Aquarius\"."
},
{
"type": "text",
"text": "Let me fetch your horoscope for Aquarius!"
},
{
"type": "tool_use",
"text": "",
"id": "call_0cad738fedeb4701b75335ff",
"name": "get_horoscope",
"input": {
"sign": "Aquarius"
}
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "call_0cad738fedeb4701b75335ff",
"content": "Aquarius: Next Tuesday you will befriend a baby otter."
}
]
}
],
"tools": [
{
"name": "get_horoscope",
"description": "Get today's horoscope for an astrological sign.",
"input_schema": {
"type": "object",
"properties": {
"sign": {
"type": "string",
"description": "An astrological sign like Taurus or Aquarius"
}
},
"required": [
"sign"
]
}
}
]
}
第二次响应:
{
"id": "chatcmpl-adbfb112-5723-9800-9b6b-c1ced58d6953",
"type": "message",
"role": "assistant",
"content": [
{
"type": "thinking",
"text": "",
"thinking": "The function returned a horoscope for Aquarius. Let me share this with the user."
},
{
"type": "text",
"text": "Here is your horoscope for today, Aquarius! 🌟\n\n**Aquarius:** Next Tuesday you will befriend a baby otter.\n\nThat sounds like a wonderful and unexpected encounter! Baby otters are absolutely adorable. Keep an eye out for any opportunities to connect with nature or animals early next week. 🦦✨\n\nIs there anything else you'd like to know?"
}
],
"model": "glm-5.2-anthropic",
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 228,
"output_tokens": 98,
"total_tokens": 326
},
"error": null
}
请求:
{
"model": "glm-5.2-anthropic",
"messages": [
{
"role": "user",
"content": "张三今年 28 岁,邮箱是 zhangsan@example.com。请提取用户信息。"
}
],
"output_config": {
"format": {
"type": "json_schema",
"name": "user_info",
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "integer"
},
"email": {
"type": "string"
}
},
"required": [
"name",
"age",
"email"
],
"additionalProperties": false
}
}
}
}
响应:
{
"id": "chatcmpl-9781df6b-f970-9085-89f9-eaa0315df8a0",
"type": "message",
"role": "assistant",
"content": [
{
"type": "thinking",
"text": "",
"thinking": "1. **分析请求:**\n * 输入文本:“张三今年 28 岁,邮箱是 zhangsan@example.com。请提取用户信息。”(张三今年 28 岁,他的邮箱是 zhangsan@example.com。请提取用户信息。)\n * 任务:提取用户信息(姓名、年龄、邮箱)。\n * 输出格式:结构化信息(例如:JSON、键值对)。\n\n2. **识别实体:**\n * 姓名 (姓名):张三\n * 年龄 (年龄):28\n * 邮箱 (邮箱):zhangsan@example.com\n\n3. **格式化输出:**\n * 提供清晰、易读的提取信息格式。键值对或 JSON 格式效果最好。\n\n *草稿 1 (键值对):*\n 姓名:张三\n 年龄:28\n 邮箱:zhangsan@example.com\n\n *草稿 2 (JSON):*\n ```json\n {\n \"name\": \"张三\",\n \"age\": 28,\n \"email\": \"zhangsan@example.com\"\n }\n ```\n\n4. **选择最佳输出:** 提供键值对通常是最直接且易读的,但添加 JSON 格式会显得非常专业。我们同时提供两者,或者只提供结构化的文本列表。为了清晰起见,我将使用简洁的文本列表。\n\n5. **最终确定回复:**\n 提取到的用户信息如下:\n - 姓名:张三\n - 年龄:28岁\n - 邮箱:zhangsan@example.com\n (同时也可以选择以 JSON 格式输出,这通常在“提取”类任务中很受欢迎)。我们直接输出结构化数据即可。"
},
{
"type": "text",
"text": "{\"name\":\"张三\",\"age\":28,\"email\":\"zhangsan@example.com\"}"
}
],
"model": "glm-5.2-anthropic",
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 32,
"output_tokens": 467,
"total_tokens": 499
},
"error": null
}
请求:
{
"model": "qwen3.7-max-anthropic",
"stream": true,
"messages": [
{
"role": "user",
"content": "用一句话介绍北京。"
}
]
}
响应:
// message_start
{
"type": "message_start",
"message": {
"id": "chatcmpl-284e68c1-9908-982c-b2bb-366a70fab6cb",
"type": "message",
"role": "assistant",
"content": [],
"model": "qwen3.7-max",
"stop_reason": null,
"stop_sequence": null,
"usage": {
"input_tokens": 0
},
"error": null
}
}
// content_block_start - thinking
{
"type": "content_block_start",
"index": 0,
"content_block": {
"type": "thinking",
"text": ""
}
}
// content_block_delta
{
"type": "content_block_delta",
"index": 0,
"delta": {
"type": "thinking_delta",
"thinking": "用户"
}
}
// content_block_stop
{
"type": "content_block_stop",
"index": 0
}
// content_block_start - text
{
"type": "content_block_start",
"index": 1,
"content_block": {
"type": "text",
"text": ""
}
}
// content_block_delta
{
"type": "content_block_delta",
"index": 1,
"delta": {
"type": "text_delta",
"text": "北京是中国的首都"
}
}
// content_block_stop
{
"type": "content_block_stop",
"index": 1
}
{
"type": "message_stop"
}
{
"type": "message_delta",
"delta": {
"type": "",
"stop_reason": "end_turn"
},
"usage": {
"input_tokens": 15,
"output_tokens": 342,
"total_tokens": 357
}
}