AxonHub 集成测试指南:基于 OpenAI Responses API 的多轮对话测试(previous_response_id 与无状态 input 数组)

发布时间:2026/10/13 2:04:47

AxonHub 集成测试指南:基于 OpenAI Responses API 的多轮对话测试(previous_response_id 与无状态 input 数组) 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.项目地址https://gitcode.com/gh_mirrors/ax/axonhub点击查看免费下载本文档围绕 AxonHub 仓库中 integration_test/openai/responses/conversation 目录下的对话类集成测试展开系统讲解如何基于 OpenAI Responses API 编写多轮对话测试既包括通过previous_response_id让 API 自动维护上下文的有状态对话也包括把完整历史塞进input数组的无状态对话并覆盖指令instructions、工具调用与上下文保持的验证手法。读完本文你将掌握在 AxonHub 的 OpenAI 兼容网关/v1/responses端点上运行、迁移和扩展多轮对话集成测试的完整套路。一、背景为什么需要 Responses API 对话测试AxonHub 是一个开源的 AI 网关对外暴露 OpenAI 兼容的/v1/responses端点因此仓库使用官方 Go SDKgithub.com/openai/openai-go/v3见 integration_test/openai/go.mod直接对其进行集成测试。与传统的 Chat Completions 相比Responses API 引入了一个关键变化多轮对话的上下文不再依赖调用方手动维护messages数组而是可以通过previous_response_id字段把上一轮返回的response.id链式传下去由服务端自动拼接上下文。conversation目录下的测试正是为了验证这一机制同时验证在链式上下文之外仍可显式通过input数组手动携带历史消息无状态方式也能获得等价效果。二、测试文件与用例清单该目录包含两个测试文件conversation_test.go 与 conversation_stateless_test.go外加一个 README.md。conversation_test.go有状态基于 previous_response_id用例验证目标TestResponsesConversation基础多轮对话与上下文保持第一轮告知“去日本旅行、喜欢蓝色”第二轮问“我喜欢的颜色是什么”应回答 blue第三轮问“我要去哪旅行”应回答 JapanTestResponsesConversationWithInstructions携带Instructions的多轮对话验证助手始终按指令太空科学导师风格回答TestResponsesConversationContextChain长对话链依次引入姓名 Alice、城市 Paris再回溯提问“我叫什么/我住哪”验证链式上下文与信息召回TestMultiTurnConversation从原 Chat Completions 对话测试迁移而来日本旅行 东京天气 算术 365×248760TestConversationWithTools对话中集成 calculate / get_current_weather 两个函数工具处理函数调用并追问后续问题TestConversationContextPreservation带系统提示词的三轮对话统计空间/天文学主题关键词命中数验证上下文跨轮保持TestConversationSystemPrompt烹饪助手系统提示词第一轮推荐意面第二轮改问披萨仍保持烹饪语境conversation_stateless_test.go无状态基于 input 数组用例验证目标TestResponsesConversationStateless无状态三连问手动把“用户消息 助手回复”逐轮累加到input数组中TestResponsesConversationStatelessWithInstructions无状态 指令参数的黑洞形成问题TestResponsesConversationStatelessContextChain用增量历史数组构造的长链对话Alice/Paris 召回说明从源码看conversation_stateless_test.go中实际还包含TestMultiTurnConversationStateless、TestConversationWithToolsStateless、TestConversationContextPreservationStateless、TestConversationSystemPromptStateless四个补充用例与有状态版本一一对应README 仅收录了前三个核心用例。以 conversation_stateless_test.go 源码为准。三、两种对话模式的原理解读3.1 有状态对话previous_response_id 链核心机制是每个 Response 都拥有唯一 ID后续请求只要带上PreviousResponseID字段指向上一轮响应的 ID服务端即可自动恢复该轮为止的完整上下文调用方无需自行拼历史消息。源码中三连问的结构如下节选自 conversation_test.go// 第一轮只有输入 params1 : responses.ResponseNewParams{ Model: shared.ResponsesModel(helper.GetModel()), Input: responses.ResponseNewParamsInputUnion{ OfString: openai.String(firstInput), }, } resp1, err : helper.CreateResponseWithHeaders(ctx, params1) // 第二轮带上上一轮 response 的 ID params2 : responses.ResponseNewParams{ Model: shared.ResponsesModel(helper.GetModel()), PreviousResponseID: openai.String(resp1.ID), Input: responses.ResponseNewParamsInputUnion{ OfString: openai.String(secondInput), }, }TestResponsesConversationContextChain则展示了通用循环写法维护一个previousID变量每轮请求后更新为resp.ID见 conversation_test.go#L171-L2434 轮内同时完成“引入事实”和“召回事实”两种验证var previousID string for i, fact : range facts { params : responses.ResponseNewParams{ Model: shared.ResponsesModel(helper.GetModel()), Input: responses.ResponseNewParamsInputUnion{ OfString: openai.String(fact.input) }, } if previousID ! { params.PreviousResponseID openai.String(previousID) } resp, err : helper.CreateResponseWithHeaders(ctx, params) // ... 校验 fact.validate(output) ... previousID resp.ID // 链式更新 }3.2 无状态对话手动维护 input 历史数组无状态模式不依赖服务端记忆而是由客户端把“用户消息 助手消息”交替追加进input数组每次请求都携带完整历史。conversation_stateless_test.go提供了两个关键构造器createUserMessage(text)通过responses.ResponseInputItemParamOfInputMessage(...)构造user角色输入项createAssistantMessage(text)通过responses.ResponseInputItemParamOfOutputMessage(...)把上一轮助手输出转成历史输入项。第三轮请求的input数组形如conversation_stateless_test.go#L106-L117params3 : responses.ResponseNewParams{ Model: shared.ResponsesModel(helper.GetModel()), Input: responses.ResponseNewParamsInputUnion{ OfInputItemList: responses.ResponseInputParam{ createUserMessage(firstInput), // 第一轮用户消息 createAssistantMessage(output1), // 第一轮助手回复 createUserMessage(secondInput), // 第二轮用户消息 createAssistantMessage(output2), // 第二轮助手回复 createUserMessage(thirdInput), // 第三轮用户消息 }, }, }TestResponsesConversationStatelessContextChain把这一过程循环化每轮先用“当前历史 当前用户消息”发起请求拿到输出后再把用户消息与助手回复同时追加进history切片conversation_stateless_test.go#L236-L273。3.3 两种模式对比维度有状态PreviousResponseID无状态input 数组上下文维护方服务端自动管理客户端手动维护历史数组请求体大小恒定仅本轮输入 一个 ID随轮数线性增长控制力度简化流程、省 token完全掌控、可截断/改写历史实现复杂度低中需自行构造消息项四、关键参数详解结合源码所有用例统一使用responses.ResponseNewParams构造请求常用字段如下Modelshared.ResponsesModel(helper.GetModel())模型来自TEST_MODEL环境变量缺省deepseek-chat见 internal/testutil/config.go。Input联合类型responses.ResponseNewParamsInputUnion字符串简写走OfString如openai.String(Hello!)结构化历史走OfInputItemListresponses.ResponseInputParam(...)。Instructions相当于系统提示词openai.String(instructions)有状态与无状态用例中每一轮都会重复携带验证指令的持续引导作用见TestResponsesConversationWithInstructions。PreviousResponseID有状态模式的核心字段openai.String(resp.ID)链式传参。Tools[]responses.ToolUnionParam每个工具用responses.FunctionToolParam定义Name、Description、Strict严格模式openai.Bool(true)与 JSON SchemaParameters含required与additionalProperties: false详见TestConversationWithTools中 calculate / get_current_weather 两个工具的构造conversation_test.go#L345-L381。五、对话中的工具调用流程TestConversationWithToolsconversation_test.go#L333-L485演示了 Responses API 下“对话 工具”的完整闭环第一轮输入“东京天气 计算 365×24”带上两个工具。遍历resp1.Output筛出item.Type function_call的条目得到[]responses.ResponseFunctionToolCall。执行工具解析fc.ArgumentsJSON按fc.Name分发到本地模拟函数simulateCalculatorFunction/simulateWeatherFunction仓库用硬编码数据模拟真实工具避免测试依赖外部服务。回填结果用responses.ResponseInputItemParamOfFunctionCallOutput(fc.CallID, result)构造 function_call_output 输入项。第二轮PreviousResponseID: resp1.IDOfInputItemList携带工具结果让模型整合出最终回答。第三轮继续链式追问“该不该带伞”验证工具结果对后续对话的影响。无状态版本TestConversationWithToolsStateless的差异在于把 function_call 与 function_call_output 也按顺序追加进历史数组再整体作为input提交conversation_stateless_test.go#L455-L531。// 有状态版本工具结果回填 toolResults append(toolResults, responses.ResponseInputItemParamOfFunctionCallOutput(fc.CallID, result)) params2 : responses.ResponseNewParams{ Model: shared.ResponsesModel(helper.GetModel()), PreviousResponseID: openai.String(resp1.ID), Input: responses.ResponseNewParamsInputUnion{ OfInputItemList: responses.ResponseInputParam(toolResults), }, Tools: []responses.ToolUnionParam{calculatorTool, weatherTool}, }六、环境配置与运行方式测试通过 internal/testutil 的Config读取环境变量NewTestHelper在配置缺失如未设 API Key时会直接t.Skipf跳过而非失败internal/testutil/helper.go#L21-L33。必需/常用变量环境变量作用默认值TEST_AXONHUB_API_KEYAxonHub API Key必需无缺省跳过测试TEST_OPENAI_BASE_URLOpenAI 兼容端点地址http://localhost:8090/v1TEST_MODEL测试模型deepseek-chatTEST_TRACE_ID追踪 ID写入AH-Trace-Id头随机生成TEST_THREAD_ID会话线程 ID写入AH-Thread-Id头随机生成TEST_DISABLE_TRACE/TEST_DISABLE_THREAD置为true关闭对应头false所有请求通过helper.CreateResponseWithHeaders(ctx, params)发送底层是Client.Responses.New(ctx, params, headerOpts...)会把AH-Trace-Id、AH-Thread-Id两个 AxonHub 专有请求头注入调用internal/testutil/helper.go#L83-L86这正是网关侧做全链路追踪与会话归组的关键。运行命令# 在目录内运行全部用例 go test -v # 分别运行单个测试文件 go test -v conversation_test.go go test -v conversation_stateless_test.go # 运行指定用例有状态 go test -v -run TestResponsesConversation go test -v -run TestResponsesConversationWithInstructions go test -v -run TestMultiTurnConversation go test -v -run TestConversationWithTools go test -v -run TestConversationContextPreservation go test -v -run TestConversationSystemPrompt # 运行无状态用例 go test -v -run TestResponsesConversationStateless也可在仓库根目录直接执行go test -v ./integration_test/openai/responses/conversation。需要 Go 1.25见 integration_test/openai/go.mod依赖安装执行go mod tidy。七、从 Chat Completions 迁移到 Responses API原对话测试位于 integration_test/openai/chat/conversation/conversation_test.go使用的是消息数组 openai.ChatCompletionNewParams。迁移到 Responses API 后主要变化README 的 Migration Notes 与两份源码对比可相互印证API 调用入口Chat.Completions.New→Responses.New测试中统一经 helper 封装。参数结构openai.ChatCompletionNewParams{Messages, Model}→responses.ResponseNewParams{Model, Input, Instructions, PreviousResponseID, Tools}。上下文管理手动维护messages数组每轮append用户消息与completion.Choices[0].Message.ToParam()→ 有状态时改用PreviousResponseID链。输入格式字符串OfString与结构化输入数组OfInputItemList双支持而 Chat Completions 只有消息数组一种形态。工具支持函数定义从shared.FunctionDefinitionParam演进为responses.FunctionToolParam多出Strict严格模式开关与additionalProperties校验README 同时提示“Responses API 的工具支持级别可能与 Chat Completions 存在差异个别用例可能被临时跳过”。八、预期行为与断言清单仓库对“什么算通过”给出了明确的断言标准可复用到你自己的测试中上下文保持后轮必须能引用前轮引入的信息——如第二轮必须出现blue、第三轮必须出现japan断言用testutil.ContainsCaseInsensitive(output, blue)做大小写不敏感匹配internal/testutil/helper.go#L168-L178。响应链previous_response_id必须维持上下文resp.ID不能为空否则t.Fatal。指令持续生效带Instructions的每轮回答都应符合指令风格如黑洞话题命中black hole / star / gravity / collapse任一关键词即可通过。信息召回长链测试用“先给事实、后提问”的方式验证alice、paris的召回。工具可用性对话过程中工具可被持续调用工具结果能进入后续对话如“带伞”追问。系统提示词影响烹饪助手场景要求响应命中至少 2 个烹饪词pasta / recipe / cook / ingredient / boil转向披萨后仍须出现pizza或dough。九、注意事项与扩展方向源码中TestResponsesConversation、TestResponsesConversationWithInstructions、TestResponsesConversationContextChain三个用例在文件头部带有t.Skip(Test uses PreviousResponseID - temporarily skipped)说明当前实现对该特性的支持仍在完善中运行时会跳过其余有状态用例未跳过可正常执行。若需扩展新的对话场景可参照现有模式新增用例 → 用testutil.NewTestHelper建 helper →CreateTestContext注入头信息 → 构造ResponseNewParams→ 用AssertNoError与ContainsCaseInsensitive断言 → 最后补充 README 中的用例清单与运行命令。对话测试的上下文长度受模型上下文窗口限制超长对话建议采用无状态模式并自行控制历史截断相关完整用例与参数说明还可见 integration_test/openai/responses/README.md 与 integration_test/openai/README.md。赞分享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.项目地址https://gitcode.com/gh_mirrors/ax/axonhub点击查看免费下载相关推荐AxonHub 会话集成测试实战基于 Anthropic Go SDK 的多轮对话、工具调用与上下文保持AxonHub 会话集成测试实战基于 Anthropic Go SDK 的多轮对话、工具调用与上下文保持 本文围绕 AxonHub 仓库中 integratiAI 应用API网关LLM 网关后端前端富文本搭建与可视化搭建的结合从光标交互到统一 DSL 协议富文本搭建与可视化搭建的结合从光标交互到统一 DSL 协议 富文本不只是能写字的组件它可能是可视化搭建中承上启下的关键交互形态既能作为搭建画布中的一个后端API网关模型推理服务AI AgentAxonHub OpenAI Responses API 内置 web_search 工具集成测试实战从工具调用到引文校验AxonHub OpenAI Responses API 内置 web_search 工具集成测试实战从工具调用到引文校验 导读 本文以 AxonHub 仓库AI 应用API网关LLM 网关后端前端上一篇Instatic与AI助手集成聊天机器人内容管理的终极指南下一篇PiKVM容器健康检查自定义脚本创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/13 2:04:47

DeepSeek Harness插件实战:解决LLM上下文流失与知识沉淀

一次完整的 DeepSeek 应用流程里,模型给出答案只是第一步。真正决定效率的是:这段对话结束后,结论、代码片段和上下文有没有被沉淀下来,能不能在下一次会话里继续复用。这个问题听起来不高级,但几乎所有重度使用 LLM 的…

2026/10/13 3:14:52

三个技术栈踩坑实录:避坑指南

摘要:干了十来年后端,Python、Java、PHP 都摸过一遍,踩过的坑能装一箩筐。这篇文章不聊高大上的架构理论,就聊聊我在不同业务场景里真实踩过的坑,以及对应的避坑思路,希望能给正在选型或者已经入坑的同学一…

2026/10/13 3:14:52

AI产品经理实战指南:从需求翻译到模型验收

简介:这是一份AI产品经理入门手册(上篇)PDF文档,专门面向正在考虑从互联网产品经理转型AI领域的人群,内容基于作者系统性学习归纳而成。手册以AI通识、AI应用领域、AI技术为主线,梳理了行业AI、AI行业、基础…

2026/10/13 3:14:52

UH-60直升机非线性动力学建模与Simulink仿真实战

飞控圈里常流传一句话:固定翼建模是入门,直升机建模是劝退。这句话不是没有道理——旋翼的挥舞运动、诱导速度的分布、尾桨的反扭矩耦合,每一个环节都带着强烈的非线性和交叉耦合,想用一套简单的线性模型糊弄过去,最后…

2026/10/13 3:14:52

金蝶云星空PLM与Altium Designer集成:BOM数据高效通关

简介:金蝶云星空V7.3产品培训讲义聚焦PLM与Altium Designer的深度集成应用,适合负责电子产品研发、物料数据管理或设计制造协同的企业技术人员与实施顾问。内容涵盖集成插件安装与配置、图纸检出与检入、原理图/PCB导入、BOM自动生成与实时更新、元器件库…

2026/10/11 0:02:13

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/12 12:01:26

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/12 12:54:07

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/13 0:04:41

基于Triton部署YOLO目标检测:从训练脚本到线上服务

简介:这份资源面向希望将目标检测模型落地到生产环境的深度学习开发者与算法工程师,聚焦于用 Triton Inference Server 部署 YOLOv9 的完整实战方案,解决从训练权重到线上推理服务之间的工程化难题。压缩包共 16 个文件,约 886KB&…

2026/10/13 0:04:41

手把手教你云端部署Qwen-Image-2.1:从GPU选型到在线文生图服务

Qwen-Image-2.1 这个开源的图像生成模型,最近在内容创作和 AI 应用圈子里热度相当高。它属于通义 Qwen 系列里的视觉生成分支,让我眼前一亮的是它对中文长文本的理解能力——以前用那些老方案生成带中文文字的图,十个里九个是“乱码印刷体”&…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑