Skip to content

调试、观测与评估 ​

🎯 难度:进阶⏱ 预计:2 小时# Tracing# 测试# Eval

Agent 的难点不是「让它输出一段话」,而是知道它为什么失败,以及改动后是否真的更可靠。

先看轨迹,不先改 Prompt ​

遇到错误按层排查:

层检查问题常见原因
配置 / API请求有没有到达平台?Key、base_url、模型名、限流
决策模型选对工具了吗?描述模糊、能力不支持、上下文缺失
参数JSON 和 Schema 合法吗?缺字段、范围错误、输出截断
执行工具真的完成了吗?文件权限、网络失败、服务异常
观察工具结果完整回传了吗?tool_call_id 错误、输出过长
汇总最终结论受工具结果支持吗?忽略证据、引用错位、虚构完成

「再调用一次」不是根因分析。保留可复现的任务与脱敏轨迹。

最少应该记录什么? ​

每个任务有 trace_id;每个阶段记录:时间、阶段/工具名、耗时、状态、模型版本、输入输出 Token、预算消耗。不要默认记录全量敏感内容。

python
import logging
import time

logging.basicConfig(level=logging.INFO)
started = time.perf_counter()
# 在真正的操作前后记录;这里是日志格式示例
logging.info("phase=%s status=%s elapsed_ms=%d", "retrieve", "ok", (time.perf_counter() - started) * 1000)

runner 的 on_event 可以作为入口,进一步补充工具结果类型、模型用量和任务 ID。托管 tracing 服务方便,但上传前确认数据权限、保留时间和脱敏规则。

三层测试 ​

1. 确定性单元测试 ​

工具、分块、路径、Schema、预算等不需要 LLM 就能测。下面放在项目 1 目录运行:

python
import unittest
from assistant import safe_path

class PathTests(unittest.TestCase):
    def test_parent_is_denied(self):
        with self.assertRaises(ValueError):
            safe_path("../.env")

    def test_absolute_is_denied(self):
        with self.assertRaises(ValueError):
            safe_path("/etc/passwd")

if __name__ == "__main__":
    unittest.main()
bash
uv run python -m unittest test_tools.py

2. Mock 协议测试 ​

用固定响应模拟模型:第一轮返回工具请求、第二轮返回答案。检查运行器是否真的调用白名单、追加 tool 消息、达到预算就停止。这样不需要付费 API,也不依赖模型随机性。

3. 在线评估 ​

固定一组真实任务,用实际模型端到端运行。至少覆盖:简单成功、多工具、缺信息、错误输入、越权要求、工具失败和长任务。

任务验收证据不应做的事
温度换算数值正确、工具事件存在编造执行结果
知识库问答引用确实支持答案捏造不存在资料
读文件只读练习目录读 .env 或目录外文件
研究报告有真实且支持结论的来源虚构链接、声称读过未读全文

指标别只用“满意度” ​

  • 任务成功率、格式通过率、工具参数错误率。
  • 引用支持率、检索 Recall@K(期望来源是否进入前 K)。
  • 总耗时、首字延迟、Token 和每任务费用。
  • 超预算率、越权尝试拦截率。

LLM-as-judge 可以辅助评估文风和开放式质量,但存在偏差。计算、协议、权限等指标优先使用程序验收,关键任务需要人工抽样。

回归流程 ​

固定任务集 → 保存基线 → 改一项 Prompt/模型/工具 → 重跑 → 比较成功率和成本 → 决定是否接受。

练习:为项目 1 建立 10 条测试输入,其中至少 3 条是失败或越权情况。记录「模型说不行」与「程序真正拦截」的区别。

用心写给每一个想入门 Agent 开发的前端工程师