实战客服 RAG 04:增加评测脚本和上线检查清单

先理解:没有评测就没有可持续迭代

一个客服 RAG 能跑起来,只说明 Demo 成功;能稳定迭代,才说明工程成立。每次修改知识、分块策略、阈值或 Prompt,都可能让旧问题变差。评测脚本的作用就是防止你“修好一个问题,弄坏十个问题”。

本篇的评测不是追求复杂论文指标,而是建立一套上线前能执行的检查:可答问题是否命中,高风险问题是否转人工,答案是否带来源,低置信度问题是否拒答。

评测集怎么持续维护

评测集一开始可以很小,但必须真实。建议从客服高频问题、历史投诉问题、容易误判的问题里挑。上线后每周把失败案例补进评测集,让它变成项目的回归测试。

上线不是终点

RAG 上线后要观察转人工率、无答案率、用户追问率、人工客服采纳率。单看“回答了多少问题”没有意义,客服系统最重要的是回答是否可信、是否减少人工负担。

本篇让客服 RAG 从“能跑”变成“能检查”。评测覆盖普通问答、关键字命中和转人工。

评测数据

data/eval/questions.jsonl

json
{"question":"耳机进水能保修吗","product":"headphone","expect_handoff":false,"must_include":["液体","保修"]}
{"question":"发票怎么开","product":"all","expect_handoff":false,"must_include":["发票"]}
{"question":"你们必须赔偿我 500 元","product":"all","expect_handoff":true,"must_include":[]}
{"question":"超过七天还能退货吗","product":"all","expect_handoff":false,"must_include":["七天"]}

评测脚本

src/evaluate.py

python
import json
from pathlib import Path
from src.retriever import retrieve, should_handoff, compose_answer

EVAL_FILE = Path("data/eval/questions.jsonl")

def run_case(case):
    docs = retrieve(case["question"], case.get("product", "all"))
    handoff, _ = should_handoff(case["question"], docs)
    answer = "转人工" if handoff else compose_answer(case["question"], docs)
    errors = []
    if handoff != case["expect_handoff"]:
        errors.append(f"handoff expected {case['expect_handoff']} got {handoff}")
    for text in case.get("must_include", []):
        if text not in answer:
            errors.append(f"missing {text}")
    return errors

def main():
    total = passed = 0
    for line in EVAL_FILE.read_text(encoding="utf-8").splitlines():
        total += 1
        case = json.loads(line)
        errors = run_case(case)
        if errors:
            print("FAIL", case["question"], errors)
        else:
            passed += 1
    print(f"passed {passed}/{total}")

if __name__ == "__main__":
    main()

执行:

bash
mkdir -p data/eval
python -m src.evaluate

如果普通问题被判成 handoff: true,先打印检索距离和来源:

python
docs = retrieve(case["question"], case.get("product", "all"))
print(
    case["question"],
    docs[0]["distance"] if docs else None,
    docs[0]["metadata"] if docs else None,
)

早期小数据集不要把阈值调得太严格。先确认 top 结果来源正确,再逐步收紧 MAX_COSINE_DISTANCE

灰度策略

阶段范围自动回复
内部测试客服团队否,只生成草稿
10% 灰度低风险问题
扩大流量低风险问题是,高风险继续人工

上线检查清单

  • 知识源有负责人。
  • 每次回答返回 sources
  • 高风险词触发转人工。
  • 评测集通过率达到目标。
  • 有延迟和错误率监控。
  • 有关闭自动回复的开关。

完成后,客服 RAG 的最小工程闭环就具备了。

实战知识库迁移 01:盘点知识源并设计分类体系
实战客服 RAG 03:实现检索、转人工和问答 API