Skip to content

第 9 章:评估、观测与调试

章节定位

前面几章已经把 LangChainRAGTool CallingLangGraph 的基本能力搭起来了。到了这一章,真正的问题不再是“能不能跑”,而是“为什么这样跑、哪里出错、效果到底好不好”。

这一章的目标,是让 AI 学习助手 从一个能工作的原型,变成一个可持续迭代、可定位问题、可做质量判断的工程系统。

配套示例

  • 目录:examples/chapter-09
  • 入口:examples/chapter-09/main.py
  • 依赖:examples/chapter-09/requirements.txt
  • 运行:cd examples/chapter-09 && python3 main.py

示例层级与边界

  • 层级:更真实的工程版
  • 本章重点:建立评估、trace 和调试的工程习惯,重点是流程可重复、结果可比较。
  • 不要误判:虽然它更接近真实工程实践,但仍是本地离线样例,不等于完整的线上观测与评测平台。

本章目标

学完这一章,你应该能做到:

  • 分清“功能正确”和“效果足够好”是两件事
  • AI 学习助手 建立最小可用的评估集
  • 用日志和 trace 找到问题发生在链路的哪一步
  • 理解为什么 LLM 应用不能只靠手工点几次就下结论
  • 为后续公开部署和版本迭代建立基础

前置知识

你需要已经掌握:

  • LangChain 的基本链式调用
  • 基础 RAG 流程
  • Tool Calling 和 Agent 的基本工作方式
  • LangGraph 的节点和状态概念

如果前面章节还没完全吃透,这一章也可以先读。因为调试和评估本身就是帮助你反向理解系统的最好方式。

核心概念

1. LLM 应用为什么难调

传统程序的输出通常是确定的,输入一样,输出也一样。LLM 应用不是这样。即使输入不变,输出也可能因为模型随机性、检索内容变化、上下文长度、工具结果不同而变化。

这意味着:

  • 你不能只看一次结果
  • 你不能只看最终回答
  • 你必须知道中间发生了什么

2. 评估、观测、调试的区别

这三个词经常混在一起,但实际职责不同:

  • 评估是判断效果好不好
  • 观测是记录系统运行时发生了什么
  • 调试是根据记录去定位并修复问题

如果没有观测,调试只能靠猜。
如果没有评估,你不知道改动到底有没有变好。
如果没有调试能力,系统一复杂就无法维护。

3. 最小评估集

对于 AI 学习助手,最小评估集不需要上来就很大。你可以先准备 10 到 20 个固定问题,覆盖这些场景:

  • 基础概念解释
  • 课程内容总结
  • 检索式问答
  • 工具调用问题
  • 边界问题和无答案问题

目的不是一次测完所有情况,而是建立一个稳定的回归基线。

4. Trace

Trace 指的是把一次请求从输入到输出的关键中间步骤完整记录下来,例如:

  • 用户问题是什么
  • 检索到了哪些文档
  • 模型看到了哪些上下文
  • 哪个工具被调用了
  • 哪一步抛出了异常

对 LLM 应用来说,Trace 往往比单个日志更重要,因为问题常常出在“中间链路”而不是最终输出。

分模块讲解

9.1 为什么 AI 学习助手 不能只靠人工试用

一个教学型 AI 应用很容易出现一种错觉:只要你自己测几次觉得“差不多”,就以为系统可以上线了。

实际上,人工试用只能发现最明显的问题,发现不了下面这些情况:

  • 某一类问题总是检索不到内容
  • 某个 Prompt 改动让结构化输出不稳定
  • 工具调用在长上下文下会退化
  • 某些问题会反复触发幻觉答案

所以第一步不是优化模型,而是建立可重复的检查方式。

9.2 为课程项目建立评估维度

AI 学习助手,建议至少从四个维度看:

  • 正确性:答案是否符合事实或课程内容
  • 完整性:是否覆盖了问题要求的关键点
  • 可解释性:是否能说明依据来自哪里
  • 稳定性:多次运行结果是否波动过大

如果是 RAG 场景,还要额外看:

  • 检索命中率
  • 引用片段是否相关
  • 回答是否真的基于检索内容

如果是 Agent 场景,还要额外看:

  • 是否选择了合适工具
  • 是否反复循环
  • 是否在错误后能恢复

9.3 最小评估集怎么设计

一个实用的做法是把评估集拆成三层:

  • 基础层:定义性问题,比如“什么是 Runnable”
  • 实战层:带步骤的问题,比如“如何搭建 RAG”
  • 边界层:故意测试系统失败能力,比如“我没给资料也要你回答课程细节”

每条评估样本最好包含:

  • id
  • question
  • expected_points
  • scenario
  • priority

这里不要求一开始就写复杂评分器,先把问题集整理清楚更重要。

9.4 观测什么

对于每一次请求,至少要记录这些信息:

  • 输入问题
  • 当前章节或模式
  • 检索 query
  • 检索结果摘要
  • 最终回答
  • 是否调用工具
  • 是否报错
  • 耗时

如果你后面接入 LangSmith 或类似工具,这些信息会被组织成 trace 页面,方便逐层展开查看。

9.5 调试的基本顺序

遇到问题时,不要直接改 Prompt。推荐顺序是:

  1. 先看输入是不是错的
  2. 再看检索内容对不对
  3. 再看上下文是否被截断
  4. 再看模型输出是否符合预期格式
  5. 最后才改 Prompt 或链路结构

这个顺序的好处是避免“盲目调参”。

最小示例说明

下面这个最小示例展示的是“固定评估集 + 逐条检查输出”的思路。它不追求复杂,但足够帮你建立第一个回归测试流程。

python
from dataclasses import dataclass


@dataclass
class EvalCase:
    id: str
    question: str
    expected_points: list[str]


EVAL_CASES = [
    EvalCase(
        id="basic-01",
        question="什么是 LangChain 的 Runnable?",
        expected_points=["可组合", "可链式执行", "统一接口"],
    ),
    EvalCase(
        id="rag-01",
        question="为什么 RAG 能降低幻觉?",
        expected_points=["检索外部知识", "让答案基于资料", "减少纯生成猜测"],
    ),
]


def score_answer(answer: str, expected_points: list[str]) -> int:
    score = 0
    for point in expected_points:
        if point in answer:
            score += 1
    return score


def run_eval(answer_fn):
    results = []
    for case in EVAL_CASES:
        answer = answer_fn(case.question)
        score = score_answer(answer, case.expected_points)
        results.append((case.id, score, answer))
    return results

这个示例的关键点不是评分算法有多高级,而是你开始把“感觉不错”变成“可记录、可比较、可复查”。

本章实践

建议你为 AI 学习助手 完成下面三个任务:

任务 1:建立评估集

先选 10 个问题,覆盖:

  • 前 4 章的基础概念
  • 1 个 RAG 问题
  • 1 个工具调用问题
  • 1 个边界问题

任务 2:记录每次运行的 trace

至少记录:

  • 问题
  • 检索结果
  • 最终回答
  • 耗时

任务 3:找出 3 个真实问题

不要追求全对,先找出以下类型的问题:

  • 哪些题回答不完整
  • 哪些题回答偏题
  • 哪些题在没有资料时会乱答

把它们写进 docs/faq/ 或单独的调试说明里。

常见坑

1. 只看最终回答,不看中间步骤

很多问题不是模型本身的问题,而是检索内容、上下文拼接或工具结果的问题。

2. 评估集太大

一开始就做几百题,通常只会增加维护成本。先做小而稳定的基线集。

3. 把一次成功当成稳定效果

LLM 应用需要多次运行观察波动,尤其是开放式问答。

4. 只评估“能不能答”,不评估“答得是否可靠”

对于课程学习助手,可靠性和可解释性和答案本身一样重要。

5. 没有版本意识

当 Prompt、检索策略或模型版本变化时,不记录版本就没法比较改动效果。

练习题

  1. AI 学习助手 写出 10 个评估问题,分别属于基础层、实战层和边界层。
  2. 设计一个你自己的回答评分规则,至少包含“正确性”和“完整性”两个维度。
  3. 选一个你前面章节的示例,列出它的输入、检索、输出和可能失败点。
  4. 想一想,如果用户问了课程范围外的问题,你应该如何记录和处理。

本章总结

这一章的核心不是某个具体框架,而是建立一种工程习惯:任何 AI 应用都要能被观察、能被比较、能被复盘。

对于 AI 学习助手 来说,这意味着你不再只是“做出一个回答器”,而是在做一个可以长期迭代的学习产品。只要这一点成立,后面的部署、扩展、公开传播才有基础。

学完本章,你现在应该会

  • AI 学习助手 设计一组覆盖基础层、实战层和边界层的小型评估集
  • 说明 trace、日志、评分规则分别解决什么问题
  • 判断一个回答问题该从评估数据、中间链路还是版本变更去排查
  • 把“感觉不错”转换成可记录、可比较的指标

最小验收 checklist

  • [ ] 我已经列出一组最小评估问题,而不是只靠临时提问
  • [ ] 我知道每次运行至少要记录哪些关键信息
  • [ ] 我能举出 1 到 3 个真实失败案例,而不是只展示成功结果
  • [ ] 我会在 Prompt、检索或模型变化时记录版本背景

建议你动手改一版

  • 先写 10 个评估问题并分组,后面每改一次链路都跑同一组问题
  • 给日志增加一个最小字段集,例如问题、检索结果、最终答案、耗时
  • 选一个历史输出,补写一段失败分析,训练自己从链路而不是从感觉定位问题

卡住时先回看这里

下一步

如果你要继续完善这个项目,下一步就是把前九章的成果整合成一个完整可访问的公开版本。第 10 章会把文档站、示例代码和部署流程连起来,形成最终的交付闭环。