1
0
Files
nex/docs/api_reference/test_mock_anthropic.md
lanyuanxiaoyao bc1ee612d9 refactor: 实现 ConversionEngine 协议转换引擎,替代旧 protocol 包
- 新增 ConversionEngine 核心引擎,支持 OpenAI 和 Anthropic 协议转换
- 添加 stream decoder/encoder 实现
- 更新 provider client 支持新引擎
- 补充单元测试和集成测试
- 更新 specs 文档
2026-04-20 13:02:28 +08:00

38 KiB
Raw Blame History

Anthropic Messages API 端到端测试用例与 Mock 设计

本文档针对 POST /v1/messages 接口,设计端到端测试用例及对应的 Mock 返回值结构。


一、测试场景总览

分类 测试用例 优先级
基础对话 1. 单轮纯文本对话 P0
基础对话 2. 多轮对话user + assistant + user P0
系统消息 3. 字符串 system prompt P0
系统消息 4. 数组 system prompt多文本块 P1
消息内容 5. 用户消息含图片base64 source P1
消息内容 6. 用户消息含图片URL source P1
消息内容 7. 用户消息含 tool_result 内容块 P0
工具调用 8. 单工具调用 P0
工具调用 9. 并行多工具调用 P1
工具调用 10. tool_choice 为 "none" P2
工具调用 11. tool_choice 指定具体工具名 P2
工具调用 12. tool_choice 为 "any"(强制调用) P2
参数控制 13. temperature + top_p + top_k P1
参数控制 14. max_tokens 截断 P1
参数控制 15. stop_sequences 截断 P2
扩展思考 16. thinking enabledextended thinking P1
扩展思考 17. thinking adaptive P2
输出格式 18. output_config 为 json_object P1
输出格式 19. output_config 为 json_schemastructured output P1
流式响应 20. 流式文本响应SSE P0
流式响应 21. 流式工具调用 P1
流式响应 22. 流式 + thinking 内容 P1
缓存控制 23. system prompt cache_controlephemeral P2
元数据 24. metadata.user_id P2
错误处理 25. 无效 model 返回 400 P1
错误处理 26. 缺少 max_tokens 返回 400 P1
错误处理 27. 缺少 messages 返回 400 P1
错误处理 28. 内容安全策略拒绝refusal P2
其他 29. disable_parallel_tool_use P2
其他 30. container 复用 P2

二、测试用例详情

用例 1单轮纯文本对话

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "你好,请介绍一下你自己"
    }
  ]
}

期望 Mock 响应200 OK

{
  "id": "msg_01test001",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "你好!我是 Claude由 Anthropic 开发的 AI 助手。我可以帮你回答问题、写作、编程、数学推理、数据分析等多种任务。我的知识截止到 2025 年 1 月。请问有什么我可以帮你的?"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 15,
    "output_tokens": 68
  }
}

验证点:

  • content[0].type == "text"
  • stop_reason == "end_turn"
  • usage 字段完整

用例 2多轮对话

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "什么是 Go 语言的 interface"
    },
    {
      "role": "assistant",
      "content": "Go 语言的 interface 是一种类型,它定义了一组方法签名。任何实现了这些方法的类型都自动实现了该 interface无需显式声明。这是 Go 语言"隐式接口"设计的核心特点。"
    },
    {
      "role": "user",
      "content": "能举个例子吗?"
    }
  ]
}

期望 Mock 响应200 OK

{
  "id": "msg_01test002",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "当然。例如定义一个 `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无需显式声明 `implements Reader`。"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 120,
    "output_tokens": 85
  }
}

用例 3字符串 system prompt

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "system": "你是一个专业的编程助手,请用简洁的语言回答问题。",
  "messages": [
    {
      "role": "user",
      "content": "什么是递归?"
    }
  ]
}

期望 Mock 响应200 OK

{
  "id": "msg_01test003",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "递归是一种函数调用自身来解决问题的方法。它包含两个关键部分:\n\n1. **基准情况**:直接返回结果的终止条件\n2. **递归情况**:将问题分解为更小的子问题,调用自身解决\n\n例如计算阶乘`n! = n × (n-1)!`,基准情况是 `0! = 1`。"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 45,
    "output_tokens": 72
  }
}

用例 4数组 system prompt多文本块

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "system": [
    {
      "type": "text",
      "text": "你是一个专业的编程助手。"
    },
    {
      "type": "text",
      "text": "请用简洁的语言回答问题,并尽量提供代码示例。"
    }
  ],
  "messages": [
    {
      "role": "user",
      "content": "什么是闭包?"
    }
  ]
}

期望 Mock 响应200 OK

{
  "id": "msg_01test004",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "闭包是指函数可以访问并"记住"其定义时所在作用域中的变量,即使在该作用域已经执行完毕后仍然可以访问。\n\n```javascript\nfunction makeCounter() {\n    let count = 0;\n    return function() {\n        count++;\n        return count;\n    };\n}\nconst counter = makeCounter();\nconsole.log(counter()); // 1\nconsole.log(counter()); // 2\n```\n\n`count` 变量被内部函数"捕获",形成了闭包。"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 85,
    "output_tokens": 95
  }
}

用例 5用户消息含图片base64 source

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "这张图片里有什么?"
        },
        {
          "type": "image",
          "source": {
            "type": "base64",
            "media_type": "image/jpeg",
            "data": "/9j/4AAQSkZJRgABAQEAYABgAAD..."
          }
        }
      ]
    }
  ]
}

期望 Mock 响应200 OK

{
  "id": "msg_01test005",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "图片中有一只橘色的猫,它正躺在棕色的沙发上晒太阳。猫的毛色是橘白相间的,眼睛是绿色的,看起来非常放松和满足。"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 1280,
    "output_tokens": 45
  }
}

用例 6用户消息含图片URL source

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "请描述这张图片"
        },
        {
          "type": "image",
          "source": {
            "type": "url",
            "url": "https://example.com/images/landscape.jpg"
          }
        }
      ]
    }
  ]
}

期望 Mock 响应200 OK

{
  "id": "msg_01test006",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "这是一幅美丽的自然风景图。前景是一片翠绿的草地,点缀着野花。中景有一条蜿蜒的小河,河水清澈见底。远处是连绵起伏的青山,山顶覆盖着白雪。天空湛蓝,飘着几朵白云。整体画面给人一种宁静祥和的感觉。"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 1520,
    "output_tokens": 82
  }
}

用例 7用户消息含 tool_result 内容块

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "北京天气怎么样?"
    },
    {
      "role": "assistant",
      "content": [
        {
          "type": "tool_use",
          "id": "toolu_01test001",
          "name": "get_weather",
          "input": {"city": "北京"}
        }
      ]
    },
    {
      "role": "user",
      "content": [
        {
          "type": "tool_result",
          "tool_use_id": "toolu_01test001",
          "content": "北京今天晴,气温 25°C东南风 2 级。"
        }
      ]
    }
  ],
  "tools": [
    {
      "name": "get_weather",
      "description": "获取指定城市的天气信息",
      "input_schema": {
        "type": "object",
        "properties": {
          "city": {
            "type": "string",
            "description": "城市名称"
          }
        },
        "required": ["city"]
      }
    }
  ]
}

期望 Mock 响应200 OK

{
  "id": "msg_01test007",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "北京今天天气很好,晴天,气温 25°C东南风 2 级,非常适合外出活动。"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 250,
    "output_tokens": 35
  }
}

验证点:

  • 能正确理解 tool_result 内容
  • 基于工具返回结果生成自然语言回复

用例 8单工具调用

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "北京天气怎么样?"
    }
  ],
  "tools": [
    {
      "name": "get_weather",
      "description": "获取指定城市的天气信息",
      "input_schema": {
        "type": "object",
        "properties": {
          "city": {
            "type": "string",
            "description": "城市名称"
          }
        },
        "required": ["city"]
      }
    }
  ],
  "tool_choice": {
    "type": "auto"
  }
}

期望 Mock 响应200 OK

{
  "id": "msg_01test008",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "tool_use",
      "id": "toolu_01test008",
      "name": "get_weather",
      "input": {
        "city": "北京"
      }
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "tool_use",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 180,
    "output_tokens": 42
  }
}

验证点:

  • stop_reason == "tool_use"
  • content[0].type == "tool_use"
  • input 包含正确的参数

用例 9并行多工具调用

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "帮我查一下北京、上海、广州三个城市的天气"
    }
  ],
  "tools": [
    {
      "name": "get_weather",
      "description": "获取指定城市的天气信息",
      "input_schema": {
        "type": "object",
        "properties": {
          "city": {"type": "string"}
        },
        "required": ["city"]
      }
    }
  ]
}

期望 Mock 响应200 OK

{
  "id": "msg_01test009",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "tool_use",
      "id": "toolu_01test009a",
      "name": "get_weather",
      "input": {"city": "北京"}
    },
    {
      "type": "tool_use",
      "id": "toolu_01test009b",
      "name": "get_weather",
      "input": {"city": "上海"}
    },
    {
      "type": "tool_use",
      "id": "toolu_01test009c",
      "name": "get_weather",
      "input": {"city": "广州"}
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "tool_use",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 200,
    "output_tokens": 120
  }
}

验证点:

  • content 数组包含 3 个 tool_use 块
  • 每个 tool_use 有不同的 ID

用例 10tool_choice 为 "none"

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "随便聊聊"
    }
  ],
  "tools": [
    {
      "name": "get_weather",
      "description": "获取天气",
      "input_schema": {
        "type": "object",
        "properties": {
          "city": {"type": "string"}
        }
      }
    }
  ],
  "tool_choice": {
    "type": "none"
  }
}

期望 Mock 响应200 OK

{
  "id": "msg_01test010",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "好的!今天天气不错,很适合聊天。你想聊些什么话题呢?可以是技术、生活、娱乐等任何你感兴趣的内容。"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 150,
    "output_tokens": 42
  }
}

验证点:

  • 尽管定义了 tools响应中不包含 tool_use 块
  • 纯文本回复

用例 11tool_choice 指定具体工具名

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "查天气"
    }
  ],
  "tools": [
    {
      "name": "get_weather",
      "description": "获取天气",
      "input_schema": {"type": "object", "properties": {"city": {"type": "string"}}}
    },
    {
      "name": "get_news",
      "description": "获取新闻",
      "input_schema": {"type": "object", "properties": {"topic": {"type": "string"}}}
    }
  ],
  "tool_choice": {
    "type": "tool",
    "name": "get_weather"
  }
}

期望 Mock 响应200 OK

{
  "id": "msg_01test011",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "tool_use",
      "id": "toolu_01test011",
      "name": "get_weather",
      "input": {}
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "tool_use",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 200,
    "output_tokens": 35
  }
}

验证点:

  • 强制使用了 get_weather 而非 get_news

用例 12tool_choice 为 "any"(强制调用)

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "帮我做点什么"
    }
  ],
  "tools": [
    {
      "name": "get_weather",
      "description": "获取天气",
      "input_schema": {"type": "object", "properties": {"city": {"type": "string"}}}
    }
  ],
  "tool_choice": {
    "type": "any"
  }
}

期望 Mock 响应200 OK

{
  "id": "msg_01test012",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "tool_use",
      "id": "toolu_01test012",
      "name": "get_weather",
      "input": {}
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "tool_use",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 150,
    "output_tokens": 30
  }
}

验证点:

  • 模型必须调用至少一个工具

用例 13temperature + top_p + top_k

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "写一首关于春天的短诗"
    }
  ],
  "temperature": 0.9,
  "top_p": 0.95,
  "top_k": 50
}

期望 Mock 响应200 OK

{
  "id": "msg_01test013",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "春风拂面花自开,\n柳絮飞舞满园香。\n燕归巢中呢喃语\n万物复苏迎朝阳。"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 25,
    "output_tokens": 32
  }
}

用例 14max_tokens 截断

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 20,
  "messages": [
    {
      "role": "user",
      "content": "请详细介绍一下人工智能的发展历史"
    }
  ]
}

期望 Mock 响应200 OK

{
  "id": "msg_01test014",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "人工智能起源于1950年代图灵提出了机器能否思考的问题。1956年达特茅斯会议正式确立了AI领域。"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "max_tokens",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 22,
    "output_tokens": 20
  }
}

验证点:

  • stop_reason == "max_tokens"
  • output_tokens == 20等于 max_tokens
  • 内容被截断

用例 15stop_sequences 截断

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "从1数到10每行一个数字"
    }
  ],
  "stop_sequences": ["5"]
}

期望 Mock 响应200 OK

{
  "id": "msg_01test015",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "1\n2\n3\n4\n"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "stop_sequence",
  "stop_sequence": "5",
  "usage": {
    "input_tokens": 22,
    "output_tokens": 10
  }
}

验证点:

  • stop_reason == "stop_sequence"
  • stop_sequence 字段包含触发截断的序列

用例 16thinking enabledextended thinking

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 4096,
  "messages": [
    {
      "role": "user",
      "content": "一个房间里有3个灯泡房间外有3个开关每个开关控制一个灯泡。你只能进房间一次如何确定哪个开关控制哪个灯泡"
    }
  ],
  "thinking": {
    "type": "enabled",
    "budget_tokens": 2048
  }
}

期望 Mock 响应200 OK

{
  "id": "msg_01test016",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "thinking",
      "thinking": "这是一个经典的逻辑推理问题。我需要找到一种方法,通过一次观察来区分三个开关。关键是灯泡有两种可观察的状态:亮或灭。但如果只用亮灭,我只能区分一个开关(开的那个)。我需要找到另一种可观察的属性...温度!灯泡开着会发热。所以我可以:先开一个开关等一会儿,然后关掉,再开另一个开关,然后进房间。亮着的是第二个开关,热的是第一个开关,冷且灭的是第三个开关。"
    },
    {
      "type": "text",
      "text": "解决方案如下:\n\n1. **打开第一个开关**,等待几分钟\n2. **关闭第一个开关****打开第二个开关**\n3. **立即进入房间**\n\n此时观察\n- **亮着的灯** → 由第二个开关控制\n- **摸起来发热的灯** → 由第一个开关控制(因为开过几分钟)\n- **既不亮也不热的灯** → 由第三个开关控制"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 95,
    "output_tokens": 280
  }
}

验证点:

  • content 包含 thinking 块和 text
  • output_tokens 包含 thinking tokens

用例 17thinking adaptive

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 4096,
  "messages": [
    {
      "role": "user",
      "content": "请帮我分析一下这个算法问题"
    }
  ],
  "thinking": {
    "type": "adaptive",
    "budget_tokens": 1024
  }
}

期望 Mock 响应200 OK

{
  "id": "msg_01test017",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "thinking",
      "thinking": "用户提到了一个算法问题,但没有具体说明是什么问题。我需要请用户提供更多细节。"
    },
    {
      "type": "text",
      "text": "我很乐意帮你分析算法问题!不过你没有具体说明是什么问题。请详细描述一下:\n\n1. 问题的具体要求是什么?\n2. 输入输出的格式是怎样的?\n3. 有没有什么约束条件?\n\n有了这些信息后我可以帮你分析解题思路和最优解法。"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 35,
    "output_tokens": 95
  }
}

用例 18output_config 为 json_object

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "提取以下信息的姓名和年龄张三今年25岁是一名工程师"
    }
  ],
  "output_config": {
    "format": {
      "type": "json_object"
    }
  }
}

期望 Mock 响应200 OK

{
  "id": "msg_01test018",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "{\"name\": \"张三\", \"age\": 25, \"occupation\": \"工程师\"}"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 45,
    "output_tokens": 28
  }
}

验证点:

  • content[0].text 是合法的 JSON 字符串

用例 19output_config 为 json_schemastructured output

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "创建一个用户信息记录姓名李四年龄30岁"
    }
  ],
  "output_config": {
    "format": {
      "type": "json_schema",
      "schema": {
        "type": "object",
        "properties": {
          "name": {"type": "string"},
          "age": {"type": "integer"},
          "email": {"type": "string"}
        },
        "required": ["name", "age"]
      }
    }
  }
}

期望 Mock 响应200 OK

{
  "id": "msg_01test019",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "{\"name\": \"李四\", \"age\": 30}"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 120,
    "output_tokens": 22
  }
}

验证点:

  • 输出严格符合 JSON schema 定义
  • 不包含 schema 未定义的字段

用例 20流式文本响应SSE

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "你好"
    }
  ],
  "stream": true
}

期望 Mock 响应200 OK, Content-Type: text/event-stream

event: message_start
data: {"type":"message","id":"msg_01stream001","role":"assistant","content":[],"model":"claude-opus-4-7","stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":10,"output_tokens":0}}

event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"你"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"好"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"我"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"是"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Claude"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"很高兴"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"为你"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"服务"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"。"}}

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":8}}

event: message_stop
data: {"type":"message_stop"}

验证点:

  • 事件顺序message_start → content_block_start → content_block_delta* → content_block_stop → message_delta → message_stop
  • message_start 包含完整的 message 对象
  • 每个 content_block_delta 包含增量文本
  • message_delta 包含 stop_reason 和最终 usage
  • message_stop 结束

用例 21流式工具调用

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "北京天气怎么样?"
    }
  ],
  "tools": [
    {
      "name": "get_weather",
      "description": "获取天气",
      "input_schema": {
        "type": "object",
        "properties": {
          "city": {"type": "string"}
        },
        "required": ["city"]
      }
    }
  ],
  "stream": true
}

期望 Mock 响应200 OK, Content-Type: text/event-stream

event: message_start
data: {"type":"message","id":"msg_01stream003","role":"assistant","content":[],"model":"claude-opus-4-7","stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":180,"output_tokens":0}}

event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"tool_use","id":"toolu_01stream003","name":"get_weather"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"{\""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"city"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"\":\""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"北京"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"input_json_delta","partial_json":"}\""}}

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"output_tokens":42}}

event: message_stop
data: {"type":"message_stop"}

验证点:

  • content_block_start 包含 tool_use 类型和工具名
  • input_json_delta 逐步拼接完整的 JSON 输入
  • stop_reason == "tool_use"

用例 22流式 + thinking 内容

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 4096,
  "messages": [
    {
      "role": "user",
      "content": "1+1=?"
    }
  ],
  "thinking": {
    "type": "enabled",
    "budget_tokens": 1024
  },
  "stream": true
}

期望 Mock 响应200 OK, Content-Type: text/event-stream

event: message_start
data: {"type":"message","id":"msg_01stream004","role":"assistant","content":[],"model":"claude-opus-4-7","stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":30,"output_tokens":0}}

event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"thinking","thinking":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"thinking_delta","thinking":"这是一个简单的"}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"thinking_delta","thinking":"数学问题。"}}

event: content_block_stop
data: {"type":"content_block_stop","index":0}

event: content_block_start
data: {"type":"content_block_start","index":1,"content_block":{"type":"text","text":""}}

event: content_block_delta
data: {"type":"content_block_delta","index":1,"delta":{"type":"text_delta","text":"1+1=2"}}

event: content_block_stop
data: {"type":"content_block_stop","index":1}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":25}}

event: message_stop
data: {"type":"message_stop"}

验证点:

  • 先有 thinking 块,再有 text 块
  • thinking_delta 类型正确
  • 两个内容块有不同的 index

用例 23system prompt cache_controlephemeral

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "system": [
    {
      "type": "text",
      "text": "你是一个专业的编程助手。",
      "cache_control": {
        "type": "ephemeral"
      }
    }
  ],
  "messages": [
    {
      "role": "user",
      "content": "你好"
    }
  ]
}

期望 Mock 响应200 OK

{
  "id": "msg_01test023",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "你好!我是 Claude很高兴为你服务。我是由 Anthropic 开发的 AI 助手,可以帮你解答问题、写作、编程等各种任务。请问有什么我可以帮你的?"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 25,
    "output_tokens": 52,
    "cache_creation_input_tokens": 15,
    "cache_read_input_tokens": 0
  }
}

验证点:

  • cache_creation_input_tokens 反映缓存创建的 token 数

用例 24metadata.user_id

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "你好"
    }
  ],
  "metadata": {
    "user_id": "user_12345"
  }
}

期望 Mock 响应200 OK

{
  "id": "msg_01test024",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "你好!我是 Claude很高兴为你服务。请问有什么我可以帮你的"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 12,
    "output_tokens": 18
  }
}

用例 25无效 model 返回 400

请求:

{
  "model": "nonexistent-model-xyz",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "你好"
    }
  ]
}

期望 Mock 响应400 Bad Request

{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "The model 'nonexistent-model-xyz' does not exist or is not available."
  }
}

用例 26缺少 max_tokens 返回 400

请求:

{
  "model": "claude-opus-4-7",
  "messages": [
    {
      "role": "user",
      "content": "你好"
    }
  ]
}

期望 Mock 响应400 Bad Request

{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "'max_tokens' is a required parameter for the Messages API."
  }
}

用例 27缺少 messages 返回 400

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024
}

期望 Mock 响应400 Bad Request

{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "'messages' is a required parameter and must be a non-empty array."
  }
}

用例 28内容安全策略拒绝refusal

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "生成违法内容..."
    }
  ]
}

期望 Mock 响应200 OK

{
  "id": "msg_01test028",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "抱歉,我无法协助生成此类内容。我的设计原则是提供有益、安全和负责任的帮助。如果你有其他问题或需要帮助的地方,我很乐意为你服务。"
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "refusal",
  "stop_sequence": null,
  "stop_details": {
    "type": "refusal",
    "category": "cyber",
    "explanation": "请求内容违反了使用政策。"
  },
  "usage": {
    "input_tokens": 18,
    "output_tokens": 42
  }
}

验证点:

  • stop_reason == "refusal"
  • stop_details 包含 refusal 详情

用例 29disable_parallel_tool_use

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "帮我查北京和上海的天气"
    }
  ],
  "tools": [
    {
      "name": "get_weather",
      "description": "获取天气",
      "input_schema": {"type": "object", "properties": {"city": {"type": "string"}}}
    }
  ],
  "disable_parallel_tool_use": true
}

期望 Mock 响应200 OK

{
  "id": "msg_01test029",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "tool_use",
      "id": "toolu_01test029",
      "name": "get_weather",
      "input": {"city": "北京"}
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "tool_use",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 120,
    "output_tokens": 35
  }
}

验证点:

  • 只调用了一个工具(而非并行调用两个)

用例 30container 复用

请求:

{
  "model": "claude-opus-4-7",
  "max_tokens": 1024,
  "messages": [
    {
      "role": "user",
      "content": "运行一段 Python 代码"
    }
  ],
  "tools": [
    {
      "type": "code_execution_20250825",
      "name": "code_execution",
      "container": {
        "type": "python",
        "version": "3.11"
      }
    }
  ]
}

期望 Mock 响应200 OK

{
  "id": "msg_01test030",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "server_tool_use",
      "id": "toolu_01test030",
      "name": "code_execution",
      "input": {
        "code": "print('Hello, World!')",
        "language": "python"
      },
      "caller": {
        "type": "direct"
      }
    }
  ],
  "model": "claude-opus-4-7",
  "stop_reason": "tool_use",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 150,
    "output_tokens": 55
  }
}

三、Mock 响应通用结构规范

非流式响应通用结构

{
  "id": "msg_<unique_id>",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text" | "tool_use" | "thinking" | "redacted_thinking" | "server_tool_use" | "web_search_tool_result" | "web_fetch_tool_result" | "code_execution_tool_result" | "bash_code_execution_tool_result" | "text_editor_code_execution_tool_result" | "tool_search_tool_result",
      "text": "<text_content>" | null,
      "id": "toolu_<id>" | null,
      "name": "<tool_name>" | null,
      "input": { /* tool input */ } | null,
      "thinking": "<thinking_content>" | null,
      "data": "<redacted_data>" | null
    }
  ],
  "model": "<model_name>",
  "stop_reason": "end_turn" | "max_tokens" | "stop_sequence" | "tool_use" | "pause_turn" | "refusal",
  "stop_sequence": "<sequence>" | null,
  "stop_details": {
    "type": "refusal",
    "category": "cyber" | "bio",
    "explanation": "<explanation>"
  } | null,
  "usage": {
    "input_tokens": <int>,
    "output_tokens": <int>,
    "cache_read_input_tokens": <int> | null,
    "cache_creation_input_tokens": <int> | null
  }
}

流式 Event 通用结构

Event Type Key Fields
message_start type: "message", id, role, content: [], model, stop_reason: null, usage
content_block_start type: "content_block_start", index, content_block: {type, ...}
content_block_delta type: "content_block_delta", index, delta: {type, text/partial_json/thinking}
content_block_stop type: "content_block_stop", index
message_delta type: "message_delta", delta: {stop_reason, stop_sequence}, usage: {output_tokens}
message_stop type: "message_stop"

错误响应通用结构

{
  "type": "error",
  "error": {
    "type": "invalid_request_error" | "authentication_error" | "permission_error" | "not_found_error" | "rate_limit_error" | "api_error",
    "message": "<human_readable_message>"
  }
}

请求必需参数

参数 类型 说明
model string 模型标识符(如 claude-opus-4-7
max_tokens integer 最大生成 token 数(必需)
messages array 消息数组,至少包含一条(必需)

请求可选参数

参数 类型 默认值 说明
system string/array - 系统 prompt
temperature number 1.0 采样温度0.0-1.0
top_p number - 核采样阈值
top_k number - 从 top K 采样
stop_sequences array - 停止序列
tools array - 工具定义
tool_choice object auto 工具选择策略
thinking object - 扩展思考配置
output_config object - 输出格式配置
stream boolean false 是否流式
metadata object - 请求元数据
disable_parallel_tool_use boolean false 禁用并行工具调用
container any - 容器标识符

Stop Reason 枚举

含义
end_turn 自然结束
max_tokens 达到 max_tokens 限制
stop_sequence 遇到自定义停止序列
tool_use 模型调用了工具
pause_turn 长运行 turn 暂停
refusal 安全策略拒绝