# OpenAI Chat Completion API 端到端测试用例与 Mock 设计 本文档针对 `POST /chat/completions` 接口,设计端到端测试用例及对应的 Mock 返回值结构。 --- ## 一、测试场景总览 | 分类 | 测试用例 | 优先级 | |------|----------|--------| | 基础对话 | 1. 单轮纯文本对话 | P0 | | 基础对话 | 2. 多轮对话(system + user + assistant + user) | P0 | | 消息类型 | 3. developer 消息(o1+ 模型) | P1 | | 消息类型 | 4. 带 tool_calls 的 assistant 消息 + tool 消息 | P0 | | 消息内容 | 5. 用户消息含图片 URL(vision) | P1 | | 消息内容 | 6. 用户消息含多模态内容(text + image) | P1 | | 消息内容 | 7. assistant 消息含 refusal | P1 | | 工具调用 | 8. 单工具调用(function tool) | P0 | | 工具调用 | 9. 并行多工具调用(parallel_tool_calls) | P1 | | 工具调用 | 10. tool_choice 为 "none" | P2 | | 工具调用 | 11. tool_choice 指定具体工具名 | P2 | | 工具调用 | 12. 废弃的 function_call 格式(向后兼容) | P2 | | 参数控制 | 13. temperature + top_p | P1 | | 参数控制 | 14. max_tokens 截断 | P1 | | 参数控制 | 15. stop 序列截断 | P2 | | 参数控制 | 16. frequency_penalty + presence_penalty | P2 | | 响应格式 | 17. response_format 为 json_object | P1 | | 响应格式 | 18. response_format 为 json_schema(structured output) | P1 | | 流式响应 | 19. 流式文本响应(SSE) | P0 | | 流式响应 | 20. 流式 + stream_options include_usage | P1 | | 流式响应 | 21. 流式工具调用 | P1 | | 推理模型 | 22. reasoning_effort 参数(o1/o3 模型) | P2 | | 错误处理 | 23. 无效 model 返回 404 | P1 | | 错误处理 | 24. 缺少 messages 返回 400 | P1 | | 错误处理 | 25. 内容安全策略拒绝(content_filter) | P2 | | 其他 | 26. n 参数多选择(multiple choices) | P2 | | 其他 | 27. seed 参数可复现 | P2 | | 其他 | 28. logprobs + top_logprobs | P2 | --- ## 二、测试用例详情 ### 用例 1:单轮纯文本对话 **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "你好,请介绍一下你自己" } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-001", "object": "chat.completion", "created": 1700000000, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "你好!我是由 OpenAI 开发的 AI 助手 GPT-4。我可以帮你回答问题、写作、编程、数学推理等任务。请问有什么我可以帮你的?" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 15, "completion_tokens": 42, "total_tokens": 57 }, "system_fingerprint": "fp_test123" } ``` **验证点:** - `choices[0].message.role` == `"assistant"` - `choices[0].message.content` 非空 - `choices[0].finish_reason` == `"stop"` - `usage` 字段完整 --- ### 用例 2:多轮对话 **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "system", "content": "你是一个专业的编程助手,请用简洁的语言回答问题。" }, { "role": "user", "content": "什么是 Go 语言的 interface?" }, { "role": "assistant", "content": "Go 语言的 interface 是一种类型,它定义了一组方法签名。任何实现了这些方法的类型都自动实现了该 interface,无需显式声明。" }, { "role": "user", "content": "能举个例子吗?" } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-002", "object": "chat.completion", "created": 1700000001, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "当然。例如定义一个 `Reader` interface:\n\n```go\ntype Reader interface {\n Read(p []byte) (n int, err error)\n}\n```\n\n`os.File` 和 `bytes.Buffer` 都实现了 `Read` 方法,所以它们都自动实现了 `Reader` interface。" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 120, "completion_tokens": 65, "total_tokens": 185 }, "system_fingerprint": "fp_test123" } ``` **验证点:** - 多轮上下文正确传递 - 响应与上下文连贯 --- ### 用例 3:developer 消息(o1+ 模型) **请求:** ```json { "model": "o1", "messages": [ { "role": "developer", "content": "你是一名数学专家。请逐步推理后再给出答案。" }, { "role": "user", "content": "15 + 23 * 2 等于多少?" } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-003", "object": "chat.completion", "created": 1700000002, "model": "o1", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "根据运算优先级,先算乘法:23 * 2 = 46,再加 15:46 + 15 = 61。答案是 61。" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 35, "completion_tokens": 48, "total_tokens": 83, "completion_tokens_details": { "reasoning_tokens": 20 } }, "system_fingerprint": "fp_test123" } ``` **验证点:** - developer 角色被正确处理 - reasoning_tokens 在详情中体现 --- ### 用例 4:工具调用 + 工具结果 **请求(第一轮 - 模型调用工具):** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "北京今天天气怎么样?" } ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "获取指定城市的天气信息", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称" } }, "required": ["city"] } } } ], "tool_choice": "auto" } ``` **期望 Mock 响应(200 OK,第一轮):** ```json { "id": "chatcmpl-test-004a", "object": "chat.completion", "created": 1700000003, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": null, "tool_calls": [ { "id": "call_abc123", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\": \"北京\"}" } } ] }, "finish_reason": "tool_calls", "logprobs": null } ], "usage": { "prompt_tokens": 80, "completion_tokens": 18, "total_tokens": 98 } } ``` **请求(第二轮 - 提交工具结果):** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "北京今天天气怎么样?" }, { "role": "assistant", "tool_calls": [ { "id": "call_abc123", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\": \"北京\"}" } } ] }, { "role": "tool", "tool_call_id": "call_abc123", "content": "北京今天晴,气温 25°C,东南风 2 级。" } ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "获取指定城市的天气信息", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称" } }, "required": ["city"] } } } ] } ``` **期望 Mock 响应(200 OK,第二轮):** ```json { "id": "chatcmpl-test-004b", "object": "chat.completion", "created": 1700000004, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "北京今天天气很好,晴天,气温 25°C,东南风 2 级,适合外出活动。" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 120, "completion_tokens": 30, "total_tokens": 150 } } ``` **验证点:** - 第一轮 `finish_reason` == `"tool_calls"` - `tool_calls` 包含正确的 function name 和 arguments - 第二轮能基于工具结果生成自然语言回复 --- ### 用例 5:用户消息含图片 URL(vision) **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "这张图片里有什么?" }, { "type": "image_url", "image_url": { "url": "https://example.com/images/cat.jpg", "detail": "high" } } ] } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-005", "object": "chat.completion", "created": 1700000005, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "图片中有一只橘色的猫,它正躺在沙发上晒太阳。猫的毛色是橘白相间的,眼睛是绿色的,看起来非常放松。" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 280, "completion_tokens": 45, "total_tokens": 325 } } ``` **验证点:** - 图片 URL 被正确传递 - 响应描述图片内容 --- ### 用例 6:用户消息含多模态内容(text + image) **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "请比较这两张图片有什么不同" }, { "type": "image_url", "image_url": { "url": "https://example.com/images/before.jpg" } }, { "type": "image_url", "image_url": { "url": "https://example.com/images/after.jpg" } } ] } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-006", "object": "chat.completion", "created": 1700000006, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "两张图片的主要区别:\n1. 第一张是白天的场景,第二张是夜晚\n2. 灯光从自然光变成了暖黄色的室内灯光\n3. 桌上的物品摆放位置有所不同" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 520, "completion_tokens": 55, "total_tokens": 575 } } ``` --- ### 用例 7:assistant 消息含 refusal **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "如何制作危险物品?" } ] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-007", "object": "chat.completion", "created": 1700000007, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "refusal": "抱歉,我无法提供涉及危险活动的信息。我的设计目的是提供有益和安全的帮助。如果你有其他问题,我很乐意协助。" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 12, "completion_tokens": 35, "total_tokens": 47 } } ``` **验证点:** - `refusal` 字段存在且非空 - `content` 为 null 或空 --- ### 用例 8:单工具调用(function tool) 同用例 4 第一轮。 --- ### 用例 9:并行多工具调用 **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "帮我查一下北京、上海、广州三个城市的天气" } ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "获取指定城市的天气信息", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名称" } }, "required": ["city"] } } } ], "tool_choice": "auto" } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-009", "object": "chat.completion", "created": 1700000009, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": null, "tool_calls": [ { "id": "call_001", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\": \"北京\"}" } }, { "id": "call_002", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\": \"上海\"}" } }, { "id": "call_003", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\": \"广州\"}" } } ] }, "finish_reason": "tool_calls", "logprobs": null } ], "usage": { "prompt_tokens": 95, "completion_tokens": 55, "total_tokens": 150 } } ``` **验证点:** - `tool_calls` 数组长度 == 3 - 每个 call 有不同 ID 和参数 --- ### 用例 10:tool_choice 为 "none" **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "随便聊聊" } ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "获取天气", "parameters": { "type": "object", "properties": { "city": {"type": "string"} } } } } ], "tool_choice": "none" } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-010", "object": "chat.completion", "created": 1700000010, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "好的!今天天气不错,很适合聊天。你想聊些什么话题呢?可以是技术、生活、娱乐等任何你感兴趣的内容。" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 50, "completion_tokens": 35, "total_tokens": 85 } } ``` **验证点:** - 尽管定义了 tools,响应中不包含 `tool_calls` - 纯文本回复 --- ### 用例 11:tool_choice 指定具体工具名 **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "查天气" } ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "获取天气", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}} } }, { "type": "function", "function": { "name": "get_news", "description": "获取新闻", "parameters": {"type": "object", "properties": {"topic": {"type": "string"}}} } } ], "tool_choice": { "type": "function", "function": {"name": "get_weather"} } } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-011", "object": "chat.completion", "created": 1700000011, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": null, "tool_calls": [ { "id": "call_weather1", "type": "function", "function": { "name": "get_weather", "arguments": "{}" } } ] }, "finish_reason": "tool_calls", "logprobs": null } ], "usage": { "prompt_tokens": 80, "completion_tokens": 15, "total_tokens": 95 } } ``` **验证点:** - 强制使用了 `get_weather` 而非 `get_news` --- ### 用例 12:废弃的 function_call 格式(向后兼容) **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "查天气" } ], "functions": [ { "name": "get_weather", "description": "获取天气", "parameters": { "type": "object", "properties": { "city": {"type": "string"} }, "required": ["city"] } } ], "function_call": "auto" } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-012", "object": "chat.completion", "created": 1700000012, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": null, "function_call": { "name": "get_weather", "arguments": "{\"city\": \"北京\"}" } }, "finish_reason": "function_call", "logprobs": null } ], "usage": { "prompt_tokens": 60, "completion_tokens": 20, "total_tokens": 80 } } ``` **验证点:** - 废弃的 `functions`/`function_call` 格式仍能被正确处理 - `finish_reason` == `"function_call"`(而非 `"tool_calls"`) --- ### 用例 13:temperature + top_p 参数 **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "写一首关于春天的短诗" } ], "temperature": 0.9, "top_p": 0.95 } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-013", "object": "chat.completion", "created": 1700000013, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "春风拂面花自开,\n柳絮飞舞满园香。\n燕归巢中呢喃语,\n万物复苏迎朝阳。" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 18, "completion_tokens": 32, "total_tokens": 50 } } ``` --- ### 用例 14:max_tokens 截断 **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "请详细介绍一下人工智能的发展历史" } ], "max_tokens": 30 } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-014", "object": "chat.completion", "created": 1700000014, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "人工智能起源于1950年代,图灵提出了机器能否思考的问题。1956年达特茅斯会议正式确立了AI领域。此后经历了多次起伏..." }, "finish_reason": "length", "logprobs": null } ], "usage": { "prompt_tokens": 20, "completion_tokens": 30, "total_tokens": 50 } } ``` **验证点:** - `finish_reason` == `"length"` - `completion_tokens` == 30(等于 max_tokens) - 内容被截断 --- ### 用例 15:stop 序列截断 **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "从1数到10,每行一个数字" } ], "stop": ["5"] } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-015", "object": "chat.completion", "created": 1700000015, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "1\n2\n3\n4\n" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 18, "completion_tokens": 10, "total_tokens": 28 } } ``` **验证点:** - `finish_reason` == `"stop"` - 内容在遇到 stop 序列时截断 --- ### 用例 16:frequency_penalty + presence_penalty **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "用不同的词汇描述'好'" } ], "frequency_penalty": 0.5, "presence_penalty": 0.3 } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-016", "object": "chat.completion", "created": 1700000016, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "优秀、出色、精彩、卓越、非凡、完美、绝佳、美妙、精彩、杰出" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 18, "completion_tokens": 15, "total_tokens": 33 } } ``` --- ### 用例 17:response_format 为 json_object **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "提取以下信息的姓名和年龄:张三,今年25岁,是一名工程师" } ], "response_format": { "type": "json_object" } } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-017", "object": "chat.completion", "created": 1700000017, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "{\"name\": \"张三\", \"age\": 25, \"occupation\": \"工程师\"}" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 35, "completion_tokens": 25, "total_tokens": 60 } } ``` **验证点:** - `content` 是合法的 JSON 字符串 --- ### 用例 18:response_format 为 json_schema(structured output) **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "创建一个用户信息记录,姓名李四,年龄30岁" } ], "response_format": { "type": "json_schema", "json_schema": { "name": "user_info", "schema": { "type": "object", "properties": { "name": {"type": "string"}, "age": {"type": "integer"}, "email": {"type": "string"} }, "required": ["name", "age"] }, "strict": true } } } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-018", "object": "chat.completion", "created": 1700000018, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "{\"name\": \"李四\", \"age\": 30}" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 85, "completion_tokens": 18, "total_tokens": 103 } } ``` **验证点:** - 输出严格符合 JSON schema 定义 - 不包含 schema 未定义的字段 --- ### 用例 19:流式文本响应(SSE) **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "你好" } ], "stream": true } ``` **期望 Mock 响应(200 OK, Content-Type: text/event-stream):** ``` data: {"id":"chatcmpl-stream-001","object":"chat.completion.chunk","created":1700000019,"model":"gpt-4o","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]} data: {"id":"chatcmpl-stream-001","object":"chat.completion.chunk","created":1700000019,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":"你"},"finish_reason":null}]} data: {"id":"chatcmpl-stream-001","object":"chat.completion.chunk","created":1700000019,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":"好"},"finish_reason":null}]} data: {"id":"chatcmpl-stream-001","object":"chat.completion.chunk","created":1700000019,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":"!我"},"finish_reason":null}]} data: {"id":"chatcmpl-stream-001","object":"chat.completion.chunk","created":1700000019,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":"是"},"finish_reason":null}]} data: {"id":"chatcmpl-stream-001","object":"chat.completion.chunk","created":1700000019,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":"AI"},"finish_reason":null}]} data: {"id":"chatcmpl-stream-001","object":"chat.completion.chunk","created":1700000019,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":"助手"},"finish_reason":null}]} data: {"id":"chatcmpl-stream-001","object":"chat.completion.chunk","created":1700000019,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":","},"finish_reason":null}]} data: {"id":"chatcmpl-stream-001","object":"chat.completion.chunk","created":1700000019,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":"很高兴"},"finish_reason":null}]} data: {"id":"chatcmpl-stream-001","object":"chat.completion.chunk","created":1700000019,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":"为你"},"finish_reason":null}]} data: {"id":"chatcmpl-stream-001","object":"chat.completion.chunk","created":1700000019,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":"服务"},"finish_reason":null}]} data: {"id":"chatcmpl-stream-001","object":"chat.completion.chunk","created":1700000019,"model":"gpt-4o","choices":[{"index":0,"delta":{"content":"。"},"finish_reason":null}]} data: {"id":"chatcmpl-stream-001","object":"chat.completion.chunk","created":1700000019,"model":"gpt-4o","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]} data: [DONE] ``` **验证点:** - 每个 chunk 的 `id` 一致 - 第一个 chunk 的 `delta` 包含 `role` - 中间 chunk 的 `delta` 只包含 `content` - 最后一个 chunk 包含 `finish_reason` - 以 `[DONE]` 结束 --- ### 用例 20:流式 + stream_options include_usage **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "你好" } ], "stream": true, "stream_options": { "include_usage": true } } ``` **期望 Mock 响应(200 OK, Content-Type: text/event-stream):** 最后一个 chunk 之前增加一个 usage chunk: ``` data: {"id":"chatcmpl-stream-020","object":"chat.completion.chunk","created":1700000020,"model":"gpt-4o","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]} ... (中间内容 chunk) ... data: {"id":"chatcmpl-stream-020","object":"chat.completion.chunk","created":1700000020,"model":"gpt-4o","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]} data: {"id":"chatcmpl-stream-020","object":"chat.completion.chunk","created":1700000020,"model":"gpt-4o","choices":[],"usage":{"prompt_tokens":10,"completion_tokens":25,"total_tokens":35}} data: [DONE] ``` **验证点:** - 倒数第二个 chunk 包含 `usage` 字段 - 该 chunk 的 `choices` 为空数组 --- ### 用例 21:流式工具调用 **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "北京天气怎么样?" } ], "tools": [ { "type": "function", "function": { "name": "get_weather", "description": "获取天气", "parameters": { "type": "object", "properties": { "city": {"type": "string"} }, "required": ["city"] } } } ], "stream": true } ``` **期望 Mock 响应(200 OK, Content-Type: text/event-stream):** ``` data: {"id":"chatcmpl-stream-021","object":"chat.completion.chunk","created":1700000021,"model":"gpt-4o","choices":[{"index":0,"delta":{"role":"assistant","content":null},"finish_reason":null}]} data: {"id":"chatcmpl-stream-021","object":"chat.completion.chunk","created":1700000021,"model":"gpt-4o","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_stream1","type":"function","function":{"name":"get_weather","arguments":""}}]},"finish_reason":null}]} data: {"id":"chatcmpl-stream-021","object":"chat.completion.chunk","created":1700000021,"model":"gpt-4o","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"finish_reason":null}]} data: {"id":"chatcmpl-stream-021","object":"chat.completion.chunk","created":1700000021,"model":"gpt-4o","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"city"}}]},"finish_reason":null}]} data: {"id":"chatcmpl-stream-021","object":"chat.completion.chunk","created":1700000021,"model":"gpt-4o","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"finish_reason":null}]} data: {"id":"chatcmpl-stream-021","object":"chat.completion.chunk","created":1700000021,"model":"gpt-4o","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"北京"}}]},"finish_reason":null}]} data: {"id":"chatcmpl-stream-021","object":"chat.completion.chunk","created":1700000021,"model":"gpt-4o","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"}\"}"}}]},"finish_reason":null}]} data: {"id":"chatcmpl-stream-021","object":"chat.completion.chunk","created":1700000021,"model":"gpt-4o","choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}]} data: [DONE] ``` **验证点:** - 第一个 chunk 包含 `role` - tool_calls 通过增量 chunk 逐步拼接 - 最后一个 chunk 的 `finish_reason` == `"tool_calls"` --- ### 用例 22:reasoning_effort 参数(o1/o3 模型) **请求:** ```json { "model": "o3", "messages": [ { "role": "user", "content": "一个房间里有3个灯泡,房间外有3个开关,每个开关控制一个灯泡。你只能进房间一次,如何确定哪个开关控制哪个灯泡?" } ], "reasoning_effort": "high" } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-022", "object": "chat.completion", "created": 1700000022, "model": "o3", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "解决方案:\n\n1. 打开第一个开关,等待几分钟\n2. 关闭第一个开关,打开第二个开关\n3. 立即进入房间\n\n此时:\n- 亮着的灯由第二个开关控制\n- 摸起来发热的灯由第一个开关控制(因为开过几分钟)\n- 既不亮也不热的灯由第三个开关控制" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 85, "completion_tokens": 120, "total_tokens": 205, "completion_tokens_details": { "reasoning_tokens": 80 } } } ``` **验证点:** - reasoning_tokens 显著增加 - 响应展示推理结果 --- ### 用例 23:无效 model 返回 404 **请求:** ```json { "model": "nonexistent-model-xyz", "messages": [ { "role": "user", "content": "你好" } ] } ``` **期望 Mock 响应(404 Not Found):** ```json { "error": { "message": "The model `nonexistent-model-xyz` does not exist or you do not have access to it.", "type": "invalid_request_error", "param": null, "code": "model_not_found" } } ``` --- ### 用例 24:缺少 messages 返回 400 **请求:** ```json { "model": "gpt-4o" } ``` **期望 Mock 响应(400 Bad Request):** ```json { "error": { "message": "'messages' is a required property and must be a non-empty array.", "type": "invalid_request_error", "param": null, "code": "missing_required_field" } } ``` --- ### 用例 25:内容安全策略拒绝 **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "生成违法内容..." } ] } ``` **期望 Mock 响应(400 Bad Request):** ```json { "error": { "message": "The content you submitted may violate our usage policies.", "type": "invalid_request_error", "param": null, "code": "content_filter" } } ``` 或者作为 completion 返回(finish_reason = "content_filter"): ```json { "id": "chatcmpl-test-025", "object": "chat.completion", "created": 1700000025, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": null, "refusal": "我无法生成此类内容。" }, "finish_reason": "content_filter", "logprobs": null } ], "usage": { "prompt_tokens": 15, "completion_tokens": 8, "total_tokens": 23 } } ``` --- ### 用例 26:n 参数多选择 **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "用一句话描述春天" } ], "n": 3 } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-026", "object": "chat.completion", "created": 1700000026, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "春天是万物复苏、百花盛开的季节。" }, "finish_reason": "stop", "logprobs": null }, { "index": 1, "message": { "role": "assistant", "content": "春风拂面,绿意盎然,处处洋溢着生机与希望。" }, "finish_reason": "stop", "logprobs": null }, { "index": 2, "message": { "role": "assistant", "content": "冬雪消融,嫩芽破土,春天带着温暖悄然而至。" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 18, "completion_tokens": 60, "total_tokens": 78 } } ``` **验证点:** - `choices` 数组长度为 3 - 每个 choice 有不同的 `index` --- ### 用例 27:seed 参数可复现 **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "随机生成一个5位数字" } ], "seed": 42, "temperature": 0 } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-027", "object": "chat.completion", "created": 1700000027, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "12345" }, "finish_reason": "stop", "logprobs": null } ], "usage": { "prompt_tokens": 18, "completion_tokens": 5, "total_tokens": 23 }, "system_fingerprint": "fp_test_seed42" } ``` **验证点:** - 相同 seed + temperature=0 应产生相同输出 - `system_fingerprint` 可用于验证 backend 一致性 --- ### 用例 28:logprobs + top_logprobs **请求:** ```json { "model": "gpt-4o", "messages": [ { "role": "user", "content": "1+1=" } ], "logprobs": true, "top_logprobs": 3 } ``` **期望 Mock 响应(200 OK):** ```json { "id": "chatcmpl-test-028", "object": "chat.completion", "created": 1700000028, "model": "gpt-4o", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "2" }, "finish_reason": "stop", "logprobs": { "content": [ { "token": "2", "logprob": -0.001, "bytes": [50], "top_logprobs": [ {"token": "2", "logprob": -0.001, "bytes": [50]}, {"token": "二", "logprob": -3.5, "bytes": [201, 147]}, {"token": " two", "logprob": -5.2, "bytes": [32, 116, 119, 111]} ] } ], "refusal": null } } ], "usage": { "prompt_tokens": 10, "completion_tokens": 1, "total_tokens": 11 } } ``` **验证点:** - `logprobs.content` 数组包含每个生成 token 的概率信息 - `top_logprobs` 包含前 K 个候选 token --- ## 三、Mock 响应通用结构规范 ### 非流式响应通用结构 ```json { "id": "chatcmpl-", "object": "chat.completion", "created": , "model": "", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "" | null, "refusal": "" | null, "tool_calls": [ { "id": "call_", "type": "function" | "custom", "function": {"name": "", "arguments": ""} | null, "custom": {"name": "", "input": ""} | null } ] }, "finish_reason": "stop" | "length" | "tool_calls" | "content_filter" | "function_call", "logprobs": null | { "content": [...], "refusal": null } } ], "usage": { "prompt_tokens": , "completion_tokens": , "total_tokens": , "prompt_tokens_details": { "cached_tokens": | null, "audio_tokens": | null }, "completion_tokens_details": { "reasoning_tokens": | null, "audio_tokens": | null, "accepted_prediction_tokens": | null, "rejected_prediction_tokens": | null } }, "system_fingerprint": "" | null, "service_tier": "auto" | "default" | "flex" | null } ``` ### 流式 Chunk 通用结构 ```json { "id": "chatcmpl-", "object": "chat.completion.chunk", "created": , "model": "", "choices": [ { "index": 0, "delta": { "role": "assistant" | null, "content": "" | null, "refusal": "" | null, "tool_calls": [ { "index": , "id": "call_" | null, "type": "function" | "custom" | null, "function": {"name": "" | null, "arguments": ""} | null, "custom": {"name": "" | null, "input": ""} | null } ] }, "finish_reason": "stop" | "length" | "tool_calls" | "content_filter" | null, "logprobs": null | { ... } } ], "usage": { ... } | null, "system_fingerprint": "" | null } ``` ### 错误响应通用结构 ```json { "error": { "message": "", "type": "invalid_request_error" | "authentication_error" | "api_error" | "rate_limit_error", "param": null | "", "code": "" } } ```