给 LLM 的 function calling 工具输出应该从裸 JSON 转成精简排版文本,这是 Anthropic / OpenAI 官方 tool use 最佳实践,也一直是我们的默认做法(忘记记录,补上)。

为什么不做裸 JSON

函数返回的原始 dict 直接 json.dumps 喂给模型有两大问题:

  • 字段名是噪音:category_name、matched_keywords、coordinates、additionalProperties 等结构性 key 白烧 token
  • 有效信息被埋没:真正有用的 description 字符串被多层 JSON 嵌套包着,模型要费力"剥壳"

导航/检索工具里,模型真正需要的只有:名称、楼号、别名、description、id。坐标、匹配词、内部字段模型用不到(坐标走导航卡由后端补全)。

关键架构:输出两层分离

工具结果不能只改给模型的文本,因为前端渲染(SSE)依赖原始 dict。正确做法:

dispatch_tool → 返回完整 dict(前端/SSE 用,含 data/coordinates)
        └─ _model_content 层 → 数据型工具转排版文本(模型用)
  • 数据型工具(search / list / view / nearby):结果文本化后喂模型
  • 渲染型工具(show_nav):只回 {ok, poi_ids} 确认,完整 data 走 SSE 只给前端
  • handle_* 返回结构不动 → 前端零影响,改动只落在 _model_content 一个函数

文本格式模板

search_poi 命中 1 个候选(关键词:法学院)
──────────────────────────────
■ 7号楼(法学院)|楼号 7#|教学楼
  别名:法学院 / 7号楼
  说明:7号楼(法学院):法学院办公楼;学工办在二楼7215室,教学办/院务办在317室。
  id: 7_LAW

要点:

  • ■ 分隔候选,| 分隔 name/楼号/分类
  • id 必须保留(模型后续调 show_poi_navigation_options 传 poi_id 用)
  • 周边检索(search_nearby)转 编号. 店名 / 地址|距离 / 电话 / id
  • 分类列表转 编号. 分类(N 处)
  • error 分支转 工具名 出错:原因

效果与验证

  • token 显著减少(剔除坐标/匹配词/嵌套),description 直接可读
  • 模型读完文本后能正确提取 id 继续调导航
  • 回归验证法:分别测"模型视角 _model_content"与"前端视角 dispatch_tool",确认 dict 与文本互不污染

相关


本文归档于个人知识库 · 领域:CS & AI · 模块:04 Project_CS_AI/AI apps