LLM 节点总是不稳定?17 条自查清单 + 4 条进阶经验,从 200 次实验里长出来
基于 Dify 1.16.1 与 Hermes Agent 实战实测(2026-08):Hermes Agent 调教实验 + Dify 节点拼装实测 + 插件开发实测
📖 摘要:Dify 的 LLM 节点、Agent 的提示词文件、插件的工具描述——三个看起来不同的场景,底层是同一个问题:怎么用文本让 LLM 稳定输出符合预期。本文把三次实战(200 次实验)里踩过的坑提炼成 17 条自查清单(六类)+ 4 条进阶经验——清单管「设计时对照查」,进阶经验管「约束怎么写、记忆怎么存、多轮怎么跑」。
📌本文要解决的核心痛点
- LLM 节点输出 JSON 老是解析失败,改了几版提示词还是不行?
- 输入为空时,模型「一本正经」地编造了一整份报价单?
- 推理模型思考 54 秒,输出却是空的?
- Agent 调工具时参数总是传错,工具描述怎么写才靠谱?
- 本文给一份六类 17 条的自查清单(输入防护 / 输出约束 / 模型参数 / 错误处置 / 上下文管理 / 工具描述)+ 4 条进阶经验(约束怎么写、记忆怎么存、多轮怎么跑)——每条都有实测证据和落地形态。
场景
过去一个月,我们在三条线同时做「让 LLM 稳定输出」这件事,而且一开始都踩了坑:
- Dify 工作流拼装:一个报价单比价助手,5 个模块串起来跑。模块 2 收到空输入时,LLM 直接编造了一整份报价数据——公司名、产品型号、价格全是虚构的,下游还当真了。
- Hermes Agent 调教:给一个 AI 助理写行为约束文件。第一版写得又长又抽象,模型「照章办事」的达标率惨不忍睹;改成「要求 + 样例」成对的结构化写法后,达标率 100%,成本还省了。
- 插件开发:给工作流加一个工单查询工具。工具描述里写了参数规则和示例,模型就能正确生成参数;没写,它就乱传。
三件事看起来毫不相关——一个是可视化编排,一个是提示词调教,一个是工具封装。但踩完发现:坑是同源的。LLM 的行为规律不会因为平台不同就改变:空输入它会编,格式不约束它会飘,描述不清晰它会猜。这篇把三次实战合起来,沉淀成一份可以对照自查的清单。
结论
LLM 输出不稳定,根因几乎都能归到六个层面:输入没防护、输出没约束、参数没选对、错误没分类、上下文没管理、工具没描述清。对应 17 条自查项 + 4 条进阶经验——清单拦得住八成的不稳定,进阶经验告诉你约束怎么写才不会过度、记忆怎么存才有用、多轮怎么跑才不漂。
清单主体:六类 17 条
| # | 方法 | 为什么(实测证据) | 落地形态 |
|---|---|---|---|
| 1 | 空输入校验:LLM 节点前必须有输入校验,空输入直接走错误出口 | 空输入时 LLM 幻觉编造数据——实测编出了完整报价单(公司名/型号/价格全虚构) | 节点前加条件判断:空输入 → 错误契约直出 |
| 2 | 类型/长度/枚举校验先行 | 非法输入进 LLM 浪费 token 且输出不可控 | 节点前代码校验,合法才放行 |
| 2b | 事实脑补拦截:输入不完整(字段缺失)也拦截 | 信息不完整时 LLM 脑补完整事实(实测:从局部日志推断出完整实验规模,实际是错的) | 节点前校验必填字段集,缺字段走错误出口 |
| 3 | 输出形态 = 指令 + 样例成对(要求 + 禁止成对) | 结构化写法实测达标率 100%、成本 1.44× 优于抽象长文;「用表格」不如给表格示例 | system 提示词:格式要求 + 具体示例 |
| 4 | JSON 输出:格式约束 + 容错双保险 | 推理模型思考模式默认开,输出带<think>前缀,下游 json.loads 必失败 | 关闭思考模式 + 代码节点剥<think> |
| 5 | 输出长度/预算控制 | 推理吃光输出预算 → 结果为空(实测 54-70 秒思考、输出空) | 节点级输出预算;长输出场景加大上限并核对 |
| 6 | 思考模式开关:任务可解构成确定步骤 → 关;多步推理/数学/代码调试 → 保留 | 关后 8.7 秒 vs 开 54-70 秒;模板化任务关掉更稳更省 | 节点级 thinking 配置按任务性质选 |
| 7 | 温度按确定性需求调 | 确定性任务高温度 → 输出漂移 | 模板化/JSON 任务用低温度 |
| 8 | 输出不对先判「哪层错」:数据/逻辑/工具/提示四桶 | 盲目改提示词是最大浪费——先问一句「是输入/推理/调用/生成哪层的问题」 | 排查流程:先分类再对症修 |
| 9 | 结构化错误出口:error_code/error_message/retryable 三件套 | 瞬时错误可重试、业务错误不重试——分不清就全重试,越重试越乱 | 子模块输出错误契约,上层按错误码路由 |
| 10 | 关键信息前置:角色 → 任务 → 输出格式 → 参考材料 | 全局约束越长达标率越低;上下文窗口有限,信息有优先级 | 提示词结构固定:角色/任务/格式在前,材料在后 |
| 11 | 防跨轮次格式传染 | 多轮对话中,历史输出格式会带偏当前轮(实测踩坑) | 每轮明确当前输出格式,不受历史影响 |
| 12 | 输入裁剪:无关信息不进提示词 | 给什么说什么——给垃圾出垃圾,token 即成本 | 节点前过滤字段,只传必要内容 |
| 13 | 工具描述 = 参数规则 + 示例 | 描述带「order_id 必须是 WO- 开头 8 位数字,如 WO-20260805」→ 模型正确生成参数 | 插件工具 description 写规则 + 示例 |
| 14 | 工具边界声明:闲聊不调、格式不对先核对 | 写清边界的工具,模型不会乱调 | 工具描述/预置提示词里写边界 |
| 15 | 校验失败显式报错,不静默降级 | 显式错误会成为模型自纠错的燃料——实测校验失败后模型能自行纠正 | 工具参数校验失败返回结构化错误 |
| 15b | 自纠错循环:首调失败≠终局失败 | Agent 场景首调空参率高——报错后模型读错误消息自纠、参数正确;error_message 质量决定自纠成功率 | 错误消息写清「错在哪/怎么改」,设重试上限防死循环 |
三个值得展开的故事
故事一:空输入,模型编了一整份报价单
比价助手拼装时,模块 2 收到的输入为空——代码节点的解析把文本丢了。LLM 节点没有输入校验,直接把空输入喂给了模型。结果模型「一本正经」地输出了完整报价数据:「上海宏图机电」「三相异步电动机」——公司名、型号、价格全是它编的。下游模块还当真了,比价结果煞有介事。
修法不是调提示词——是加输入校验:空输入直接走错误出口,不让 LLM 处理。LLM 是生成器不是守门员,空输入它不会说「我没数据」,它会编。
故事二:思考了 54 秒,输出是空的
一个需要结构化输出的节点,用推理模型跑。模型思考模式默认开,推理过程吃光了输出预算——结果是 text 字段为空,下游 json.loads 直接崩。实测:思考开 54-70 秒 + 输出空 vs 关思考 8.7 秒 + 完整输出。
判断标准:任务能被解构成确定步骤(模板化生成/确定性解构/延迟敏感/成本敏感)就关;多步推理/数学逻辑/代码调试/跨文档分析必须保留。思考模式是「模型能力不足的补偿」——任务确定时,补偿就是浪费。
故事三:工具描述怎么写,模型就怎么调
插件开发时对比实测:工具描述写了参数规则和示例(「order_id 必须匹配 WO- 后跟 8 位数字,例如 WO-20260805」),模型就能正确生成参数;描述含糊,它就乱传。更关键的:写了边界声明(「闲聊不要调用」「格式不对先核对」),模型在格式错误时不会硬调工具,而是先提示用户修正。
LLM 调用工具是概率行为——描述质量决定成功率。规则 + 示例 + 边界,三件套。
进阶经验:清单之外的 4 条(约束怎么写、记忆怎么存、多轮怎么跑)
清单 17 条管「节点/约束设计时查什么」。还有 4 条经验不在清单里——因为它们属于「约束工程」和「交付形态」,是 200 次实验里的另一类发现:
进阶 1:铁律会过度验证——约束写得越绝对,模型执行越用力
实测:一条铁律单独写(不带样例不带解释),模型会过度执行——成本 2.28 倍、单任务 token 消耗飙到 76 万(无约束的 3 倍)。修法:「要求 + 禁止」成对写、给具体样例——同样是约束,结构化写法的成本只有 1.44 倍,达标率反而 100%。
进阶 2:记忆是第二上下文——粒度决定达标率和成本
实测三档对照:无记忆达标率 94.1%;粗粒度(5 条一句话)达标率持平但成本降到 0.80 倍;细结构化(10 条分类)达标率 98% 但成本 1.24 倍。结论:记忆粒度是「精度 vs 成本」的权衡——精度敏感场景用细结构化,成本敏感场景用粗粒度,不存在免费午餐。
进阶 3:全局约束有长度副作用——放错层级会拉长所有输出
实测:把「汇报三要素」写进全局约束,每轮输出都被拉长(全局约束影响所有会话的输出长度)。修法:输出长度敏感的要求放任务级 prompt,全局层只管行为纪律——约束分层的边界就在这。
进阶 4:多轮对话即约束——对话本身是最轻的约束手段
实测多轮形态(6 项验收 30/30 全过):纠偏一次到位、追加需求、跨轮记忆、干扰恢复——对话中纠正一次,后续轮次自动遵守。修法:多轮交付场景不用堆约束文件,「对话纠偏 + 环境事实进记忆」就够了——单轮(自动化/批量)才需要全套约束。
边界与版本
- 实测环境:Dify 1.16.1 + Hermes Agent(deepseek 系列模型)。跨版本/跨模型使用前按「版本钉扎」习惯复核——模型行为随版本演进会变
- 适用:任何带 LLM 属性的节点/约束/工具描述设计(工作流 LLM 节点、Agent 节点、插件工具、行为约束文件)
- 不适用:纯确定性逻辑(不需要 LLM 的环节不要为了用而用);每条的经验值是 2026-08 实测,量化边界(如温度具体值)待更多数据校准
- 第 8 条(四桶判断)与第 9 条(错误契约)是交付流程层面的机制,详细展开见同专栏《执行驱动交付(EDD)》系列
收尾
17 条清单 + 4 条进阶经验,本质是一句话:LLM 不会自己变稳,稳定是设计出来的——输入你守,输出你约,参数你选,错误你分,上下文你管,工具你描述;约束别写太狠、记忆要选粒度、多轮靠对话。把这句话落成清单和进阶经验,设计时对照查一遍,比上线后救火省十倍。
💬讨论区:你遇到过最离谱的 LLM 输出是什么?是空输入编数据,还是格式飘到没法解析?评论区聊聊,一起把这份清单补厚。
如果觉得有收获,欢迎点赞 + 收藏 + 关注,这是激励我持续更新的最大动力。
本文基于真实项目交付与内部实战实验撰写(2026-08)。文中数据均来自实测记录,方法论部分以「已验证 / 推断待验证」标注边界。