章节12 / 14
- 01AI Harness 不是测试脚本,而是 AI 系统的质量控制台
- 02先写任务协议,再谈评测指标
- 03Golden Dataset:把“感觉不错”变成可回归样例
- 04评测不是一个分数:判分器、断言和人工复核怎么组合
- 05结构化输出 Harness:先挡住形状错误,再处理业务错误
- 06Tool Harness:模型只能提议动作,执行权必须被隔离
- 07RAG Harness:先评检索,再评回答
- 08Agent Harness:把多步智能体变成可暂停、可恢复、可审计的状态机
- 09红队与安全 Harness:把提示注入当成常规回归项
- 10观测 Harness:trace 里该看见什么,不该记录什么
- 11CI 回归门禁:让 Prompt、模型和检索改动都要过关
- 12线上反馈回流:用户反馈怎样变成下一版样例
- 13模型路由与发布 Harness:灰度、回滚和成本风险一起看
- 14综合项目:交付一个 AI Harness Engineering 蓝图
本文目录12 节
线上反馈回流:用户反馈怎样变成下一版样例
本指南介绍如何将线上用户的真实反馈(包含赞同、反对、纠错等行为)结构化为 feedback taxonomy,经过过滤、脱敏、复盘和样例晋级机制,最终通过 LangSmith 和 DVC 转化为下一代 AI 应用的黄金评测数据集,实现评测样例的高效回流与版本控制。
- 完成前序单元的练习或理解对应 harness 概念
- 了解基础的 Git 操作与大模型 Trace 机制
- 设计一套符合业务场景的 feedback taxonomy 标签体系
- 实现包含 PII 脱敏的反馈样例晋级与过滤逻辑
- 利用 LangSmith 与 DVC 建立具备版本追踪的评测数据集更新机制
将线上反馈视作“留言箱”是建设 AI 应用时常见的误区。如果只把反馈当成被动查阅的日志,评估数据集(Eval Dataset)就会迅速与真实业务场景脱节。高效的 AI Harness 工程需要建立一条从线上 Trace 到 Harness 样例的供应链:把用户在线上产生的真实交互,提炼、清洗、标注并晋级为测试集的“黄金样例”,从而让评测标准与真实世界的变化保持同步。
线上 Trace 到 Harness 样例的供应链设计
线上反馈回流并不是简单地把报错日志丢进测试集。真实的用户交互往往伴随着大量的噪音(如无意义的问候、重复发送的消息等)。要建立高效的供应链,需要明确数据流转的各个生命周期:
[线上用户交互]
│
▼ (Trace 捕获)
[原始日志与显式反馈]
│
▼ (按 Feedback Taxonomy 归类)
[结构化反馈队列]
│
▼ (PII 脱敏与冗余过滤)
[候选样例池]
│
▼ (人工/模型复盘 + 标注)
[晋级测试用例] ──► [版本化测试数据集 (LangSmith / DVC)] ──► [CI/CD 评测门禁]
在这个流水线中,每一个环节都有明确的准入和准出标准,确保只有高质量、有代表性的数据才能进入最终的黄金测试集。
设计 Feedback Taxonomy:如何把模糊的“不好用”结构化为评测维度
当用户在使用 AI 应用时点击了“踩”(Thumbs Down),或者在意见反馈框里写下“回答不沾边”,这些数据是无法直接用于自动评测的。我们需要定义一套 Feedback Taxonomy(反馈分类法),将这些模糊的主观感受转化为结构化的技术指标。
以下是一个推荐的 Feedback Taxonomy 结构设计:
| 反馈一级分类 | 二级标签 (Taxonomy Tag) | 现象描述 | 对应 Harness 评测维度 |
|---|---|---|---|
| 正确性 (Accuracy) | hallucination | 模型虚构了事实或提供了不存在的代码库方法 | 事实一致性 (Factual Consistency) |
ungrounded_claim | 模型的结论在提供的上下文 (Context) 中找不到依据 | RAG 忠实度 (Faithfulness) | |
| 格式与约束 (Format) | json_invalid | 要求输出 JSON,但格式解析失败 | 结构化输出校验 (Schema Assertion) |
tool_call_failed | Agent 无法正确提取参数以调用指定工具 | 函数调用率 (Tool Call Rate) | |
| 安全性 (Safety) | jailbreak_attempt | 用户试图绕过系统提示词,或者模型输出了不合规内容 | 红队安全拦截 (Guardrails) |
| 体验与性能 (UX) | latency_high | 首字延迟或整体响应时间超过业务容忍极限 | 延迟基准 (Latency Benchmark) |
bad_tone | 回答语气过于生硬、啰嗦或不符合角色设定 | 语气风格对齐 (Tone Alignment) |
在代码层面,每一次用户交互产生的 Trace,都应该能关联一个或多个上述 Taxonomy 标签。例如,当用户触发“踩”时,前端交互应该弹出微型单选框引导用户选择二级标签,或者通过后端异步的大模型对用户的投诉文本进行多分类标记,将其自动归类到对应的 Taxonomy 标签下。
自动过滤与脱敏:保护用户隐私的 PII 剔除机制
如果用户反馈中包含敏感的个人身份信息(PII),在将其录入评测数据集之前,必须经过自动化脱敏或人工脱敏,因为直接将未处理的敏感数据暴露在评测集中会违反合规要求并带来数据泄露风险。脱敏机制应作为数据进入候选样例池前的硬性门禁。
通常采用基于规则(如正则表达式匹配手机号、邮箱、身份证)和基于命名实体识别(NER)模型的双重方案来对原始 Trace 进行脱敏。以下是一个简化的脱敏处理脚本示例:
import re
def redact_pii(text: str) -> str:
"""
对输入的文本进行基础 PII(个人敏感信息)脱敏
"""
# 替换电子邮箱
email_pattern = r'[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+'
text = re.sub(email_pattern, "[REDACTED_EMAIL]", text)
# 替换中国大陆手机号
phone_pattern = r'(?:\+86|86)?1[3-9]\d{9}'
text = re.sub(phone_pattern, "[REDACTED_PHONE]", text)
# 替换银行卡号(简易匹配 16-19 位数字)
card_pattern = r'\b\d{16,19}\b'
text = re.sub(card_pattern, "[REDACTED_CARD]", text)
return text
# 测试脱敏效果
raw_input = "我的手机号是 13812345678,邮箱是 user@example.com,请问我的账单为什么扣了 100 元?"
clean_input = redact_pii(raw_input)
print(clean_input)
# 输出: 我的手机号是 [REDACTED_PHONE],邮箱是 [REDACTED_EMAIL],请问我的账单为什么扣了 100 元?
在实际的自动化流水线中,如果发现脱敏后的文本长度变化过大或关键上下文丢失(例如,测试用例本身就是为了测试对特定电话号码格式的提取),则必须将该样例标记为 needs_manual_review(待人工审核),而不要让它直接自动流转入库。
误报与漏报的日常复盘:判定“黄金用例”的晋级标准
线上收集到的反馈数据并不能 100% 转化为有效的测试样例,我们需要在日常复盘中对其进行评估。这就需要区分误报(False Positive Feedback)与漏报(False Negative Feedback):
- 误报:用户点击了“踩”或投诉,但经过人工分析发现模型的回答完全符合预期(例如:用户询问违法行为,模型按照安全守则予以拒绝,用户因此给出了差评)。这类反馈不能晋级为测试集的“错误示范”,反而应当作为“安全拒绝”的正面标杆。
- 漏报:用户没有给出负面反馈,甚至给出了“赞”,但通过后台抽样或异常日志监控发现模型其实输出了存在幻觉的内容、或泄露了不该泄露的中间思考过程。这类样例是极高价值的“隐藏陷阱”,必须作为负面用例晋级到测试集。
如果新收集的反馈样例没有经过多方校验就直接加入黄金测试集,应该立即停止该自动化流程,否则测试集会因为引入噪声或特定版本偏差而丧失其作为质量红线的准确性。
为了规范复盘,我们需要建立**样例晋级卡(Case Promotion Card)**机制。只有满足以下条件的样例,才可以从候选池中“晋级”:
- 明确的期望输出 (Ground Truth):该用例必须能够被人工或高阶模型标注出明确的理想输出(Expected Output)或判定规则(Assertions)。
- 边界代表性:该样例能够代表一类尚未被现有测试集覆盖的边界场景(Edge Case),避免用例集膨胀。
- 可复现性:在相同的 prompt 和参数设定下,该输入能够稳定复现特定的缺陷。
基于 LangSmith 与 DVC 的数据集版本控制与回流实现
一旦样例通过复盘并获得晋级,我们需要在工具链中予以实现。根据 LangSmith 官方文档关于数据集管理 (Manage datasets) 的说明,开发者可以直接从运行轨迹 (Traces) 中筛选并回流样例到指定的数据集中。因此,我们应该利用这一能力将用户在线上产生的真实高价值对话一键转化为测试用例,而不是手动复制粘贴。
以下是利用 LangSmith SDK 过滤出包含负面反馈(thumbs_down)的线上 Trace,并将其追加回流到开发测试集中的 Python 代码:
import os
from langsmith import Client
# 初始化 LangSmith 客户端(需配置环境变量 LANGCHAIN_API_KEY)
client = Client()
# 1. 筛选线上带有 "thumbs_down" 反馈的 traces
traces = client.list_runs(
project_name="production-chatbot",
run_type="llm",
error=False, # 确保不是因为代码崩盘导致的错误,而是业务层面的反馈
filter='and(eq(feedback.key, "thumbs_down"), eq(feedback.score, 1))',
limit=10
)
# 2. 将高价值 Trace 的输入输出,流转回流至评估数据集
dataset_name = "chatbot-regression-suite"
# 如果数据集不存在则创建
if not client.has_dataset(dataset_name=dataset_name):
dataset = client.create_dataset(dataset_name=dataset_name, description="由线上用户差评反馈回流组成的回归测试集")
else:
dataset = client.read_dataset(dataset_name=dataset_name)
for run in traces:
# 运行 PII 脱敏
safe_input = redact_pii(str(run.inputs.get("question", "")))
safe_output = redact_pii(str(run.outputs.get("output", "")))
# 写入数据集,并标记其来源追踪
client.create_example(
inputs={"question": safe_input},
outputs={"expected": safe_output}, # 注意:如果是负面反馈,这里的 expected 需要在复盘时人工修正为正确的回答
dataset_id=dataset.id,
metadata={
"source_run_id": str(run.id),
"taxonomy": "user_thumbs_down",
"promoted_at": "2026-05-28"
}
)
print(f"成功回流样例到 LangSmith 数据集: {dataset_name}")
结合 DVC Data Registry 的实践,大型 AI 团队在管理评测资产时,往往需要将测试集与模型代码版本进行显式绑定。这启示我们,即使 LangSmith 提供了数据集的版本管理,我们也应该使用 DVC 将大型测试数据注册到企业远程存储,以确保在 CI/CD 流程中能与特定模型 release 版本进行精细对齐。
如果在使用 LangSmith 导出数据集时发现版本标签混淆,可以通过在 DVC Data Registry 中对底层数据文件打上明确的 Git Tag 来进行版本锚定,除非团队已经有一套跨平台的统一元数据服务,否则双重标记能最大程度防止追溯失败。
通过 DVC 管理本地导出的测试集 JSON 文件:
# 将 LangSmith 导出的测试集保存为本地文件
# 格式示例:data/eval_set_v1.0.0.json
# 初始化 DVC 并将其添加至跟踪
dvc init
dvc add data/eval_set_v1.0.0.json
# 提交 DVC 产生的指针文件到 Git,以便实施版本控制
git add data/.gitignore data/eval_set_v1.0.0.json.dvc
git commit -m "chore: 升级黄金测试集版本,回流了5个5月28日的线上用户真实反馈样例"
# 将实际的大文件推送至远程对象存储(如 S3 或 OSS)
dvc push
失败诊断:回流流程中的常见阻塞与降级策略
在生产环境中运行回流机制时,极易遇到以下异常情况。团队需要针对这些故障制定明确的降级策略:
- 反馈数据过载导致人工复盘积压:
- 现象:线上日活突增,带有标签的反馈数据每天产生上千条,人工校验团队根本无法处理。
- 降级策略:启用预过滤分类器。优先使用较轻量的大模型(如 GPT-4o-mini 或本地 Llama 模型)进行初步筛选,过滤掉相似度极高的冗余提问,只保留 Embedding 向量空间里与现有测试集距离最远、最具多样性(Diversity)的前 5% 数据进入待审队列。
- API 凭证失效与链路中断:
- 现象:线上日志系统到 LangSmith 的链路由于网络抖动或 Token 过期导致中断,回流任务失败。
- 降级策略:回流任务必须采用异步解耦设计。将线上 Trace 优先持久化至本地数据库或安全的消息队列(如 Kafka),回流脚本以定时任务(Cron Job)形式拉取。如果写入 LangSmith 失败,应该将断点记录在元数据库中,下次运行时重试,切忌直接在业务主流程中同步等待回流结果。
- 输入输出不匹配导致的断言崩溃:
- 现象:回流的新用例格式不兼容老版本的评测断言,导致自动化 CI/CD 跑测流水线直接挂掉。
- 降级策略:新回流的用例必须默认进入
staging分支测试集。只有通过了格式完整性校验和 Dry-Run 运行的用例,才能合入main分支黄金测试集。
练习验收:设计并运行一条完整的“反馈-晋级-评测”流水线
1. 练习目标
手动模拟一次线上反馈回流与版本变更,你需要将一条代表性的“坏样例”转化为带有版本标记的测试集的一部分,并运行一次测试回归。
2. 交付物与执行步骤
-
步骤一:构建一份模拟反馈输入文件
raw_feedback.jsonjson { "user_query": "你们的系统是不是有漏洞?我的手机是 13900001111,刚才输入密码后提示我系统繁忙,但我账户扣款了!", "assistant_response": "哈哈,真不走运。请稍后再试。", "user_feedback": "thumbs_down", "user_comment": "语气极其恶劣,而且泄露了我的手机隐私!" } -
步骤二:编写清洗与格式化脚本
process_feedback.py编写脚本完成以下动作:- 对
user_query中的手机号进行脱敏,替换为[REDACTED_PHONE]。 - 将反馈归类为
bad_tone标签。 - 设定明确的预期输出
expected_output为:"非常抱歉给您带来不便,我们的客服已经记录了该问题。请提供您的交易单号,我们会立即帮您核实退款进度。" - 导出为符合评测规范的测试集文件
eval_dataset_v1.0.1.json。
- 对
-
步骤三:版本锚定 使用 DVC 对更新后的
eval_dataset_v1.0.1.json进行跟踪,并在本地 Git 中提交对应的.dvc指针变更。
3. 验收方式
检查你的 Git 提交历史中是否包含以下文件变更组合:
data/eval_dataset_v1.0.1.json.dvc- 脱敏后的数据文件中不含任何真实手机号,且预期输出已纠正为无偏、礼貌的文本。
来源与时效说明
- 关键来源与访问时间:
- 本指南关于数据集的版本管理(Dataset Versioning)及回流技术,基于 LangChain 官方文档
LangSmith - Manage datasets(访问日期:2026-05-28)。 - 版本管理的多级存储与数据源追踪,参考了
DVC Data Registry工具实践(访问日期:2026-05-28)。 - 数据集的回归门禁与评测定义,参考了
OpenAI Evals与评测平台的回归测试体系设计(访问日期:2026-05-28)。
- 本指南关于数据集的版本管理(Dataset Versioning)及回流技术,基于 LangChain 官方文档
- 适用范围:适用于任何基于大语言模型、Agent 系统的质量监控、评测回归与工程化发布流程。
- 时效复核触发条件:当 LangSmith 改变其 Dataset 导出的 SDK API,或者 DVC 发布了不向下兼容的数据存储控制命令行时,本教程中的代码与命令部分需重新进行调试和修订。
线上反馈回流:用户反馈怎样变成下一版样例:把判断写进 Harness 证据链
线上反馈只有进入数据集版本,才会真正改变下一次评测。本课交付物是 一套 feedback 到 dataset 的处理流程和版本变更记录,它必须能被复跑、复核、追踪和复盘。
如果 线上反馈回流:用户反馈怎样变成下 还没有对应的输入样例,先不要讨论自动化覆盖率,因为没有样例就无法判断 harness 是否真的抓住问题。 如果一次评测失败会影响发布,应该保留失败输入、模型输出、工具轨迹和判分理由,否则团队只能凭记忆争论。 如果你准备把某个结果自动放行,必须先写清人工复核的例外条件,只有例外条件明确时,门禁才不会变成新的风险源。
发布事故复盘至少要连接模型版本、prompt 版本、检索版本和工具版本。围绕 线上反馈回流:用户反馈怎样变成下一版 做排查时,记录步骤、样例、指标、风险、修复动作和复测结果。
LangChain 的《Manage datasets》说明:支撑 dataset versioning、过滤、导出和从 traces 回流数据集。;这意味着 线上反馈回流:用户反馈怎样变成下 要把来源转成可执行断言。DVC 的《DVC Data Registry》提醒:支撑用 Git 与 remote storage 管理 dataset/model file 版本。;因此本课必须写清自动判断和人工判断的边界。OpenAI 的《Working with evals》提供的证据是:支撑 AI 输出评测集、评测运行、模型质量回归和上线门禁。;所以当前结论按 2026-05-28 的来源状态使用。
复核触发条件要具体:如果模型 API/SDK、评测工具版本、Agent 框架、RAG 指标、安全规范、合规政策、平台 release/changelog 或关键来源页面变化,需要重新运行本课样例并更新 harness。
练习验收:把 线上反馈回流:用户反馈怎样变成下一版 接入一个最小 AI 应用,提交包含输入样例、评测结果、失败诊断、来源证据、人工复核结论和下一步修复动作的记录。缺少任何一项,都标记为 needs_review。