AI PLAY玩法更新持续收录
← 回到更新流

2026-09-03 · 原文发布日

药品投诉趋势挖掘并触发CAPA升级

流程定时从投诉系统API拉新投诉并去重,把每条叙述交给Claude提取产品、批次、缺陷类别和严重度(解析失败走安全默认值),再按产品加缺陷类别聚类,用z分数对照滚动历史均值检测异常激增;被判为统计异常的簇会经HTTP API建CAPA升级单并发Slack告警,所有簇都写入趋势存储API供持续追踪。灵敏度、基线和各端点均可配。

原文要点

n8n模板库Oneclick AI Squad发布的药品投诉趋势工作流,非付费模板。定时或手动触发后从投诉系统API拉取新投诉,用工作流静态数据去重,无新件直接结束、不调用模型。每条叙述交Anthropic Claude提取产品、批次、缺陷类别与严重度,解析失败回落安全默认值;按产品加缺陷类别聚类,对照滚动历史均值计算z分数并更新基线。被判定统计异常的簇经HTTP API创建CAPA升级单并向Slack频道(默认#quality-capa-escalations)告警,全部簇写入趋势存储API。需为投诉源、CAPA、趋势存储各配HTTP Header Auth凭据,加Anthropic与Slack凭据,端点与z分数灵敏度在配置步调整。

这次做成什么

在自有n8n环境复刻“定时拉新→去重→AI结构化抽取→聚类→z分数异常检测→CAPA升级与Slack告警→趋势归档”的完整监测流水线。本站提供独立练习方案:用合成投诉JSON代替真实投诉系统、给出抽取提示词与z分数参考代码,演示5条投诉聚成4个簇、其中1个触发CAPA升级的全过程。

准备什么

  • n8n实例,支持Schedule Trigger、HTTP Request、AI Agent与Slack节点
  • Anthropic API密钥,以及可发帖的Slack工作区并建好目标告警频道
  • 投诉源、CAPA工单、趋势存储三个HTTP端点;练习阶段可用本站模拟JSON替代
  • 理解均值、标准差、z分数的基本概念,以便调整异常判定灵敏度

具体怎么做

  1. 集中配置参数

    在流程开头放Set节点作为配置步:写入三个端点URL、Slack频道名(练习用#quality-capa-escalations)、z分数阈值(本站练习取2.5)、滚动窗口长度(12期)与最少历史期数(4期)。后续节点统一用表达式引用该配置,避免阈值散落各处难以调参。

  2. 定时拉取与去重

    Schedule Trigger按小时或每日触发,HTTP Request节点带Header Auth凭据GET投诉源API的近期投诉列表。接Code节点读取工作流静态数据(this.getWorkflowStaticData)中已处理的complaint_id集合,过滤重复后立即写回更新后的集合;若过滤后为空,走结束分支,不发任何Anthropic请求,控制模型费用。

  3. Claude结构化抽取

    对每条新投诉添加AI Agent节点挂Anthropic模型,系统提示使用本站抽取提示词,要求只输出含product、batch_lot、defect_category、severity的JSON。后接Code节点try/catch解析:失败时填安全默认值defect_category=unclassified、severity=medium、product=unknown,并打parse_failed=true标记,单条坏输出不中断整批。

  4. 聚类与z分数检测

    Code节点按product+defect_category拼key聚合本周计数。对每个簇,从趋势存储(练习用本地JSON)读取该key的历史周期计数,代入本站z分数代码:z=(本周计数-均值)/标准差,标准差为0时z记0;历史不足最少期数不判异常。满足z大于阈值即anomaly=true,并把本周计数追加进滚动窗口作为下周基线。

  5. 升级、告警与归档

    IF节点按anomaly分流:true分支用HTTP Request向CAPA端点POST建单(body含cluster_key、count、z_score、sample_ids),再用Slack节点向告警频道发簇摘要;false分支跳过升级。最后所有簇统一POST到趋势存储API记录count、mean、std、z_score与anomaly,供下周对照与持续追踪。

可直接复制的材料

Claude投诉结构化抽取提示词

本站独立编写,可直接粘贴为AI Agent系统提示;缺陷类别枚举可按贵司分类体系增删,但要与聚类口径一致。

你是药品质量投诉结构化助手。阅读一条投诉叙述,抽取四个字段并只输出一个JSON对象,不要输出任何解释文字。
字段要求:product为产品名,无法识别填"unknown";batch_lot为批号,无法识别填"unknown";defect_category只能从[packaging, contamination, labeling, efficacy, adverse_reaction, device_malfunction, other]中选一个;severity只能选low、medium、high、critical,叙述含糊时选medium。
投诉叙述:{{narrative}}
输出格式:{"product":"...","batch_lot":"...","defect_category":"...","severity":"..."}

z分数异常检测Code节点参考代码

本站独立编写的参考实现;clusters输入需由聚类节点组装,history来自趋势存储的滚动窗口。

const clusters = $json.clusters; // [{key, count, history:[...]}]
const zThreshold = 2.5;   // 本站练习设定,实际在配置步调整
const minHistory = 4;     // 历史不足该期数不判异常
return clusters.map(c => {
  const h = c.history || [];
  const mean = h.length ? h.reduce((a,b)=>a+b,0)/h.length : 0;
  const variance = h.length ? h.reduce((a,b)=>a+(b-mean)**2,0)/h.length : 0;
  const std = Math.sqrt(variance);
  const z = std > 0 ? (c.count - mean)/std : 0;
  const updated = [...h, c.count].slice(-12);
  return { json: { cluster_key: c.key, count: c.count, mean: Number(mean.toFixed(2)), std: Number(std.toFixed(2)), z_score: Number(z.toFixed(2)), anomaly: z > zThreshold && h.length >= minHistory, history_next: updated } };
});

合成投诉测试数据

本站虚构投诉数据,产品名与批号均为编造;练习时让投诉源端点返回此JSON即可模拟一次拉取。

[
 {"complaint_id":"CMP-1001","narrative":"患者反映止痛灵批号PL2603的铝箔泡罩破损,两片药片受潮变色。","received_at":"2026-09-01"},
 {"complaint_id":"CMP-1002","narrative":"药店反馈止痛灵批号PL2603外包装盒印刷批号与内板批号不一致。","received_at":"2026-09-01"},
 {"complaint_id":"CMP-1003","narrative":"用户称服用降压平BJ2508后出现轻微头晕,停药后缓解。","received_at":"2026-09-02"},
 {"complaint_id":"CMP-1004","narrative":"医院报告止痛灵PL2603泡罩密封开裂,怀疑运输途中受潮。","received_at":"2026-09-02"},
 {"complaint_id":"CMP-1005","narrative":"消费者投诉止咳糖浆瓶口塑封缺失,瓶身批号看不清。","received_at":"2026-09-03"}
]

输入与输出示例

本站虚构演示,未实际调用Claude或任何API;z值按所给历史手工核算,抽取结果按叙述内容推定。

输入

投诉源返回上方5条合成投诉;趋势存储中止痛灵|packaging的历史8期计数为[0,1,0,1,0,0,1,0],其余簇历史为[0,0,1,0]。

对应输出

{"processed":5,"anthropic_calls":5,"parse_failed":0,"clusters":[{"cluster_key":"止痛灵|packaging","count":2,"mean":0.38,"std":0.48,"z_score":3.36,"anomaly":true,"capa_ticket":"CAPA-2026-014","slack":"#quality-capa-escalations"},{"cluster_key":"止痛灵|labeling","count":1,"mean":0.25,"std":0.43,"z_score":1.74,"anomaly":false},{"cluster_key":"降压平|adverse_reaction","count":1,"mean":0.25,"std":0.43,"z_score":1.74,"anomaly":false},{"cluster_key":"止咳糖浆|packaging","count":1,"mean":0.25,"std":0.43,"z_score":1.74,"anomaly":false}]};仅止痛灵|packaging触发CAPA建单与Slack告警,4个簇全部写入趋势存储。

做完检查这些

  • 同一批complaint_id重复运行,第二次显示0条新投诉且Anthropic调用数为0
  • 提交一条无任何批号与产品线索的含糊投诉,得到parse_failed=true、defect_category=unclassified、severity=medium
  • 止痛灵|packaging簇本周计数2、历史均值0.375、标准差约0.484时,z约3.36并生成CAPA单与Slack消息
  • 历史不足4期的簇即使z超过2.5也不升级,只写入趋势存储
  • 分别停用三个HTTP凭据,执行日志能明确指出是哪一个端点鉴权失败

容易卡住的地方

  • 冷启动没有历史基线时z分数失真,先积累数周数据再开升级,否则误报淹没质量团队
  • 工作流静态数据主要在生产执行中持久,手动测试的去重记录未必保留,联调时留意重复拉取
  • Claude偶发在JSON外附加解释文字,解析必须try/catch并回落安全默认,不能中断整批
  • 阈值2.5、窗口12期、最少4期均为本站练习值,实际灵敏度需按投诉量级在配置步核定
  • 原文默认Slack频道名与三个端点都是占位,照抄会把告警发到不存在的频道
  • 合成数据仅供隔离练习,不要把真实患者投诉内容混入测试环境

原文与作者资料 ↗

本站借助AI整理来源事实,独立编写中文操作指南与示例。示例不代表实际运行结果;来源效果尚未由本站独立复现。付费模板与模型、服务费用分别计算。

原文标题
Mine pharma complaint trends and trigger CAPA alerts with Claude and Slack
原作者
Oneclick AI Squad
原始发布日期
2026-09-03T13:42:42.860Z
来源
https://n8n.io/workflows/19132