online branch: main

2026-10-02

RSS llms.txt GitHub

Agent 运行数据怎么组织:从日志记录到可复核的证据

$
Agent 运行数据怎么组织:从日志记录到可复核的证据

假设产品团队和客服团队正在评估同一个 Agent。产品看板显示失败率 12%,客服导出的表格却高出很多。两边都能拿出原始记录,都认为自己的数没错。

此时追问“谁的算法有问题”有点早。产品可能按每轮回答统计,客服按整段对话统计;产品只算有评分的记录,客服把没得到结果的对话也算进去了。即使两套查询都执行正确,它们回答的仍是不同问题。

这不是某次真实会议的复述,而是一个用于说明口径的假设场景。做 Agent 产品时,这类争议比“埋点有没有上报”更值得提前处理:你能打开每条执行记录,并不意味着你已能解释看板上的百分比。

上一篇讨论的是执行过程该怎么留下来。这一篇从两个团队对不上数开始,逐层查清它们分别数了什么,再回到字段设计。先定义判断,再决定要留下哪些数据,比先建一张字段很多的表更省返工。

先把失败率写成一句完整的话

“失败率 12%”省略了太多条件。可以把它补成:“在过去 7 个业务日、生产环境的账户变更类客服对话中,已结束且完成结果判定的会话,有 12% 未解决问题;每段会话只算一次,不含测试和重复上报。”

这仍只是口径示例,但它已经能让别人重算。要形成可复核的指标,至少要说明以下五项。

口径项 需要回答什么 在客服场景里容易混淆的地方
分子 什么条件算失败 转人工、用户说没解决、工单重开是否都算,是否允许重叠
分母 哪些对象有资格被统计 全部请求、全部会话、已结束会话,还是有反馈的会话
时间窗 按什么时间归入哪一天 请求发生、对话结束、评分到达,可能不是同一天
去重 同一对象重复出现时算几次 重试、重复上报、多轮信号、工单再次打开
采样 记录覆盖了哪些对象 随机留一部分,还是优先留失败与高价值请求

“过去一周”也不是足够清楚的时间口径。跨时区系统要明确业务时区;按事件发生时间统计与按采集时间统计不能混用。尤其是对话结束数天后才出现的业务结果,必须约定回写原会话所属时间窗,还是在结果到达当天单独统计。

Langfuse 的客服示例把 ticket_reopened 定义为客户在七天内为同一问题再次联系支持。这七天是结果判定窗口,不是一个可以随手删去的形容词。对昨天刚结束的会话直接判断“七天内没有重开”,会把尚未观察满窗口误当成成功。客服示例

所以,除了五项计算口径,延迟结果还要标明“已观察完整”“待观察”或类似状态。口径文件需要告诉读者哪些数字已经稳定,哪些数字还会因新事件回写而变化。

如果五项写法不同,先拆成两个指标,不必强行让它们一致。如果五项一致而数字仍不同,再查原始数据、查询逻辑、时区、缺失字段与上报链路。没有证据支持“对不上数绝大多数都是口径问题”这种频率判断;把口径放在排查前面,是因为它容易核对,也直接决定查询应该做什么。

正文重点图解

一段十轮对话,到底算一次还是十次

假设一段对话来回十轮,最后客户仍没解决问题。你可以评价每轮回答,也可以评价整段对话,但不能把这两个判断用同一个名字装起来。

如果十轮全部有各自的失败判定,轮级统计会增加十条失败、十条总量,会话级统计增加一段失败、一段总量。这不意味着失败率必然差十倍:在这段对话自身,两者都是 100%。差异来自整批数据里,不同结果的会话有不同轮数,轮级统计会给长对话更大的权重。

例如,下面仍是演算用的假设数据。一段失败对话有十轮,另有九段成功对话各一轮。如果把失败对话的十轮都判失败,轮级失败率是 10/19,约 52.6%;会话级失败率则是 1/10,也就是 10%。这两个数都能算对,适用的问题却不同。

轮级指标适合问“这一轮的检索或回答出了什么错”;会话级指标适合问“这段交互有没有解决问题”。同一会话里的多轮通常相互关联,拿它们当完全独立样本做统计推断,还可能高估有效样本量。

因此,记录里要分清三种身份。

标识 它识别什么 能支持的问题
主体标识 客户、租户、用户或账户 同一客户是否跨多次交互重复遇到问题
会话标识 一段连续交互或一个业务过程 本次对话如何结束,之后是否重开
执行标识 一次调用、一次 Agent 运行 这一轮经过了哪些步骤,具体错在哪里

一个主体可以有多个会话,一个会话可以包含多次执行。不能用用户 ID 把某个人一个月的对话都装进同一会话,也不能在每轮生成新“用户身份”,让跨会话分析断掉。

这些标识在某个业务系统中可能有映射关系。例如,一段会话能查询到其客户。这不代表两个字段可以互相替代;更不能假设所有应用都是“一段会话只对应一个人”。协作场景可能有多个参与主体,关系必须按业务定义。

Langfuse 的客服示例提供了一个有用的信号分层:handoff_requested 和 question_repeated 定位某一轮;session_outcome、conversation_rating 和之后到达的 ticket_reopened 评价整段对话。前者告诉你问题从哪轮显露,后者告诉你交互结束后发生了什么。实际项目可以调整分层,但要保留“判断对象与挂载对象一致”的原则。

session_outcome 在这个示例中采用 resolved、abandoned、handed_off 三类结局。当业务定义要求最终结局互斥,用一个分类字段更容易保证每段只计一次。多个布尔字段也不是技术上不能实现,只是需要额外的一致性约束;否则同一段同时“已放弃”和“已转人工”,分子就容易重复计算。

“没反馈”不能替用户回答

两个团队查清统计单元后,下一步可能发现:产品只统计有标签的记录,客服把所有结束的会话都列了出来。

这时不能给缺失标签统一补“中性”,更不能补“成功”。没有反馈只说明没有收到反馈,原因可能是没看见入口、不愿花时间、已经离开,或觉得没必要评价。它与真实满意度之间没有固定的一一对应关系。

一个较早、但能说明机制的研究来自 Yahoo! LaunchCast。Marlin 等人在 UAI 2007 的论文中报告,64.85% 的调查用户认为自己对歌曲的偏好会影响是否评分。表 1 中,对喜欢程度为 Love 的歌曲,93.91% 选择“非常频繁”评分;对 Neutral 的歌曲,这一比例是 36.50%。这里的选项是 Very Often,不是把 Often 与 Very Often 相加后的“经常”。这组调查数说明评分选择受到偏好影响,不能把未评分对象视为随机缺失;它并不是 AI 客服的满意度调查。论文

LLM 对话里也能看到类似的选择差异,但比例要回到各自样本。SPUR 论文的线上覆盖分析显示,其样本中的按钮反馈偏正向,文本反馈偏负向。两种渠道覆盖的人群和表达动机不同,不能把它们当成可以直接拼接的统一满意度样本。SPUR

WildFeedback 对 148,715 段多轮对话进行信号识别,论文报告约 12.8% 含反馈信号;SAT 对话计数是 5,447,DSAT 是 13,582。它按“至少含一条相应信号”标记对话,因此不要未经去重确认就把两个类别之和解释为互斥的满意与不满意人群。这些数字描述论文的语料和识别方式,不能作为任何客服产品的天然反馈率。WildFeedback,表 1

Meta 的 RLUF 研究则用了另一种反馈:Love 表情。论文报告,约 0.1% 的模型消息收到这种反应;训练奖励模型时,正例又被上采样到训练数据的 10%。0.1% 是线上模型消息的反应覆盖率,10% 是人为构造的训练分布,两者都不是“用户满意度”。如果拿训练样本中的正例比例解释线上用户行为,即便计算没有任何错误,结论也会错。RLUF,3.1.1 节

落到指标上,缺失要有明确去向:可以作为独立状态展示,也可以在某项评分的计算中排除,但排除时要同时报告覆盖量和覆盖率。“有评分会话中的满意比例”可以使用,名称和说明必须让人看出它只评价了部分会话。

风险也不是固定向一个方向偏。有些场景更满意的人愿意评分,有些场景更生气的人才留下文字。把缺失当满意会高估,把“已反馈样本”直接外推全体也可能高估或低估;偏差方向需要根据反馈机制判断。

总体数字一致了,为什么仍解释不了投诉

即使两个团队终于算出相同的失败率,这个总体数仍可能掩盖问题。账户变更类请求与故障排查类请求,客户群和任务难度不同,混在一起比较版本,容易把业务构成变化误读为能力变化。

Langfuse 的客服示例提醒:转人工率、重复率因工单类别与客户群而异,应比较某个类别与它自己的历史。另一个容易漏掉的群体是默默放弃的人:他们不会请求转人工,只看转人工率就看不到他们的结局。

这时需要业务维度,也就是能让你筛选、分组或解释记录的字段。它们不是一套必须逐级完成的操作流程:可以先分组再过滤,也可以先筛选特定客户再比较版本。设计时只需说清每个字段要支持哪个问题。

维度 应保留的含义 需要提前约定的边界
主体 租户、客户、账户、角色或脱敏用户标识 是否需要个体粒度;跨会话身份是否稳定
时间 事件发生时间、业务日期、观察窗口 时区、迟到数据、业务日定义
环境 生产、预发、测试、本地 空值如何处理,测试请求如何排除
场景 日报生成、账户诊断、报表问答或客服任务族 分类粒度、未知类型、是否允许多标签
版本 prompt、模型、流程、代码和相关数据源版本 哪些变更会改变行为,能否追溯一次执行
结果 业务结局、失败类别、采纳方式和判断状态 判定对象、标签来源、未标注与待观察如何处理

这些是设计方向,不是要一次性上齐的字段清单。只有当字段影响系统行为,或能帮助解释结果,才值得承担采集和维护成本。

以投放产品作类比,一次日报生成可带账户、业务日期、日报场景、prompt 版本和数据流程版本。再记录“原样采纳”“修改后采纳”“未采纳”,能比单一采纳按钮提供更多信息。但“未采纳”与“还没看”仍要分开,采纳本身也不证明建议正确。

人工修改还可以区分措辞调整、事实纠正、缺失内容补充。这借用了客服示例中 edit_type 的 none、tone、corrected、added 分类思路。只改语气与改了错误事实,需要不同的修复;如果一条实际回复同时有多种修改,项目还应定义主分类优先级或采用多标签,不必机械照搬示例。

有场景和版本,你可以定位“哪个客户、哪个任务、哪个版本的表现不同”,但不能由此直接认定某次变更造成退化。版本发布时可能同时换了客户群、数据源或模型。维度帮助缩小调查范围;要判断因果,还需要受控比较、复现或其他证据。

字段多了以后,先别把高基数当原罪

原始资料容易导出一个过强结论:“维度必须低基数,唯一标识不能分组。”这会误伤本来需要的分析。

请求 ID 通常每条都不同,拿它统计“每组失败率”当然没多少价值;但用户 ID、账户 ID 和会话 ID 可以关联多条记录。按账户看一周问题、按用户识别重复求助、按会话汇总结局,都是有效分组。是否适合聚合,要看业务目的与组内样本量,而非字段是不是 ID。

低基数尤其适合场景类型、操作名、环境等需要稳定汇总的维度。把订单号拼进步骤名,今天的 process-order-8945 与明天的 process-order-9120 就不会自动聚成“处理订单”。Langfuse 建议把动态值放进 metadata,操作名保持稳定。模型版本同样可以独立记录,不必把模型名写成操作名。trace 命名建议

维度设计可以按五个问题检查,而不是给所有字段一个“低基数通行证”。

检查问题 可行做法 常见反例
聚合粒度与样本量合适吗 场景汇总与账户排障采用不同粒度 每条都单独一组,却用组内 P95 比较质量
名称与含义稳定吗 稳定键、展示名和版本分别管理 改展示标签时顺手改掉查询键
一个字段表达一个概念吗 环境与渠道分开记录 用 ios_beta 同时编码客户端与发布环境
交叉切片还有足够数据吗 围绕实际调查逐步增加切片 一开始要求所有维度组合都均衡覆盖
业务人员能解释取值吗 有定义、未知值与判定规则 只有埋点开发者知道缩写含义

六个维度各有四种取值,理论上会形成 4⁶,也就是 4,096 个组合。大量空格或只有一条数据的格子,不自动证明字段选错了,也可能只是流量不足、某些组合业务上不存在。它提醒的是:不要从稀疏格子计算看似精确的结论,也不要要求所有交叉维度都从第一天起平衡。

“正交”在这里指字段语义尽量分开,不要求统计上独立。客户等级与任务难度可能相关,仍可以各自保留;分析时应解释相关关系,不能因为字段拆开了就假设混杂已被消除。

还要区分维度与存储位置。metadata 是承载附加信息的一种容器,其中既能放备注,也能放可过滤、可分组的场景字段。维度是分析用途,不是与 metadata 互斥的数据层。自由文本反馈可以保留原文,同时派生极性、失败类型等结构化字段;派生标签还需要注明评估器和版本,才能知道变化来自行为还是标签规则。

版本更新后,历史不能跟着悄悄改写

假设“日报”更名为“日报生成”。如果查询键直接换掉,依赖旧名称的筛选与图表可能少算数据。但这不等于历史永久无法比较:可以用稳定内部键、别名映射、迁移记录或重算恢复连续性。

真正要警惕的是没有记录语义变化。同样叫“成功”,昨天定义为“模型返回”,今天定义为“结果已写入目标系统”,曲线继续连着,反而容易让人误以为可以直接比较。

字段定义和指标口径都应有版本。变更后要约定历史是重算、映射后比较,还是保留断点。true、1、yes 不应在同一字段里随意混用;如果为了兼容已有系统允许多种表达,要有明确规范化规则。

数据集里的过期行是另一个问题。Langfuse 建议在 prompt、工具、策略或产品行为改变后归档或更新陈旧条目。这是维护测试样本的有效性,不是“维度只能归档、不能改名”的证据。字段更名与数据集退役各有自己的迁移办法,不能用同一条建议替代两种治理。

指标本身也会过期。一个指标的定义清楚,不代表它值得长期追踪。Langfuse 举过 OpenAI 收据处理 walkthrough 的例子:商家名提取错误率达到 85%,但错误与系统最终的审计决策无关,团队因此停止追踪它。这个例子来自 OpenAI 的讲解,经 Langfuse 转述,不属于 Amazon 的 NLU 论文。指标选择

连续数月 100% 的评分也可以重新审视:它可能缺乏区分度,但不能自动推断成“口径太松”,更不能据此删掉硬约束护栏。决定保留与否,要看风险和决策用途。针对指标反复调 prompt 后,还应拿新的人工标签检查是否过拟合原有评分规则。

追到某一条失败,再检查它的内部结构

现在两个团队有了共同口径,也能筛出“某客户、某场景、某版本”的目标记录。下一步打开其中一条,才轮到执行链路。

从分析角度,一条执行记录需要几类信息。下面是本文用于整理采集需求的分层,不是某个观测工具的官方六层标准。

信息层 应记录什么 缺失会妨碍什么
标识 trace ID、会话 ID、必要的主体关联 定向回看、跨轮关联与延迟结果回写
时间 起止时间、步骤耗时、必要的事件时间 定位等待、区分先后与并行
层级 父子关系、所属编排单元 还原每个动作属于哪段执行
类型 模型、工具、检索、编排、评估等 筛选某类操作,解释对应输入输出
内容 各步可用的输入、输出和工具参数 判断哪一步偏离预期
属性 场景、环境、版本、结果及标签来源 比较同类记录并解释差异

“当时没记下来”会限制事后调查,但也别一概写成“永久补不回来”。一些属性可以从发布记录、工单或业务库补齐;瞬时输入、外部状态与中间结果未必能重建。要分清可补的关联信息与已经消失的执行事实。

Langfuse 的客服案例用一条演示 trace 展示了层次:draft-support-reply 总耗时 3.1 秒,包含两个 retriever、一个 tool 和一个 generation。演示中的检索类似工单、搜索帮助文章、取账户信息、草拟回复分别是 0.5、0.4、0.3、1.9 秒;生成节点标注 gpt-4.1、1.4k token、0.01 美元。官方页面明确说明这是概念示例,这些不是公开披露的真实生产性能,也不是成本报价。

其中 draft-support-reply 是名称,不是唯一 ID;account-changes 是示例任务类别,也不能当作某条 dataset item 的唯一标识。这两个区别看起来细,却正好影响“能不能把结果写回正确对象”。

同样,步骤有树形归属,不代表因果关系已经被证明。你看到检索结果缺少目标文档、生成回答又引用了错误政策,可以形成一个有依据的故障假设;要确认修复有效,仍需复现、补充检查或实验。树告诉你发生了什么以及归属关系,时间告诉你先后,输入输出帮助解释依赖,三者共同支持排查。

“推理内容”也要按接口实际提供的范围理解。可以保留供应商返回的推理摘要、可见决策信息和工具选择,但不要声称能拿到模型完整内部思考。OpenAI 官方说明其持久化推理不暴露原始推理,摘要与隐藏的推理 token 是不同对象。Reasoning models

服务一多,身份贯通比再加标签更急

一次账户诊断如果经过应用服务、检索服务和工具服务,各服务都留下了日志,却各自新建执行身份,调查者仍可能拼不回一次请求。新增“部门”“渠道”这样的标签补不了断掉的关联。

跨服务观测要保留共同 trace 上下文,并给各服务自己的步骤使用独立 span 身份与正确父子关联。服务名称、版本、边界事件也应能查询。这里不是要求所有节点共用同一个 ID:共享的是同一次 trace 的关联,各节点仍需自己的 span ID。

OpenTelemetry 的 trace 概念文档给出了同一 trace ID、不同 span ID 与父节点关联的示例,说明一个请求如何跨进程、服务形成端到端视图。日志本身也可以有 TraceId、SpanId 与结构化属性。因此不能把“日志”简单定义成平面文本,或断言日志天然不支持关联。Traces;Logs

如果跨服务无法形成同一棵完整树,明确关联或链接也比静默断裂好。读者应知道哪一段没有证据,避免把“查不到失败”误读为“没有失败”。

工具返回“成功”与目标状态已变化,也要分开。涉及写入、发送、修改配置的动作,需要目标系统的回执、审计事件或必要的状态回读。证据独立于模型自述即可,不要求一定另买一个“系统外部”的观测平台。回执表明请求被受理,回读可能证明结果已持久化,它们的证明范围也应注明。

最后核对采样和隐私:数据没收全,不等于不能用

采样改变覆盖范围,未必自动把比率变成有偏的数。等概率随机采样可以估计总体比率,但会增加不确定性;如果优先保留错误或投诉记录,样本里的失败率就不能未经校正代表总体。

高频稳定链路可以用抽样控制成本。低频高价值任务、新上线能力、排障与投诉复盘,通常更需要完整留证;这是一项风险与成本的取舍,不能只给它们盖上“绝对不可采样”的章。即便业务决定采用定向采样,也要记录覆盖策略、适用窗口、样本来源和已知盲区。

把异常样本用于错误分析,把具有明确抽样机制的样本用于估计发生率,两个用途可以并存。失败分类体系告诉你出现了哪些问题,发生率则要求合适的分母和代表性。只读最差案例,能发现修复线索,不能直接得出“整体都很差”。

采集边界还受隐私要求约束。明文邮箱、手机号和详细对话可能方便追踪,也会增加暴露面。先确定调查目的,能用租户、账户、脱敏标识、地区分档或是否命中敏感内容解决的问题,就不需要为了“将来可能有用”再收更细的信息。

粗化也不是无代价:删掉所有身份关联,可能无法识别同一客户重复求助;只留“含敏感信息”一个布尔字段,可能无法检查是否误报。最小化采集与分析能力需要具体取舍,不能声称二者永远没有冲突。敏感信息是否可以保留、保存多久、谁可访问,应依业务目的与适用要求决定,不能从“高基数”直接推出法律结论。

WildFeedback 论文并非没有脱敏方案。其附录介绍 WildChat 使用 Presidio、SpaCy 命名实体识别和自定义规则去除个人可识别信息,并处理 IP 信息。这说明公开数据也要核对实际处理范围;已有脱敏措施,不代表不存在再识别或残余隐私风险。

访问敏感记录的权限与审计、输出中的泄漏检查,是另外的验收项。客服示例中的 data_leak 和 out_of_scope_help 从第一天就存在,针对已经发送的回复做标记,以便团队跟进;示例里的安排不是通用的发送前拦截保证。即使检查从未触发,也只能说“在已覆盖记录与当前检测能力下未检出”,不能由此断言从未发生。

回到两个团队的表格,值得一起保存的并不只是一个终于一致的百分比。应当留下它的统计对象、五项口径、未知和待观察状态,以及一次能回到原始记录的复核路径。

当客户再次投诉时,团队可以先判断这是新出现的失败类型,还是已有类型在某类任务里增加;再找到具体执行,检查输入、版本与目标状态。如果指标变动无法引出这些行动,继续增加字段未必有帮助,先改写要回答的问题。

资料与核查说明

主要框架依据 Langfuse Academy 的错误分析、数据集设计、客服示例、指标选择及trace 设计建议。本文的五项口径和信息分层是为产品分析组织的工作方法,不是官方标准或因果证明。

反馈数字分别来自 RLUF(2025)、SPUR(ACL 2024)、WildFeedback(ACL 2026)和 Marlin 等的 UAI 2007 论文。不同产品、统计单元和标签方法的比例不应横向直接比较。

原素材还引用 Amazon NLU 研究中的 14.3%→39.0%。原论文表 2比较生产缺陷样本与 DIM 筛出的目标缺陷样本中 NLU 错误的占比。它说明筛选会改变样本构成,不是“同一批样本只换个公式”,也不是总体质量提升了 24.7 个百分点。这组数字适合用于检查抽样与分母,不宜替代当前产品的结果证据。

本文开头的团队争议、12%口径例子与十轮对话演算均为假设示例;投放场景是业务类比,不代表作者或某家公司已有这样的线上结果。