[错误] 在 function_to_json 中无法访问的 KeyError 块和易损类型回退
作者: QiuYucheng2003创建于 2026年6月14日更新于 2026年6月14日
- 描述 利用静态代码审查 util.py,发现了函数_to_json 实用函数中的一个逻辑缺陷。 在参数解析循环中,代码尝试使用字典默认方法查找类型标注,并包含在 try...except KeyError 块中: try: param_type = type_map.get(param.annotation, "string") except KeyError as e: raise KeyError(...) 缺陷: 1. 无法访问的代码: Python 字典上的 .get() 方法在缺少键时不会引发 KeyError,而是安全地返回默认值 ("string")。因此,except KeyError 块是完全无用的代码,永远不会执行。 2. 静默的类型降级:如果函数使用复杂的类型提示(例如 typing.List、typing.Dict 或自定义对象/类),type_map.get() 将无法匹配它们,并默认将它们的模式类型设置为 "string"。这会导致生成不正确的工具定义,而不是捕获不受支持的类型或正确处理它。 2. 重现步骤 注意:此问题通过静态程序分析和代码架构审查确定。 1. 定义具有不受支持或复杂类型提示的工具函数(例如 def my_tool(data: list))。 2. 将此函数传递给 function_to_json(my_tool)。 3. 注意,没有抛出 KeyError(尽管 except 块中有意),而参数被默默地生成为 {"type": "string"),而不是实际的结构化 JSON 数组/对象,或抛出明确的异常。 3. 预期行为 如果代码基础意图是为未映射或无效类型抛出错误,则应使用直接字典访问(type_map[param.annotation])来触发 KeyError 块。或者,如果需要默默回退,则应删除死的 try...except 块,并正确解析复杂的类型别名,以防止生成错误的 JSON 方案,用于向上级 LLM 工作程序调用。 4. 实际行为 except KeyError 语句是死代码,而复杂类型默默地回退为 "string",降低了工具定义导出到模型的正确性。 5. 影响 代码可维护性:包含死/误导性的异常处理路径。 功能缺陷:传递具有结构化类型的参数会生成不正确的 JSON 方案(将 typing 复杂嵌套数组/对象转换为简单的平面字符串),导致工具调用执行在运行时默默失败或产生幻觉。 6. 建议的修复 如果目标是强制执行严格的类型,则应修改查找方式,以使用直接索引,从而允许 KeyError 传播到 except 块。或者,如果需要默默回退,则应删除死的 try...except 块,并实现适当的类型解析器,用于标准类型提示: # 如果意图是为未知类型抛出错误: for param in signature.parameters.values(): try: # 使用直接查找,允许 KeyError 传播到 except 块 param_type = type_map[param.annotation] except KeyError as e: # 回退优雅地或抛出有意义的异常 param_type = "string" ...
内容来源: openai/swarm