跳到主要内容

工具调用与评测实践

在 Agent 最小可运行项目 之上,补上:多工具 schema、失败重试、轨迹日志、离线评测骨架(手写 loop 与 [LangGraph 编排实践](/docs/ai/Agent/LangGraph 编排实践) 都适用)。题型对照见 Agent 系统高频题。

目标与验收​

验收项标准
多工具至少 2 个工具,按 name 分发
重试模拟一次工具失败后成功或降级
轨迹每步写入 JSONL(step/tool/args/ok/error)
评测脚本读取用例,输出通过率

工具注册与 schema​

TOOLS = {
"add": {
"desc": "两数相加",
"schema": {"a": float, "b": float},
"fn": lambda a, b: a + b,
},
"get_order": {
"desc": "按订单号查询状态(mock)",
"schema": {"order_id": str},
"fn": lambda order_id: {"id": order_id, "status": "shipped"},
},
}

def validate_args(name: str, args: dict):
schema = TOOLS[name]["schema"]
missing = [k for k in schema if k not in args]
if missing:
raise ValueError(f"missing args: {missing}")

失败重试(分类)​

import time

def call_with_retry(name, args, retries=2):
last_err = None
for i in range(retries + 1):
try:
validate_args(name, args)
# 演示:第一次强制失败
if i == 0 and name == "get_order":
raise TimeoutError("mock timeout")
return TOOLS[name]["fn"](**args), None
except TimeoutError as e:
last_err = e
time.sleep(0.05)
except ValueError as e:
return None, e # 参数错:不重试
return None, last_err

轨迹日志​

import json
from pathlib import Path

def log_span(path: str, record: dict):
Path(path).parent.mkdir(parents=True, exist_ok=True)
with open(path, "a", encoding="utf-8") as f:
f.write(json.dumps(record, ensure_ascii=False) + "\n")

# 每步:
# log_span("traces/run1.jsonl", {
# "step": 1, "tool": "get_order", "args": {...}, "ok": False, "error": "mock timeout"
# })

面试可说:轨迹用于排障、评测、审计,比只存最终答案有用。

离线评测骨架​

cases.jsonl:

{"id": "t1", "input": "查订单 A100 状态", "expect_tool": "get_order"}
{"id": "t2", "input": "1+2", "expect_tool": "add"}
def eval_cases(path: str, agent_run):
total = passed = 0
for line in open(path, encoding="utf-8"):
case = json.loads(line)
total += 1
result = agent_run(case["input"]) # 返回 {"tools_used": [...], "output": "..."}
if case["expect_tool"] in result["tools_used"]:
passed += 1
print(f"pass={passed}/{total}")

先评「有没有调对工具」,再评最终答案字符串;与业务对齐后再加人工抽检。

实践要点​

  1. schema 校验失败不要盲目重试;超时类才重试。
  2. 轨迹 JSONL 是评测与面试复盘的共同素材。
  3. 评测从「工具是否选对」开始,比一上来比开放文本更稳。
  4. 面试挂钩:成功率 + 轨迹质量 + 成本,三件套一起说。
  5. 跨会话是否「还认识用户」见 [Agent 记忆分层实践](/docs/ai/Agent/Agent 记忆分层实践),不要靠把轨迹整段当长期记忆。
  6. 生产 trace 字段与线上抽样见 可观测与线上评测;本篇只管离线 JSONL 骨架。