我在工厂大模型产线上烧了8个月,才发现运维得重学概率论

我是沈青锋,第三次创业。第一次做SaaS,踩了定制化需求的坑;第二次搞物联网硬件,烧了供应链的钱。这次我盯着传统制造业,用AI改造产线。具体来说,是给工厂上大语言模型和视觉大模型,做质检、排程和异常检测。客户是那些利润薄、不敢轻易停线的中小型制造商,年营收在2到5个亿之间。他们的问题很直接:人工质检漏检率3-5%,排程靠老师傅经验,异常停机一次损失几万块。

前两次创业教会我一件事:技术得能用ROI说话,别画饼。所以我带团队进车间,先跑可行性验证,再签合同。但我们栽在一个意想不到的地方——不是模型精度不够,而是运维模型的不确定性。当大模型开始生成输出,传统运维那套确定性思维就废了。这不是升级工具的问题,是得从工程文化上重构我们怎么管生成结果。

这篇文章不推荐任何工具,也不谈未来趋势。我只分享在真实产线上,面对不可预测的输出、难以复现的缺陷和持续漂移的模型,我们怎么把运维哲学从“控制”转向“治理概率”。

30秒速览

  • - LLMOps核心挑战是管理生成结果的不确定性,MLOps的确定性运维思维在此失效。
  • - 关键实践:监控输出分布(而非单点错误)、接受不可复现、构建概率治理文化。
  • - 新角色模型可靠性工程师(MRE)负责模型行为观测、人机协同和成本控制。
  • - 在制造业落地中,输出漂移、模型腐化和成本失控是最大陷阱,需用容错和试验应对。
  • - 运维文化从“控制状态”转向“治理概率”,引入JS散度监控、灰度推理和人机仲裁。

第一次看见大模型在产线上“发疯”

真实场景:苏州一家PCB厂的视觉质检

2024年10月,我们和苏州一家印刷电路板(PCB)制造商签约。他们每天产20万片板子,6条SMT贴片线,用5个质检员轮班。痛点很明显:人工疲劳导致漏检,尤其是微小焊点缺陷,尺寸误差在50微米以内。漏检一旦流入下游组装,退货成本每次10万元起。(延伸阅读:当我用骁龙X Elite跑通YOLOv8的NPU推理,才发现Copilot+不过是道开胃菜

我们的方案是用视觉大模型做自动化质检。不自己训练模型(那太贵且数据不足),而是基于开源视觉模型,用他们的历史缺陷图片fine-tune一个分类头。模型输入是工业相机拍的高清图(2048×1536像素),输出是“合格”、“焊点缺陷”、“线路刮伤”等6个类别。系统部署在边缘服务器上,每张图推理时间200毫秒,一天处理2万张。

上线第一周,漏检率从原来的4.2%降到1.8%,客户很满意。但第二周,问题来了:同一个电路板位置,模型下午2点和2点10分的判断结果不同。有时把合格板判为“焊点缺陷”,有时反向。质检员开始不信任系统,甚至关掉自动判读,回去人工抽检。

输出不可预测:不是bug,是特征

我拉上团队紧急排查。检查代码,没动过;检查相机,灯光稳定;模型权重,是同一个。但输出分布确实在漂移。用几批测试图像发现,模型对“焊点缺陷”类的置信度从0.92降到了0.78,但精度没变。为什么同样的输入,输出概率分布变了?

这就是大模型的概率本质。视觉大模型不是确定性的if-else,它在隐空间做自注意力计算,受输入噪声(灯光微妙变化)和模型内部状态影响。即使输入像素值相同,浮点运算顺序不同(CPU vs GPU线程调度),也可能导致输出差异。更致命的是,fine-tune后的模型容易过拟合特定批次数据,遇到新的纹理分布就“犹豫”。

我们没写一行bug,但系统行为在变。这个教训花了我们6个月——不是技术实现难,是接受这个事实:大模型产线里,可复现性不再是默认保证。

ROI被运维成本吃掉

为了稳定输出,我们加了几个措施:重新采样推理(对可疑图像跑3次投票)、人工抽检复核、更新fine-tune数据。结果运维成本飙升:GPU服务器从1台加到2台,质检员反而多了1个负责复核,模型更新每月一次,需要停线2小时。算总账:系统省下的质检人力成本是15万/年,但额外运维支出8万,净收益缩水。

这不是工具选的不好,是我们没意识到大模型运维的本质——管理不确定性,而不是消除它。

确定性运维的旧地图,找不到概率系统的新逻辑

传统运维的三根支柱:声明式、不可变、可复现

干了十多年软件,我熟悉的运维围绕几个核心:声明式配置(Kubernetes YAML)、不可变基础设施(容器镜像,一次构建到处运行)、可复现的部署(代码版本+环境锁死)。监控指标清晰:CPU使用率、内存、P99延迟、错误率。出问题,看日志,定界,回滚。(延伸阅读:我把SD 1.5搬上骁龙X Elite NPU,单步1.2ms延迟背后是4个仿真没告诉我的坑

这个大模型质检系统却让这些支柱摇摇欲坠。比如,声明式配置:我怎么声明模型的输出行为?定义一个“允许的置信度波动范围”?但波动是模型的内在特性。不可变基础设施:模型权重文件是唯一的变量吗?不,推理时的环境(温度、噪声)也在变模型。可复现部署:同样模型,同样输入,不能保证同样输出。

传统运维假设系统是确定性状态机,大模型却是个概率分布函数。

两个世界的分水岭:从管理状态到管理分布

用一张表说明白这差异。下表是我在项目中总结的,MLOps和LLMOps在相同维度上的对比。注意,MLOps虽然处理模型版本和漂移,但最终是处理结构化预测(分类、回归),输出有明确的正确值。LLMOps处理生成任务,输出是文本或序列,正确与否不再是二值。

维度 MLOps (传统机器学习运维) LLMOps (大模型运维)
输出本质 离散值/分数,有明确标签或指标 生成序列,正确性取决于语义和上下文
故障模式 模型精度下降、数据分布偏移 输出幻觉、风格突变、偏见、与业务逻辑冲突
版本控制对象 模型权重、训练数据、特征流水线 同上,外加推理参数(温度、top-p)、提示词版本
测试方法 离线的测试集A/B测试,精确率/召回率等 需要人工评估或辅助Judge模型,指标如BLEU/ROUGE可能失效
运维核心指标 服务延迟、吞吐量、预测偏差 成本/调用、输出语义漂移、用户干预率
可复现性 通常可复现,锁定环境和随机种子 很难完全复现,需接受概率波动

我们的误区:一开始用MLOps的理念套LLMOps。建了模型注册表,用Jenkins pipeline部署,监控用Prometheus。但没人监控“质检输出语义是否合理”,只监控推理延迟。当质检员反馈结果奇怪时,我们看监控一片绿灯,延迟100ms,错误率0.1%,但“奇怪”体现在概率分布上,传统仪表盘看不见。

我意识到,运维必须升级到观测模型的行为“气味”,而不仅是健康。这需要新的文化。

模型腐化、输出漂移、成本失控——三个没预料的泥潭

模型腐化:大模型在产线上“失忆”

模型腐化是我造的词,指模型在部署后,由于环境数据与训练数据差异累积,性能逐步退化。对于我们的PCB质检模型,腐化来自两方面:第一,上游工艺调整。客户为降低成本,换了焊料品牌,焊点反光特性不同,模型没在新的样本上训练,开始误判。第二,时间跨度。生产6个月后,产线积累了大量新缺陷类型(如新的划伤纹理),模型不认识,置信度要么极高(错判)要么极低(丢弃)。

我们每月做一次模型重训,但发现问题时,废品率已波动了1个百分点。这个腐化是逐步的,像温水煮青蛙。不是一次大故障,是输出分布持续向左移。

输出漂移的调试:从日志到概率诊断

输出漂移更难抓。同一个位置、同一光照下,模型对一张合格板的“合格”置信度从95%跌到88%,没低于阈值,但下游操作员开始质疑。调出日志,输入图像字节完全一样,模型版本一样。我们做了逐层activation对比,发现中间层特征权重在热更新(动态量化优化)后微变,但理论上不该影响结果。

根源:推理引擎为了加速做了算子融合,浮点精度取舍不同。这是一个软硬件栈的堆叠不确定性。我决定不再追求完全一致的输出,而是监控输出分布。写了一段代码来捕捉这种漂移,它不关心单个结果对错,只检测整体分布是否突变。(延伸阅读:我们的工厂大模型被提示注入攻破三次后,我翻遍了攻防武器库


# 监控视觉大模型输出分布的漂移
import numpy as np
from scipy.spatial.distance import jensenshannon
from collections import deque
import time
import json

class OutputDriftMonitor:
    def __init__(self, num_classes=6, window_size=1000, drift_threshold=0.15):
        self.num_classes = num_classes
        self.window_size = window_size
        self.drift_threshold = drift_threshold
        self.reference_dist = None  # 参考分布
        self.current_window = deque(maxlen=window_size)

    def set_reference_dist(self, dist_array):
        """基线概率分布,来自最初验证集"""
        assert len(dist_array) == self.num_classes
        self.reference_dist = np.array(dist_array, dtype=np.float64)

    def add_inference(self, probabilities):
        """每次推理调用传入概率向量,如[0.92, 0.01, ...]"""
        self.current_window.append(probabilities)
        if len(self.current_window)  self.drift_threshold

        # 记录日志(可对接监控系统)
        log_entry = {
            "timestamp": time.time(),
            "js_divergence": js_dist,
            "current_dist": current_avg_dist.tolist(),
            "reference_dist": self.reference_dist.tolist(),
            "drifted": drifted
        }
        print(json.dumps(log_entry))
        return drifted, js_dist

# 典型用法
monitor = OutputDriftMonitor(num_classes=6, window_size=500)
# 设置参考分布为:合格0.95, 焊点缺陷0.02, 线路刮伤0.01...
monitor.set_reference_dist([0.95, 0.02, 0.01, 0.01, 0.005, 0.005])

# 推理循环中调用
for prob_vec in inference_stream:
    drifted, js = monitor.add_inference(prob_vec)
    if drifted:
        print("警告:输出分布漂移,JS散度=%.3f" % js)
        # 触发重校准或人工抽检

这个脚本没解决漂移原因,但让不可见变成可见。我们用Grafana展示JS散度趋势,当超过阈值时,自动触发抽检流程。从被动救火变成主动治理。

成本失控:每张推理的钱流去哪了

大模型推理成本不是固定的。质检模型原来用NVIDIA L40S GPU,一张图片平均0.03元成本(电费+硬件折旧)。后来引入二次投票,成本变成0.09元。再考虑模型更新训练、存储、边缘设备运维,单张板质检成本到了0.15元。对比人工成本0.1元,反而更贵。更可恨的是,成本上涨不是一次性的,是随着“为了稳定输出”而叠床架屋。

我们开始用FinOps角度追踪,将成本归属到每个推理调用。比如,编写成本仪表板代码,实时展示每千次调用的花费。但问题是,成本控制也得拥抱不确定性——你无法提前知道哪个batch会触发再推理。所以我们设了预算上限和优先级队列,高价值产线用更多资源,低价值做降级。

教训是:大模型运维里,成本是与概率绑定的,得动态治理。

声明式和不可变那套,在大模型面前碎了一地

声明式配置的困局:我怎么能声明“输出不该有创意”?

传统运维中,声明式配置定义最终状态,系统自己收敛。比如K8s Deployment:我要3个pod副本,它就维持3个。在大模型质检中,我“声明”的是:模型准确率>99%。但系统怎么自动收敛?调整模型温度?增加提示词?模型本身没有收敛机制。输出是生成的,不是控制的。

我们试过用K8s的自定义资源(CRD)描述模型要求,写Operator去动态调整模型温度。但效果很差,因为温度调低,模型变得保守,拒绝的图片增多;调高,幻觉多。这不是收敛,是跷跷板。声明式在这里失效,因为目标状态不是离散的,是一个概率空间。

不可变基础设施的幻想:每变一次模型,产线就抖一抖

“不可变”思想要求环境一致性。但实际产线上,环境永远在变:灯光衰减、相机镜头脏污、产品批次不同。这些变化反馈到模型,就需要模型更新适应。模型必须可变,但不可变发布。我们试过版本化模型,类似镜像标签,但模型输出不是镜像二进制,它的行为在推理时就变了。

一次教训:我们发布了一个“更准”的模型版本v1.2,测试集精度提升了0.8%,但上线后,老图(来自旧批次)的拒收率大幅上升。因为新模型过拟合了新数据。不可变的模型版本,输出行为却不可控。最后我们只能做“灰度推理”:同时部署新旧模型,用影子流量对比,人工确认才切换。(延伸阅读:AWS Inf2推理实例:号称成本直降40%,但我的压测数据揭示了什么投资委员会必须知道的事

可复现调试的失败:同一张图,我抓不到那个bug

最痛苦的是调试一个间歇性误判。操作员反映,板子ID 20250315_1432有次被判“缺陷”,复检时又判“合格”。我们抓取这张图,本地Docker环境跑同样模型,复现率为0。后来发现,生产服务器用A100 GPU,本地用A10,算子细节不同。概率性系统里,bug不能固定,只能通过大量采样估计发生率。这倒逼我们建立试验文化。

给概率系统搭观测、试验和容错的底座

观测性:从“监控到死”到“感知分布”

概率系统需要新仪表盘。传统指标保留,但加一层语义监控。我们建了三个视图:

1. 输出分布热力图: 实时展示各类别概率分布随时间的变化,用直方图叠加。看到分布左移,立刻知道模型在“犹豫”。

2. 成本-价值曲线: 横轴是推理次数,纵轴是累计成本,叠加业务价值(减少的漏检损失)。看到成本斜率上扬,价值平缓,就该调整。

3. 用户干预日志: 每次人工override模型判断都有原因标签,如“光变”“新缺陷”“模型乱判”。形成反馈环。

技术实现上,我们用OpenTelemetry的span传递自定义属性,把模型输出的概率向量、JS散度作为span属性,发送到Jaeger,再用Grafana拼接。这样观测从“请求延迟”升级到“语义健康”。

试验文化:允许模型犯错,但得在圈里

既然无法消除错误,我在团队立了新规:每个模型更新必须经过“安全沙盒试验”。沙盒不是离线测试,而是在线阴影模式——让新模型消费实时数据,但输出只记录不执行。对比真实判断,计算风险暴露时间。

有一次,我们试验一个用最新GPT-4o视觉API(作为参考模型)辅助标注的方案。GPT版输出质量高,但成本是边缘模型的10倍。我们没直接换,在沙盒跑了2周,发现高峰期API延迟抖动大,导致超时,不适合核心线。这避免了线上事故。(延伸阅读:我看了三年企业AI账单:90%的大模型调用是在烧钱,SLM才是盈利的分水岭

试验文化核心是:别信一次测试结果,用持续试验来管理不确定性。类似混沌工程,但注入的是模型变量。

容错设计:当质检模型说“不知道”时,别炸线

概率系统必须内置降级路径。我们改造了质检管道:


# 容忍模型不确定性的推理管道
import time
from typing import Optional

class RobustInference:
    def __init__(self, model, fallback_model=None, confidence_threshold=0.8):
        self.model = model  # 主模型
        self.fallback_model = fallback_model  # 备用模型(更贵但稳)
        self.confidence_threshold = confidence_threshold

    def predict(self, image, max_retries=2):
        """带有重试和降级的推理"""
        for attempt in range(max_retries):
            result = self.model.predict(image)
            conf = result['confidence']
            if conf >= self.confidence_threshold:
                return result
            # 置信度低时,重试
            time.sleep(0.05 * (attempt + 1))  # 递增等待
        # 所有重试耗尽,启动降级
        if self.fallback_model is not None:
            return self.fallback_model.predict(image)
        else:
            # 标记为需人工复核
            return {"class": "REVIEW_REQUIRED", "confidence": 0.0}

# 在生产中,fallback可以是用规则或人工
class RuleBasedFallback:
    def predict(self, image):
        # 传统机器视觉规则,如边缘检测判断
        return {"class": "uncertain_simple_check", "confidence": 0.5}

fallback = RuleBasedFallback()
inference = RobustInference(main_model, fallback_model=fallback, confidence_threshold=0.85)
output = inference.predict(input_img)
if output['class'] == 'REVIEW_REQUIRED':
    # 触发人工
    trigger_human_review(input_img, output)

这段逻辑没消除不确定性,但防止单个模型输出导致灾难性后果。容错设计让系统在不确定中幸存。

人机协同:到底谁对模型输出负责?

划分职责:运维工程师不再管“对不对”

传统运维SRE(站点可靠性工程师)关心系统可用性、延迟、资源。但当问题变成“模型输出不达标”时,SRE束手无策,因为他们不训练模型,也不懂业务上下文。我们被迫重新划分角色。

我把运维工程师定位为确定性基础设施的守护者,包括GPU集群、网络、容器等。另立一个新角色,暂时叫“模型守卫”(后演化为MRE),负责模型行为治理:监控分布、管理提示词版本、触发重训、仲裁人机冲突。

这张职责分工表后来成为我们内部MRE面试的基础:

职责域 运维工程师 (SRE团队) 模型守卫 (MRE)
系统可用性 保证推理服务99.9%在线,响应延迟<200ms 关注长尾延迟对模型行为的影响
容量规划 根据QPS扩缩容节点 根据模型复杂度(tokens量)预估成本并设置预算
监控 收集传统监控数据:CPU/GPU利用率、错误率 设计并维护输出分布、JS散度、语义一致性仪表板
变更管理 协调模型版本上线,滚动更新 评估新版本输出变化风险,制定灰度观察策略
故障响应 自动重启、回滚节点 判断输出问题是否须人工干预,发起复核流程
成本优化 选择性价比高的硬件实例 平衡模型精度与推理成本,如动态路由到低价模型

这划分明确了:没人再对“模型输出是否正确”拍胸脯。责任转到分布治理上。

实施一个判断守卫:用小模型管大模型

人不可能7×24盯着。我们训练了一个轻量级“守卫”分类器,输入原始图像和主模型的top-2类别及其置信度,输出“agree/human_review”。守卫在边缘CPU上跑,延迟5ms。它能捕捉明显的冲突,比如主模型说合格,传统特征却显示焊点面积异常。

下面是守卫判断的简单工作流:


# 简化的守卫协同工作流(使用伪代码)
import numpy as np

class GuardModel:
    """轻量级判断器,基于统计特征"""
    def __init__(self, rule_file='guard_rules.json'):
        # 载入规则:如焊点圆度<0.7时,强制review
        self.rules = json.load(open(rule_file))
    
    def evaluate(self, image_features, main_model_result):
        """返回'pass'允许输出,或'human_review'触发人工"""
        # 计算传统特征(已有代码)
        roundness = image_features['solder_roundness']
        area = image_features['solder_area']
        
        model_class = main_model_result['class']
        model_conf = main_model_result['confidence']
        
        # 规则:如果模型说是合格,但焊点圆度太低,则不信任模型
        if model_class == "合格" and roundness  0.9 and area < self.rules['max_defect_area']:
            return "pass"
        # 其余信任模型
        return "pass"

# 主流程
main_output = main_model.predict(image)
guard_result = guard.evaluate(extract_feature(image), main_output)
if guard_result == 'human_review':
    # 入人工复核队列
    human_queue.append((image_id, main_output))
else:
    # 自动执行
    production_line_action(main_output)

这个守卫不是完美的,但降低了完全依赖大模型的风险。本质上是构建多层概率治理,每一层容忍一定的不确定性。

设立模型可靠性工程师(MRE),我们的组织实验

MRE的诞生:从反对到接受的180天

起初,我提议招一个“模型可靠性工程师”,团队都不解。运维老大说“这不就是高级标注员?”,算法组长说“应该归数据科学管”。我坚持在运维团队里设这个角色,因为MRE解决的是生产稳定性问题,不是模型开发。

我们挖了一个做过传统SRE、后来转ML的工程师。他的日常工作清单:

  • 每天看输出分布JS散度曲线,发现异常联系现场工程师复核。
  • 管理提示词(如果用到语言模型)的版本,类似代码review。
  • 运行成本-价值分析,周会向上汇报模型ROI。
  • 协调人机交互:质检员有争议时,MRE召集三方会诊(质检、工艺、数据),制定仲裁规则。
  • 设计容错策略,比如守卫模型的更新。

6个月后,这个角色成了粘合剂。一次危机:模型在夜班批量误判,因为工厂为节能调暗了部分区域灯光。SRE收到延迟告警,没反应;MRE从输出分布陡变(合格类概率从0.93掉到0.81)立即注意到,5分钟内切换到备用规则,避免了4小时的废品。从那以后,再没人质疑角色定位。

避坑清单:我们烧钱换来的LLMOps实践守则

最后,总结从项目中挖出的血泪教训,不系统但管用:

  1. 别追求100%可复现: 接受推理结果有概率波动,监控分布代替单点正确性。
  2. 成本仪表板必须实时: 每张推理的成本是动态的,设置硬上限和软降级,防止成本吞噬利润。
  3. 模型更新要灰度,用影子模式: 不直接替换,新模型消费流量但输出只记录,收集至少1周数据再决策。
  4. 输出漂移告警用JS散度,别用精度: 精度计算延迟,JS散度及时反映分布变化。
  5. 设立人机协同规则,而不是替代人: 模型守卫或规则兜底,让操作员仲裁复杂案例,收集数据反哺模型。
  6. 招聘MRE,别让SRE兼管: 概率系统需要专门的治理角色,理解业务语境和模型局限性。
  7. 预算按价值分级: 高价值产线允许更多重试和人工介入,低价值线接受更大不确定性,降低资源投入。
  8. 永远准备降级路径: 从大模型→规则→人工的三级管道,确保工厂不会因模型停机。

这些坑,每个都花了钱和时间。LLMOps不是运维工具升级,是工程师思维的重构。从控制到治理,从确定性到概率,从可复现到可观测。制造业的利润薄,更经不起乱搞。如果你也正把大模型部署到生产环境,或许这些血泪有点用。

本文由 AI 辅助生成,经人工审核后发布。内容由 沈青锋 基于实战经验指导完成。

觉得有用?

沈青锋

连续创业者,第三个项目在做AI+制造业。前两个项目一个做SaaS一个做IoT,都和技术+产业的结合有关。认为AI最大的价值不在聊天机器人,而在让传统行业运转得更好。写文章的目的是分享创业路上的思考和教训。

发表评论