news 2026/8/19 14:45:17

【Bug已解决】create_agent: model_to_tools router can return “model“ but path_map omits it -> KeyError(‘m…

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Bug已解决】create_agent: model_to_tools router can return “model“ but path_map omits it -> KeyError(‘m…

【Bug已解决】create_agent: model_to_tools router can return "model" but path_map omits it -> KeyError('model')

一、现象长什么样

create_agent支持用一个model_to_tools路由器:根据当前模型/上下文,决定走哪条"模型+工具"的处理路径。路由器根据输入返回某个路由键(route key),再用path_map(路由键→处理路径的映射)找到对应逻辑。

问题在于:路由器在某些情况下会返回键"model",但path_map根本没有"model"这个键。于是派发时path = path_map[route]route == "model"命中不了 →KeyError: 'model'create_agent直接崩。

表现:大多数情况正常(路由到path_map里有的键),但一旦输入触发了"返回 model"这个分支,就 100% 崩溃,且报错是裸KeyError,不提示"path_map 缺了 model 这条路由"。

二、背景

create_agent的设计里,model_to_tools是一个可调用对象/路由函数,签名类似:

def model_to_tools(state) -> str: # 返回路由键 ...

调用方再拿返回的键去path_map查处理路径:

route = model_to_tools(state) path = path_map[route] # 若 route 不在 path_map -> KeyError

路由器的"输出空间"(可能返回的键集合)和path_map的"键集合"本应完全一致。但路由器是用户/框架提供的,可能返回"model"(比如当判定"只需模型、无需工具"时),而path_map只定义了"tools"/"no_tools"等,漏了"model"。两端无单一事实来源,约定靠默契,于是 KeyError。

三、根因

根因两点:

  1. 路由输出空间与 path_map 不同步:路由器能返回"model"path_map没对应项。
  2. 派发用裸下标path_map[route]直接取下标,键缺失即KeyError,无兜底、无清晰错误。

本质:把"路由键集合"和"路径映射键集合"当成两处独立维护的字典,缺单一事实来源,一端加了路由另一端忘了加映射。

四、最小可运行复现

下面缩略逻辑复现 KeyError:

def model_to_tools(state): if state.get("need_model_only"): return "model" # 路由器返回了 model return "tools" path_map = {"tools": tool_path, "no_tools": no_tool_path} # 没有 "model" route = model_to_tools({"need_model_only": True}) path = path_map[route] # KeyError: 'model'

修复:path_map 补齐 "model",且派发用.get+ 清晰错误。

path_map = {"tools": ..., "no_tools": ..., "model": model_only_path} route = model_to_tools(state) path = path_map.get(route) if path is None: raise KeyError(f"route '{route}' not in path_map; keys={list(path_map)}")

五、解决方案(第一层:最小直接修复)

最小修法:在create_agent装配时,校验路由器可能返回的键都存在于path_map;派发用.get并给清晰错误。

def create_agent(model_to_tools, path_map, sample_states): # 校验:路由器对样例输入返回的键都必须在 path_map for st in sample_states: route = model_to_tools(st) if route not in path_map: raise ValueError(f"router returned '{route}' but path_map lacks it") def dispatch(state): route = model_to_tools(state) path = path_map.get(route) if path is None: raise KeyError(f"route '{route}' not in path_map; have {list(path_map)}") return path(state) return dispatch

这一层让缺映射在装配期就暴露,而非运行期裸 KeyError。

六、解决方案(第二层:结构化改进)

把"路由键 ↔ path_map 一致性"固化成策略对象,作为单一事实来源,明确路由输出空间必须 ⊆ path_map 键。

from dataclasses import dataclass, field from typing import Callable, Dict, List @dataclass(frozen=True) class LangChainCreateAgentRouterPolicy: """create_agent 路由/path_map 一致性策略的单一事实来源。""" path_map: Dict[str, Callable] = field(default_factory=dict) expected_routes: List[str] = field(default_factory=list) fail_closed: bool = True def validate_router(self, router: Callable, probes) -> None: for st in probes: route = router(st) if route not in self.path_map: if self.fail_closed: raise AssertionError( f"router returned '{route}' not in path_map keys {list(self.path_map)}") def dispatch(self, router, state): route = router(state) path = self.path_map.get(route) if path is None: raise KeyError(f"route '{route}' missing; keys={list(self.path_map)}") return path(state) def validate(self) -> None: if self.fail_closed and not self.path_map: raise AssertionError("path_map empty but fail_closed")

create_agentpolicy.validate_router+policy.dispatch,一致性集中。

七、解决方案(第三层):断言 / CI 守护

用 pytest 锁死一致性:

import pytest from policy import LangChainCreateAgentRouterPolicy as P def test_router_key_in_path_map(): p = P(path_map={"tools": lambda s: s, "model": lambda s: s}) p.validate_router(lambda s: "model", [{"x": 1}]) # 不抛 def test_missing_key_rejected(): p = P(path_map={"tools": lambda s: s}) # 无 model with pytest.raises(AssertionError): p.validate_router(lambda s: "model", [{"x": 1}]) def test_dispatch_clear_error(): p = P(path_map={"tools": lambda s: s}) with pytest.raises(KeyError) as e: p.dispatch(lambda s: "model", {}) assert "model" in str(e) def test_policy_valid(): P(path_map={"tools": lambda s: s}).validate()

CI 加一条:用覆盖各路由分支的样例 state 跑validate_router,断言所有路由键都在 path_map。

八、排查清单

  • create_agent 崩KeyError: 'model'?→ 路由器返回 model 但 path_map 缺它。
  • 路由输出空间和 path_map 是否同步?→ 必须 ⊆,用 policy 校验。
  • 派发是否裸path_map[route]?→ 改用.get+ 清晰错误。
  • 缺映射能否装配期发现?→ validate_router 在装配时校验。
  • 是否只在某些输入才崩?→ 路由到 model 分支才触发,需样例覆盖。
  • 是否有"路由键⊆path_map"测试?→ 必须有。

九、小结

create_agentmodel_to_tools路由器能返回键"model",但path_map漏了它,派发path_map[route]直接KeyError('model')。根因是路由输出空间与 path_map 键集合无单一事实来源、不同步。第一层装配期校验路由键都在 path_map、派发用.get给清晰错误;第二层用LangChainCreateAgentRouterPolicy把一致性固化成单一事实来源;第三层用 pytest 守护。路由派发的通用原则:路由器的输出空间必须是 path_map 键集合的子集,且派发绝不用裸下标,缺键要给可读错误

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/19 14:41:33

开源维护中的协作边界

开源维护中的协作边界 先界定讨论范围 这篇记录围绕“开源维护中的协作边界”整理检查思路。文中的实现片段只用于说明控制流和错误处理,不能替代实际环境中的配置、测试或上线结论。 需要先核对的条件 围绕“开源维护中的协作边界”,先确认输入来源、依…

作者头像 李华
网站建设 2026/8/19 14:41:09

大语言模型与ROS 2融合:六足机器人智能决策与运动控制实践

1. 项目概述:当大语言模型遇见机器人操作系统最近在机器人圈子里,一个话题的热度持续攀升:如何让大语言模型(LLM)与机器人操作系统(ROS)进行深度对话。这不仅仅是技术上的“缝合”,而…

作者头像 李华
网站建设 2026/8/19 14:38:44

免费三国杀卡牌制作器实战指南:5分钟做出一张能打印的武将卡

免费三国杀卡牌制作器实战指南:5分钟做出一张能打印的武将卡 【免费下载链接】Lyciumaker 在线三国杀卡牌制作器 项目地址: https://gitcode.com/gh_mirrors/ly/Lyciumaker 深夜的玩家群里,一句"界张辽要是真出了该多好"引来好几个小伙…

作者头像 李华