ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

LLM应用质量治理:基于Dify的会话复盘工作流

LLM应用质量治理:基于Dify的会话复盘工作流 那段时间我一直在盯一个客服Agent的线上表现。数据看板是绿的响应时长正常token消耗平稳报错率几乎为零可业务方还是天天来找我用户明明已经把问题说得很清楚了Agent绕了一大圈最后给了一个听着没毛病但完全不解决实际问题的答案。这种问题实时监控根本看不见只有事后把对话记录一条条翻出来才能意识到哦原来刚才那句话坏在这里。我当时就想能不能让AI自己去做这个事后回顾把这种靠人翻聊天记录才能得出来的后见之明变成一个自动化的复盘流水线这就是hindsight这个项目的由来。我基于Dify搭了一套复盘工作流把主应用跑完的会话记录定期收回来用LLM按维度评析最后产出一份可以直接指导优化动作的会话复盘报告。这篇文章就是把我在Dify上落地hindsight的完整思路、实现细节和踩坑记录写出来给做LLM应用质量治理的同学做个参考。1. 为什么AI应用最缺的不是监控而是事后复盘先说一个我自己的判断大部分LLM应用团队质量建设都集中在两个阶段——上线前的评测和上线后的监控。但这两个阶段之间存在一个巨大的空档恰恰是AI应用事故最常发生的地方。上线前评测用的是你精心构造的测试集。你当然会把常见问题、边界case、刁钻prompt都放进去但测试集永远覆盖不了真实用户的多轮对话。真实会话里会出现用户误解、情绪化表达、中途改主意、上下文漂移甚至用户自己对需求都没想清楚的情况。这些在评测阶段几乎不可能暴露。线上监控呢通常只能告诉你这通对话花了多少token调了几次工具有没有报超时错误。监控强调的是可量化的异常但LLM应用最致命的错误往往是语义层面的——回答态度很好、结构也很完整、措辞也很礼貌就是答非所问。这种质量问题监控系统的阈值无论怎么调都试不出来。所以我越来越觉得AI应用真正缺的是第三个阶段事后复盘。把已经跑完的对话重新过一遍用另一组更强的模型、更从容的上下文视角去审视当时的每一个回答到底合不合理。这就像打球时的录像回放——比赛已经结束了但你看回放能判断出哪个球处理得不够好。hindsight这个名字就是从这个想法来的。英文hindsight直译是后见之明说的是事后回头看的能力。人很容易在事后看清当时的失误但AI应用不会自动这么做。我想做的就是给每个Dify应用配一个自动化的事后之眼让复盘成为应用流水线上一个正式环节。我在设计hindsight时一开始纠结过为什么不用现有的可观测性平台后来想明白了可观测性平台解决的是系统出了什么故障hindsight要解决的是这轮对话为什么没帮到用户。前者看的是服务指标后者看的是语义质量完全是两套东西。对AI应用来说一个用户带着问题来带着问题走这在监控面板上一切正常但放在hindsight眼里这就是一次必须立案的事故。2. hindsight的落地形态在Dify里搭一个复盘子工作流有了想法之后第一个问题就是hindsight到底应该长什么样是一套独立服务还是嵌入Dify的插件我最终选择的是在Dify里搭一个单独的复盘工作流和主应用解耦通过数据接口接收会话记录。这样改动最小主应用完全不用动复盘逻辑也可以独立迭代。2.1 为什么不用插件而用独立工作流Dify本身支持插件机制可以做服务端化的扩展。但我评估了一下复盘场景和普通的插件触发逻辑不太匹配。插件通常是应用运行到某个节点时被调用而复盘是一个会话结束后基于整段会话做回顾。会话都没结束插件根本拿不到完整上下文。另外复盘工作流既需要处理批量会话数据又需要跑多轮LLM评析如果把这种重逻辑塞进主应用里会直接影响线上请求的响应时间。所以我把hindsight设计成一个独立工作流定时或手动触发从主应用拉会话记录跑完复盘后把结果写回数据库。主应用全程无感。2.2 完整的工作流结构我在Dify里搭建的hindsight工作流大致分成四段数据接入段从Dify日志接口或数据库里拉取指定时间范围的会话记录清洗成统一的复盘格式。每条记录包含用户输入序列、Agent输出序列、中间检索结果摘要、工具调用记录。预筛选段先用规则把明显没问题的会话过滤掉比如用户单轮提问、Agent一次作答、用户没有追问、时长低于阈值。这类会话占比通常很高直接进LLM评析纯属浪费token。评析段把筛选后的会话按维度拆分每个维度用独立的LLM评析器打分。这是hindsight的核心我后面单独展开讲。结果落库段把各维度的打分、证据引用、改进建议统一成JSON写回复盘结果表同时生成一份人类可读的复盘报告。这个结构最让我满意的一点是预筛选这道闸门。一开始我没做预筛选所有会话都送进LLM评析一天的对话量大约是三千通按四个维度各评一次每天光评析就要花掉上百万token。加上这个预筛选闸门之后真正进入评析段的会话量减少了六成以上成本曲线一下就平缓了。2.3 数据接入的几个细节坑会话记录从主应用那边导出来的时候格式远比你想象的脏。多轮对话里经常出现空字段、用户消息被截断、工具调用参数过长的现象。我做了几个清洗动作踩过的坑值得说下。一是统一消息角色。Dify日志里用户消息和Agent消息都带不同的附加字段如果不做归一化评析器识别角色时容易出错。我把所有消息统一成包含role、content、timestamp、metadata四个字段的结构。二是截断策略。长会话不能简单从中间切断否则会把用户的关键意图拦腰截断。我的做法是先用关键词和意图分类器把会话切成若干段落每个段落单独作为评析单元。如果一个会话有多个明显阶段比如用户先问A问题解决后又问B问题就按阶段拆开评析比整段塞给评析器效果更好。三是中间步骤摘要。主应用里的RAG检索结果、工具调用返回很多时候占了原始日志的很大体积。评析器并不需要看完整的检索原文只需要知道检索了哪些知识点相关性打分多少最终采纳了哪个文档。我会在数据接入段把中间步骤压缩成摘要字段避免评析器被无关信息干扰。3. 复盘维度的设计与评析器提示词这是hindsight的重头戏评析工作流搭起来之后真正决定复盘质量的是维度设计和提示词写法。我前前后后改了很多版直接把当前在用的方案放出来。3.1 五个复盘维度的取舍我一开始列了十几维后来收敛到五个意图对齐度、知识命中率、确定性边界、会话效率、表达可用性。维度要回答的问题典型扣分场景评析依据意图对齐度Agent最终有没有解决用户最初的问题用户问AAgent答了B用户追问不是这个意思后Agent才纠正整段会话的语义轨迹知识命中率回答是否基于可靠信息RAG检索结果为零Agent仍然编造了一个具体数据检索摘要 回答引用确定性边界Agent是否清楚自己不知道什么信息不足时强行给结论或反过来明明有能力却频繁说我不能确定回答中的确定性措辞会话效率用了多少轮才达到目标用户问同一个问题三次每次Agent都给不同答案轮数 重复问题检测表达可用性回答格式、语气、结构是否便于用户吸收全是长段落没有分点专业术语没有解释语气生硬最终回答文本这五个维度里意图对齐度最容易评也最能反映核心体验。我先让它跑后来发现光有意图对齐不够有些会话用户的问题被解决了但Agent明明是在信息不足的情况下瞎蒙对的。所以又把确定性边界加进来。知识命中率则专门用来盯RAG类应用如果你做的是纯对话应用这个维度可以换成知识覆盖度。不建议一开始就上太多维度。评析器这东西维度越多每个维度的关注力就越分散评出来的分反而不准。我实测下来的经验是先跑两三个核心维度等复盘结论和人工判断基本一致了再逐步加维度。3.2 评析器的三段式Prompt骨架每个维度我都写了一个独立的评析器节点。Prompt结构统一为三段任务定义、输入材料、输出格式。以确定性边界维度为例Prompt大致长这样你是一个会话质量评析器负责评估确定性边界维度。 任务定义 针对输入的会话记录判断Agent是否在信息不足时强行给出确定结论 或者是否在具备回答能力时过度回避。注意区分合理拒绝与回避问题。 输入材料 1. 会话原文按角色分隔 2. 中间检索结果摘要若为空说明Agent未进行检索 3. Agent最终回答 评析要求 - 如果会话中Agent明确说信息不足/无法确定并给出用户可行的下一步路径不应扣分。 - 如果会话中Agent未提供任何依据却断言某个精确数字或事实必须扣分。 - 每条评分必须附具体证据不允许只给分数不给原因。 输出格式 {score: 1-5的整数, evidence: 一句话证据, suggestion: 可执行的改进建议}这里最关键的技巧是提供三段式输入材料。我最初的版本只传会话原文结果评析器经常把Agent正确拒绝回答这种情况误判成能力不足。后来加上中间检索结果摘要评析器就能判断不回答到底是基于检索后的合理判断还是根本没去查。这个改动让确定性边界维度的准确率提高了约三成。还有个小细节评分标准要写不应扣分和必须扣分这类句子而不是只写请按5分制评分。LLM对评分的理解高度依赖对锚点行为的描述。你要给出具体的、可对照的行为样例否则它会把大多数会话都评成4分。3.3 为什么把评析写成按维度拆分而不是一个大Prompt这里我要单独说一下设计原因。最初我图省事写了一个全会话质量评析器一个Prompt里同时要求评意图、评知识、评效率、评表达。测试集上看起来还行一上真实数据就露馅了。问题是这样的一个Prompt里任务太多模型会倾向于把分数往中间靠拢各方面都说得过去哪方面都不突出。而且一旦中间某个评析点触发了歧义会影响整份报告的质量比如知识命中率评出差分模型为了保持一致性会顺手把表达可用性也压低。按维度拆成独立评析器之后每个评析器只需要专注一件事上下文窗口更干净评分标准更聚焦输出也更稳定。代价是调用次数变多了但Dify工作流的并行节点可以同时跑多个评析器延迟并没有翻倍。实测单个会话的评析耗时在3到5秒左右完全可以接受。拆成独立评析器还有个好处你可以对某一个维度单独迭代。比如知识命中率总评不准你只需要改这一个评析器的Prompt其他维度完全不受影响。如果是大Prompt模式改一个地方就得全量回归迭代成本高很多。3.4 输出结构统一成JSON的意义我让所有评析器都输出JSON结构而且字段名完全一致。为什么要坚持JSON因为复盘结果不只给人看还要落库、聚合、做趋势分析。比如我想查昨天所有涉及知识命中率投诉的会话如果评析结论全是自然语言段落查都没法查。JSON化之后score字段可以直接做排序evidence字段可以作为badcase证据suggestion字段可以作为优化任务描述一套数据三处复用。Dify里对接这一步我用了结构化输出的功能直接在节点配置里声明输出schema省去了解析自然语言回包的痛苦。你如果用别的编排平台记得让评析器输出严格JSON别嫌麻烦。4. 跑真实会话时踩过的坑和处理方法hindsight上线跑了一个多月评析结论从偶尔靠谱到基本可信之间我踩了不少坑。选四个最典型的说清楚能帮你少走弯路。4.1 复盘者的幻觉评析器会脑补会话里不存在的内容第一个大坑是评析器自己会产生幻觉。我不知道大家有没有遇到过这种情况评析器对一个会话打出了Agent在回答中提及XX数据的结论但你翻原始会话Agent根本没提过这个数据。原因不复杂。LLM评析器读完整段会话之后会把多个来源的信息混在一起包括来自知识库检索摘要的片段、用户介绍的背景信息、甚至它自己预训练时见过的知识然后误认为这些都是Agent的回答内容。处理办法是强制评析器只依据会话原文作答同时在提示词里明确警告原文中没有出现的信息视为不存在。我还加了一步后置校验——让评析器在evidence字段里必须引用原文片段否则这条评分直接判为无效。效果很明显幻觉类误判基本上被拦住了。4.2 提示词自证偏差你越暗示找问题它越能找到问题这个坑我觉得是最隐蔽的。一开始我的提示词里写了很多请重点关注Agent是否出现错误回答如果用户表达不满请扣分之类的话本意是让评析器更敏锐。结果测试集评分偏高偏低波动很大后来看了几条具体case才发现评析器被我的找问题暗示带偏了把一些本来正确的回答也扣了分。我管这个叫提示词自证偏差。评析器本来就倾向于寻找你描述的特征你越是详细描述问题长什么样它越会把中性内容往问题方向靠。修正方法是把提示词改成中性引导先定义正常行为的表现再定义扣分行为的表现两边权重对等。这样评析器不会单方向寻找异常。还有一个技巧是给评析器一个免责出口允许它输出4分或5分并且在Prompt里明确说如果会话一切正常请大胆给高分。这条看似没用实际极大改善了评分分布分数不再挤在2到3分之间。4.3 成本控制全量评析谁都跑不起我们线上的会话量不算大但全量评析依然让我在第一个月的云账单上吃了一惊。四个维度评析器加上主应用的token消耗成本翻了接近一倍。当时我意识到复盘工作流不能像监控一样全量开。后来我做了两级降本第一级是规则预筛。刚才提过大约六成会话在预筛选阶段就被过滤掉了。剩下的四成里再用几条硬规则二次过滤有用户明显负面反馈的、Agent回答长度异常的、用户重复提问的、会话轮次超过五轮的这类会话优先评析。第二级是采样评析。如果某类会话的数量实在太大比如同一时段的大量同质化咨询我会按比例采样百分之十到二十做评析。为什么敢于采样因为复盘要的是发现共性问题的不是追求精确统计。同质化会话里抽十分之一就够定位问题了。这两招用下来hindsight的评析成本控制在整体应用成本的百分之十二以内收益远大于支出。4.4 长会话的上下文截断问题还有一个细节坑多轮长会话动不动就超过评析器的上下文窗口。一开始我直接把中间部分截断只留开头和结尾结果评析器经常漏掉关键转折——比如用户和Agent在第五轮达成了一致但第八轮用户突然质疑如果不看第五轮上下文根本不知道为什么用户会质疑。解决方法是把会话按意图段切分。我用了一个轻量的分类器识别用户消息背后的意图变化当用户的新消息和上一条意图不一致时就认为开启了新阶段。每个阶段作为一个独立评析单元评析结果再汇总到会话级报告。这样既不会丢关键上下文又能保证评析单元长度可控。切分之后多轮会话的评析准确度提升很明显。我强烈建议不要对长会话做粗暴截断宁可多调几次评析器也不要让模型在残缺信息下做判断。5. 复盘结果的消费方式让hindsight的结论真正变成改进动作评析报告如果只是躺在数据库里那这个项目就只做了一半。hindsight真正的价值在于把后见之明转化为下一步动作。我目前主要用复盘结果做四件事。第一件事是自动生成badcase清单。我定义了一个规则意图对齐度低于3分、或者确定性边界为1分的会话自动进入badcase池。这些case会按证据字段汇总成表格每周发给标注同学做二次确认。确认后的badcase用于微调训练集和评测集。这样做的效果比人工翻聊天记录找badcase快了一个数量级。第二件事是联动知识库补全。当知识命中率维度出现连续扣分时我会看检索摘要里是否出现了低相关度文档如果是就把这个缺失主题自动记录到知识库补全任务里。知识库管理员只需要照着清单去补文档不用再一遍遍问到底缺什么知识。第三件事是生成质量热力图。我把评析结果按小时和时间维度聚合能直接看到哪个时段、哪类问题高发。比如我们发现每天上午十点到十一点的会话量最大同时意图对齐度明显低于其他时段因为这个时段用户涌进来Agent的预处理队列压力大回答经常串线。没有评析数据这种趋势根本看不出来。第四件事是做Agent策略对比。我们同时上线了几个不同Prompt版本的主应用hindsight的评析结果可以直接作为版本对比的参考。哪个版本的确定性边界得分高哪个版本的会话效率得分低数据一拉就能看到。这比依赖A/B测试指标快得多因为A/B测试通常只看转化率看不见语义质量差异。现在hindsight已经是我们质量运营流程里一个常规环节每周一自动生成上周的复盘报告质量团队和算法团队各取所需。我个人的体会是做LLM应用不能只关注模型能力这一个变量应用上线后的持续反馈回路同样关键。hindsight本质上就是用另一个模型去审视当前模型的输出形成一个自动化的质量反馈环。最后分享一个我最近在琢磨的小扩展方向把复盘的评析结果和用户后续行为关联起来。比如某个会话被评析器打了低分那这位用户三天内的留存和回归率会不会有显著差异如果这个关联能验证那hindsight的评分就不只是质量指标还能当作用户体验的代理指标。目前我还在收集数据阶段等跑出结果再单独写一篇。
返回列表