ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

用OpenClaw+DeepSeek+Prometheus搭建预测性维护系统

用OpenClaw+DeepSeek+Prometheus搭建预测性维护系统

凌晨两点,车间主任打电话说三号产线停了。排查到天亮,发现是减速机轴承保持架碎了,备件没有,供应商当天还送不了货——那条产线一天产值几十万,就这么干等着。

这种场景在制造业待过的人都懂。设备“不坏不修”是事后维修,按固定周期换件是定期维护,本质上都是在赌概率。真正想要的是预测性维护:靠数据把“设备快坏了”这件事提前识别出来,在故障发生前安排停机检修。这篇就把我用 OpenClaw 加 DeepSeek 加 Prometheus 从零搭的一套可落地原型讲清楚,代码全部可复现。适合正在做设备运维数字化、想引入智能体又不知道怎么串流程的工程师,也适合对“大模型怎么落地到工控场景”感兴趣的开发者。

整个方案的核心思路很简单:传感器数据进 Prometheus,模型算异常分数,OpenClaw 当大脑做任务编排,DeepSeek 负责把技术信号翻译成人话,最后自动发告警、生成维护建议。下面按我的实际搭建顺序展开。

1. 机制选型拆解:为什么是这个三件套

1.1 预测性维护要解决的真实痛点

先看看传统维护模式的问题在哪。

事后维修最大的问题是停机成本不可控。设备坏了才修,生产已经停了,备件往往也没有,维修时间完全取决于故障复杂度和供应链响应速度。定期维护则容易陷入两个极端:换早了浪费,换晚了照样坏。我见过不少工厂的“计划性保养”其实就是按日历换油、换轴承,根本不管设备实际状态,成本不低,效果肉眼看不出来。

预测性维护把问题变成三个环节:

环节要解决的问题典型手段
数据采集设备当前状态能不能被量化振动、温度、电流、转速传感器
状态识别异常信号能不能被提前发现时域频域特征、异常检测模型
决策闭环发现异常后怎么办告警、诊断报告、维护工单

前两个环节业内已经很成熟,真正难的是第三个。设备报警了,给谁报?报什么内容?要不要立刻停机?还是继续观察?这些问题过去只能靠老师傅经验,现在正好可以交给智能体去组织信息、调用工具、生成可执行的维护建议。

1.2 三件套各自的角色定位

OpenClaw、DeepSeek、Prometheus 三个组件一开始看起来不像一个生态里的东西,但用顺了会发现它们恰好互补。

Prometheus 负责“记”。它天生就是干时序数据监控的,采集传感器指标、存指标、算告警规则都顺手。设备振动值、温度、电流这些数据本质上就是时间序列,塞进关系型数据库反而别扭,Prometheus 这种按时间组织的数据模型天然契合。

OpenClaw 负责“编”。它是一个开源智能体编排框架,能定义 Agent、配置工具调用、编排多步工作流。简单说,它可以在检测到异常后自动完成一串动作:查历史指标、调模型算分、组装上下文、呼叫大模型分析、最后把结果发到企业微信或钉钉。如果没有这一层,你得自己写一堆胶水代码把各个环节黏起来。

DeepSeek 负责“说”。模型算出来一个异常分数0.87,这个数字对维修工来说没有意义。DeepSeek 的作用是把“分数0.87+振动频谱出现2倍频边带+温度上升5度”翻译成“疑似轴承外圈磨损,建议停机检查并准备替换件”,这才是维修班组能直接拿来做事的信息。用 DeepSeek 主要是推理成本低、响应快,中文表达也贴合工厂实际场景。

三者的关系可以类比成一个值班团队:Prometheus 是仪表盘和记录仪,OpenClaw 是值班调度员,DeepSeek 是那个能把技术问题讲明白的专家。

1.3 为什么不选更常见的组合

前期也考虑过其他方案,简单说下取舍。

第一种是“MQTT+规则引擎”。够轻,但规则引擎只能覆盖“特征值超限”这种显式逻辑,应付不了多参数耦合的早期故障。比如振动值和温度单独看都在正常范围,但两者联合趋势异常,规则引擎需要人为穷举组合,写起来没完没了。

第二种是“自研监控+模板报告”。监控部分倒是不难,但报告一旦要结合上下文动态生成,模板就僵了。模板只能把固定字段填进固定文本,故障描述稍微复杂一点就不适用,而且没法回答维修工的追问。

第三种是“全链路大模型处理”。把原始数据直接丢给大模型做判断,看着很酷,实际不可靠。时序特征的数值精度、告警判定这种逻辑密集型的活儿,大模型并不擅长,而且成本高。正确做法是大模型只做最后一步语义分析,前面交给确定性的算法和规则。

2. 整体架构与数据流设计

2.1 系统五层架构

我在实际项目里按五层来组织系统,每层职责单一,方便单独替换和测试。

第一层是数据采集层。设备侧装传感器,常见的有振动加速度传感器、温度探头、电流互感器。现场设备通过 PLC 或工业网关汇聚数据,再走 Modbus/TCP 或 OPC UA 到边缘网关。原型阶段没有真实传感器的话,可以用脚本模拟波形数据,后面细说。

第二层是指标存储层。统一走 Prometheus 的指标模型,设备标识放在 label 里,例如machine="CNC_03"。推数据用 Pushgateway,查询用 PromQL。

第三层是特征与模型层。定时任务从 Prometheus 拉原始波形指标,计算时域频域特征,调用训练好的异常检测模型得到健康分数。这一层输出的是标准化数字,不带业务含义。

第四层是智能体编排层。OpenClaw 监听模型层的输出,达到阈值就触发工作流。工作流内部会先收集上下文,再调用 DeepSeek 生成诊断结论,最后决定通知级别和内容。

第五层是通知与展示层。告警消息走 Alertmanager 分发到企业微信/钉钉/邮件,同时把模型分数和事件记录推给 Grafana 做可视化。管理层看趋势,维修组收任务,各取所需。

2.2 数据流转的关键路径

最核心的一条链路是这样的:传感器采集的振动原始波形,经边缘网关汇聚后,以 5 秒间隔推送特征值和原始波形摘要到 Prometheus。模型服务每 30 秒拉取最近时间窗口的数据,计算特征向量并调用模型,得到健康分后写回 Prometheus。

OpenClaw 的定时 Job 每 30 秒执行一次检查动作,用 PromQL 查模型健康分。当分数低于阈值时,工作流开始执行:先查最近 1 小时的振动原始值、温度趋势、设备基本信息,然后调用 DeepSeek 的 API,传入拼接好的诊断上下文,让它输出故障类型、置信度、建议动作。最后根据置信度选择告警通道——高置信度直接拉群,低置信度只发日报汇总。

这条路径里的每一步数据格式我都做了统一:特征值用浮点数,事件记录用 JSON,告警消息用纯文本加 markdown 链接。这样任意一层出现问题,排查起来都只影响相邻层,不会形成链路雪崩。

3. 环境准备与基础配置

3.1 组件清单与版本选择

先把我实际用的组件和版本列一下,你搭的时候可以直接抄。

组件版本用途
Python3.10+数据采集、特征计算、模型推理
Prometheus2.45+指标存储、告警规则计算
Pushgateway1.6+接收边缘节点推送的指标
Alertmanager0.26+告警路由与通知分发
Grafana10.x可视化看板
OpenClaw最新发布版智能体编排与工作流执行
scikit-learn1.3+异常检测模型训练
FastAPI0.104+模型推理服务

版本不用太纠结,只要 Prometheus 2.x、scikit-learn 1.x 以上就能跑通。但要注意 OpenClaw 的插件 API 不同版本有差异,安装后建议先跑一下自带的openclaw doctor检查命令,确认基础环境没问题。

3.2 安装与初始化

安装过程分成四步。

第一步,创建 Python 虚拟环境并安装依赖:

mkdir pdm-project && cd pdm-project python3 -m venv venv source venv/bin/activate pip install openclaw prometheus-client pushgateway numpy scipy scikit-learn fastapi uvicorn requests

第二步,下载并启动 Prometheus 与 Pushgateway。我习惯用二进制直接跑,方便在车间离线环境部署:

wget https://github.com/prometheus/prometheus/releases/download/v2.45.0/prometheus-2.45.0.linux-amd64.tar.gz tar xzf prometheus-2.45.0.linux-amd64.tar.gz cd prometheus-2.45.0.linux-amd64 ./prometheus --config.file=prometheus.yml

Pushgateway 是独立进程,默认监听 9091 端口。

第三步,初始化 OpenClaw。首次运行会生成一个配置文件目录,里面包含agents/、tools/、flows/三个核心目录。可以用指令快速体验:

openclaw init --name pd-agent openclaw agent list

第四步,把 DeepSeek 的 API Key 配置到环境变量,避免写死在代码里:

export DEEPSEEK_API_KEY=sk-xxxx export DEEPSEEK_BASE_URL=https://api.deepseek.com

注意:在工业现场部署时,API Key 不要放到 Prometheus 配置里,也不要提交到 git 仓库。建议用独立的密钥管理方案,或至少用环境变量注入。

3.3 DeepSeek 访问封装

DeepSeek 的接口协议是 OpenAI 兼容格式,用 requests 就能调。我封装了一个模块,统一处理接口调用和异常重试。

# deepseek_client.py import os import requests import json def chat(messages, temperature=0.2, max_tokens=1024): api_key = os.environ["DEEPSEEK_API_KEY"] resp = requests.post( f"{os.environ.get('DEEPSEEK_BASE_URL', 'https://api.deepseek.com')}/chat/completions", headers={"Authorization": f"Bearer {api_key}"}, json={ "model": "deepseek-chat", "messages": messages, "temperature": temperature, "max_tokens": max_tokens, "response_format": {"type": "json_object"} }, timeout=30 ) resp.raise_for_status() return json.loads(resp.json()["choices"][0]["message"]["content"])

temperature 设在 0.2 而不是更高,是因为诊断报告需要确定性,不需要创造性。如果输出要直接对接下游系统,用response_format强制 JSON 输出能省掉很多解析上的麻烦。

4. 数据采集与特征工程实现

4.1 传感器数据模拟与采集脚本

没有真实设备时,用模拟数据先把链路打通,这个步骤非常关键。否则等到接线接通再调试,排错成本高得多。

我写了一个模拟振动传感器的脚本,生成两种状态的数据:正常状态和轴承内圈磨损退化状态。

# simulate_sensor.py import time import numpy as np from prometheus_client import CollectorRegistry, Gauge, push_to_gateway FS = 2560 # 采样率 Hz def generate_vibration(fault=False): t = np.arange(FS) / FS # 转频 25Hz,正常时以转频能量为主 signal = 0.8 * np.sin(2 * np.pi * 25 * t) # 添加随机噪声 signal += np.random.normal(0, 0.15, size=t.shape) if fault: # 故障时:内圈故障特征频率 118Hz,边带调制 signal += 2.2 * np.sin(2 * np.pi * 118 * t) * (1 + 0.6 * np.sin(2 * np.pi * 25 * t)) signal += np.random.normal(0, 0.3, size=t.shape) return signal def compute_features(signal): rms = np.sqrt(np.mean(signal ** 2)) peak = np.max(np.abs(signal)) crest = peak / rms if rms > 0 else 0 kurt = ((signal - np.mean(signal)) ** 4).mean() / ((signal - np.std(signal)) ** 4 + 1e-8) spec = np.abs(np.fft.rfft(signal)) dominant_freq = np.fft.rfftfreq(FS, 1.0 / FS)[np.argmax(spec)] return rms, crest, kurt, dominant_freq def main(): registry = CollectorRegistry() g_rms = Gauge("vibration_rms", "振动均方根", ["machine"], registry=registry) g_crest = Gauge("vibration_crest", "峰值因子", ["machine"], registry=registry) g_kurt = Gauge("vibration_kurtosis", "峭度", ["machine"], registry=registry) g_freq = Gauge("vibration_dominant_freq", "主频", ["machine"], registry=registry) fault_flag = False while True: # 每 60 轮切换一次故障状态,模拟退化过程 if int(time.time() / 60) % 5 == 4: fault_flag = True else: fault_flag = False signal = generate_vibration(fault=fault_flag) rms, crest, kurt, freq = compute_features(signal) labels = {"machine": "CNC_03"} g_rms.labels(**labels).set(rms) g_crest.labels(**labels).set(crest) g_kurt.labels(**labels).set(kurt) g_freq.labels(**labels).set(freq) push_to_gateway("localhost:9091", job="vibration_push", registry=registry) time.sleep(5) if __name__ == "__main__": main()

这里的关键是故障特征频率的设定。轴承内圈故障特征频率不是随便写的,它和轴的转频、轴承节径、滚珠数量有关。在模拟阶段用 118Hz 加上边带频率,是因为真实轴承故障的振动信号会有明显的调制现象,边带间隔等于转频 25Hz。这个细节让后续特征区分度更高,模型也更好训练。

4.2 特征提取:从原始波形到健康指标

预测性维护不能直接把原始波形丢给模型,得先提炼特征。我常用四个特征组合。

均方根值 RMS 反映振动能量大小,设备越健康 RMS 稳定在一个基线;峰值因子是峰值除以 RMS,对早期缺陷敏感,因为轴承点蚀会产生冲击,但 RMS 还没明显增大;峭度对冲击类故障非常敏感,正常信号约等于 3,故障时可能跳到 5 以上;频谱主频则能判断能量是否从转频附近转移到故障特征频率附近。

这四个特征在上一节的compute_features函数里已经算出来了。我建议把它们拆开存到 Prometheus 的不同指标中,而不是合成一个复合指标,这样可以分别设定告警阈值,也方便在 Grafana 里做联动分析。比如只看峭度很容易被单次冲击干扰,但“峭度升高同时主频跳到 118Hz”就是非常明确的轴承故障信号。

4.3 数据上报到 Prometheus

很多第一次搞这个的人会问:Prometheus 不是拉模式(pull)吗,设备数据怎么进来合适?

答案是分场景。像 MySQL 或 HTTP 服务这种常驻进程,用 exporter 让 Prometheus 主动拉没问题。但车间里的边缘网关、传感器采集器是变化的数据源,而且可能随时启停,用 Prometheus 的 Pushgateway 推模式更合理。脚本里push_to_gateway就是干这件事。

Pushgateway 有个坑后面详说:指标不主动清理会一直残留。所以要确保每次推送时带上唯一标识,比如machine标签区分设备,重启采集脚本时再清理一次旧指标。

5. 故障预测模型的训练与验证

5.1 无监督异常检测:为什么选孤立森林

故障样本在真实工况下非常少,甚至没有。所以我不选择“用故障数据训练分类器”这条路,而是用无监督的孤立森林。

孤立森林的核心逻辑是:正常数据在特征空间里分布得很密集,异常数据“与众不同”,用随机超平面去切分,异常数据会更快被孤立出来。它的计算成本低,高维特征也扛得住,很适合设备健康度这种实时性要求高的场景。

训练代码非常简单:

# train_model.py import numpy as np import joblib from sklearn.ensemble import IsolationForest # 假设历史正常数据已经收集好了,这里做模拟 normal_features = np.random.normal([0.6, 3.1, 3.2, 25.0], [0.05, 0.15, 0.2, 0.5], size=(10000, 4)) fault_features = np.random.normal([1.8, 4.2, 5.1, 118.0], [0.08, 0.3, 0.4, 2.0], size=(200, 4)) X_train = normal_features model = IsolationForest(n_estimators=200, contamination=0.02, random_state=42) model.fit(X_train) # 保存模型 joblib.dump(model, "anomaly_model.joblib")

训练数据只用了正常数据,这是无监督方案的天然优势——新设备、新产线部署时不需要积累故障案例,采集一周正常数据就能出第一版模型。

5.2 模型输出怎么映射成健康分

孤立森林输出的是 decision_function 分数,值越大表示越正常,但这个分数业务方看不懂。我把它做了一次映射:

def health_score(model, features): raw = model.decision_function(features.reshape(1, -1))[0] # 线性映射到 0-100,分数越低越危险 score = 50 + 50 * (raw / max(abs(raw), 1e-6)) return float(np.clip(score, 0, 100))

映射公式不是严格的概率,但胜在直观:80 以上正常,60-80 关注,60 以下告警。实际部署时你可以根据自己的数据和现场接受度调整。

5.3 模型评估与阈值标定

在模拟数据上做了离线验证。用 10000 条正常数据训练,再用 200 条故障数据和 2000 条正常数据做测试,调节 threshold 观察效果:

阈值召回率(故障检出)虚警率(正常误报)结论
0.7598.5%6.2%虚警偏高
0.7097.0%3.1%可接受
0.6590.5%1.2%漏报偏高
0.6082.0%0.4%偏保守

现场建议先从“宁可多报不可漏报”开始,跑两周收集反馈后再收紧阈值。预测性维护项目死在第一周的通常不是模型不准,而是虚警太多导致班组不再信任系统。

5.4 模型服务化

我把训练好的模型包在一个 FastAPI 服务里,方便 OpenClaw 和 Prometheus 定期调用。

# model_service.py import joblib import numpy as np from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() model = joblib.load("anomaly_model.joblib") class Features(BaseModel): rms: float crest: float kurtosis: float dominant_freq: float @app.post("/health") def predict(f: Features): arr = np.array([f.rms, f.crest, f.kurtosis, f.dominant_freq]) return {"health_score": health_score(model, arr)} def health_score(model, features): raw = model.decision_function(features.reshape(1, -1))[0] score = 50 + 50 * (raw / max(abs(raw), 1e-6)) return float(np.clip(score, 0, 100))

启动服务:

uvicorn model_service:app --host 0.0.0.0 --port 8000

到这里,数据链路和模型链路已经通了。接下来是 OpenClaw 和 DeepSeek 重头戏。

6. OpenClaw 智能体编排与 DeepSeek 接入

6.1 智能体工作流设计

OpenClaw 的编排核心是“事件触发 + 工具调用”。我设计了这样一个工作流:

正常状态时,OpenClaw 作为常驻 Agent 周期查询 Prometheus 中每台设备的健康分。这一步用的是定时触发器,周期 30 秒。

分数不低于 70 就正常轮询。分数低于 70 后进入诊断流程:先调用“查历史指标”工具,取得该设备最近 1 小时的 RMS、峭度、主频趋势和温度变化;再调用“模型服务”确认一次原始特征是否真的异常,避免单点抖动;然后聚合上下文,组装提示词,调用 DeepSeek;最后按照置信度决定告警方式。置信度大于 0.8 的,立即发企业微信并附带停机建议,置信度在 0.5-0.8 的,发日志记录并在日报里汇总。

# openclaw_flow.yaml triggers: - type: schedule cron: "*/30 * * * * *" steps: - id: query_health tool: prometheus_query params: query: "health_score < 70" promql: true - id: fetch_context tool: prometheus_query params: query: | {__name__=~"vibration_rms|vibration_kurtosis|vibration_dominant_freq", machine="CNC_03"}[:1h] - id: confirm_anomaly tool: http_call params: url: "http://localhost:8000/health" method: POST - id: diagnose tool: deepseek_chat params: prompt_template: "prompts/diagnose.j2" - id: notify tool: wecom_notify params: channel: "设备运维告警群"

这个设计的核心是:OpenClaw 只做流程编排和工具调度,不承担模型运算,也不承担自然语言生成。它更像是值班长,知道什么时候找谁、把什么材料给谁。

6.2 提示词模板设计

DeepSeek 输出质量很大程度上取决于提示词。我用的诊断模板如下:

你是设备诊断工程师。请根据以下传感器特征和趋势,判断设备是否存在异常,并给出维护建议。 设备信息: - 设备编号:CNC_03 - 设备类型:数控加工中心主轴 - 轴承型号:6308(假定) 当前特征值: - 振动RMS:{rms} - 峰值因子:{crest} - 峭度:{kurt} - 主频:{dominant_freq} Hz 历史趋势(最近1小时): {rms_trend} {freq_trend} 要求: 1. 如果判断为异常,给出可能的故障部位和故障类型 2. 给出置信度(0到1) 3. 给出建议动作:立即停机/计划维修/持续观察 4. 以JSON格式输出,字段为:fault_type, probability, action, reason

注意把采集到的数值全部填充到模板里,而不是让 DeepSeek 自己去查数据。大模型不擅长精确查询,但很擅长在给定数据上做推理归纳,分工要明确。

6.3 DeepSeek 诊断调用实测

前面封装了deepseek_client.chat,实际调用的拼接逻辑如下:

def build_diagnosis(context): prompt = DIAGNOSE_TEMPLATE.format(**context) result = deepseek_client.chat([ {"role": "system", "content": "你是一名严谨的设备诊断工程师,输出必须是有依据的。只能基于给定数据做判断,禁止编造数据。"}, {"role": "user", "content": prompt} ]) return json.loads(result)

在模拟故障场景下,真实输出大致是这样:

{ "fault_type": "轴承内圈磨损", "probability": 0.87, "action": "计划维修", "reason": "频谱主频从25Hz跳变到118Hz,并伴随25Hz边带调制,符合内圈故障特征频率;峭度从3.1升高到5.2,存在明显冲击脉冲。建议在12小时内安排停机检查,并准备6308轴承备件。" }

这段输出里最值钱的是“12小时内安排停机检查”和“准备备件”——这已经不是单纯的告警,而是可执行的工作指令。现场班组收到后可以直接安排,比看一堆曲线快得多。

6.4 与 OpenClaw 工具的对接方式

OpenClaw 的一个特点是工具按插件机制注册,把 DeepSeek 封装成一个 Tool 也非常简单。我在项目里注册了三个 Tool:

prometheus_query负责执行 PromQL 查询并返回结果。deepseek_chat会调用前一节的 API 封装。wecom_notify走企业微信机器人 Webhook。

tools: - name: deepseek_chat entry: tools.deeepseek_chat.call params_schema: tools.deeepseek_chat.parameters - name: prometheus_query entry: tools.prometheus_utils.query params_schema: tools.prometheus_utils.parameters

定义好之后,工作流节点里就能直接通过tool: deepseek_chat调用。这个封装的好处是后续想换模型,只改工具入口,不动工作流定义。

7. Prometheus 告警联动与可视化

7.1 告警规则设计

模型分数的告警规则直接写在 Prometheus 配置里,由 Prometheus 统一计算和触发。

# rules/predictive_maintenance.yml groups: - name: equipment_health rules: - alert: EquipmentHealthCritical expr: health_score < 60 for: 1m labels: severity: critical annotations: summary: "设备 {{ $labels.machine }} 健康分过低" description: "当前分数 {{ $value }},请立即检查。" - alert: EquipmentHealthWarning expr: health_score < 70 for: 5m labels: severity: warning annotations: summary: "设备 {{ $labels.machine }} 健康分异常" description: "当前分数 {{ $value }},建议安排检查。"

注意for: 1m和for: 5m。这个参数非常关键,它要求指标持续异常一段时间才触发告警。没有这个参数,瞬时抖动就会造成大量误报。加了以后,告警数量肉眼可见地下降。

7.2 Alertmanager 通知路由

Prometheus 负责“发现异常”,Alertmanager 负责“把异常送对人”。车间场景下我做了两级路由:critical 级直接发到当前值班维修组长个人和企业微信告警群;warning 级进日报汇总;所有告警都落到 Grafana 事件列表做复盘。

route: group_by: ["machine", "alertname"] group_wait: 10s group_interval: 5m repeat_interval: 4h routes: - match: severity: critical receiver: wecom-critical - match: severity: warning receiver: daily-report receivers: - name: wecom-critical webhook_configs: - url: "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx"

group_by: ["machine", "alertname"]能避免同一台设备多个指标同时异常时重复刷屏,这一条在告警降噪里面重要性排第一。

7.3 Grafana 看板要点

可视化我按四块来做:

设备总览面板:一张地图或者列表,每台设备一个色块,绿黄红三色代表健康状态。振动趋势面板:展示 RMS 和峭度的时间曲线,叠加健康分曲线。频谱热力图:展示主频随时间的变化,故障特征频率出现时可以肉眼看到斜线。事件记录表:展示所有告警、恢复时间、维护动作,形成完整闭环。

看板的价值在于让老师傅能“用眼睛验证系统判断”。如果他们看到曲线确实和系统报警吻合,信任度会迅速建立。如果系统报警了但曲线看起来正常,则需要回去检查特征或修改阈值。

8. 常见问题与排查技巧实录

8.1 故障现象速查表

搭建和运行过程中一定会遇到问题,我把最常见的几个整理成表。

现象可能原因排查方法解决方案
健康分数始终 100特征范围与训练数据不一致打印原始特征值检查采集脚本是否推了低倍率数据
告警风暴没有设置for持续时长看 Prometheus 规则是否配置for加for: 1m
Pushgateway 旧指标残留没有清理已下线设备查看pushgateway页面指标上线时用push_to_gateway前先 delete
DeepSeek 返回乱码返回过长或温度过高检查 max_tokens 和 temperature降到 1024 和 0.2
模型误判新设备新设备正常工况不同对比不同设备的特征分布按设备类型分开训练模型
Alertmanager 不推送Webhook 地址不可达看 Alertmanager 日志用 curl 手动测试 URL

8.2 误报与漏报治理

误报比漏报更伤系统,因为一旦老师傅觉得“系统天天狼来了”,后续真报警也没人重视了。

最常见的一个坑是峭度瞬时冲击。有时候加工过程本身会产生冲击,比如断续切削,峭度会瞬间飙到 6 以上。解决办法是模型输入不做瞬时值,而是取 3 分钟滑动平均值,再加上确认步骤——OpenClaw 工作流里调用模型服务做二次确认,就是针对这个场景。

漏报的主要原因是特征覆盖不足。振动特征只能反映旋转类故障,润滑不良、温升异常要靠温度特征补充,电流异常要靠电流特征。所以第一版模型只用振动特征可以,但别指望它覆盖所有故障类型。

8.3 存储层深坑:Prometheus 数据生命周期

Prometheus 默认存储保留期是 15 天,这个对预测性维护来说远远不够。设备退化趋势往往要看几个月,保留期太短会导致无法分析长期趋势。

我在启动参数里显式加了保留期配置:

./prometheus --storage.tsdb.retention.time=180d

另一个坑是 Pushgateway 的指标残留问题。设备改造或停机后,Pushgateway 里还留着旧的指标数据,会导致 Grafana 上出现“幽灵设备”。采集脚本启动时先调 HTTP DELETE 清理对应 job 的旧数据:

curl -X DELETE http://localhost:9091/metrics/job/vibration_push/instance/localhost

8.4 模型漂移与定期重训练

设备在长期运行中会磨损,正常状态的基线也会缓慢变化。一个模型用半年后可能虚警率明显升高。

我的做法是每周自动汇总一周内所有被系统标记为“确认正常”的特征数据(维修班组确认后打标签),每月末用这些数据增量微调模型。这个流程在原型阶段可以用脚本手动跑,但要注意保留原始数据用于回滚。

9. 复盘与扩展建议

回头梳理这套系统,真正的价值点不在单个模型或单个工具,而在于把采集、存储、推理、语义分析、通知拉成了一条完整的链。技术选型上也印证了一个观点:大模型最适合的不是替代确定性逻辑,而是处理那些“老师傅能看出来但说不出来”的信息压缩与转换。

有几个经验想重点分享。第一,先跑通链路再优化精度。我第一次搭建时模型连 70% 召回率都不到,但整个链路是通的可视化能看到每一层的输入输出,优化起来非常快。第二,告警降噪优先级高于模型精度。告警风暴会让整个系统失去信任,宁可先保守、多人工确认。第三,通知文案直接决定系统使用率。一个“健康分67”不如一句“建议本周检查主轴轴承,备件型号6308”,后者才是运维人员真正需要的。

后续如果要往生产环境推进,可以考虑扩展三个方向:接入更多传感器类型,比如电流信号和油液分析数据,提升故障诊断的覆盖度;把 DeepSeek 的诊断结果自动生成维修工单,对接现有的 CMMS 系统;用历史数据训练 RUL(剩余使用寿命)回归模型,在“要不要修”之外进一步回答“还能撑多久”。

如果你正准备做类似的设备预测性维护,我的建议是从一台设备开始。选一台故障损失最大、传感器最好装的设备,把数据采回来、告警发出去,让老师傅看到系统确实能在坏之前“说”出来,后面再推广就容易得多。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进