本地小模型跑自动化:格式全对,业务仍错
作者用 CPU 上的 Qwen 1.8B 对六类 n8n 工作流进行了 192 次测试,JSON 无破损,但出现线索误判、发票字段错误和知识库外编答。部分流程对比了直接使用模型输出与增加代码校验的表现。
AI 深度解读
小模型能吐出合法 JSON,就能接管自动化流程吗?作者把六个自用 n8n 工作流接到 CPU 上运行的 Qwen 1.8B,每个用例重复三次,共跑了 192 次:JSON 解析错误为零,内容却出现了虚假热线索、错误账单金额和编造的客服答复。
这次测试值得看,是因为作者记录了失败怎样穿过校验、触发下游动作。结论很明确:小模型可以承担部分提取和起草工作,但评分、升级人工、发送通知等决定,需要代码接管。
192 次 JSON 全对,为什么业务还会出错
测试环境是自托管 n8n 1.123.84,Ollama 在 CPU 上运行 Qwen 1.8B,量化为 Q4_K_M,通过 OpenAI 兼容的 /v1 接口调用,设置 temperature 0.2、response_format: json_object,没有使用付费 API。
作者用 Python 脚本调用各工作流的 webhook,保存每次原始响应;已有防护版本的流程,则把原始版和带校验的版本并排测试。所谓防护,就是在 LLM 后面加一个 Code 节点,检查输出,再决定后续是否执行。
192 次响应全部可以解析为 JSON,这是这套配置下的实测结果。但合法 JSON 只能证明数据装进了正确的容器,不能证明里面的事实正确。
销售线索评分最能说明问题。提示词要求返回 score,范围为 0–100,以及 tier,取值为 hot/warm/cold。18 次测试中,有预算、六周内要落地的 CTO 得到 85 分,只想为大学项目索取免费模板的人也得到 85 分。模型又把几乎所有人标成 warm,导致 13/18 次评分和等级互相矛盾。
下游流程按 score >= 70 发送 Slack 通知,因此有七次会把非热线索推过去,其中还包括推销垃圾外链的消息。
Validate 节点标记了 14/18 次异常,抓住了全部评分与等级冲突,也通过 backlink|guest post|seo|crypto 正则,在 3/3 次垃圾推广测试中强制将等级改为 cold。但加了防护,仍有 8/18 次等级判断错误。
校验能拦住自相矛盾,不能把没有区分度的评分变成可靠排序。
作者建议改为提取 has_budget、is_decision_maker、timeline_weeks、company_size,再由 Code 节点计算分数。这样,业务规则至少变得明确、可检查。
对照原文校验,为什么仍会放过错误
发票提取测试用了六类文档:GST 税务发票、咖啡店小票、自由职业者发票、AWS 账单、手写风格电费账单和发货邮件。
Chai Point 小票上的 02/11/2026,在印度语境下是 11 月 2 日,模型却连续 3/3 次提取成 2026-02-11。AWS 账单明写 Total $54.61,模型连续 3/3 次返回文中不存在的 62.93。作者判断,模型自行加总后算错了。
它还在 3/3 次测试中,把 Account 4491-2210-7783 当成 invoice_number,尽管提示词要求未知时用 null、禁止猜测。账单日期也在 2/3 次原始运行中,被提取成账期起点 2026-09-01。其余四类文档的主要提取结果则全部正确。
防护节点检查 total、invoice_number、gstin、due_date 是否能在源文本中找到,检查 subtotal + tax = total,并要求日期符合 YYYY-MM-DD。
这套规则抓住了全部三次虚构金额,也抓住了两次凭空补出的到期日期:原文只写「15 天内付款」。但它也产生三次误报,因为正确日期 2026-10-28 无法直接匹配文中的 28 Oct 2026。
先归一化,再比较,才有意义。
更难的是语义错误。二月与十一月颠倒后,日期格式仍然合法;账号字符串确实出现在文档里,却不代表它就是发票号。最终,18 次带防护运行中,仍有四次携带错误字段通过检查。
作者计划加入文档 locale,明确日期为 DD/MM,拒绝距离当天超过 60 天的日期,并拒绝以 Account 等词开头的发票号。这些是拟补充的规则,原文没有给出修复后的测试结果。
让模型判断自己是否可信,问题出在哪里
FAQ 测试的知识库只有三行,覆盖退款期限、两个价格和支持时间。作者分别问了三个已覆盖、三个未覆盖的问题。
数据驻留和 Zoho 相关问题得到了保守答复,但「是否有优惠年付计划」连续 3/3 次得到否定答案,并返回 escalate: false。知识库没有这条信息,模型却把「没找到」回答成了「没有」。
防护节点只核对回答中的数字、价格和邮箱是否来自知识库。这个假答案没有这些内容,因此顺利通过。此外,五次运行的 escalate 为 null 或缺失,原流程却将其当作无需升级人工。
作者提出返回 kb_line,说明答案引用了哪一行;没有引用,或引用行与答案缺少关键词对应,就由代码升级人工。这给审核留下了依据,但关键词匹配也只是筛查手段,不能证明回答被引用内容支持。
评论回复同样暴露了小模型的执行边界。原提示词生成的 24 条回复中,16 条有套话,14 条没有提及评论细节。v2 加入禁用表达和具体性要求后,两项都降到 11/24,但检查节点最终把 22/24 条交给店主审核。问题包括残留套话、虚构联系方式、泛化的感谢开头,以及在一星「idli 里有头发」的评论回复中提到退款。
作者据此判断,这个 1.8B 模型难以同时遵守五条风格规则,更适合生成草稿。
表现稳的是经过提示注入防护的邮件分流。六封攻击邮件各跑三次,18 次攻击均未触发预期动作,全部进入人工审核。模型原始输出有三次顺从了攻击,但动作由代码决定,所以没有继续执行。
代价也清楚:普通邮件只有 12/18 次分类正确,人工负担更重。共享的 38 核 CPU 机器上,分流平均耗时 7.2 秒、p95 为 31 秒;带防护的发票流程平均 6.6 秒,原始版在繁忙时出现过约 90 秒的离群值。作者称 JavaScript 校验节点没有可测的额外开销,但机器同时运行其他任务,这些延迟只能作粗略参考。
我的判断
我认同把动作权限收回代码。尤其是 escalate 缺失时默认转人工,这直接修正了一个危险的默认值:信息不完整,不该自动获得放行资格。
但这组结果不能变成「1.8B 模型不行」或「JSON mode 永不出错」的普遍结论。它只覆盖特定模型、量化、提示词和用例;每个用例重复三次,也没有提供更大模型、其他模型或不同提示策略的完整对照。对模型能力上限的判断,仍带有经验成分。
领域规则也有适用范围。例如距离当天超过 60 天就拒绝,适合部分近期单据流程,却会误伤历史账单补录。账号前缀黑名单、关键词引用检查,都需要结合真实输入继续调整。
相较于直接换更大模型,增加校验和收紧权限能先解决一批明确问题;更大模型是否值得引入,则要用同一批业务用例比较正确率、延迟和人工审核量。原文没有给出足以替团队完成这个选择的数据。
能拿来做什么
- 在 n8n 或 Node 自动化中,把模型输出先交给独立校验步骤,检查字段类型、来源、字段间关系,再执行通知或发送动作;
escalate: null和字段缺失都应进入人工处理。 - 做线索评分时,让模型返回预算、决策权和时间要求等事实,把评分公式写进代码,并把「所有输入都得高分」加入回归用例。
- 做票据提取时,同时保留源文本和归一化结果,明确日期地区约定;金额出现于原文只是第一关,还要检查它是否真是总额。
- 做 FAQ 和评论回复时,保留知识库引用或人工审核入口。复现本地接入可修改 Config 节点的
baseUrl: 'http://127.0.0.1:11434/v1'和模型名,再在 LLM 后增加 Code 节点验证输出。