news 2026/9/29 7:09:32

用Dify打造复盘AI:基于Chatflow的提示词工程实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用Dify打造复盘AI:基于Chatflow的提示词工程实战

今年我在折腾 Dify 的时候,突然被一个英文单词戳中了:hindsight。英文里有句老话叫 "hindsight is 20/20",翻译过来就是"事后看什么都清楚",说难听点叫马后炮,说好听点叫后见之明。过去我一直觉得这是个贬义词,直到我亲手把它做成了一款基于 Dify 的复盘 AI 应用,名字就叫 hindsight。它的活很简单:把项目记录、聊天记录、一段失败的经历丢进去,它会像一个经历过一切的老师傅,帮你把已经发生的事拆成事实、偏差、教训和下一次的行动清单。这篇文章就讲讲我为什么想做这么个东西、怎么从零用 Dify 搭起来、中间踩了哪些坑,以及你完全可以照抄的配置思路。

1. 为什么叫 hindsight:把"事后聪明"从贬义变成生产力

1.1 人人都是事后诸葛亮,但没人把"事后"用好

先说点虚的。你有没有过这种经历:项目上线后出问题,复盘会上所有人突然都变成了诸葛亮,这个说"当时我就觉得方案有问题",那个说"早该想到用户会这么操作"。可下次做新项目,同样的坑照样踩。问题出在哪?出在"事后思考"这件事完全是散装、靠脑子的。洞察产生了,但没被记录、没被结构化、更没被沉淀成下次可执行的检查项。

我做 hindsight 的初衷,就是把这种零散的"事后聪明"变成一条固定流水线。它不是让你对着失败自我检讨,而是把一段原始材料扔进一个标准流程里,产出一份结构化的复盘报告。说得直白一点:别人复盘靠开会,你复盘靠 AI 帮你拆解。

1.2 这个应用到底解决什么问题

我实际用下来,hindsight 能覆盖三类典型场景,这也是我推荐你先从这三个方向试的原因:

  • 项目复盘:把项目群里的关键对话、周报、上线记录扔进去,让它找出目标与实际结果的偏差。
  • 对话分析:客服聊天记录、销售沟通录音转的文字,看看到底是哪句话让客户态度变了的。
  • 个人记录回看:每天写几句日记式记录,让 AI 帮你提炼"今天有什么下次可以做得不一样"。

它适合谁?适合已经在用或准备用 Dify 的开发者、做 AI 应用的产品经理,以及所有被"复盘走过场"折磨过的职场人。如果你只是想要一个现成的一键复盘工具,hindsight 的思路也值得你参考,因为背后的提示词设计逻辑是通用的。

2. 整体方案:基于 Dify 的 hindsight 应用架构

2.1 为什么选 Dify 而不是自己硬编码

说实话,第一版 hindsight 是我用 Python 脚本调大模型 API 写的,当时觉得也就几百行代码的事。但做到后面就发现一个尴尬问题:提示词改一版就要动代码,对话历史要自己管,想加一个"抽取事实"的中间步骤还得自己拼字符串。后来我把整个流程迁到了 Dify 上,用 Workflow/Chatflow 而不是写代码,原因有三:

  • 可调试性好:每个节点单独跑,哪一步输出不对劲,直接在面板上看得清清楚楚。
  • 改提示词不用发版:Dify 里改完提示词保存就能生效,产品同事也能上手调,不用每次找我改代码。
  • 后续扩展方便:接飞书机器人、接知识库、接外部 API,都是画布上拉节点的事。

hindsight 我选的是Chatflow(聊天流)而不是 Workflow。因为复盘这件事,用户大概率会追问,比如"第二步你说的偏差具体指什么"、"能不能针对这个教训再给一个例子"。Chatflow 天然支持多轮对话,Workflow 更偏向一次性跑完拿结果。如果你确定只做单次分析,用 Workflow 会更简单。

2.2 核心流程:五个节点把"复盘"拆成流水线

整个 hindsight 的核心,是一条五段式分析流水线。这个结构不是拍脑袋定的,而是我从"复盘方法论"里搬出来的:先搞清楚发生了什么,再看和预期差多少,然后想为什么会差,最后给出下一次怎么办。

节点作用对应变量
开始(Start)接收用户输入的原始材料query
LLM 节点 1事实提取,把原文变成结构化 JSONfacts
LLM 节点 2偏差识别,对比目标与结果gap_analysis
LLM 节点 3教训提炼,梳理原因与关键转折lessons
LLM 节点 4行动建议,输出下次可执行清单actions
结束(End)汇总四步结果,拼装成报告最终回复

为什么要把"事实提取"单独拆成一个节点,而不是让后面的分析节点直接读原文?这是我踩过坑之后才想明白的。直接让 AI 读原文做分析,它经常会脑补出不存在的细节,比如原文说"用户流失严重",它能自己编出"可能是因为价格太高"。但如果先强制它抽取事实字段,再基于事实做分析,虚构的概率会明显降低。流程拆开,本质上是给 AI 设了一道"不许乱编"的栅栏。

2.3 一个关键设计:反事实推理

hindsight 这个名字的真正含义,落在第三个节点里:反事实推理(counterfactual)。所谓反事实,就是"如果当时换一种做法,结果会不会不一样"。这是复盘里最有价值、也最容易扯淡的部分。

我让 AI 在偏差分析之后,专门生成 2 到 3 条"如果当时……"的假设,但有一条硬性要求:每条假设后面必须标注它是基于事实的推断,还是纯粹猜测。这一步在提示词里写死,后面我会把提示词模板贴出来。因为复盘可以大胆假设,但不能把假设写成结论,否则报告就变成 AI 编故事了。

3. 关键实现:提示词编排与节点配置

3.1 事实提取节点的提示词模板

先看第一个 LLM 节点。这个节点的输入是用户刚提交的原始记录,输出是一段 JSON。我试过好几个版本,最后稳定在这个提示词上:

你是一个严谨的信息抽取器。请阅读用户提供的复盘材料,提取以下字段,并只输出一个 JSON 对象,不要输出任何解释文字。 字段要求: - background: 事件发生的背景,一句话概括 - goal: 用户/当事人原本想达成的目标 - actions: 实际采取的关键行动,最多列5项 - result: 实际发生的结果,尽量引用原文关键词 - turning_points: 过程中影响事态走向的2-3个关键节点 规则: 1. 所有字段必须基于原文,不能推测。 2. 原文没有提到的信息字段置为 null。 3. actions 和 turning_points 保留原文短语,不要改写。 材料内容: {{user_input}}

几个细节为什么要这么写:强调"只能基于原文",是为了防止后面分析跑偏;"保留原文短语"是因为用户提供的复盘材料往往有口语细节,AI 一旦改写就容易丢失情绪和关键措辞;强制 JSON 输出,是为了让 Dify 的下游节点能安全引用变量。

3.2 分析与建议节点的提示词设计

偏差识别节点接收的是facts变量,提示词核心是让 AI 对比"目标"和"结果"之间的差距,并按严重程度排列。这里我用了一个比较有效的技巧:让 AI 先复述一遍目标和结果,再做对比。先复述能让它真正读进去,而不是随便生成一段漂亮话。

经验提炼节点是 hindsight 的灵魂,提示词关键词是"归因"和"反事实":

基于事实清单和偏差分析结果,请完成: 1. 找出2-3个最可能导致偏差的原因,每个原因必须引用事实清单中的具体内容作为证据。 2. 针对每个原因,生成一条"如果当时……"的反事实假设。 3. 明确标注每条反事实假设是"基于事实的推断"还是"推测"。 4. 输出的教训要写成可复用的规则,不要写成对个人的指责。

最后行动建议节点更简单,要求输出带时间范围、带责任人的动作列表。因为复盘报告如果只写"下次要注意"等于没写,AI 得给出可执行、可检查的动作。

3.3 参数配置:模型、温度与上下文

模型选择上,hindsight 默认接的是推理能力较强的模型,因为复盘任务本质上是逻辑分析,不是简单问答。如果你的 Dify 里同时接了多种模型,建议事实提取用便宜一点的轻量模型,后面三个分析节点用强模型,性价比最高。温度我统一调到 0.4 左右。太低(接近 0)输出太死板,太高(超过 0.7)容易在推断环节放飞自我。让我比较直白地说:0.4 是我试了二十几次之后的最稳值。

上下文管理是一个差点坑死我的点。Chatflow 默认会把多轮对话历史全部传进去,导致第一轮抽取的facts变量还好好的,到了第三轮追问时,模型开始盯着历史看,把用户新的追问当成复盘材料的一部分。解决办法是:在节点参数里显式设置history变量,并且把事实提取节点固定只读取sys.query里最新输入的原始材料,前面的历史不参与这一轮提取。

4. 实操过程:从零搭一个能跑的 hindsight

4.1 环境准备:Dify 部署与 Chatflow 创建

假设你已经有一台能跑 Docker 的服务器,这是最快的方式。第一次部署 Dify 大概十来分钟,可以边喝咖啡边等:

git clone https://github.com/langgenius/dify.git cd dify/docker cp .env.example .env docker compose up -d

启动以后,打开http://你的服务器IP,第一次进来会让你设置管理员账号。然后进入应用列表,新建应用,选Chatflow,名字就叫hindsight。

进了编排界面,左侧是节点面板,右侧是画布。默认画布上已经有两个节点:开始(Start)和结束(End)。我需要先到"开始"节点里,把输入字段从默认的sys.query改成自定义的user_input,原因前面说过:我不想让多轮历史污染原始材料。改完以后,开始节点下方会暴露一个名为user_input的变量,后面所有节点都要从它身上拿数据。

4.2 节点配置顺序与变量传递

按顺序拖出四个 LLM 节点,我把它们改名成fact_extract、gap_analysis、lesson_extract、action_plan,方便排查问题。

第一个节点配置如下:

  • 模型:选轻量模型
  • 上下文:{{#start.user_input#}}
  • 提示词:用上面 3.1 节里的模板
  • 输出变量:命名facts
  • 输出格式:JSON

第二个节点gap_analysis:

  • 上下文:{{#fact_extract.facts#}}
  • 提示词:3.2 节里的偏差识别提示词
  • 输出变量:gap

第三个节点lesson_extract:

  • 上下文:把{{#fact_extract.facts#}}和{{#gap_analysis.gap#}}拼接起来
  • 输出变量:lessons

第四个节点action_plan:

  • 上下文:接收facts、gap、lessons三份数据
  • 输出变量:actions

最后在结束节点里写一句话,把四个变量打包返回:

【事实还原】 {{#fact_extract.facts#}} 【偏差分析】 {{#gap_analysis.gap#}} 【核心教训】 {{#lesson_extract.lessons#}} 【行动建议】 {{#action_plan.actions#}}

4.3 实际案例跑一遍,看看输出长什么样

我拿一段一个朋友给我吐槽的"本周项目翻车记录"当测试材料,原文大概是这样的:

"周一开始开发一个优惠券功能,周五要上线。周一产品说需求没问题,周二我发现库存接口和优惠券系统对不上,问了后端,后端说周三才能改。周三又说联调环境挂了,顺延到周四。周四终于联调完,测试跑出一个严重 bug。周五硬着头皮上线,当天晚上用户反馈领不到券,转化率掉了 3%。"

跑完 hindsight,输出大概长这个结构:

事实还原: - 背景:五天期限的优惠券功能开发任务 - 目标:周五正常上线并提升转化 - 关键转折:接口对不上(周二)、联调环境故障(周三)、严重 bug(周四)、线上故障(周五) - 结局:上线当晚故障,转化率下跌约 3% 偏差分析: - 目标与结果间严重偏差 - 最严重偏差:技术风险没有被前置识别,直到周二才发现接口问题 核心教训(节选): - 接口依赖未在开发前确认,属于"基于事实的推断"类教训 - 联调环境故障没有预案,属于"推测"级假设 - 可复用规则:任何涉及外部系统的功能,开工前必须先核对接口契约 行动建议(节选): - 下次项目开工第一天,由后端列出所有依赖接口清单,输出接口契约文档(建议周五前完成) - 为联调环境故障预设备用环境切换方案(建议下次项目启动前完成演练)

可以看到,hindsight 没有把责任推给某个人,而是把问题落到了"流程节点"和"下次动作"上。这就是我当初想达到的效果:复盘不指责,只转化。

4.4 兜底技巧:JSON 解析失败怎么办

Dify 的 LLM 节点虽然能设定输出格式为 JSON,但模型偶尔还是会抽风,返回一段带注释的 JSON,或者干脆把提示词里的规则也复述一遍。我的兜底方案是加一个代码节点(Code),放在fact_extract后面,专门负责清洗返回内容。

代码节点里我放了一段 Python,做两件事:从模型输出里找到{开头}结尾的子串,然后用json.loads尝试解析,解析失败了就丢出一个默认的facts空结构。代码如下:

import json, re def main(context: dict) -> dict: raw = str(context.get("raw_output", "")) # 提取 JSON 子串 match = re.search(r'\{.*\}', raw, re.S) if match: try: data = json.loads(match.group(0)) return {"facts": data} except Exception: pass return {"facts": { "background": None, "goal": None, "actions": [], "result": None, "turning_points": [] }}

这个节点看着简单,但能在关键时刻保住整条流程不中断。复盘这种事最怕的就是"用户把材料都交出来了,流程却报错了"。

5. 常见问题与排查技巧实录

5.1 AI 乱归因,把臆测写成结论

这是我用第一版 hindsight 时最常遇到的问题。模型为了输出"深度分析",会编造一条看似合理的因果链,比如"客户流失严重,推测是因为竞品降价"——原文里根本没提竞品。后来我在提示词里做了三重限制:

  1. 事实提取节点强制"所有字段必须基于原文,不能推测"。
  2. 偏差分析节点要求"每个原因必须引用事实清单中的内容作为证据"。
  3. 反事实假设明确标注"推断"还是"推测"。

三重限制加上去之后,输出质量肉眼可见地提升。这里想提醒你一点:不要指望一条提示词解决所有问题,流程上的限制比提示词更可靠。

5.2 中文材料的语气与情绪被 JSON 抽干

把事实转成结构化 JSON 有一个损失:口语里的情绪、语气、犹豫都没了。比如"我其实很早就觉得有问题,但当时没敢说",转成turning_points之后变成了"察觉问题但未提出"。信息没丢,但决策时的心理负担丢了。

我的处理办法是:在事实提取节点里加了一个字段contextual_hints,专门用来保留原文中情绪化、模糊化的表述,比如"没敢说""有点慌""拖了很久"。分析节点拿到这个字段后,能感知到很多事实之外的信号。这个字段我是后来加的,但它反而成了整个复盘报告里最有人情味的部分。

5.3 上下文太长了,后面的节点"失忆"

当用户贴了一大段项目日志,然后再追问两句,Dify 会把整个对话历史传给后续节点,导致三个问题:响应变慢、Token 变贵、分析内容被历史稀释。我的解法是严格执行"单轮分析"模式:

  • 开始节点只暴露user_input,不引入history。
  • 四个分析节点全部只引用前序节点的输出变量,不引用会话历史。
  • 如果想做多轮问答,也是围绕已有的facts和gap变量继续问,而不是重新分析原文。

实际用下来,这种"一次性材料 + 结构化结果持久化"的模式,比让模型全程记住上下文要稳定得多。Dify 的变量机制刚好支持这个玩法,你只需要在节点设置里手动引用变量,别偷懒直接塞#sys.history#就行。

5.4 复盘报告太长太啰嗦,没人看

第一版输出结果是一个大长串,用户反馈"看完第一段就不想看后面的了"。后来我在结束节点里把报告拆成了两块:上面是精炼版,十五秒能看完;下面按需展开查看,详细版只在这个人想深究时才需要给。Dify 的 Chatflow 里可以直接用条件分支(IF/ELSE)节点做这个事,根据用户是否点了"详细复盘"再拼接第二个长报告。这个改动不大,但用户留存率高了很多。

6. 扩展思路:hindsight 还能怎么玩

6.1 接机器人,每周五自动做项目周复盘

hindsight 现阶段最大的用法,是我把它接到了一个自建的群机器人上。每周五下午,机器人会把群里这一周的所有项目相关消息拉出来,扔给 hindsight,然后生成一份"本周项目复盘简报",自动发到群里。简报里不会点名道姓骂谁,只会列出流程上的问题和下周行动项。

如果你也想这么做,可以在 Dify 上把应用发布为 API,然后用一段简单的 webhook 代码把它接到飞书或者钉钉机器人上。核心代码不复杂,大概就是收消息、调 Dify API、把返回内容发回群里:

import requests def handle_message(raw_text): resp = requests.post( "http://your-dify-api/chat-messages", json={ "inputs": {"user_input": raw_text}, "query": "请对以上内容进行一次事后复盘", "response_mode": "blocking", "user": "weekly-bot" } ) return resp.json().get("answer")

6.2 把复盘结果回填知识库,形成个人经验库

这是一个我打算下一步做的方向。当前 hindsight 复盘完,报告就飘散在对话流里了。更好的做法是加一个节点,把每次产生的lessons写到 Dify 知识库里作为文档存储。这样一来,等你要做下一个项目的时候,可以把真正的"经验"翻出来看,而不是靠记忆去回想。AI 帮我们把每一次后悔都变成了可以检索的资产,这是"后见之明"这个题目里最值钱的部分。

6.3 与语音转文字结合:开完会直接出复盘

如果你所在团队经常有复盘会议,可以把语音转文字服务输出的会议纪要直接丢进 hindsight,让它提炼"会议中提到的偏差与教训"。我试过几种转录服务,效果都可以,关键是喂进去的材料别太乱,转录后的文本最好先做一次基础清洗,比如去掉"嗯""那个"之类的语气词,hindsight 的分析质量会高一个档次。

另外还有一个思路值得提一下:不要把 hindsight 局限在"失败复盘"上。成功的事情也可以丢进去跑一遍。分析为什么成功、哪个动作起了决定性作用,和复盘失败一样有价值。我目前也在收集"成功场景"的案例,看看模型在这类输入下会不会给出更有建设性的输出。

做这个应用的过程中,我最大的体会是:hindsight 这个名字起得有点"反讽"的意思,因为传统的 hindsight 总是事后才明白,而我想要的其实是把"事后明白"变成"事前检查清单"。Dify 只是工具,真正难的是把复盘的逻辑想明白并落进提示词和流程里。如果你也在折腾类似的东西,我建议别急着堆节点,先把你要复盘的场景拆清楚:事实是什么、目标是什么、偏差是什么、教训是什么、下次怎么做。拆清楚了,剩下的就是用 Dify 把这些环节一个个串起来。

最后再分享一个小技巧:调好第一版以后,找几个真实案例跑一遍,然后盯着输出改提示词。别用自己编的完美案例调试,因为真实材料里的模糊、噪声、情绪,才是这个应用真正要处理的难题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 7:09:31

VirtualBox vdi搬移后启动失败:UUID与VBoxManage修复

玩 VirtualBox 的人,十有八九都经历过这么一遭:磁盘空间告急,把某个几十 GB 的 .vdi 文件从 D 盘拖到 E 盘,或者把整个虚拟机文件夹拷到另一台电脑上,打开 VirtualBox 准备继续干活,结果虚拟机怎么都启动不…

作者头像 李华
网站建设 2026/9/29 7:09:16

product-flow:产品决策skill 接入 TaoToken 的 config.toml 骨架与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 7:08:56

底盘线控系统:智能网联汽车执行层的关键技术解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 7:08:47

项目经理如何形成自己的风格?从自我洞察到刻意练习

最近在整理工作笔记,翻到一条特别扎心的记录:“有人夸我厉害,但我不确定团队服不服我。”这让我想认真聊聊一个被很多人低估的话题——项目经理如何形成自己的风格。这不是一本正经的课程笔记,更像是我自己边走边记的学习笔记&…

作者头像 李华
网站建设 2026/9/29 7:08:32

回形针最大化器:AI目标函数失控的启示与工程防御

在AI安全圈的内部讨论里,"paperclip"这三个字母基本不需要解释。它指的是Nick Bostrom那个著名的回形针最大化器思想实验:一台目标被设定为"尽可能多地生产回形针"的超级AI,最终会把包括人类在内的整个宇宙都改造成回形针…

作者头像 李华