1. 先搞清楚大家在争什么:工业Agent与实时控制的边界
"实时控制的工业Agent"这个说法,最近一年在圈子里被反复提起。做AI的人觉得这是下一个爆发点,做工业自动化的人听完往往只是笑笑。我两边都待过,既写过梯形图,也搭过基于大模型的智能体流程,所以特别能理解这种认知错位从哪来。
先把概念掰开。工业Agent,指的是跑在工业场景里、能感知设备状态并自主决策的智能体,通常由大模型做推理内核,配合工具调用去读写数据。实时控制,在工业语境里有非常明确的硬指标:确定性、周期性、抖动范围可控。一个PLC扫描周期可能是1毫秒到10毫秒,抖动要求往往在微秒级。而AI Agent的推理链路,从输入到输出,动辄几百毫秒到几秒,还带着概率性。
这三者放在一起,矛盾就出来了。标题说"现在是伪命题",不是说工业Agent没价值,而是说"让AI Agent直接承担实时控制回路"这件事,在当前技术条件下站不住脚。这个判断我认同,而且理由比大多数人想的更硬。
热词里那一堆PLC、DCS、Modbus、OPC UA、数控机床、变频器通讯,其实都在指向同一个事实:工业现场的数据采集和控制执行,早就有一套成熟、稳定、经过几十年验证的体系。AI Agent要进来,得先想清楚自己站在哪一层,而不是一上来就喊"替代PLC"。
这篇文章我想把这件事讲透。适合谁看?如果你是做AI应用想切入工业的开发者,能帮你避开几个致命的方向性错误;如果你是做工业自动化想了解AI能干什么的工程师,能帮你判断哪些环节真的值得引入智能体。两种背景的人看完,应该都能对"边界在哪"有个清晰的认识。
2. 为什么"实时"两个字是绕不过去的硬门槛
2.1 实时控制的确定性要求,和AI的概率性天生冲突
工业控制里说的"实时",和互联网里说的"实时"完全不是一回事。互联网的实时是"用户感觉不到延迟",几百毫秒都能接受。工业的实时是"必须在规定时间内完成,早一点晚一点都算失败"。
举个具体例子。一个典型的运动控制场景,伺服轴的位置环刷新周期可能是125微秒,电流环更快。PLC在每个周期内要完成输入采样、逻辑运算、输出刷新,整个过程必须在周期时间内闭环。如果某一次运算超时了,轻则产品报废,重则设备撞机。这种场景下,控制逻辑的执行时间上界是设计时就确定死的,不允许有"这次慢了点"的情况。
AI Agent的推理链路是什么样?大模型生成token是串行的,输出长度不确定,推理时间随负载波动。就算你用本地小模型,延迟也受GPU调度、批处理队列影响。更关键的是,Agent的决策是概率性的——同样的输入,可能给出不同的输出。这在控制回路里是灾难。
注意:任何声称"用大模型做实时控制"的方案,你第一句就该问:最坏情况下的响应时间是多少?抖动范围多大?如果对方答不上来,这个方案就不用往下看了。
2.2 从PLC扫描周期看"实时"到底有多严苛
我拿一个实际项目的数据说话。之前做过一个包装线控制,用的是主流中型PLC,主任务扫描周期设定8毫秒。这8毫秒里要跑完大概两千条梯形图指令,加上几十个模拟量通道的处理。实测扫描周期抖动在正负0.3毫秒以内,这是能接受的。
再看通讯。用Modbus RTU读一批从站数据,波特率115200,读20个寄存器,一轮下来大概十几毫秒。如果用OPC UA,订阅模式下的数据更新周期通常配置在100毫秒到1秒。注意,这里说的是数据更新周期,不是控制周期。也就是说,通过OPC UA拿到的设备状态,本身就是"过去时"。
AI Agent如果基于OPC UA的数据做决策,它看到的现场状态至少滞后几十到几百毫秒。等它推理完再下发指令,又是几百毫秒过去。这个时间尺度,做监控、诊断、优化建议绰绰有余,做实时闭环控制完全不够。
2.3 一个容易被忽略的点:抖动比平均延迟更致命
很多人评估延迟只看平均值,这是外行做法。控制系统怕的不是"平均慢",而是"偶尔特别慢"。平均200毫秒、偶尔飙到2秒的链路,比稳定300毫秒的链路危险得多。
AI推理恰恰是这种"长尾延迟"的重灾区。显存不够时的换页、批处理队列里排在长请求后面、模型首次加载、GC停顿,都会造成偶发的巨大延迟。这些在Web服务里顶多让用户多等一会,在控制回路里就是事故。
所以我的结论很直接:AI Agent可以参与工业,但不能进入硬实时回路。它应该站在实时层之上,做那些对时间不敏感、但对智能程度要求高的事。
3. 工业Agent真正能落地的位置在哪
3.1 分层架构:把实时层和智能层彻底分开
想清楚这件事,架构就顺了。工业系统本来就是分层的,我把它和AI Agent的定位对应起来看:
| 层级 | 典型组件 | 时间尺度 | AI Agent能否介入 |
|---|---|---|---|
| 现场层 | 传感器、执行器、变频器 | 微秒到毫秒 | 否 |
| 控制层 | PLC、DCS控制器 | 毫秒到几十毫秒 | 否 |
| 监控层 | SCADA、HMI、组态软件 | 百毫秒到秒 | 有限介入,只读为主 |
| 管理层 | MES、历史数据库 | 秒到分钟 | 可以介入 |
| 决策层 | 排产、优化、诊断 | 分钟到小时 | 核心战场 |
看清楚这张表,工业Agent的定位就明确了:它属于管理层和决策层,不属于控制层。它读的是监控层往上的数据,输出的是建议、报告、优化参数,而不是直接的控制指令。
这个边界不是保守,是工程常识。就像你不会让财务系统去直接控制机床一样,AI Agent也不该越过PLC去碰执行机构。
3.2 数据采集:Modbus和OPC UA到底怎么选
Agent要吃数据,绕不开协议。现场最常见的两条路:Modbus和OPC UA。我实际用下来的感受是,两者定位不同,别混着用。
Modbus(RTU和TCP)简单、轻量、兼容性极好,几乎任何PLC、仪表、变频器都支持。缺点是数据模型扁平,没有语义,读上来的就是一堆寄存器地址,你得自己维护"哪个地址对应哪个物理量"的映射表。做小规模采集、点对点通讯,Modbus很香。
OPC UA是面向对象的,有信息模型,节点带语义,支持订阅和复杂数据类型。做多设备、多厂商、需要统一数据模型的场景,OPC UA明显更合适。缺点是配置复杂,证书、端点、命名空间这些概念对新手不友好。
实操建议:如果只是给Agent喂几个关键设备的运行状态,Modbus TCP加一张映射表就够了,别过度设计。如果要做全厂数据汇聚、多品牌设备统一接入,老老实实上OPC UA,前期配置麻烦,后期省心。
提示:用Modbus读PLC时,务必确认寄存器地址的编址方式。有的文档从0开始,有的从1开始,还有的把功能码和地址混在一起写。我踩过这个坑,读上来的数据整体偏移一位,排查了半天。
3.3 从"读数据"到"给建议"的完整链路
一个能落地的工业Agent,链路大概是这样:
- 采集层用Modbus或OPC UA定时拉取设备状态,写入时序数据库
- Agent通过工具调用查询数据库,拿到某段时间的运行数据
- 大模型结合工艺知识做分析,比如判断温度PID波动是否异常
- 输出诊断结论和参数调整建议,推送给工程师
- 工程师确认后,手动或半自动下发参数
注意第5步,人在回路是关键。Agent给建议,人做决策,这是当前最稳妥的模式。等积累足够多的验证数据,再考虑把某些低风险环节自动化。
4. 实操:搭一个不碰实时回路的工业Agent
4.1 环境与工具选型
我拿一个真实做过的场景来演示:监控一条产线的温度控制回路,用Agent分析PID波动原因并给建议。
技术栈我选的是Python + FastAPI做服务,LangChain或LangGraph做Agent编排,时序数据用InfluxDB或TimescaleDB,采集用pymodbus或asyncua。为什么这么选?Python生态在AI侧最成熟,FastAPI轻量好部署,时序库专门为这种带时间戳的工业数据设计,查询效率比关系库高。
采集部分,如果设备支持OPC UA,用asyncua的订阅模式,数据变化时才推送,比轮询省资源。如果只有Modbus,就定时轮询,周期设1秒左右,别设太快,工业现场的网络和PLC都受不了高频轮询。
# Modbus TCP 采集示例,读取保持寄存器 from pymodbus.client import ModbusTcpClient import time client = ModbusTcpClient('192.168.1.10', port=502) client.connect() def read_temperature(): # 读取地址40001开始的10个寄存器,注意编址偏移 result = client.read_holding_registers(address=0, count=10, slave=1) if not result.isError(): # 假设第一个寄存器是温度,缩放因子0.1 return result.registers[0] * 0.1 return None while True: temp = read_temperature() if temp is not None: print(f"当前温度: {temp} 摄氏度") time.sleep(1)这段代码里有个细节值得说:address=0对应的是文档里的40001,因为pymodbus内部从0编址,而很多PLC文档从1编址。这个偏移是新手最容易翻车的地方。
4.2 让Agent读懂设备状态:工具调用的设计
Agent要分析问题,得先能拿到数据。我给它设计了几个工具函数,让它按需调用,而不是一次性把所有数据塞进上下文。
# 查询某时间段温度数据的工具 def query_temperature_history(start_time: str, end_time: str): """查询指定时间段的温度记录,返回时间序列""" # 从时序库查询,返回列表 query = f''' SELECT time, value FROM temperature WHERE time >= '{start_time}' AND time <= '{end_time}' ORDER BY time ''' # 执行查询并返回结果 return execute_query(query) # 查询PID参数的工具 def get_pid_params(loop_id: str): """获取指定回路的PID参数""" return {"P": 2.5, "I": 0.8, "D": 0.1, "loop_id": loop_id}工具设计的原则是粒度适中。太粗,Agent一次拿太多数据,上下文爆炸;太细,Agent要调很多次,延迟高。我一般按"一个物理量一个工具"来切,查询范围让Agent自己指定。
4.3 温度PID波动分析的完整流程
假设现场反馈某段温度波动大,温差超过正负5度。Agent的处理流程:
第一步,Agent调用query_temperature_history,拉取最近两小时的温度曲线。第二步,它分析曲线的特征——是周期性振荡,还是随机波动,还是阶跃后的过冲。第三步,结合get_pid_params拿到的参数,判断问题方向。
这里有个经验:周期性振荡通常是P太大或I太小,随机波动往往是干扰或传感器问题,阶跃过冲大是D不足或P过大。这些判断规则可以写进Agent的系统提示词里,让它有章可循。
第四步,Agent输出建议。比如"检测到周期约90秒的等幅振荡,建议将比例增益P从2.5降到1.8,观察两个周期后再调整"。这种建议具体、可执行,工程师看了就知道怎么动手。
注意:Agent给出的参数调整建议,一定要带"观察周期"和"回退方案"。工业现场最怕的就是改完参数没人盯着,出了问题找不到原因。
4.4 参数计算:为什么建议值不能拍脑袋
上面说P从2.5降到1.8,这个数不是随便写的。临界比例度法的思路是:先找到系统开始等幅振荡时的临界增益Ku和振荡周期Tu,然后按经验公式算。对于PID,常用的是Ziegler-Nichols整定公式:
- P控制:Kp = 0.5 * Ku
- PI控制:Kp = 0.45 * Ku,Ti = 0.83 * Tu
- PID控制:Kp = 0.6 * Ku,Ti = 0.5 * Tu,Td = 0.125 * Tu
如果实测振荡周期Tu约90秒,当前处于等幅振荡说明增益接近Ku。假设Ku约3.0,那PID的Kp建议值就是0.6 * 3.0 = 1.8。这就是1.8的来历。
Agent要做的是把这个计算过程自动化:从数据里识别振荡周期,估算Ku,套公式给出建议值。这套逻辑写进工具函数里,比让大模型自己"感觉"要靠谱得多。
5. 那些年踩过的坑:常见问题与排查
5.1 通讯层问题速查
工业现场的问题,一大半出在通讯上。我整理了一张速查表:
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 读不到数据 | IP或端口错、从站地址错 | ping通后确认端口,逐个试从站号 |
| 数据整体偏移 | 寄存器编址方式不一致 | 对照文档确认0基还是1基 |
| 偶发通讯超时 | 网络干扰、轮询太快 | 降轮询频率,检查屏蔽接地 |
| 数据跳变 | 数据类型解析错 | 确认是16位还是32位,有无符号 |
| OPC UA连不上 | 证书、端点、安全策略 | 先用无安全策略测试,再逐步加 |
这张表里的每一条,我都在现场遇到过。特别是"数据整体偏移",新手几乎必踩。还有"数据类型解析错",比如一个32位浮点数占两个寄存器,你得按正确的字节序拼起来,不同厂商的字节序还不一样。
5.2 Agent层面的典型故障
Agent本身也会出问题,而且往往更隐蔽。
上下文超限:一次查询返回几万条数据,直接把上下文撑爆。解决办法是让工具函数做聚合,返回统计特征而不是原始点,或者限制返回条数。
工具调用死循环:Agent反复调用同一个工具,拿不到想要的结果就再调。这通常是提示词没写清楚"什么情况下该停止"。我一般会在提示词里明确"最多查询三次,三次后必须给出结论"。
幻觉参数:Agent编造一个不存在的寄存器地址或参数名。这是大模型的通病,解决办法是把可用的地址和参数做成工具函数的枚举,让它只能从给定范围里选。
忽略单位:温度是摄氏度还是华氏度,压力是帕还是巴,Agent经常搞混。所有数据在入库时就统一单位,并在工具返回时带上单位标注。
5.3 一个真实的排查案例
有次Agent报告某设备温度异常,建议停机检查。工程师去现场一看,设备好好的。回头查数据,发现是采集程序在某个时间点重启,重启期间写入了一批默认值0,Agent把0当成了真实温度。
这个坑的教训是:数据清洗要在Agent之前做。采集层要能识别无效值、缺失值,打上标记,而不是把脏数据直接喂给Agent。后来我在采集程序里加了判断,读失败时写入null而不是0,Agent的工具函数遇到null会跳过。
6. 关于"AI Agent扛并发"这件事的冷思考
热词里有个"ai agent 怎么扛并发",这个问题在工业场景里其实是个伪需求。工业现场的并发量,和互联网完全不是一个量级。
一条产线几十个测点,一个车间几百个,一个厂几千个。就算全部接入Agent,并发查询也就几十到几百QPS。这个量级,一个普通的FastAPI服务加个连接池就扛住了,根本用不着分布式那一套。
真正难的不是并发数,是数据量和查询效率。时序数据一天可能几千万条,Agent查询时如果全表扫描,再强的并发架构也白搭。所以重点应该放在时序库的索引设计、降采样、冷热分离上,而不是纠结Agent能同时处理多少请求。
我的做法是:原始数据按天分区,超过一周的自动降采样成分钟级均值,超过一个月的降成小时级。Agent查询近期数据走原始表,查历史趋势走降采样表。这样既保证精度,又控制查询时间。
7. 我对这个方向的真实判断
回到标题。说"实时控制的工业Agent是伪命题",我完全同意,但想补充一句:伪的是"实时控制",不是"工业Agent"。
工业Agent的价值,在于它能把散落在各个系统里的数据串起来,用自然语言交互的方式,帮工程师快速定位问题、给出建议。这个价值是真实的,而且现在就能落地。我见过太多工厂,数据躺在各个PLC和数据库里,没人有精力去分析,Agent恰好能补上这一环。
但如果你指望它去替代PLC做闭环控制,那至少现在不行。不是模型不够强,是实时性这个物理约束绕不过去。等哪天推理延迟能稳定压到毫秒级、抖动可控,再谈这件事也不迟。
我个人在实际项目里的体会是:把Agent定位成"工程师的智能助手",而不是"控制器的替代品",落地阻力会小很多,价值也更容易被认可。先让它读数据、给建议、做诊断,跑顺了再谈更深的介入。这个节奏,比一上来就喊颠覆要靠谱得多。
最后分享一个小心得:给Agent写系统提示词时,一定要把"你不负责实时控制,你只负责分析和建议"这句话写进去。我试过不写,结果Agent偶尔会生成"建议立即下发控制指令"这种危险输出。加上这句约束后,它的行为边界就清晰多了。工业场景里,让AI知道自己的边界在哪,比让它多聪明更重要。