时序数据是 Agent 见过最「不友好」的数据------一行行数字,LLM 看了也懵。Tool 的设计决定了 Agent 是「看懂数据」还是「被数据淹没」。
问题:LLM 不擅长读原始数据
把 100 行原始时序数据扔给 LLM:
json
[
{"ts": 1718400000, "temp": 72.5, "vibration": 4.8, "pressure": 0.9, ...},
{"ts": 1718400001, "temp": 72.6, "vibration": 4.9, "pressure": 0.9, ...},
... // 98 more rows
]
两件事会发生:
- Token 爆炸------100 行 ≈ 2000+ token,一次查询就吃掉大部分上下文
- LLM 迷失------一堆数字里看不出趋势、找不到异常
Agent 需要的是摘要,不是原始数据。 Tool 的职责是把原始数据「翻译」成 LLM 能理解的结构化摘要。
设计模式 1:预聚合 + 采样
不要给 LLM 全量数据,给统计摘要。
java
// 差:返回 100+ 条原始数据点
public List<Map<String, Object>> queryRaw(String deviceId, int minutes);
// 好:返回一个聚合统计 + 最新数据点
@Tool("查询指定设备的历史遥测数据..." +
"返回最近1小时的统计摘要和最新数据点。")
public String queryDeviceHistory(String deviceId) {
Map<String, Object> stats = tdengine.queryStats(deviceId, 60); // avg/max/min
Map<String, Object> latest = tdengine.queryLatest(deviceId); // latest point
return formatJson(stats, latest);
}
聚合后从 2000 token 降到 200 token,LLM 反而能更准确地判断。
设计模式 2:正常范围标注
仅仅给数字不够------LLM 不知道什么是「正常」、什么是「异常」。
json
// 差:只有数字
{"temp": 72.5, "vibration": 4.8}
// 好:标注正常范围 + 是否超限
{
"temp": {"value": 72.5, "unit": "°C", "normalRange": "40-65", "status": "ABOVE"},
"vibration": {"value": 4.8, "unit": "mm/s", "normalRange": "0-2.8", "status": "CRITICAL"}
}
正常范围是 Tool 的领域知识,应该写在 Tool 代码里,而不是指望 LLM 自己去判断。
设计模式 3:多粒度接口
不同的用户意图需要不同粒度的数据:
| 用户问法 | 需要的数据粒度 | Tool 方法 |
|---|---|---|
| 「CNC-001 现在状态怎么样?」 | 最新一个数据点 | queryLatest |
| 「过去一小时的趋势怎么样?」 | 分钟级聚合 | queryHistory(60min) |
| 「这周的平均振动值?」 | 小时级聚合 | queryWeekly |
| 「振动是从什么时候开始升高的?」 | 原始数据 + 趋势 | queryTrend |
java
@Tool("查询指定设备最近5分钟的实时遥测趋势。")
public String queryRealtimeData(String deviceId) {
// 返回最近 5 分钟原始数据,最多 10 条
}
@Tool("查询指定设备过去1小时的统计摘要和最新值。")
public String queryDeviceHistory(String deviceId) {
// 返回 avg/max + latest
}
两个 Tool 方法,一个给「看趋势」,一个给「看摘要」。LLM 根据用户意图自动选择。
设计模式 4:异常数据自动标记
不需要 LLM 逐行扫描数据找异常------让 Tool 先做一轮预处理。
java
// Tool 内部预检
if (vibration > 2.8) {
summary.put("vibrationStatus", "CRITICAL");
summary.put("vibrationExceedPercent", (vibration - 2.8) / 2.8 * 100);
}
Tool 输出里直接带「振动超限 71%」------LLM 拿到的已经是结论性质的信息,只需要做最终判断。
完整示例
改造后的 DeviceDataTool 输出:
json
{
"deviceId": "CNC-001",
"latest": {
"temp": 72.5, "vibration": 4.8, "pressure": 0.9, "rpm": 1500, "current": 28.5
},
"statsLast60Min": {
"avg_temp": 68.3, "max_temp": 72.5,
"avg_vib": 3.2, "max_vib": 4.8,
"avg_pressure": 0.85
}
}
LLM 拿到这份数据后能轻松判断:
- 当前温度 72.5°C,高于一小时平均 68.3°C → 温度在上升
- 当前振动 4.8mm/s,一小时最大 4.8 → 振动在尖峰
- 结合知识库 → 「轴承磨损导致温度升高 → 振动超标 → 建议立即检查」
一句话总结
不要让 LLM 做 Tool 该做的数据处理。时序 Tool 的核心职责是预聚合、标注正常范围、标记异常------把原始数据变成 LLM 可直接推理的「诊断素材」。好的 Tool 不是一个数据库查询接口,而是一个领域数据分析师。
代码仓库:github.com/LaoLiang-agent/industrial-agent-long
本文由 LaoLiang 原创,首发于掘金/知乎/微信公众号。转载请联系作者。