尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

openai-agents-python 对话状态所有权指南:五种多轮对话策略的选型、服务端续接与源码原理

openai-agents-python 对话状态所有权指南:五种多轮对话策略的选型、服务端续接与源码原理 openai-agents-python 对话状态所有权指南五种多轮对话策略的选型、服务端续接与源码原理【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python多轮对话的工程难点不在多问几轮而在于回答一个前置问题下一次模型请求里到底应该包含什么是完整历史、可重放的历史片段、还是仅仅一个增量openai-agents-python 将这一问题的答案定义为对话状态所有权Conversation State Ownership并以此为准绳约束会话、压缩、重试、恢复与 handoff 的全部行为。本文以仓库内.agents/references/conversation-state-ownership.md为骨架结合src/agents/run_internal/oai_conversation.py、src/agents/run_config.py、src/agents/run_state.py等源码实现系统讲解五种对话策略的适用边界、服务端托管续接的底层去重机制、过滤器/重试/恢复的语义约束以及压缩与 handoff 场景下的兼容性规则。读完你将能够为任意多轮场景正确命名状态所有者并写出不会重复上下文、可安全重试与恢复的对话代码。一、状态所有权先回答谁持有对话状态任何涉及多轮输入、会话sessions、conversation_id、previous_response_id、auto_previous_response_id、压缩compaction、重试、call_model_input_filter或RunState恢复的改动都应以状态所有者是谁为起点。状态所有者决定了下一次模型请求的内容形态原文档给出的五种策略对比如下策略状态所有者下一轮输入使用result.to_input_list()显式重放应用程序可重放的历史 新一轮内容SDK 会话应用存储 SDK同一会话 新一轮内容conversation_idOpenAI Conversations API同一会话 ID 仅新一轮内容previous_response_id或auto_previous_response_idOpenAI Responses API上一个响应 ID 仅新一轮内容RunState恢复序列化的 Agents SDK 运行恢复同一个被打断的运行这不是一种新的对话策略其中RunResult.to_input_list()位于 result.py支持通过mode参数控制重放粒度SDK 会话策略的客户端侧存储契约详见 .agents/references/session-persistence.md。核心约束正常使用中必须选择一种策略。如果将客户端管理的重放/会话与服务端管理的续接混用除非实现层面显式地对两个所有者做协调与去重否则会造成上下文重复。从源码结构看这也是为什么RunConfig中的相关字段conversation_id、previous_response_id、auto_previous_response_id与session会被刻意设计成互斥校验的关系见下文第四节。二、服务端托管续接Server-Managed Continuation服务端托管续接指把对话历史交给 OpenAI 服务端持有客户端只发送增量。该能力的核心载体是OpenAIServerConversationTracker位于 src/agents/run_internal/oai_conversation.py它负责conversation_id、previous_response_id、auto_previous_response_id三者的增量delta计算。2.1 三类互补的已确认视图从该类的 docstring 可以看到追踪器维护三套互补视图共同决定哪些增量仍然可以安全发送对象同一性Object identity当前 Python 进程内已准备/已投递条目的对象引用。代码中特意保留对象引用而非id(obj)整数避免后续内存分配复用过期地址见sent_items、server_items字段的注释。稳定的服务端标识provider 返回的稳定服务端条目 ID 与工具调用 IDserver_item_ids、server_tool_call_ids。内容指纹Content fingerprints用于重试/恢复路径——这些路径上对象会被重建对象同一性失效只能靠内容指纹去重。对应字段包括sent_item_fingerprints、accepted_input_item_ids、server_output_fingerprints等指纹由 run_internal/items.py 中的fingerprint_input_item()计算。对应到原文档的规则只发送服务端尚未确认的条目对象同一性仅在单进程内有效恢复与重试路径还依赖稳定的条目 ID、工具调用 ID 与内容指纹。2.2 响应链的更新规则track_server_items()在处理模型响应时只有当conversation_id为空且当前处于previous_response_id或auto_previous_response_id续接模式、且响应确实携带response_id时才会更新previous_response_id。这与原文档的告诫一致从最近一个真正拥有 ID 的响应更新previous_response_id不要因为相邻的某个 provider 响应缺少 ID 而抹掉一条有效的响应链。注意_normalize_server_item_id()会忽略FAKE_RESPONSES_ID占位符——非 Responses 系列 provider 产出的占位 ID 不会被用于去重。2.3 互斥与组合限制会话持久化不能与服务端托管续接组合。validate_session_conversation_settings()位于 src/agents/run_internal/agent_runner_helpers.py在传入 session 的同时检测到conversation_id、previous_response_id或auto_previous_response_id任一非空/启用时直接抛出UserErrorSession persistence cannot be combined with conversation_id, previous_response_id, or auto_previous_response_id. 该函数在 run.py 的新运行与RunState恢复两条路径上都会被调用。不要引入第二个历史写入者除非你明确定义了协调与去重语义。conversation_id与previous_response_id/auto_previous_response_id链式续接是互斥的状态所有者不可同时启用。三、增量、重试与过滤器的语义约束3.1call_model_input_filter作用于增量call_model_input_filter见 run_config.py在模型调用前对已准备好的模型负载执行。原文档特别提醒在服务端托管续接下该负载可能已经是新一轮增量而非完整历史——过滤器作者必须意识到自己看到的不是完整会话不能假设可以基于全量历史做裁剪或注入。3.2 发送确认、回滚与重试追踪器围绕已发送标记提供了一套精确的状态机对应原文档的硬性要求prepare_input()组装下一轮模型输入跳过重复条目与审批条目tool_approval_item并登记已准备条目 → 原始来源对象的映射。mark_input_as_sent()在请求发出前立刻将返回的列表标记为已发送防止嵌套准备过程再加入未发送条目。rewind_input()在重试失败的请求前回滚该追踪状态从sent_items中解除对象引用、丢弃对应指纹并放回remaining_initial_input队列使这些条目可以被重新发送。mark_input_as_accepted()请求成功后将出现在服务端请求中的 pending 输入 ID 记入accepted_input_item_ids在成功后保留该状态避免后续轮次重放。此外validate_pending_input_filter()会拒绝那些无法安全追溯到 pending RunState 输入的过滤器重写结果必要时抛出UserError提示保留输入条目对象、返回未修改副本或省略 pending 条目。3.3 流式与非流式必须对齐流式与非流式两条路径对追踪器的更新必须保持一致两者都要维护相同的增量、重试与响应 ID 语义。对应仓库中的Runner.run()与Runner.run_streamed()均走同一套OpenAIServerConversationTracker逻辑且RunState中会同步保存追踪器的conversation_id、previous_response_id、auto_previous_response_id见 run_state.py。3.4 有状态重试需要可重放性证据原文档强调不要盲目重发一个可能已经推进了服务端状态的请求。这正是追踪器三重视图存在的意义——重试前通过对象同一性、服务端 ID、内容指纹三重校验确认哪些条目真的未被服务端接收。hydrate_from_state()则负责在恢复时重建这些知识遍历原始输入、保存的模型响应、生成的 run items 与可选的会话历史把已确认内容灌入追踪器注释中明确说明它挑选真正携带 id 的最近响应避免非 Responses provider 的无 ID 响应破坏链。四、RunState恢复 ≠ 对话续接这是最容易被混淆的一对概念原文档用一句话划清界限对话续接conversation continuation把上下文带入新一轮对话对应conversation_id/previous_response_id策略RunState恢复继续一个被打断的、尚未结束的运行例如中断、审批暂停、序列化后恢复对应序列化的 Agents SDK 运行。两者不可互相替代。RunState会持久化对话标识符并通过hydrate_from_state()重建追踪器知识但恢复过程必须满足三条硬约束不得重放已确认的输入、不得丢失未发送的工具输出、没有模型调用时不得递增轮次计数。在 run.py 的恢复路径中apply_resumed_conversation_settings()会先从RunState取出续接设置再执行校验随后以run_state._original_input作为起始输入由hydrate_from_state将旧输入标记为已发送从而保证恢复后只发送真正的新增量。五、压缩Compaction与状态所有者的关系压缩用于在会话过长时精简历史。原文档给出两条规则compaction_modeprevious_response_id依赖一条可用的已存储响应链compaction_modeinput从客户端持有的条目重建输入是服务端链不可用时的回退方案——例如storeFalse导致后续无法按响应 ID 回查时。源码印证位于 src/agents/memory/openai_responses_compaction_session.py压缩模式类型为Literal[previous_response_id, input, auto]。其模式解析函数_resolve_compaction_mode()同文件 L676-L688的逻辑是显式指定非auto时直接采用指定值auto模式下若store is False或没有response_id则回退为input否则使用previous_response_id——与参考文档的描述完全一致。另一条规则是压缩必须保持选定的状态所有者不要既从本地历史做压缩又把这些历史通过服务端托管续接重放一遍那等于同时创建两个事实来源。六、Handoff 下的状态规则服务端托管续接对 handoff 有特殊约束根源在于服务端托管对话只发送增量handoff 输入过滤器不受支持。Handoff.input_filter与RunConfig.handoff_input_filter见 run_config.py在服务端托管会话激活时应抛出异常而不是重写一份已经被服务端拥有的历史。RunConfig.handoff_input_filter的 docstring 明确写着Server-managed conversationsconversation_id、previous_response_id、auto_previous_response_iddo not support handoff input filters.nest_handoff_history应被禁用并发出警告。该字段是客户端历史变换将历史压缩进有序的 assistant 摘要段见 run_config.py当服务端托管续接激活时仓库会自动禁用该行为并告警仅以增量输入继续。生成条目与会话条目必须保持区分。handoff 处理过程中下一轮的模型输入可能是被过滤过的但客户端会话托管激活时会话历史需要完整的、未过滤的条目序列——prepare_input()中已准备条目 → 原始来源对象的映射prepared_item_sources、prepared_item_sources_by_fingerprint正是为这种区分服务的。七、变更审查清单无论你修改请求构造、新增过滤器还是调整恢复逻辑原文档建议按以下清单逐项自检在改动请求构造之前先命名状态所有者明确每一条受影响路径上模型收到的是完整历史还是增量分别验证首轮、后续轮、重试、中断、序列化恢复与流式行为分开测试工具调用与工具输出——调用 ID 与输出指纹承担不同的去重职责确认过滤、压缩与会话持久化没有引入第二个事实来源。八、源码导航与延伸阅读本文全部结论均可在以下仓库路径中复核状态追踪核心src/agents/run_internal/oai_conversation.pyOpenAIServerConversationTracker及增量计算运行主循环与校验接入src/agents/run_internal/run_loop.py、src/agents/run.py、src/agents/run_internal/agent_runner_helpers.pyvalidate_session_conversation_settings会话持久化契约src/agents/run_internal/session_persistence.py、docs/sessions/index.md、.agents/references/session-persistence.md运行状态与恢复src/agents/run_state.py运行配置字段src/agents/run_config.pyhandoff_input_filter、nest_handoff_history、call_model_input_filter及RunConfigWrapper的续接字段压缩模式解析src/agents/memory/openai_responses_compaction_session.py指纹与条目工具src/agents/run_internal/items.py使用示例docs/running_agents.md其中包含借助responses_websocket_session()与previous_response_id串联多轮请求的完整代码模式另外原文档的 Sources 还引用了 OpenAI 官方的对话状态指南与 running-agents 指南作为外部权威参考在修改服务端托管续接行为之前建议以最新官方 API 参考为准再次核对仓库内.agents/skills/openai-knowledge/提供了对应的知识检索技能。总体而言把状态所有者作为第一性原理本文介绍的五类策略、三类去重视图与一套审查清单即可覆盖绝大多数多轮对话的工程场景。【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表