一、写在前面:为什么写这篇文章?

最近在做一个 IoT 设备监控系统,本来是一个传统的 Spring Boot 项目,负责采集 EMQX 数据、调用 JetLinks API、统计设备状态。

但做着做着,我发现一个问题:代码越写越多,规则越写越死

  • 设备ID格式不统一?写正则匹配

  • 健康分怎么算?定权重公式

  • 数据异常怎么判断?设阈值

  • 用户问"在线设备多少?"?写 switch 分支

每一个需求都要改代码、加规则、重新部署。

于是我开始思考:能不能让 AI 来做这些事?

结果发现,这条路比我想象的复杂得多,但也值得多得多。

这篇文章,我想和大家分享一个真实 IoT 系统如何被 AI 重构的过程,以及传统开发 vs AI 开发的本质区别


二、最初的想法:调用 API 就完事了?

刚开始,我的想法很简单:

"AI 不就是调个接口吗?我传问题,它返回答案。"

于是写了个简单的 OllamaClientUtil,把用户问题直接发给 qwen2.5:1.5b 模型。

结果呢?

用户问:"在线设备多少?"

模型回答:"在线设备是指能够通过网络连接到服务器的设备,通常包括...(以下省略500字)"

它根本不知道去哪里查数据!

我意识到:AI 需要数据,数据在数据库里,数据库需要代码去查

AI 能帮我的不是"替我做",而是"帮我决定做什么"。


三、传统开发 vs AI 开发:一个真实案例的对比

以设备状态查询为例,我们来看看两种开发方式的差别。

传统开发模式

1. 意图识别:写正则匹配

java

// 用户输入:"设备001在线吗?"
if (question.matches(".*设备\\d+.*在线.*")) {
    String deviceId = extractDeviceId(question);
    return queryDeviceStatus(deviceId);
}

每增加一种表达方式,就要加一条正则。

2. 数据查询:写 SQL

java

String sql = "SELECT online_status FROM device_status WHERE device_id = ?";
String status = jdbcTemplate.queryForObject(sql, String.class, deviceId);

3. 回答生成:拼接字符串

java

return "设备" + deviceId + "状态:" + status;

4. 添加新问题:"设备001健康分多少?"

java

// 1. 加正则
if (question.matches(".*设备\\d+.*健康分.*")) { ... }

// 2. 加 SQL
String sql = "SELECT health_score FROM device_health WHERE device_id = ?";

// 3. 改代码 → 编译 → 部署

问题:每加一个功能,都要改代码、发版。用户换种说法,系统就不认识了。


AI 开发模式

1. 定义工具(一次)

java

register(new AgentTool(
    "query_device_status",
    "查询设备状态。参数: deviceId",
    Map.of("deviceId", "设备ID"),
    args -> {
        String deviceId = (String) args.get("deviceId");
        return queryDeviceStatusFromDB(deviceId);
    }
));

2. AI 决策

java

// AI 返回
{"tool": "query_device_status", "args": {"deviceId": "001"}}

// 执行工具
String result = tool.getExecutor().apply(args);

3. 用户换种说法,AI 自动识别

用户说 AI 决策
"设备001在线吗?" query_device_status
"001设备状态?" query_device_status
"设备001咋样了?" query_device_status
"001号设备怎么样?" query_device_status

不用改代码!

4. 添加新功能:注册新工具

java

register(new AgentTool(
    "analyze_device_health",
    "分析设备健康分。参数: deviceId",
    Map.of("deviceId", "设备ID"),
    args -> analyzeHealth(args.get("deviceId"))
));

AI 自动学会什么时候该用这个工具。


直观对比表

维度 传统开发 AI 开发
理解用户表达 写正则,一条一条加 AI 自动理解,不用加
添加新功能 改代码 → 编译 → 部署 注册新工具,热生效
用户换种说法 不认识,要加规则 自动识别
业务规则变化 改代码逻辑 改 Prompt 或加知识
代码量 随功能线性增长 工具数增长,主逻辑不变
维护成本 越来越高 稳定

四、第一次尝试:让 AI 识别意图

我的第一个改进:让 AI 识别用户意图,然后代码执行对应的查询。

java

// 意图识别结果
{"intent": "统计设备数量", "deviceId": "全部", "timeRange": "今天"}

// 代码路由
switch (intent) {
    case "统计设备数量": return countDevices();
    case "查询设备状态": return queryDeviceStatus(deviceId);
}

效果立竿见影:

  • "在线设备多少?" → AI 识别意图 → 代码统计 → 返回结果

  • "设备001状态?" → AI 识别意图 → 代码查数据库 → 返回结果

但问题来了:意图种类是有限的。用户说"设备001咋样了?",AI 还能识别吗?"设备001最近有没有问题?"呢?

加更多的意图 → 改代码 → 加 switch 分支 → 重新部署。

我又回到了老路上:改代码。


五、第二次尝试:让 AI 自己选工具

这次我换了个思路:不让 AI 选意图,而是让它选工具

java

// 工具定义
- count_online_devices: 统计在线设备
- query_device_status: 查询设备状态
- analyze_log: 分析日志
- learn_knowledge: 学习新知识
- search_knowledge: 搜索知识库

// AI 决策
{"tool": "count_online_devices", "args": {}}

这样,添加新功能不需要改 switch,只需要注册新工具。

java

register(new AgentTool(
    "sync_devices_from_jetlinks",
    "从 JetLinks 同步设备列表",
    args -> syncDevices()
));

AI 成了"大脑",代码成了"手脚"。


六、真正的挑战:让 AI 理解你的业务

工具化之后,AI 确实能调用工具了。但还有一个核心问题:AI 不懂你的业务

用户说:"emqx@iot-emqx 不是设备"

AI 会怎么处理?它不知道这是在告诉它一个规则,还是真的在问设备状态。

于是我们加入了知识学习功能:

java

// 用户告诉 AI 知识
"emqx@iot-emqx 不是设备"

// AI 存入知识库
INSERT INTO ai_knowledge VALUES ('emqx@iot-emqx 不是设备')

// 后续用户问 "emqx@iot-emqx 是什么?"
// AI 从知识库检索,回答:"emqx@iot-emqx 不是设备"

这样,AI 能听懂业务了


七、最意外的坑:动态网页抓取

为了让 AI 能学习文档,我们加了"学习网页"功能。

结果语雀的网页抓不到内容!折腾了很久,最后发现:语雀是动态渲染的,Jsoup 抓不到

试了 HtmlUnit,试了 Selenium,都太重。

最后发现:语雀的正文其实在 HTML 里是静态的,只是我们没找到正确的选择器。

java

// 正确提取语雀正文
String text = doc.select(".lake-content").text();

教训:不要一上来就用重型工具,先看看是不是自己没找对地方。


八、最终架构:AI Agent 模式

经过几个月的迭代,系统最终变成了这样:

text

用户问题
    ↓
AgentExecutor(AI 决策)
    ↓
选择工具(AI 自己决定)
    ↓
执行工具(调用业务代码)
    ↓
润色回答(AI 美化)
    ↓
返回用户

核心能力:

能力 实现方式
设备状态查询 AI 调用 query_device_status
设备统计 AI 调用 count_online_devices
知识学习 AI 调用 learn_knowledge
日志分析 AI 调用 analyze_log
网页学习 AI 调用 learn_from_url

九、核心收获:AI 开发的几个认知

1. AI 不是魔法,是决策引擎

AI 不替你写代码,不替你查数据库,它帮你决定查什么、怎么查、怎么回答

2. 小模型能干活,但别指望它完美

我用的是 qwen2.5:1.5b(1.5B 参数),在 CPU 上跑。它不能像 ChatGPT 那样理解所有复杂表达,但简单意图识别、工具选择、知识检索完全够用。

关键是:给它明确的工具列表和清晰的示例

3. 知识库是 AI 的灵魂

通用模型不懂你的业务。你得教它。

  • 教它:设备ID格式

  • 教它:日志路径

  • 教它:什么是异常

AI 学得越多,越懂你。

4. 工具化比意图识别更灵活

意图识别 → 改代码加 switch → 麻烦
工具化 → 注册新工具 → 不改主逻辑

java

register(new AgentTool(
    "新功能",
    "功能描述",
    args -> 执行代码
));

5. 动态网页是个坑

如果只是学文档,Jsoup 够用了。别一上来就上 Selenium。


十、传统开发 vs AI 开发:本质区别

传统开发 AI 开发
你告诉计算机怎么做 你告诉 AI 做什么
规则写死在代码里 规则在 Prompt 里,可随时改
添加功能要改代码 添加功能注册工具
用户表达必须精确匹配 AI 理解语义,容错性强
维护成本越来越高 维护成本稳定

十一、什么时候用 AI 开发?

场景 推荐方式
功能固定、用户少 传统开发
功能多变、用户表达多样 AI 开发
需要快速响应业务变化 AI 开发
需要用户教系统新知识 AI 开发

十二、写在最后

这个项目让我深刻体会到:AI 不是来替代你的,是来放大你的能力的

你仍然需要写代码:

  • 连接数据库

  • 调用 API

  • 处理业务逻辑

但 AI 帮你做了最头疼的事:理解用户意图、决定执行什么、让系统更灵活

如果你也在做类似的系统,希望这篇文章能给你一些启发。关键要明白为什么用ai,传统的开发项目是做功能点,比如查看设备情况,就是查询数据库,显示信息。一个功能点一组代码。ai可以在一定程度上像普通人一样交流。数据也多样。以前设备状态一定是格式化收集在数据库表,需要就是点击查询按钮去sql查询,写对应的sql语句。现在也要写。但是更加通用。另外就是数据源,可以是文件本,可以是查询数据库表。一段文字让ai识别自己提取信息。

你的系统也可以有自己的 AI 大脑。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐