用Dify搭建LLM复盘工作流:让AI告别事后偏差
你有没有过这样的经历项目上线一周后出了故障复盘会上大家七嘴八舌——“其实当时评审就该拦住”“我早说那个接口设计有问题”“数据校验就是少了这一步”。会议室里充满了事后才显得无比正确的判断但下一个迭代类似的坑照样踩。这种感觉的关键词就是 hindsight事后才看明白。心理学里有个对应的词叫 hindsight bias事后偏差结果一旦确定人就倾向于相信自己早就预料到了。这一偏差不纠正所有复盘都只是集体表演。我最近做了一个叫 hindsight 的小项目目标是让大模型帮我把“事后聪明”改造成“事前雷达”记录事件、还原事实、区分“当时能知道的”和“事后才明白的”最终输出一份不掺马后炮的分析报告。整个项目跑在 Dify 上用它来编排工作流、管理提示词、接模型。这篇文章会把项目的完整思路、工作流搭建过程、中间踩过的坑以及几处我认为最关键的设计点全部写出来。想自己复刻一套复盘分析工具的人或者对 Dify 搭建 LLM 应用感兴趣的人都能从里面找到可直接照抄的部分。项目本身不大但思路值得慢慢盘。1. 复盘这件事为什么总变成一场集体表演先别急着上工具。我花了大半个月确认了一件事绝大多数团队的复盘流程失败的原因根本不在“工具不好用”或“大家不积极”而在一个更底层的认知问题——我们都在用后见之明审视过去。1.1 会议室里的“事后诸葛亮”我做这个项目之前观察过七八个团队的真实复盘场景。几乎每个会议都遵循同一个剧本事故发生了时间线贴出来有人开始问“当时为什么没发现”然后最有经验的那个人开始回忆“其实我早就觉得这里有问题”。这句“我早就觉得”非常典型但大多时候它是记忆重构出来的假象。心理学实验早就证明在结果公布之后再让人复盘当初的判断人的记忆会悄悄把自己往“猜对了”的方向修正。这不是道德问题是认知机制本身就是这样运行的。这也解释了为什么复盘记录容易变成两堆垃圾一堆是情绪化的指责“谁谁谁当时不上心”另一堆是毫无可操作性的口号“以后要加强测试”“要提高安全意识”。前者制造对立后者制造疲劳。日子久了大家就学会了在复盘会上如何安全地附和会议变成仪式文档变成存档问题原地踏步。1.2 为什么“写总结”救不了团队很多人以为复盘做得差是因为形式不对于是今天用 KPT明天换成 4L后天又开始写 AAR。这个方法换成那个方法最后还是没效果。我的判断是问题不在方法名称而在三个结构性缺陷。第一记忆失真。复盘依赖人脑回忆而人脑的记忆是会篡改的。大多数人不会提前记录决策时的信息环境只能靠事后倒推。倒推出来的“原因”天然带着结果的光芒。第二把相关当因果。事情发生后所有在当时发生过的事实都摆在眼前人很容易挑出几个“看起来和结果有关”的编一条自洽的故事线。这个故事线通常不是完整因果链只是最省力的叙事。第三行动建议没有约束条件。复盘常见的产出是“要增加自动化测试”“要补充监控指标”但没有负责人、没有触发条件、没有验证方式三个月后谁都不记得甚至当时写下这条的人自己都忘了它是为什么而写。1.3 复盘的真正痛点信息不对称我把这些现象归结成一个词信息不对称。复盘时人心里有两套信息——一套是事件发生时真实可得的一套是结果公布后才获得的。真正有价值的复盘是搞清楚“当时的信息环境到底支持做什么判断”而不是“现在回头看应该怎么做”。我当时就跟自己说如果一个工具能强制把这两套信息分开让团队在复盘时只能基于“当时可得信息”下结论这件事就成了一半。hindsight 这个名字一开始就是冲这个念头去的。2. hindsight 的核心思路把“事后聪明”改造成“事前雷达”想清楚痛点之后我开始设计这个系统的核心逻辑。它不是一个简单的“把事件描述丢给大模型让它总结几点教训”的工具——那种工具我试过输出的东西跟会议室里大家喊的口号没什么区别。2.1 一个关键的划分事实和判断必须分离整个项目最核心的设计决策是把“事实”和“判断”强行分成两道工序。事实是什么是可以被时间戳、人名、具体操作验证的信息“15:02 支付服务返回超时”“发布单在 18:40 通过审核”“A 同学在评审会上提出过缓存穿透风险未形成决议”。判断是什么是推测、情绪、归因“因为并发太高导致超时”“早就该加熔断”“负责人不够重视”。绝大多数复盘问题就出在第一步——事实还没理清所有人就开始甩判断。所以 hindsight 的第一道工序是“事实还原”这一步只允许产出清单不允许产出任何评价。我甚至在提示词里写死规则这一轮你如果给出了归因或评价整份输出作废。2.2 三层次分析模型事实还原、归因分析、行动生成我参照了事后复盘领域常用的结构把分析流程固定为三个层次每一层有独立的模型调用层与层之间只传递结构化数据不传递废话。第一层是事实还原层输入是用户填写的原始事件描述输出是三类清单已确认事实、存疑信息、信息缺口。第二层是归因分析层输入是第一层的清单输出是多维度归因并且每条归因必须标注“该信息在事件发生时是否可得”。第三层是行动生成层输入是第二层的结果输出是带有负责人、触发条件、验证方式的行动条目并且明确忽略所有“不可预判”的归因。这三层不是一次性扔给大模型让它一次生成而是拆成三次调用。原因很简单大模型一次做三件事时中间的推理过程是不可控的它可能在归因阶段就把事实加工歪了。拆开之后每一层都只做一个动作结果稳定得多。2.3 决策日志对抗事后偏差的入场券如果只靠事后输入系统再怎么设计也逃不过信息失真因为它唯一的语料来源就是事后回忆。所以我加了第二个关键设计决策日志。具体做法是在 Dify 里建了一个最简单的知识库专门存放团队或个人的“事前预判”记录。格式非常朴素一个表单包含时间、事件背景、你的判断、信心值1-5。每次开工之前、每次发版之前、每次做重要方案之前花两分钟填一条。存进去的时候不需要任何整理就是原话。复盘时hindsight 会把事件发生前的决策日志作为参考材料喂给归因分析层。模型拿“当时实际想的”来对比“事后复盘说的”如果两者偏差太大输出里会显式标注出来。这个设计的目的不是抓谁撒谎而是让所有人看见我们的记忆在多大程度上被结果扭曲了。数据一旦摆在台面上集体表演就很难继续了。2.4 系统整体结构hindsight 最终跑通的形态是一个典型的 Dify 工作流外加一个用于检索的知识库和几段固化好的提示词。用户输入入口是一个结构化的表单而不是一个自由文本框——这一点非常关键后面我会单独解释。表单字段包括事件标题、发生时间、事件描述、已知影响、当时的决策日志关联 ID、参与角色。提交后工作流自动执行三层分析最后输出一份 Markdown 格式的复盘报告可以直接复制进团队的文档系统。从技术实现难度来说这个项目没有任何炫技成分没有微调模型没有 RAG 之外的检索技巧更没有什么复杂算法。它真正的价值全在流程约束和提示词设计上。而这恰恰是大多数做“AI 复盘助手”的人忽略的部分。3. 用 Dify 搭建 hindsight工作流设计与关键节点实现Dify 是这两年很火的开源 LLM 应用开发平台你可以把它理解成一个可视化的工作流画布把模型调用、知识检索、条件分支、变量处理串成一条流水线不需要写太多后端代码。选它而不是直接用 Python 调 API原因很实际迭代提示词方便团队里不懂代码的人也能参与调整而且输出模板、知识库这些基础能力开箱即用。3.1 工作流节点逐个拆解我的工作流一共六个节点按顺序串起来。先说清楚这不是 Dify 官方文档式教程我不讲每个按钮在哪只讲每个节点在这个项目里承担什么职责、以及我踩过的坑。第一个节点是开始节点也就是输入表单。我在上面定义了六个输入变量event_title、event_time、event_desc、impact、decision_log_ref、roles。如果让我重做一遍我依然会坚持用结构化字段而不是一个巨大的 textarea。原因是我测试过自由文本框里用户往往会写一大段情绪化叙事模型很容易被叙事带偏。当你强制他分字段填写他反而会稍微收敛一点描述也更接近事实。第二个节点是知识检索节点在 Dify 里叫知识库。我挂了一个名为“hindsight-memory”的知识库里面存的是历史复盘报告和历史决策日志。这里有一个很实用的配置检索模式选“向量检索”top_k 设为 3。不需要更多复盘相似案例有个三五条就够参考多了反而干扰分析。第三个节点是第一个 LLM 节点“事实还原”。这里我绕过了一个大坑——千万不能把知识检索的结果和用户输入直接塞进同一个提示词。检索出来的历史案例属于“参考信息”用户输入属于“待分析对象”两者一旦混在一起模型常常会把历史案例里的事件当成当前事件来分析。我在提示词里用分隔符强制区分效果立刻稳定了。第四个节点是第二个 LLM 节点“归因分析”。它的输入是第一个 LLM 节点的结构化输出加上从知识库检索到的事件发生前的决策日志如果有的话。这个节点我专门配置了一个低温度temperature 设 0.2。原因后面会细说。第五个节点是第三个 LLM 节点“行动生成”。输入是归因分析输出输出是行动清单。这里我设计了一个硬性过滤规则归因中被标注为“不可预判”的条目直接不进入行动生成环节。宁可少给建议也不给假建议。第六个节点是模板转换和结束节点。我让所有 LLM 节点输出 JSON 格式的数据然后在模板节点里拼接成带标题、表格、复选框的 Markdown 报告。JSON 的好处是后续如果要接别的系统可以直接机器读。3.2 三层提示词的写法这三段提示词是整个项目的心血我直接贴出来你可以拿去改。事实还原层提示词你是一名复盘分析师。下面是一段事件描述由当事人提交。 你的任务只有一个把事实和判断/情绪强制分离。 事实的定义拥有时间戳、人名、系统名、可验证的具体操作。 判断的定义推测、情绪、指责、马后炮包含应该早就本来等词。 输出格式JSON { confirmed_facts: [事实1, 事实2], disputed_items: [需要进一步确认的表述], info_gaps: [目前缺失的关键信息] } 硬性规则 1. 不要解释不要铺垫。 2. 不要把当事人的主观结论当成事实收录。 3. 对每一条事实必须附带(时间:xxx, 来源:xxx)。 4. 如果你认为无法区分请放入 disputed_items。归因分析层提示词你是一名风险管理专家。下面是经过事实还原的事件事实清单以及事件发生前团队的决策日志如果存在。 你的任务基于这些材料给出多维度归因分析。 约束 1. 禁止使用应该早就本来明显等事后语言。 2. 对每条归因必须标注当时信息可得性available当时能获得/ unavailable当时无法获得。 3. 区分系统根因和流程根因两个维度。 4. 若某归因无法获得当时证据支撑请评估依据强度strong / medium / weak。 输出格式JSON { root_causes: [ {dim: system|process, cause: ..., evidence: ..., info_available: true/false, evidence_strength: strong|medium|weak} ], hindsight_notes: [指出两个明显的后见之明表述并解释为什么它们在当时不可得] }行动生成层提示词根据以下归因分析结果生成可执行的改进行动清单。 规则 1. 只针对 info_availabletrue 的归因生成行动。 2. 每条行动必须包含action做什么、owner角色而非人名、trigger什么情况下触发、verification怎么验证做完了且有效。 3. 禁止生成加强意识提高警惕加强测试这类空话。 4. 如果一条归因有 medium/weak 的证据必须在行动中附带一个验证性任务而不是直接改造。 输出格式JSON { actions: [ {action: ..., owner: ..., trigger: ..., verification: ...} ], ignored_causes: [列出因当时不可得而忽略的归因] }三段提示词有一条共同原则每一层都只做一件事并且每一层都用 JSON 把输出锁死。你问我要哪一段最重要我会说归因层那两条规则最重要——禁止事后语言和标注信息可得性这两条直接决定了输出不是马后炮。3.3 参数配置与输出模板模型选择上我默认用 gpt-4o-mini 这一个档位足够用成本也低。三个 LLM 节点我用同一套模型但温度不同事实还原层 0.1归因分析层 0.2行动生成层 0.4。温度不能倒过来理由很简单——事实还原和归因是基础越稳定越好最后生成行动时可以稍微放开一点让表达更自然。输出模板我在 Dify 的模板节点里拼了一个 Markdown 报告结构如下事件概览、事实还原结果含疑点和信息缺口、决策日志对比、归因分析表含可得性标注、行动清单复选框形式、被忽略的归因。复制到飞书或 Notion 后复选框能直接勾选行动项就可以当任务管理用不用二次加工。4. 最难的一环让 AI 输出不带“后见之明”的分析如果你照着上面的工作流搭完跑几个测试案例大概率会发现一个尴尬的问题模型输出的分析跟传统复盘的废话其实差不太多。这不是你配置错了而是因为大模型同样深受“后见之明”困扰。4.1 大模型天然倾向“事后诸葛”大模型训练数据的特征决定了它天生就是事后视角——它看到的是已经发生了的、带答案的案例。你给它一段事故描述问它“原因是什么”它给出的答案天然站在上帝视角因为它知道最终结果。最典型的体现就是输出里出现“果然”“这就解释了为什么”“显然是因为”。我最早用单次调用写过一个版本让模型直接读完整事件描述、直接产出归因。结果 10 个测试案例里有 7 个输出都带着一种已被剧透的视角。这个问题的本质是你只给了它结果没给它还原到事件发生时刻的“信息状态”。所以对策也很清晰要在提示词层面强制模型做“视角切换”并明确禁止它使用结果信息来倒推过程。4.2 用“事前预判”提示词反向约束最有效的办法就是我在 2.3 里提到的决策日志。模型在归因分析时如果能拿到事件发生前团队写的“我当时判断是 X信心 3 分”它就有了参照系能够对比“事前预期”和“事后现实”的差距。配合决策日志我在归因提示词里加了一个强制动作要求模型必须输出 hindsight_notes 字段把明显的事后判断挑出来点名。比如用户复盘写“当时就应该看到监控曲线异常”模型会标注该监控曲线在第 20 分钟才出现明显拐点而系统报警延迟正是待查根因因此这一判断在当时不可得。这个字段的效果惊人——它把模糊的“我们该早点发现”变成了一条具体的、关于信息时间线的分析。4.3 反事实约束与置信度校准除了视角切换我还在归因层做了两处细节加固。第一处叫反事实约束提示词里明确要求模型对每条归因追问“如果把这个信息从场景里拿掉结论还成立吗”。这一步在实际测试里能把不少虚假因果滤掉。举个例子有一次复盘把故障归因于“代码评审不认真”反事实问一下评审就算认真也会因为当时缺失一份接口文档而无法发现兼容性问题于是归因从“人不认真”转向“接口文档缺失”方向完全不同。第二处叫置信度校准。我让模型在证据不足时明说证据强度 weak而不是硬挤一个结论出来。这一点花了我很长时间才想通。以前我总希望 AI 给出确定答案后来发现复盘场景里敢于说“不确定”才是价值。weak 的归因不会被删掉但会单独进验证任务流程而不是直接变成行动。4.4 分析质量怎么评估你可能会问怎么知道这套设计真的有效我给自己的评估定了一个很朴素的指标抽查报告里所有行动条目问它“这条行动在事件发生前对应的信息是否可得”。可得性为否的条目越少说明马后炮越少。另一个辅助指标是“归因可执行率”。知识库里沉淀了一个季度的归因记录后发现没有决策日志的项目归因可执行率大概在 30% 左右有决策日志做参考的项目能到 65% 以上。虽然样本有限但方向很明显给模型的参照信息越接近“事发当时”输出越能落地。5. 上线两个月实测它能拦住什么又拦不住什么说这么多不如看一次真实输出。项目从一个内部工具变成我们小团队每周固定使用的流程已经跑了两个月。下面的案例我脱敏了细节但结构完整。5.1 一次真实的故障复盘输出事件背景一次线上服务超时恢复耗时 40 分钟。传统写法很容易变成“监控不到位报警太慢以后要加强监控”。hindsight 跑出来的报告有几个值得说的输出。事实还原层先干了一件事把“没有熔断机制”和“监控报警慢”拆开了。它敏锐地发现“没有熔断机制”作为一条事实本身没问题但事件发生时架构评审记录里显示有人 30 天前提议过熔断方案没有形成决议这条信息在事发时是可得信息。而“监控报警慢”则被标为存疑——监控阈值在事发当天上午刚被调整过调整时无人提交变更评审模型把这条列入了信息缺口。归因层的结论没有停在“缺熔断”这个表层而是指出更准确的流程根因是“阈值变更未走评审”因为如果走了评审变更影响就会被评估报警延迟问题在事发前就有机会被发现。这条归因的证据强度是 medium模型建议先做一次阈值变更记录审计来验证。行动层最后给出的三条行动分别是熔断方案在下一个发布窗口内进入技术方案评审触发器是“任何对接口超时时间或重试策略的变更”监控阈值变更必须绑定变更评审单触发器是“提交监控配置修改”对近 30 天所有监控阈值变更做一次审计验证方式是“输出变更清单并标注审批状态”。看完这份输出我最大的感受是它没有给出任何石破天惊的结论但它把“人云亦云”的复盘硬生生掰成了“可核验、可追踪”的流程记录。同一次事故以前复盘的结论是“加强监控”现在的结论是三件具体的事。5.2 踩坑记录模型顺着你说、上下文漂移、信息过载两个月里踩的坑不少最典型的有三个我一个个说。第一个坑是模型顺着用户说。用户在原描述里如果带了主观倾向“明显是缓存策略的问题”事实还原层的模型有时会不自觉地把这句话当成事实收录。我在 3.1 里说的分隔符方案解决了大部分但真正关键的一招是让事实还原层输出时强制附带来源标签“来源当事人描述”模型就不容易把“人说的”当成“发生过的”。第二个坑是长流程中的上下文漂移。Dify 工作流跑下来如果某个环节把整个聊天记录或者大段原文传给下一个节点很容易出现中间某一步的分析结论“漂”掉。我后来定了一条铁律节点之间只传结构化数据原始事件描述只进第一个节点后面环节一律不传。这样既省 token又控制漂移。第三个坑是信息过载。有段时间团队成员图省事把一整段聊天记录直接贴进事件描述。结果是模型抓到一堆无关细节输出又长又散。最后我在表单里加了字段长度限制并且加了必填的“影响范围”字段逼着提交人先自己把信息压缩一遍。这算是用流程设计对抗模型的注意力问题。5.3 我加的三处“人工闸门”纯自动化在复盘这种场景里是不可能的我加了三处人工闸门。第一处事实还原结果提交前需要事件当事人确认确认后才允许进入归因分析。第二处归因分析里每一条 availabletrue 的归因需要一位不直接相关的同事复核。第三处行动清单生成后由团队负责人做最后筛选决定哪些进排期。这三处闸门让系统永远处于“人定案AI 拟稿”的位置而不是反过来。在这个过程里有一句话让我印象很深。团队里有位同事第一次看报告时说“原来我当时不是没看到是信息根本没有到我这里。”这句话说得很朴素但恰恰是 hindsight 想解决的问题大多数“早知道”其实都是“事后才知道”。能把这两种“知道”区分开复盘才真正有它的价值。6. 想复刻这个项目的人我建议你先搞定这三件事如果你看完想自己搭一个类似的系统我在代码和配置层面能帮的都在上面了。但还有三件不在技术范围内的事我建议你在动手之前先想清楚。6.1 数据习惯比模型更重要技术方案再漂亮也抵不过没有数据。这个项目能不能转起来真正的前提是团队有没有记录决策日志、记录事件、使用工具的习惯。所以最开始不要追求完整流程只做两件事让每个人提交事件前花五分钟填字段、让负责人每周固定时间跑一次工作流。等这个习惯养成了再逐步加知识库和决策日志否则一上来就是空跑。6.2 提示词要在真实案例里磨我贴出来的三套提示词是经过一个季度迭代才成型的。第一次版本只有两层第二次加了“信息可得性”标注第三次才加了 hindsight_notes 字段。如果你直接拿去用一开始可能不稳定这很正常。我的建议是拿最近三个月真实发生的三四个案例去测看输出的行动清单里有没有空话、归因里有没有明显的事后语言然后针对性地在提示词里补约束规则。提示词工程不是写出来的是改出来的。6.3 期望管理它不是决策替代品把话说清楚hindsight 解决的是复盘过程中的信息失帧问题它不替你做判断不替你定责任更不会告诉你“如果重来一次该怎么做”。它的输出永远只是草稿需要人去认领、去复核、去决定是否执行。想拿它当自动决策工具的人会让团队陷入另一种形式的甩锅“AI 都提示过了你们还犯错”。最后再分享一点个人体会。我最初做这个项目是想“让 AI 帮我们复盘”做完之后才发现它真正改变的不是复盘效率而是大家对“知道”这件事的理解——知道不发生在结果之后知道是发生在行动之前的信息积累。每次看到报告里那句“该信息在事件发生时是否可得”的标注我都觉得这个概念比任何一份漂亮的复盘文档都重要。如果你也想做类似的事先从这个标注开始哪怕没有工作流没有 Dify只是每场复盘会上多问一句“当时我们到底能知道什么”就已经赢了大多数人。