- AI 应用
- API网关
- LLM 网关
- 后端
- 前端
【免费下载链接】axonhub
⚡️ Open-source AI Gateway — Use any SDK to call 100+ LLMs. Built-in failover, load balancing, cost control & end-to-end tracing.
本篇文章以 AxonHub 仓库中的 Anthropic 多工具集成测试 为脉络,完整讲解如何通过官方anthropic-sdk-go在一个请求中声明多个 function tool,并覆盖"顺序执行、并行执行、强制工具选择(tool choice)"三大经典场景。读完本文,你将掌握 Anthropic Messages API 多工具调用的完整请求-响应循环、工具结果回填的对话续写写法,以及如何在 AxonHub 网关上通过 集成测试 环境验证这套流程。
一、测试场景与定位
integration_test/anthropic/tool_multiple/目录专门用于验证"多个工具同时可用"时模型的行为,测试文件与说明文档如下:
- README.md — 测试用例与工具定义说明;
- tool_multiple_test.go — 全部测试的完整 Go 实现。
该目录是整个 Anthropic SDK 集成测试 体系的一部分,与 单工具测试(tool_single/)互补:单工具目录验证"一个工具"的基础调用闭环,本目录则聚焦"一次请求暴露多个工具"时模型的工具选择、多轮调用与结果合并。
测试的核心观察点是响应中的stop_reason是否为tool_use。当模型决定调用工具时,Anthropic 会在同一次响应中返回一个或多个tool_usecontent block;测试据此进入"解析工具参数 → 模拟执行 → 回填 tool_result → 追加对话"的循环。
二、测试环境准备
多工具测试依赖一套统一的测试基础设施,定义在 integration_test/anthropic/internal/testutil/ 中,其中 config.go 负责读取环境变量,helper.go 提供客户端与断言封装。
2.1 必需环境变量
测试启动时NewTestHelper会调用ValidateConfig,缺少 API Key 时直接t.Skipf跳过该用例。需要设置的关键变量如下:
| 环境变量 | 作用 | 默认值(以 config.go 为准) |
|---|---|---|
TEST_AXONHUB_API_KEY | AxonHub / Anthropic API 密钥,缺失则跳过测试 | 无(必填) |
TEST_ANTHROPIC_BASE_URL | 网关或上游地址 | http://localhost:8090/anthropic |
TEST_MODEL | 测试所用模型 | deepseek-chat(注意:集成测试总览 文档中描述默认值为claude-3-5-sonnet-20241022,与源码默认值存在差异,实际行为以 config.go 源码为准) |
TEST_TRACE_ID | 指定 trace ID | 未设置时自动生成trace-<random> |
TEST_THREAD_ID | 指定 thread ID | 未设置时自动生成thread-<random> |
TEST_DISABLE_TRACE | 置为true可关闭 trace 头 | false |
TEST_DISABLE_THREAD | 置为true可关闭 thread 头 | false |
一个典型的配置命令:
export TEST_AXONHUB_API_KEY="your-anthropic-api-key" export TEST_ANTHROPIC_BASE_URL="http://localhost:8090/anthropic" # 可选,默认即此值 export TEST_MODEL="claude-3-5-sonnet-20241022" # 可选 export TEST_TRACE_ID="test-trace-123" # 可选 export TEST_THREAD_ID="test-thread-456" # 可选2.2 与 AxonHub 的链路对接
所有请求都会携带 AxonHub 规范的两个请求头(见 config.go):
AH-Trace-Id:请求追踪标识;AH-Thread-Id:会话线程标识。
helper.CreateMessageWithHeaders(helper.go)通过option.WithHeader在调用点注入头部,从而让网关侧能够建立完整的请求追踪链路,这与 AxonHub 端到端追踪能力保持一致。
三、测试中的两个模拟工具
目录说明文档明确了两个被测试的工具(详见 README.md):
Weather Tool
- 函数名:
get_current_weather - 参数:
location(string,必填)— 城市名 - 模拟行为:按城市返回 mock 天气数据
Calculator Tool
- 函数名:
calculate - 参数:
expression(string,必填)— 数学表达式 - 模拟行为:对简单表达式求值
在 Go 代码中,二者通过anthropic.ToolParam声明为 JSON Schema 风格的定义,例如(节选自 tool_multiple_test.go):
weatherTool := anthropic.ToolParam{ Name: "get_current_weather", Description: anthropic.String("Get the current weather for a specified location"), InputSchema: anthropic.ToolInputSchemaParam{ Type: "object", Properties: map[string]interface{}{ "location": map[string]string{ "type": "string", }, }, Required: []string{"location"}, }, } calculatorTool := anthropic.ToolParam{ Name: "calculate", Description: anthropic.String("Perform mathematical calculations"), InputSchema: anthropic.ToolInputSchemaParam{ Type: "object", Properties: map[string]interface{}{ "expression": map[string]string{ "type": "string", }, }, Required: []string{"expression"}, }, } tools := []anthropic.ToolUnionParam{ {OfTool: &weatherTool}, {OfTool: &calculatorTool}, }要点:ToolParam由Name、Description、InputSchema三部分组成;InputSchema遵循 JSON Schema 规范,Properties描述每个参数,Required声明必填参数。模型会依据 Description 判断何时使用该工具,因此描述写得越明确,工具路由越准确。若需补充参数描述,可在Properties的 value 中增加"description"字段(单工具测试 tool_single_test.go 展示了这一写法)。
四、测试用例详解
4.1 TestMultipleToolsSequential — 多工具顺序执行
该用例模拟"一次提问需要先后使用多个工具"的场景,提示词为:
Please use the available tools to: 1) Get the current weather in New York, and 2) Calculate 15 * 23. Provide both results.
请求构造(tool_multiple_test.go):
messages := []anthropic.MessageParam{ anthropic.NewUserMessage(anthropic.NewTextBlock(question)), } params := anthropic.MessageNewParams{ Model: helper.GetModel(), Messages: messages, Tools: tools, MaxTokens: 1024, }执行流程:
- 发起首次请求:
helper.CreateMessageWithHeaders(ctx, params)返回响应; - 检测工具调用:判断
response.StopReason == anthropic.StopReasonToolUse; - 解析并模拟执行:遍历
response.Content,用block.AsToolUse()取出tool_use块,json.Unmarshal解析Input中的参数,再按函数名分派到simulateWeatherFunction/simulateCalculatorFunction; - 回填结果并续聊:将模型响应
response.ToParam()追加进messages,然后为每个tool_use构造anthropic.NewToolResultBlock(toolUseBlock.ID, result, false),包装进anthropic.NewUserMessage后追加,最后用完整历史再次调用; - 校验终答:验证 final response 非空,且内容综合了两个工具的信息。
这里的关键是tool_use 块必须按 ID 对应回填 tool_result,模型才能把结果关联到对应的调用。
4.2 TestMultipleToolsParallel — 并行工具执行
该用例一次请求同时需要多个独立信息,提示词为:
Please use the available tools to: 1) Get weather for New York, 2) Get weather for London, and 3) Calculate 100 / 4. I need all three results.
Anthropic Messages API 允许在单次响应中返回多个 tool_use 块。测试的续聊逻辑与顺序用例相同,但处理的是同一响应中的多个调用,并在最终校验中加入内容断言(tool_multiple_test.go):
if !strings.Contains(strings.ToLower(finalText), "weather") && !strings.Contains(strings.ToLower(finalText), "25") { t.Errorf("Expected response to contain weather or calculation info, got: %s", finalText) }即最终回答必须包含来自天气工具与计算器工具的信息(100 / 4 = 25)。仓库中 Anthropic 协议侧的并行工具转换有对应的测试数据佐证,可参考 llm/transformer/anthropic/testdata/anthropic-parallel_multiple_tool.request.json 与 llm/transformer/anthropic/testdata/llm-parallel_multiple_tool.stream.jsonl,从中可见网关在协议转换层对并行工具调用(多个 tool_use 同时出现)的完整处理样本。
4.3 TestToolChoiceRequired — 强制工具选择
有些查询必须走指定工具,此时可通过ToolChoice强制模型调用特定函数。该用例的提示词为:
Please use the calculate tool to compute 50 * 30 and tell me the result.
请求构造(tool_multiple_test.go):
params := anthropic.MessageNewParams{ Model: helper.GetModel(), Messages: messages, Tools: tools, ToolChoice: anthropic.ToolChoiceUnionParam{ OfTool: &anthropic.ToolChoiceToolParam{ Name: "calculate", }, }, MaxTokens: 1024, }测试首先断言响应一定是StopReasonToolUse(若模型直接回答则t.Fatalf),随后确认被调用的正是calculate函数(tool_multiple_test.go):
if toolUseBlock == nil { t.Fatal("Expected calculate function to be called") }值得注意的细节:在续聊的第二轮请求前,需要清空 ToolChoice(tool_multiple_test.go):
params.Messages = messages params.ToolChoice = anthropic.ToolChoiceUnionParam{}否则模型在拿到tool_result后仍可能被强制继续调用工具而无法给出最终文字回答。终答校验使用testutil.ContainsAnyCaseInsensitive(finalText, "1500", "1,500", "one thousand five hundred")(该工具函数定义在 helper.go),允许模型以不同格式呈现结果。
五、工具执行模拟实现
测试不依赖真实第三方服务,而是通过本地 mock 函数模拟执行结果。
天气工具(tool_multiple_test.go)内置了四个城市的固定天气数据:
| 城市 | 温度 | 天气 | 湿度 |
|---|---|---|---|
| New York | 22°C | Partly cloudy | 65% |
| London | 18°C | Rainy | 80% |
| Tokyo | 25°C | Sunny | 60% |
| Paris | 20°C | Clear | 55% |
| 其他城市 | 20°C | Sunny | 50%(默认) |
城市名通过normalizeLocation(转小写)做简单归一化后查表。
计算器工具(tool_multiple_test.go)则直接对固定表达式返回预期值:
switch expression { case "15 * 23": return 345 case "100 / 4": return 25 case "50 * 30": return 1500 case "10 + 5": return 15 default: return 42 // Default answer }需要说明:simulateCalculatorFunction是固定查表实现,并非真正解析任意表达式(源码注释也明确指出真实实现应使用数学库)。因此运行测试时应使用与用例提示词一致的表达式;这也是集成测试中"模拟工具(tool simulation)"的通用做法,即只验证协议闭环,不引入外部计算依赖。
六、运行测试
6.1 目录内直接运行
按 README.md 提供的命令,在integration_test/anthropic/tool_multiple目录下执行:
# 运行本目录全部多工具测试 go test -v . # 运行指定的单个用例 go test -v -run TestMultipleToolsSequential go test -v -run TestMultipleToolsParallel go test -v -run TestToolChoiceRequired6.2 通过 Makefile 运行
integration_test/anthropic/Makefile 提供了test-tools目标,会同时跑单工具与多工具两组用例:
make test-tools其等价命令为:
go test --count=1 -v ./tool_single go test --count=1 -v ./tool_multiple使用--count=1可避免 Go 测试缓存在本地未变更代码时直接复用上次结果,保证每次都是真实调用。
6.3 运行前提
- Go 版本与依赖:仓库 go.mod 声明
go 1.25.2并依赖github.com/anthropics/anthropic-sdk-go v1.26.0,首次运行前执行go mod tidy; - API Key:必须设置
TEST_AXONHUB_API_KEY,否则用例会被Skip跳过; - 网络可达:
TEST_ANTHROPIC_BASE_URL默认指向http://localhost:8090/anthropic(即本地 AxonHub 网关的 Anthropic 协议入口),若直连 Anthropic 官方地址请显式覆盖; - 模型能力:多工具并行与强制 tool choice 依赖模型对 Anthropic 工具调用协议的支持,README 中亦提示"并行工具调用并非所有模型都支持"(见 README.md)。
6.4 常见失败排查
- 测试被跳过:
TEST_AXONHUB_API_KEY未设置或配置校验失败,用例以Skipf退出; - 未检测到工具调用:模型直接给出文本回答,此时用例走"直接响应"分支并校验文本非空。若希望模型必然调用工具,应使用
ToolChoice强制指定; - 终答校验失败:
TestMultipleToolsParallel要求回答包含 weather 信息或计算结果25;TestToolChoiceRequired要求出现1500。若模型回答表述偏差,可结合go test -v输出的t.Logf日志定位。
七、总结与扩展阅读
多工具集成测试覆盖了 Anthropic 工具调用协议的三个关键模式:多工具声明(Tools)、结果回填续聊(ToolResultBlock+response.ToParam())、强制路由(ToolChoice)。这套模式可直接复用到 Agent 应用开发中:任何需要"模型自主挑选多个函数并汇总结果"的场景(查天气 + 算账 + 搜资料等),都可以参照 tool_multiple_test.go 的循环结构实现。
如需继续深入,可参考仓库内以下资料:
- 集成测试总览 — 全部 Anthropic 测试用例(QA、单工具、多轮对话、流式、追踪)索引;
- 单工具测试说明 — 与多工具场景互补的基础调用示例;
- 测试基础设施 — 环境变量与客户端配置的完整源码;
- Makefile — 各测试套件的快捷运行目标;
- llm/transformer/anthropic/ — 网关侧 Anthropic 协议转换实现,其中 testdata 目录存放了并行多工具请求/响应/流的转换样本,可作为理解网关如何处理多工具调用的源码级参考。
- AI 应用
- API网关
- LLM 网关
- 后端
- 前端
【免费下载链接】axonhub
⚡️ Open-source AI Gateway — Use any SDK to call 100+ LLMs. Built-in failover, load balancing, cost control & end-to-end tracing.
相关推荐
AxonHub 集成测试实战:多工具调用(Function Calling)的顺序执行、并行调用与强制 Tool Choice 全解析
AxonHub 集成测试实战:多工具调用(Function Calling)的顺序执行、并行调用与强制 Tool Choice 全解析 本文围绕 AxonHub
AI 应用API网关LLM 网关后端前端AxonHub 会话集成测试实战:基于 Anthropic Go SDK 的多轮对话、工具调用与上下文保持
AxonHub 会话集成测试实战:基于 Anthropic Go SDK 的多轮对话、工具调用与上下文保持 本文围绕 AxonHub 仓库中 integrati
AI 应用API网关LLM 网关后端前端AxonHub 单 Trace 多请求链路测试深度解析:基于 Anthropic Go SDK 的多轮对话与工具调用验证
AxonHub 单 Trace 多请求链路测试深度解析:基于 Anthropic Go SDK 的多轮对话与工具调用验证 本文以 integration_tes
AI 应用API网关LLM 网关后端前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考