做工业质量系统这些年,我越来越觉得SPC(统计过程控制)这类经典工具正处在一个尴尬的位置:控制图每天都在生成,报警邮件每天也在发,但现场真正能在报警之后追根因、定对策的,少之又少。很多质量工程师的日常是"打开WebSPC看板、截个异常图、发到工作群",然后就没有然后了。
原因不是大家不重视质量,而是传统SPC系统的能力边界太清晰:网页化只解决了"看图和报表"的问题,判异之后的根因分析依然要靠人工去翻设备参数、查工单批次、核对物料信息,一个异常点查上半天,时间一久自然变成报警疲劳。
这套AI-SPC系统的出发点,就是把这个缺口补上:基于LangGraph编排完整的SPC智能分析流程,基于MCP让大模型安全地触达测量数据、工艺参数、工单系统,把"控制图判异、根因归因、对策建议、审核闭环"串成一个可追踪、可回放、可人工介入的Agent工作流。这篇是工程复盘笔记,适合两类人看:一是有MES、SCADA数据基础、正准备做AI质检智能体的后端或算法工程师;二是质量信息化负责人,想搞清楚AI-SPC到底能落地到什么粒度。
1. 为什么传统WebSPC不够用:先想清楚AI要补哪个环节
1.1 SPC的闭环里,最缺的是"分析"那一环
SPC的核心思想其实很朴素:用统计量判断生产过程是否处于受控状态。传统做法是先按时间顺序采集样本,按子组计算均值、极差或标准差,画成X-bar-R图或X-bar-s图,再套用几条判异准则,超界、连串、趋势都会被标记出来。
这套方法论本身没有问题,问题出在工程落地上。我见过不少企业的WebSPC系统,功能停留在三个阶段中的前两个:第一阶段是单机Excel表格时代,第二阶段是C/S客户端时代,第三阶段才勉强做到B/S网页化,让质量工程师能在浏览器里看到实时控制图和报警列表。
但SPC真正的完整闭环是四件事:过程监控、异常判异、根因分析、对策执行。传统WebSPC很努力地做了前两件,后两件几乎全靠人工。判异规则说"连续6点递增"异常,可为什么递增?是环境温湿度漂移、设备老化、来料批次波动、还是参数设定错误?系统不会告诉你,工程师得自己开一堆系统去查。
1.2 AI-SPC的定位:接管从报警到归因的"中间地带"
我对AI-SPC的理解不是让大模型去画控制图,也不是让它替代质量工程师做最终决策,而是让AI接管"报警之后到拿出候选根因之前"这段最消耗人力的地带。
具体来说,系统要能做三件事:第一,判异规则命中后,自动锁定异常点所在的时间窗口;第二,通过工具调用去查同窗口内的设备参数、工单批次、工艺设定和历史检测数据,形成多维证据;第三,由大模型基于这些证据生成带引用来源的根因假设和处置建议,推送给质量工程师审核。
举个例子,某产线的回流焊温度特征值在X-bar图上连续7点上升,AI不会只说"存在趋势异常",它会去调MCP工具查这段时间的风速设定、链速、加热区温度曲线、当日锡膏批次,然后给出类似"链速从1.02降到0.98、加热区3实测温度偏高6℃,与同批次锡膏活性变化叠加,可能是温区内热电偶漂移"这样的分析。
1.3 为什么会选LangGraph和MCP
这个技术选型是在对比过三条路线之后定的。
第一条路线是传统硬编码:用Python写死判异规则、写死归因查询逻辑,再配一个规则引擎。缺点是每个新场景都要改代码,归因逻辑越加越复杂,完全谈不上智能。
第二条路线是"一个Agent自由发挥":把数据查询工具全部丢给大模型,让它自己决定调用顺序。问题很明显,大模型在关键统计环节可能出现幻觉,也缺乏对流程的可控性,在质量场景里这是不可接受的。
第三条路线就是我们最终采用的LangGraph加MCP:用LangGraph把分析流程定义成有向图,节点是确定性的计算步骤或LLM推理步骤,边决定流程走向,支持条件分支和人机协同;用MCP把所有外部数据能力封装成标准工具,大模型只能通过这些工具拿数,拿不到的部分就明确说"无证据"。这套组合最大的好处是流程可控、过程可回放、权限有边界。
2. WebSPC系统架构总览:数据、服务、Agent三层怎么协作
2.1 从控制图到Agent工作台的完整数据流
整个WebSPC系统可以拆成四层,我们内部习惯叫"前端工作台、接入网关、Agent编排层、MCP工具层"。
前端工作台负责控制图渲染、异常列表和AI报告展示,技术上是常见的Web应用,图表部分用的开源图表库,控制图这类图形本身不复杂,真正复杂的是让用户能在一张图上同时看到原始测量点、控制限、判异标注和AI归因结论。
接入网关是一层FastAPI服务,承担任务创建、身份认证、审计日志和SSE推送。用户在页面上选择工序、时间范围和子组大小,点"开始分析"后,网关创建一条分析任务,之后所有进度都通过服务端推送实时更新到页面上。
Agent编排层是LangGraph实例,负责跑完整个SPC分析流程。MCP工具层则是大模型和外部系统的唯一通道,封装了测量数据服务、工艺参数服务、工单服务、报警通知服务。数据流是这样的:
操作员选择工序和时段 → 网关创建SPC分析任务 → Agent先拉测量数据 → 计算控制图统计量 → 判异规则引擎输出异常点 → 若无异常只生成日常摘要 → 若有异常进入归因节点 → Agent通过MCP并行查询工艺参数、工单批次、设备信息 → 生成带证据的根因假设 → 推送到前端等待质量工程师审核 → 审核通过后自动创建改进措施任务。
2.2 三层架构的边界划分
这个系统最核心的设计决策,是把"确定性计算"和"智能推理"严格分开。
统计量计算和控制限计算属于确定性逻辑,不允许大模型参与。X-bar-R图的均值、极差、标准差、控制限,每一个数值都必须能追溯回原始数据,接受任何精度审查。这部分我放在独立的判异规则引擎里,输入是一段时间的测量数据,输出是结构化判异结果,比如哪个点触发了哪条规则、超了多少倍标准差。
智能推理部分则交给LangGraph里的Agent节点,让它负责语义层面的归因分析。这里有个很容易犯的错误,就是一开始我们试图用大模型直接判断"这个点是否异常",效果非常不稳定。同样的数据多问几次会得到不同的结论,这不是模型笨,而是数值判异本来就不该交给语言模型。
2.3 为什么在这个架构里同时需要LangGraph和MCP
LangGraph解决的是"流程怎么走",MCP解决的是"能力怎么接",两者不冲突也不重叠。
没有LangGraph,MCP工具给了大模型之后,调用顺序和分支逻辑是失控的。没有MCP,LangGraph的节点想查数据只能写死数据库连接,那权限、审计和跨系统调用又会变成一笔糊涂账。
我把二者分工讲得直白一点:LangGraph是项目经理,它决定先做统计、再判异、再归因、再审核;MCP是后勤接口,它规定项目经理只能通过指定的单据去领料,不能自己闯进仓库乱翻。这样即使哪天LLM换了一个更强的版本,甚至换成开源模型,整个流程骨架都不会塌。
3. LangGraph编排AI-SPC分析流程:状态驱动的智能体实现
3.1 先定义状态:一次SPC分析会话的工作记忆
LangGraph的编程模型和普通函数调用最大的区别在于:整个工作流共享一个状态对象,像一张不断被填写的工作台,每个节点只负责更新自己关心的字段,读自己需要的字段。状态用类型字典定义,下面是我们SPC分析任务的状态结构:
from typing import TypedDict, Optional class SPCState(TypedDict): task_id: str process_id: str time_range: tuple[str, str] subgroup_size: int measurements: list[dict] statistics: dict rule_hits: list[dict] anomaly_points: list[dict] evidence: dict[str, list[dict]] hypotheses: list[dict] countermeasures: list[dict] review_status: str report_id: Optional[str]这个状态设计有几个隐性的好处。一是可持久化,分析过程中途挂掉,可以从checkpoint恢复;二是可追踪,每个节点执行前后把状态快照落库,出了错能回放整个分析路径;三是天然支持多轮交互,质量工程师在审核节点补充了信息后,状态里的hypotheses可以被修正并进入下一轮分析。
3.2 节点与条件分支:异常才进入归因,正常只出摘要
我们把一次分析定义成下面这些节点,节点名和函数一一对应:load_measurements、compute_statistics、run_rules、summarize_only、investigate_anomalies、generate_hypotheses、propose_actions、human_review。
关键在于条件分支的写法。run_rules执行完判异规则后,根据rule_hits是否为空决定走哪条路:没有异常就走summarize_only节点,生成一段"该时段过程受控"的简短摘要,直接结束,不浪费LLM调用;有异常才进入investigate_anomalies。对应LangGraph的图构建逻辑大致是这样:
from langgraph.graph import StateGraph, END workflow = StateGraph(SPCState) workflow.add_node("load", load_measurements) workflow.add_node("stat", compute_statistics) workflow.add_node("rules", run_rules) workflow.add_node("summarize", summarize_only) workflow.add_node("investigate", investigate_anomalies) workflow.add_node("hypothesis", generate_hypotheses) workflow.add_node("action", propose_actions) workflow.add_node("review", human_review) workflow.set_entry_point("load") workflow.add_edge("load", "stat") workflow.add_edge("stat", "rules") workflow.add_conditional_edges( "rules", route_by_anomaly, {"normal": "summarize", "anomaly": "investigate"} ) workflow.add_edge("investigate", "hypothesis") workflow.add_edge("hypothesis", "action") workflow.add_edge("action", "review") workflow.add_edge("summarize", END) workflow.add_edge("review", END)route_by_anomaly是根据rule_hits是否为空返回分支名的纯函数。这种显式的条件边比直接在节点内写if-else要清晰得多,因为每个分支都是一等公民,可以被单独测试,也可以在图上直观呈现。
3.3 人机协同节点:让质量工程师"插队"介入
SPC场景的特殊性在于AI不能拍板。根因假设可以大胆生成,但最后的处置决策必须交给有经验的质量工程师确认。
我们用的是LangGraph的human-in-the-loop机制:propose_actions生成对策草案后,流程在human_review节点暂停,状态落到数据库,前端工作台收到事件后展示"待审核"卡片。质量工程师可以点通过,也可以填一段修正意见,比如"链速变化不是主因,优先查热电偶"。修正意见会写回状态,触发流程从generate_hypotheses重新再跑一轮。
这个设计决定了系统能否真正上线。没有人工确认节点的AI-SPC,在质量管理体系里是站不住的。你在前端看到的不是"AI自动完成分析",而是"AI提出假设,人做判断,系统记录整个决策链"。
3.4 可追踪设计:每个分析步骤都能回放排查
所有节点的输入、输出、调用的MCP工具、耗时,都会写入审计表。每一条记录对应一次完整分析会话,关联task_id。上线之后我们排查问题基本都是靠这个回放机制。
有一次典型排查:某个工序的判异规则明明命中了,但生成的报告里没有归因结论。回放发现是MCP查询工艺参数时超时,导致evidence为空,generate_hypotheses节点在"没有证据"的情况下选择直接退出。后来我们在节点里加了降级策略:部分证据缺失时,明确标注"证据不完整,假设置信度下调",而不是静默失败。
4. MCP接入层实战:让大模型安全地触达生产数据
4.1 把SPC周边能力封装成MCP工具
MCP层的设计原则只有一个:大模型能调用的能力,必须全部经过显式定义,数据库连接字符串绝对不能出现在Agent进程里。
我们封装了四组MCP工具。测量数据服务提供get_measurements_by_range,用于查询指定工序在指定时间窗口内的原始测量值;工艺参数服务提供get_process_parameter_history,用于查设备参数、温湿度环境参数的历史曲线;工单服务提供get_work_order_by_batch和get_material_batch_info,用于把异常时间窗口的物料批次信息捞出来;报警通知服务提供notify_quality_alert,用于审核通过后自动通知相关人员。
每个工具都有独立的服务进程,MCP Server和Agent进程通过标准协议通信。这样做的好处是,任何一个工具服务挂了,Agent能明确感知到哪个数据源不可用,而不是整个分析流程崩溃。
4.2 一个工具定义的完整示例与调用时序
以测量数据服务为例,MCP工具定义如下:
{ "name": "get_measurements_by_range", "description": "查询指定工序在指定时间段内的测量值序列,返回按采集时间排序的数据点。", "inputSchema": { "type": "object", "properties": { "process_id": {"type": "string"}, "start_time": {"type": "string", "format": "date-time"}, "end_time": {"type": "string", "format": "date-time"}, "limit": {"type": "integer", "default": 5000} }, "required": ["process_id", "start_time", "end_time"] } }LangGraph的归因节点在调用这个工具时,会先拿到一批候选数据,再进行下一步分析。真正的调用时序是:
首先判异节点输出异常点在10:12到10:35之间,归因节点把时间窗传给get_process_parameter_history,查温度、湿度、风速等参数;再调get_work_order_by_batch,确认这段时间生产的批次号;两个查询结果都进入状态里的evidence字段。LLM只负责阅读evidence字段并推理,不能自己去构造数据。
4.3 权限边界、审计日志和幻觉控制
MCP工具虽然好用,但权限问题必须前置设计。我们的做法是按工具粒度做白名单:某个Agent只能调用分配给它的工具,质量工程师角色能看到全部工具调用记录,但普通操作员只能看到结果摘要。每次工具调用的入参、返回数据条数和耗时都记审计日志。
幻觉控制是这个环节的重中之重。大模型在归因时最大的风险不是"答错",而是"答得有理有据但数据是编的"。我们做了两条硬约束:一是所有假设必须引用MCP返回数据中的字段,报告里"证据"区域只能渲染真实返回的数据条目;二是结构化输出校验,LLM必须返回指定JSON格式,其中evidence_ids必须对应证据列表里的真实索引,校验不通过就重新生成。
实测下来,加了这些约束之后,归因假设的采纳率有明显提升,而且即使假设错误,质量工程师也能从证据链里快速定位是哪条依据不成立。
5. 核心实现细节:控制图计算、判异规则与自动报告
5.1 计算X-bar/R图控制限,这部分必须可靠
控制图是整个系统的数据地基,统计量算错后面全错。我们常用的子组大小n=5,X-bar-R图的控制限公式如下:
子组均值X̄和子组极差R由样本数据直接计算,总体估计量为X̄的平均值和R的平均值。X-bar图的控制限为UCL = X̄ + A2 × R̄,LCL = X̄ - A2 × R̄;R图的控制限为UCL = D4 × R̄,LCL = D3 × R̄。查表可知n=5时A2≈0.577,D3≈0,D4≈2.114。
对应的Python实现:
import numpy as np def xbar_r_limits(subgroups: list[np.ndarray]) -> dict: x_bar = float(np.mean([np.mean(g) for g in subgroups])) r_bar = float(np.mean([np.max(g) - np.min(g) for g in subgroups])) A2, D3, D4 = 0.577, 0.0, 2.114 # 子组大小为5时查表 return { "x_bar": x_bar, "r_bar": r_bar, "x_ucl": x_bar + A2 * r_bar, "x_lcl": x_bar - A2 * r_bar, "r_ucl": D4 * r_bar, "r_lcl": D3 * r_bar }这段代码看起来简单,但有几个前置细节。子组划分规则必须和生产节拍对齐,不能简单按固定条数硬分;测量数据要先做异常点清洗,但不允许随意剔除"看起来不对"的点,剔除必须留痕;控制限用历史数据滚动计算还是固定学习期计算,要跟工艺工程师确认清楚。
5.2 常用判异规则的工程化实现
我们把常用判异规则做成了可配置的规则集,每条规则都是独立函数,输出规则编号、命中的点、严重程度。下面是我们启用的主要规则:
| 规则编号 | 判异描述 | 典型含义 |
|---|---|---|
| 规则1 | 单个点超出3σ控制限 | 过程突然失控或测量异常 |
| 规则2 | 连续9点落在中心线同一侧 | 过程均值发生偏移 |
| 规则3 | 连续6点单调递增或递减 | 存在持续趋势性变化 |
| 规则4 | 连续14点相邻点交替上下 | 数据存在混合分布或过度调整 |
| 规则5 | 连续3点中有2点距中心线超过2σ(同一侧) | 均值漂移早期信号 |
| 规则6 | 连续5点中有4点距中心线超过1σ(同一侧) | 过程变异增大 |
| 规则7 | 连续15点落在中心线1σ范围内 | 数据分层或可能是假数据 |
| 规则8 | 连续8点距中心线均大于1σ(同一侧) | 长期偏移累积 |
有一个工程经验值得展开说:多条判异规则联动时误报率会叠加,如果严格按"命中任意一条就报警",很多稳定工序会被频繁打扰。我们的做法是给每条规则配置权重,比如规则1权重是3,规则5是1,只有当命中规则的加权分达到阈值时才升级为人工关注。这个阈值可以先保守设高,跑两周再看报警收敛情况。
5.3 自动生成带证据引用的根因分析报告
归因节点产出的不是一段自由文本,而是结构化的分析报告,包含异常概述、统计依据、证据条目、根因假设列表、对策建议、待确认事项六部分。
生成逻辑分成两步。第一步是提取差异特征,把异常时间窗口的工艺参数和历史基线窗口做对比,比如"设定温度240℃、实际均值246.3℃、偏差超过基线1.8倍标准差",这一步是确定性计算,避免LLM凭空比较数值。第二步才是LLM的语义归纳,让它基于差异特征和工单信息生成假设,每个假设都要标明支持证据和置信度。
报告整体推送到前端时,质量工程师可以逐条查看证据来源,点开某条证据就能看到原始数据时间序列。这个"可追溯"特性是系统能获得信任的关键,如果只给结论不给证据,这套AI-SPC大概率会被当成玩具。
6. 从Demo到产线试点:实测结果和高频坑
6.1 试点场景和关键效果
我们在某电子制造企业的SMT车间做了两条产线的试点,范围是回流焊温度特征值的X-bar-R图监控。试点周期四周,从只读模式切到"AI建议+人工确认"模式。
有两个数字印象很深。第一个是日均报警次数从原来的37次降到12次,主要功劳是规则权重分级,把大量低严重度规则命中降级为日志记录而不是工作群打扰。第二个是从报警到拿到首版候选根因的时间,从平均三四个小时压缩到系统自动分析的三四分钟之内,质量工程师审核后再决定是否继续深入。
当然,归因建议不是每条都对。四周试点的AI候选根因被审核采纳的占比大约是六成,另外四成里有一半是证据不足被驳回,剩下一半是质量工程师补充了业务背景后修正了结论。这个结果比预期好,但离全自动还有距离,也正因为有这四成的"不靠谱",我们已经把"人工确认"列成了架构里的强制节点。
6.2 高频问题排查表
把试点过程中踩过的坑整理成一张表,排在前面的几个最值得记住:
| 现象 | 根因 | 解决方案 |
|---|---|---|
| 控制图在换班节点出现规律性"跳变" | 采集服务时区不统一,数据落库用了本地时间 | 统一按UTC存储,前端按展示时区转换 |
| LLM生成了数据中不存在的"峰值"描述 | 未强制引用MCP返回字段 | 证据白名单+结构化输出校验 |
| MCP查询在大数据量下超时 | 工具服务未做分页和超时降级 | 默认limit分页,超时降级为证据不完整提示 |
| 同一条规则报警密集轰炸 | 权重未分级,规则联动误报 | 规则加权计分,低权重命中只记录不打扰 |
| LangGraph重放历史任务时状态错乱 | 检查点未关联外部task_id | 状态快照按task_id持久化,恢复时重放节点日志 |
时区问题是我们第一天就被坑到的:产线采集系统用的是本地时间,数据库是另一个时区,凌晨班次的数据画出来全是锯齿。后来统一成UTC存储才算根治。这个问题在文档里很难提前预料,但一旦出现,排查成本很高,还是靠审计表中的时间戳比对发现端倪。
6.3 一点复盘:这套架构到底改了什么
回头看,LangGraph和MCP的引入并没有推翻SPC本身,相反,它们是让SPC重新被"用起来"的基础设施。
LangGraph解决的是流程编排复杂度。当分析链路里存在确定性计算、LLM推理、人工审核三种节点,并且有回退、重试、条件分支时,图的表达能力比链式调用强太多。MCP解决的是系统间集成复杂度。它把测量数据、工艺参数、工单系统、报警通知统一成标准接口,Agent侧不需要知道这些数据存在哪、怎么连,只需按工具契约调用,权限和审计也天然有了边界。
我个人最大的体会是,不要一上来就追求全自动闭环。AI-SPC最有价值的落地形态,是"AI负责把脏活累活干完,把最可能的答案和证据一起摆到人面前,人负责最后拍板"。这个分工越早想清楚,架构越稳,现场越愿意用。
最后再分享一个小建议:别拿美化过的演示数据跑AI-SPC,直接拉一个月的真实历史报警数据离线回放一遍,你会发现光是align班次、时区、批次信息就够忙一阵子的。但这步做完,后面上线时的麻烦会少掉一大半。我们就是这样在正式部署前用历史数据把判异规则的误报率反复压下来的。