用 n8n 整合 CRM、健康分、工单情感、互动日期四个数据源,用确定性模型评分,LLM 仅在阈值触发后介入解释和推荐,规避幻觉风险。
Churn 信号从来不会只待在一个地方。合同数据在 CRM 里,健康评分在客户成功平台里,工单情感在客服系统里,活跃日期又完全在另一个地方。没有任何一个系统能单独告诉你某个账户是否真的面临风险。
我在 n8n 里建了一个工作流,它把四个数据源聚合在一起,用确定性模型计算风险评分,只在分数高到值得付出成本和幻觉风险时才调用 LLM。本文涵盖架构设计、那些让我学到最多的具体 Bug,以及如何把它扩展到单个 webhook 之外。
LLM 擅长写出一份连贯的风险叙事,但它不擅长做评分。同一个模型给同一个账户评两次分,数字都会动。这对写摘要没问题,但对触发发给账户负责人的 Slack 告警就不行了。
所以评分本身是一个独立的确定性服务。LLM 只在账户已经跨过阈值之后才会介入,而且即使介入,它唯一的工作是解释和建议,绝不负责定数字。
完整流程如下:
Webhook 在续约风险事件触发。
请求被验证。
账户在四个源系统中被解析(或被记为未解析并停止)。
四个信号源并行抓取数据。
确定性评分服务计算出风险分数。
低于阈值:记为低风险,流程结束。
达到或超过阈值:一个 LLM 生成流失分析,另一个 LLM 审计它。
审计不同意:路由给 Slack 人工处理。
审计同意:运行护栏检查。
护栏失败:记日志并停止。
护栏通过:针对该账户的最新告警运行去重检查。
是重复:抑制并记日志。
不是重复:发送告警,并把结果回写到 CRM 和 CS 平台。
每个下游系统对同一个账户都有自己的 ID。解析步骤接受内部 ID 或公司名,然后通过映射表进行关联,映射不上时用 ILIKE 模糊匹配公司名作为兜底。如果什么都解析不到,工作流会记日志并停止,而不是胡乱猜测。
评分跑在一个小 FastAPI 服务里,使用固定权重:
总分上限为 1.0。达到 0.65 或以上就是高风险,进入 LLM 分析。其余的记日志后结束。
有一个 Bug 教会我的比这个服务其余部分加起来还多。缺失的活跃数据通过 COALESCE 默认为零。零被解读为"今天活跃过",这恰恰压制了最需要被标记的那些账户:那些完全没有活跃历史的账户。修复方案是用 -1 作为哨兵值,把它当作独立的风险因子来处理,而不是一个静默的默认值。缺失数据本身就是信号,别让默认值把它藏起来。
对于超过阈值的账户,一个 LLM 生成流失分析并给出行动建议。然后由第二个、不同的模型来审计这个输出:证据是否真的支持结论、是否有任何部分被夸大、建议的行动是否与风险程度相称。
审计步骤使用不同的模型很重要。调用同一个模型两次会有相同的盲区。一个真正不同的模型能 catch 更多问题。在测试中,审计器 catch 了一个真实的分歧:一组支持工单表面上看是负面的,但实际上表明的是一个正在完成迁移的活跃客户,而不是即将流失的不活跃客户。那个案例被路由给了人工,而不是基于错误结论发出自动告警。
即使审计通过了,在内容发出之前还有一个护栏步骤检查告警内容:账户负责人是否正确、没有无依据的声明、结构是否符合下游系统的预期。如果失败,就记日志并停止,不会发出。
同一个账户的续约风险事件可能会收到多于一次。朴素的修复是"检查是否已存在告警,如果没有就插入"。这有竞态条件:两个并发请求都可能通过检查,然后才轮到任何一个插入。
真正的修复是在数据库层面在账户和风险分数上加 UNIQUE 约束,这样数据库本身就会拒绝重复插入,而不是依赖应用逻辑来 catch。我用并发请求压测了同一个账户,确认只有一条告警通过了。
工作流的每条路径最终都落在八种明确的已记录结果之一:告警已发送、低风险、重复被抑制、护栏违规、审计分歧、未解析的 ID、无效请求、评分服务不可用。当出问题的时候,问题从来不是"为什么工作流失败了",而是"这个执行落在了八种状态中的哪一种,以及为什么"。
上面的版本一次处理一个事件。扩展出去会有一些变化:
API 网关立即 ack webhook,然后交给队列处理,这样源系统无需等待完整管道。
队列有一个死信主题,用来存放反复处理失败的消息。
n8n 以队列模式运行:一个主实例加多个独立 worker,通过 Redis 协调,这样重的执行不会阻塞新的传入事件。
数据库前面放连接池,因为一群 worker 直连 Postgres 会很快耗尽连接数。
每次执行也往仓库表写一条"黄金记录",这样风险模式可以跨时间分析,而不只是实时反应。
出站调用通过静态出口 IP 发出,因为大多数 CRM 和客服 API 是按 IP 白名单放行,而不是接收任意来源的流量。
先用确定性方式评分。让 LLM 解释,而不是做决定。
把缺失数据当作独立的风险因子,而不是静默默认值。
让第二个、不同的模型扮演对抗角色,而不是重跑同一个模型。
把幂等性推入数据库。应用层检查赢不了竞态。
记录结果,不只是错误。"它失败了"不是诊断。知道自己走到了哪种终结状态,才是。
这些单独拎出来都不复杂。真正让它跑起来的是:坚决不让 LLM 碰任何需要一致性的东西,坚决不让"愉快路径"架构跳过并发和可观测性工作,直到它在生产环境里崩掉。
更多自动化架构内容见 automiq.fi,n8n 模板见 n8n Creator Hub,或在 LinkedIn 上联系。