Agent 不能只看告警,还要看数据——设备过去一小时的温度、振动、压力趋势。时序数据库就是 Agent 的「历史记忆」。
为什么 Agent 需要时序数据?
现在的 DeviceAgent 能查告警、能搜维修知识,但缺了最关键的一块:设备运行数据。
「CNC-001 振动异常」——异常是相对于什么?正常范围是多少?振动值是一瞬间的尖峰还是持续上升趋势?这些问题,告警信息和知识库都回答不了。只有历史时序数据能回答。
时序数据库(TSDB)就是做这件事的——高效存储和查询带时间戳的设备遥测数据。
为什么选 TDEngine?
工业设备的数据特征和互联网完全不同:
| 特征 | 互联网数据 | 工业设备数据 |
|---|---|---|
| 采集频率 | 毫秒级 | 秒~分钟级 |
| 数据量 | 每个用户独立 | 每台设备持续产生 |
| 查询模式 | 点查为主 | 聚合 + 窗口查询为主 |
| 存储周期 | 天~周 | 月~年 |
TDEngine 是专为时序场景设计的,天然支持超级表(Super Table)——一个表模板适配所有同类设备。
-- 一个超级表定义,自动管理所有设备的数据
CREATE STABLE devices (
ts TIMESTAMP,
temp FLOAT,
vibration FLOAT,
pressure FLOAT,
rpm FLOAT,
current FLOAT
) TAGS (device_id BINARY(64), device_type BINARY(32), factory BINARY(64));
新增一台设备只需一行 CREATE TABLE 引用超级表,不需要重复建表。
架构
DeviceSimulator → MQTT → MqttToTdengineBridge → TDEngine
(批量写入,5秒刷新)
↓
用户 → Agent → DeviceDataTool → TdengineDataService → REST API → TDEngine
(聚合查询:avg/max/latest)
两条数据流:
- 写入流(实时):设备模拟器 → MQTT → Bridge → TDEngine
- 查询流(按需):Agent → Tool → REST API → TDEngine
实现
1. TDEngine Websocket 服务
TDEngine 提供了 Websocket 能力,不需要 JDBC 驱动:
// 初始化超级表
CREATE STABLE IF NOT EXISTS industrial.devices ...
// 插入数据
INSERT INTO industrial.d_CNC_001 USING industrial.devices
TAGS ('CNC-001','CNC','factory-A') VALUES (now,72.5,4.8,0.9,1500,28.5)
2. MQTT → TDEngine 桥接
@Component
public class MqttToTdengineBridge {
// 订阅 MQTT topic: industrial/devices/+/data
// 解析 JSON payload → 缓存到内存队列
// 每 5 秒批量写入 TDEngine
}
3. Agent Tool 改写
原来的 DeviceDataTool 用随机数模拟数据,现在改为真实 TDEngine 查询:
@Tool("查询指定设备的历史遥测数据,包括温度、振动、压力、转速、电流等关键指标。" +
"输入设备ID,返回最近1小时的关键指标统计和最新数据点。")
public String queryDeviceHistory(String deviceId) {
Map<String, Object> stats = tdengine.queryStats(deviceId, 60); // 60分钟聚合
Map<String, Object> latest = tdengine.queryLatest(deviceId); // 最新数据点
return formatJson(deviceId, stats, latest);
}
LLM 拿到的不再是随机数,而是真实的设备运行数据。
关键设计决策
批量写入 vs 逐条写入
5 秒批量刷新一次,单次最多写 100 条。这在数据可靠性和写入延迟之间取了平衡——设备数据的采集间隔通常是秒级,5 秒的写入延迟完全可接受。
Websocket vs JDBC 驱动
TDEngine 的 Java 驱动(taosc)需要安装本地动态库。对于 Docker 化的部署来说,Websocket 更简单——不需要额外的依赖,跨网络调用也无额外配置。
DeviceDataTool 的查询设计
一个 Tool 方法返回最新的一个数据点 + 过去一小时的聚合统计,而不是返回原始全量数据。这样做有两个理由:
- 控制 token 消耗:100 条原始数据点 ≈ 2000+ token;一条聚合统计 ≈ 200 token
- LLM 更擅长读聚合数据:avg/max 比 100 行数字表更容易被理解
测试
# 启动 TDEngine
docker compose up -d tdengine
# 初始化 Schema
curl -X POST http://localhost:8080/api/agent/tdengine/init
# 模拟设备数据(通过 MQTT)
# DeviceSimulator 自动发布 → Bridge 自动吸入
# Agent 对话验证
curl -X POST http://localhost:8080/api/agent/chat \
-H "Content-Type: application/json" \
-d '{"message":"CNC-001 最近一小时的振动趋势怎么样?"}'
下一步
TDEngine 集成后,Agent 具备了完整的感知能力——实时告警 + 历史数据 + 知识库检索。接下来是MVP 集成:把这些能力编排成一个完整的「从告警到工单」的诊断链路。
本文由 LaoLiang 原创,首发于掘金/知乎/微信公众号。转载请联系作者。