# 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-<unique_id>",
  "object": "chat.completion",
  "created": <unix_timestamp>,
  "model": "<model_name>",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "<text>" | null,
        "refusal": "<text>" | null,
        "tool_calls": [
          {
            "id": "call_<id>",
            "type": "function" | "custom",
            "function": {"name": "<name>", "arguments": "<json_string>"} | null,
            "custom": {"name": "<name>", "input": "<json_string>"} | null
          }
        ]
      },
      "finish_reason": "stop" | "length" | "tool_calls" | "content_filter" | "function_call",
      "logprobs": null | { "content": [...], "refusal": null }
    }
  ],
  "usage": {
    "prompt_tokens": <int>,
    "completion_tokens": <int>,
    "total_tokens": <int>,
    "prompt_tokens_details": {
      "cached_tokens": <int> | null,
      "audio_tokens": <int> | null
    },
    "completion_tokens_details": {
      "reasoning_tokens": <int> | null,
      "audio_tokens": <int> | null,
      "accepted_prediction_tokens": <int> | null,
      "rejected_prediction_tokens": <int> | null
    }
  },
  "system_fingerprint": "<fingerprint>" | null,
  "service_tier": "auto" | "default" | "flex" | null
}
```

### 流式 Chunk 通用结构

```json
{
  "id": "chatcmpl-<unique_id>",
  "object": "chat.completion.chunk",
  "created": <unix_timestamp>,
  "model": "<model_name>",
  "choices": [
    {
      "index": 0,
      "delta": {
        "role": "assistant" | null,
        "content": "<text_chunk>" | null,
        "refusal": "<text_chunk>" | null,
        "tool_calls": [
          {
            "index": <int>,
            "id": "call_<id>" | null,
            "type": "function" | "custom" | null,
            "function": {"name": "<name>" | null, "arguments": "<partial_json>"} | null,
            "custom": {"name": "<name>" | null, "input": "<partial_json>"} | null
          }
        ]
      },
      "finish_reason": "stop" | "length" | "tool_calls" | "content_filter" | null,
      "logprobs": null | { ... }
    }
  ],
  "usage": { ... } | null,
  "system_fingerprint": "<fingerprint>" | null
}
```

### 错误响应通用结构

```json
{
  "error": {
    "message": "<human_readable_message>",
    "type": "invalid_request_error" | "authentication_error" | "api_error" | "rate_limit_error",
    "param": null | "<parameter_name>",
    "code": "<error_code>"
  }
}
```

