"事后复盘"这件事,绝大多数人都是靠拍脑袋完成的。项目结束了,群聊散了,复盘文档写出来没人看,下次踩坑继续踩。我当初做hindsight这个基于 Dify 的复盘智能体,就是想解决这个真问题——让 AI 替你把零散的记录、聊天记录、临时笔记自动整理成有结构、能追溯、能指导后续动作的复盘内容。如果你在找 Dify 的实战项目参考,或者也想做一个"自己会思考"的复盘工具,这篇文章应该能给你一条完整的实现路径。
1. 项目整体设计与思路拆解
1.1 为什么选 Dify 而不是直接写代码
先说结论:这个项目从头到尾没有写过一行传统 Web 后端代码,核心逻辑全部跑在 Dify 的工作流编排和 Prompt 工程上。很多人一说到做 AI 应用,第一反应就是写 Python 调 API、自己维护会话状态、自己搭前端。但 hindsight 的目标根本不是做一个高并发 To C 产品,而是一个能快速落地、能持续调整逻辑、能让人人参与的复盘工具。Dify 恰好把最麻烦的三件事——上下文管理、多轮对话编排、可视化调试——全都抽象成了图形化界面。
选型的时候我也对比过 LangChain 自己搭一套,但最后放弃了。原因很直接:LangChain 在一个 ReAct Agent 里塞进太多抽象,出问题的时候你根本不知道是 Retriever 的问题还是 Memory 的问题。Dify 的工作流画布上,每一步节点都能单独调试,输入输出一眼就能看到,对于"给非技术同事做知识库复盘"这种场景要友好得多。hindsight 从一开始就不是给我自己用的,是要给团队里每个项目经理、运营、产品都能上手的工具。
1.2 hindsight 要解决的三个"事后问题"
hindsight 这个名字来源于英语里"in hindsight"这个表达——事后回头看。复盘的本质就是对已经发生的事做二次加工,但人工加工有几个难点:第一,信息碎片化严重,散落在聊天记录、会议纪要、飞书文档里;第二,复盘文档套话太多,"加强了沟通""提升了效率"这种话写了等于没写;第三,复盘的结论无法沉淀成下一次行动的依据。
hindsight 的设计目标就是针对这三个问题。它做的事情可以拆成三层:第一步是收集,把散乱的原始材料扔进应用,不管是一个 URL 还是一大段聊天记录;第二步是结构化提炼,AI 按固定模板输出"目标回顾、真实结果、根因分析、改进动作"四段式复盘;第三步是行动连接,把改进动作导出成可追踪任务,而不是一句空话。
1.3 整体架构和核心流程
整个应用基于 Dify 的 Chatflow(聊天流)搭建。输入侧用了一个带文件提取能力的入口节点,支持用户粘贴文本,也支持上传文档由系统自动抽取全文。中间的主干是三个大模型节点,分别承担"事实抽取"、"根因分析"、"行动建议"三个角色,而不是用一个巨大的 Prompt 把所有任务做完。最后接一个知识库检索节点,检索历史复盘记录,避免同一类问题在团队里反复犯。
这里我做了一个关键取舍:为什么不用一个 Agent 节点把所有推理一次跑完?因为"事实抽取"要的是忠实,不能瞎编;"根因分析"要的是发散,要敢推断;"行动建议"要的是具体,必须有责任人。三种不同的认知任务混合在一个 Prompt 里,互相干扰非常严重。拆开之后,每个节点各司其职,调试的时候也能精准定位是哪一步输出质量出了问题。
2. 核心模块拆解与提示词工程要点
2.1 事实抽取节点的 Prompt 设计
hindsight 里最重要的一个 Prompt 是事实抽取。我给它起名叫"不要发挥"节点。这个节点的任务只有一个:把用户输入里所有和"事件"有关的信息剥离出来,按照固定 Schema 输出。Schema 包括时间、参与方、目标、实际发生动作、外部条件、阻碍因素。输出必须是严格的 JSON,不允许解释,不允许补充背景,不允许"帮用户润色"。
实际操作时,我在系统提示词里写了这样一句硬性要求:只输出 JSON,不要输出任何与提取事实无关的话。如果输入内容里某个字段确实不存在,用 null 而不是编造。这句话看起来简单,但解决了绝大多数的幻觉问题。很多初学提示词的朋友喜欢把 Prompt 写得特别长特别细致,结果模型反而抓不住重点是哪里。事实抽取这个环节,我的经验是宁可简单粗暴,不要让模型有"自由发挥"的余地。
2.2 根因分析节点的五问框架
根因分析节点的 Prompt 是整个项目里花时间调得最多的部分。我一开始用简单的"请分析失败原因",结果输出全是"时间不够""需求不清晰"这类表面结论,价值很低。后来参考了丰田生产系统的"5 Why"逻辑,设计了一套带约束的追问框架。
具体做法是在系统提示词里给模型一条虚拟的追问路径:第一问,直接原因是什么;第二问,这个直接原因是由什么决策导致的;第三问,这个决策是基于什么信息做出的;第四问,这些信息在事前是否可以获得;第五问,如果现在重来一次,最值得改变哪一步。每一问都要求模型结合前一步的事实抽取结果来回答,并且最后要汇总成一个三层因果链:表层因素、中间因素、根层因素。
实测下来,这个框架最大的收益是让模型的回答从"描述性"变成了"推理性"。它不再替用户写出"沟通不到位"这种废话,而是能明确说"在 6 月 2 日的评审会上,需求方提出变更,但未同步到开发文档,导致 6 月 10 日联调时才发现数据模型不一致"。这个质量差距,是普通 Prompt 无法达到的。
2.3 行动建议节点的 SMART 约束
行动建议节点我用了反向约束法。不是告诉模型"请给出具体建议",而是告诉它"以下输出格式是非法的",把所有套话样板提前拦截掉。规则包括:不允许输出"加强""提升""优化"这类无法验证的词;不允许把"建议"写成一个没有主语的完整句;每个行动必须包含执行人角色、可验证的产出、截止时间逻辑。
这里有个小技巧想分享给大家。在 Prompt 末尾,我刻意加了一句话:如果你输出的某条建议可以被任何项目套用,删除它。这句话对结果的影响远超想象。它本质上是在引导模型理解——复盘的产出必须具有项目特异性,普通适用的建议等于没有建议。运行几轮之后,输出里"定期同步进度""加强评审质量"这类垃圾建议基本消失了。
2.4 长文本上下文的管理策略
Dify 的 Chatflow 有一个容易被忽略的特性:节点之间的上下文是可以精精精确裁剪的。我在中期做过一个优化,把最初的"直接把全部原文传给后续节点"改成了"原文先做第一次压缩"。具体是在事实抽取节点后面加了一个专门用于上下文压缩的 LLM 节点,把用户原始输入压成一份不超过 500 字的"复盘素材摘要",然后所有后续节点只吃这份摘要,不碰原始输入。
来源是这个项目的实际运行经验。当用户粘贴了几万字的聊天记录时,如果每次都全量带入上下文,不说 token 成本高,模型对核心信息的注意力也会明显分散,输出质量下降严重。压缩这一步实际上是在模拟人类复盘时的做法——先快速泛读,把自己对事件的理解写下来,再基于理解去追问。Dify 的工作流天然允许这种"信息漏斗"式的设计,用起来非常顺手。
3. 实操走一遍:在 Dify 上从零搭出 hindsight
3.1 前置准备:模型选型与知识库配置
我用的是 Dify 的 Chatflow 应用,模型在多个节点上统一选了通义千问 Max 版本。选这个主要是因为它在长文本抽取和结构化输出上比较稳定,而且配合 Dify 内置函数调用时,JSON 输出的格式错误率比其它模型低很多。当然你也可以按自己的需求选 GLM-4 或 DeepSeek,但要注意一个节点处选择模型的能力下限必须大于任务难度,任务里最难的是根因分析,因为它要多步推理。
知识库我初始化了大约 50 篇历史复盘文档,全部是团队之前写过的真实项目复盘。导入方式就是把 Markdown 文件批量传到 Dify 的知识库里,分段模式用"自定义分段",每段大概 800 个 token,检索模式选"向量检索"。这一步的核心目的是让行动建议节点能参考过去复盘里的有效做法,避免"每次复盘都是第一次复盘"。
3.2 工作流节点搭建顺序
整个 Chatflow 的节点顺序我建议这么搭:
- 起始节点:设置用户输入字段,一个是 text 类型的"原始材料",一个是 file 类型的"附件文件".
- 文档提取器节点:如果有上传文件,用它抽取文件文本,与 text 输入拼接。
- 上下文压缩节点:把输入压缩成 500 字复盘素材摘要。
- 事实抽取节点:输出结构化 JSON。
- 知识检索节点:用 JSON 里的"项目领域"和"关键词"字段做检索,拿到历史复盘片段。
- 根因分析节点:结合摘要、事实 JSON、历史片段,输出三层因果分析。
- 行动建议节点:结合根因分析输出,输出带执行人的行动列表。
- 结果汇总节点:把以上所有结果拼成一份完整的复盘报告 Markdown。
- 结束节点:输出报告,并设置"结果"变量作为会话流的下游入口。
我在做的时候,第 5 步知识检索节点最初是放在行动建议之前的,但运行了几轮发现,历史复盘对根因分析也有很强的参考价值——很多问题本质上是旧问题的变体,直接看历史能加快定位。所以后来把检索提前到了根因分析之前。这个调整让因果链的输出更精准。大家在复现时,也可以根据自己项目的实际情况调整节点顺序,但建议至少跑 20 条真实数据后再说,别凭感觉乱动。
3.3 关键变量和内存设置
Dify 的 Chatflow 里,节点之间的数据流转依赖变量引用。这步新手容易栽坑,我详细说一下。
在起始节点,我声明了一个 input 变量,叫raw_text。文档提取器节点导出的文本,我用了一个中间变量来存,叫file_text。然后在"材料拼接"这一步,用 Dify 的 J2 模板编辑器写:{{#sys.query#}}加上{{file_text}}。这里的sys.query是 Dify 系统级变量,代表用户当前输入。如果你直接引用了一个不存在的变量名,运行时会报空值,排查起来比较费劲。
各节点的输出存储,我统一用了"变量写入"的方式,比如事实抽取节点的输出存到fact_json,根因分析存到root_cause,行动建议存到action_plan。最终汇总节点的模板把这三段引用部分分别嵌入 Markdown 模板里。Dify 在节点配置区有"输出变量"这一栏,记得要在每个节点都确认输出变量的 key,不然下一个节点根本无法引用。
3.4 调试过程中的实测记录
实测里最典型的一次输入是粘贴了一段 2000 字的活动上线复盘。原始文本里夹杂了很多人名、具体日期、聊天截图转的文字。第一轮运行时,事实抽取把"开会时小李说可能无法按时交付"这种主观表述当成了事实。我在事实抽取节点的 Prompt 里加了"只保留已经发生的动作,推测性语言写入 hindrance 字段"。改完之后,抽取结果的准确性提升很明显。
另一个实测问题是根因分析太啰嗦。默认温度是 0.5,但根因分析这种需要发散的任务,我建议把温度调到 0.7 到 0.8,同时把 max_tokens 设置到 2000 左右,否则模型会因为输出空间不够而压缩推理过程,结论显得跳。行动建议节点的温度则是相反的,要调低到 0.2 左右,因为这里更需要确定性而不是天马行空。每个节点单独调温度,这也是拆分节点的一个重要收益。
3.5 复盘报告的输出模板
最后输出的复盘报告我不想让它看起来像 AI 生成的标准答案,所以在 Markdown 模板上做了定制。结构是:
# 复盘:[项目代号] ## 一、目标与事实 - 预期目标: - 实际结果: ## 二、因果链分析 - 表层因素: - 中间因素: - 根层因素: ## 三、可复用经验 - 这次做对了什么: - 这次不该做什么: ## 四、后续行动 | 行动项 | 负责人 | 验收标准 | 触发条件 |"触发条件"这一列特别有用,它把行动建议变成了"如果下次再出现某情况,就执行某操作"的规则,把复盘结果真正变成了下一次项目启动前的检查清单。这个设计我是从军事行动后的 AAR(行动后复盘)流程里借来的,效果很好。
4. 常见问题与排查技巧实录
4.1 提示词节点输出解析失败
大家用 Dify 时最常见的问题绝对是"输出内容不是有效的 JSON"。我在 hindsight 的早期版本里也掉进过这个坑。模型的输出偶尔会带着解释性文字,比如先来了句"根据您的需求,以下是 JSON"然后再输出。这种情况 Dify 的"结构化输出解析"节点会直接挂掉。解决思路有两个:一是在 Prompt 里加硬约束,说"只允许输出 JSON,任何非 JSON 内容都会导致流程中断";二是在 Dify 里使用"代码节点",里面写一个正则提取逻辑,从模型输出的任意文本中把第一个{到最后一个}之间的内容全部抓出来,然后尝试JSON.parse,失败就用默认值兜底。
我最终的做法是两者结合。靠代码节点做正则兜底后,流程的稳定性上了一个台阶。特别注意,别把模型输出直接用来做变量引用,必须先经过解析节点或代码节点转成合法的json类型,否则下游节点取值时会得到空字符串。
4.2 长文本截断导致复盘缺失关键信息
Dify 对每个节点的输入是有 token 上限的,如果用户粘了几万字的原始聊天记录,即使你有压缩节点,第一步拼接时也可能超限。我在测试时用过一个 3 万字的会议记录,直接导致文档提取器节点报错。解决办法是在入口处就做"分段预处理",可以用 Python 代码节点实现简单的文本切分,比如按每 3000 字切一段,分别调用事实抽取节点,最后合并结果。这个方案虽然增加了工作流的分支数量,但在真实场景里是最稳的。
后期我甚至用 Dify 的情节"迭代器"节点,把原始文本先按章节切块,再逐块抽取事实,最后统一汇总。如果你也有超长文本的需求,建议谨慎预切,不要试图把"全部考虑周全"押在单个 LLM 调用上。
4.3 知识库检索质量不高
知识库是复盘的记忆库,如果检索不准,后面的行动建议就没有历史依据。这个问题我在上线两周后才发现。原因是文档分段方式太粗,很多历史复盘里是杂糅了多项目内容,一个分段里同时包含前后两个项目的复盘,导致向量检索的命中结果语义混乱。解决方法是把历史文档先按项目代号做二级目录,然后用 Dify 的"多路径检索"模式,一个路径按项目代目检索,另一个按全文关键词检索,结果做并集后再交给根因分析节点。
实测配置后,知识检索命中的相关内容效率提升了大约 30%,特别是"同类问题历史处理方式"这类问题的召回明显更准。一个小细节:在分段时,要给分段元数据里加上项目代号和复盘日期,这样渲染引用片段时可以显示"该项目风格参考"字样。
4.4 应用卡死或长时间不返回
还有一类问题是应用运行到一半整个会话卡住,一般是因为某个 LLM 节点的 max_tokens 设置太大,同时网络延迟,超时时间不够用。Dify 里的"超时时间"默认值是 120 秒,如果用了 8k 甚至 16k 的 max_tokens,模型推理时间很容易超过这个值。我当时就把根因分析节点的超时时间改成 300 秒,问题解决了。另外提醒一句,节点级别的超时时间可以在节点设置的"高级"里找到,别总调全局配置,精准修改才不影响其它节点。
4.5 多轮会话中的"上下文污染"
这是复盘类工具比较容易忽视的点。Dify 的 Chatflow 默认会把当前会话之前的对话历史也作为上下文传给模型,但我们做"单份材料复盘"时,上一轮复盘的材料对这次分析完全没用,甚至会产生干扰。我的做法是在起始节点加了一个运行开关,核心逻辑是"每次输入新材料时就清空会话记忆",具体来说,Dify 提供了一个"清空对话历史"的模块,在材料变量更新时触发,这样每一轮复盘都像是从零开始,但又可以显式把历史复盘结论写入输入框。
如果你的业务场景需要跨会话累计记忆,那不能直接清空,而是要在知识库里保留上轮输出。但我实测下来,复盘场景里单轮输入最干净,跨轮引用很容易让模型把不同项目的细节混淆。
5. 个人实际使用中的一点心得
hindsight 这个项目从我在工作流画布拖出第一个节点,到上线给团队使用,总共花了大约两个礼拜。中途推翻过一次根因分析的设计方案,数据格式也调整了三次,但整体的信心一直比较足——因为 Dify 的调试成本低,任何节点改动都可以立刻在"预览"里验证,不用重新部署整套代码。
现在我每天的工作习惯是下班前把当天的会议记录或聊天记录粘贴进 hindsight,第二天早上直接看生成的复盘报告。它的价值不在于告诉我"今天发生了什么"——这件事我自己清楚,而在于它把那些当时没注意到、事后才发现影响巨大的细节,结构化地摆在了我面前。这大概就是在"事后"视角里,AI 能提供给人类的最实用帮助:用事后聪明,校正下一次的事前决策。
最后再分享一个小技巧:在行动建议节点里,我给每条建议补了一个字段叫replay_time(重演时间),在项目启动会的前一天,把 hindsight 输出翻出来,逐条对照当前项目是否还会踩同样的坑。这个习惯坚持了两个月,团队新项目的启动风险明显降低了。复盘工具能不能发挥作用,不在于它使用了多聪明的算法,而在于你是否真的会在下一次行动之前,愿意回头看一眼。