基于LLM的IoT项目实践

几年前,我曾想过,“我可以使用 Alexa 来管理物理设备吗?”我创建了一个简单的演示项目,向我的业余无线电朋友展示。你会说,“Alexa,将我的天线旋转 90 度”,我的模型天线就会神奇地转动。这是一个有趣的周末项目,使用了 Raspberry Pi、步进电机和微型模型天线。如果你好奇的话,我在 YouTube 上发布了它。

1、智能玩具屋

Alexa 实验很棒,但也存在一些问题。使用 Alexa,你应该非常精确地使用短语。在我的应用程序中,Alexa 希望你说,“Alexa,将我的天线旋转 XX 度”,只有这个确切的短语才会起作用。随着大型语言模型 (LLM) 的可用性不断提高,我开始考虑使用它们来管理电机、设备和传感器。

“如果我得到一个玩具屋,”我想,“并添加一堆传感器和一个微控制器,并为它们编写一个 REST API 服务器,会怎么样?”然后,我会请LLM将人类语言转换为 REST API 请求,并将它们发送到服务器。此外,我想要一些看起来逼真的东西,而不仅仅是一堆散落在我桌子上的传感器。

幸运的是,我在亚马逊上找到了我所需要的东西:一座木屋,上面连接着许多传感器和一个微控制器。我不得不称赞我从 Keyestudio 购买的套件的卓越品质:构建和连接传感器非常容易,软件在第一次运行时就运行正常!如果你以前尝试过类似的套件,你应该知道它并不常见。

该套件包括一个简单的 Arduino 控制器和一个实现一些业务逻辑的示例程序:例如,当屋顶上的雨量传感器上有信号时,伺服电机会关闭窗户。

它工作正常,但我需要一个服务器来响应远程请求。

2、物联网服务器

我决定改用 Raspberry Pi Pico W 和 MicroPython。 Pico 的“W”版本为我提供了所需的连接,我打算使用 MicroPython 实现一个简单的 REST API 服务器。

3、使用 AI 助手

由于它变得越来越普遍,我请 Claude.ai 帮我完成这个项目:

我想用 MicroPython 为 Raspberry Pi Pico 编写一个程序。它应该运行连接到 WiFi 的 Web 服务器。Web 服务器应该接受 REST 请求并在 Pico 上执行操作,例如:从传感器获取信息、打开和关闭 LED、打开和关闭电机(伺服和步进器)。请帮我为这个应用程序创建一个 API。

Claude 回答了一个可用于我们计划的 API 的 curl 命令列表。我喜欢这种方法:我首先设计了预期的用户体验(在我们的例子中是 REST API),然后开始实现它。

它创建了一个非常简单的 Web 服务器,没有使用任何框架,只使用套接字。我问我们是否可以使用像 Flask 这样的框架,Claude 告诉我,使用 MicroPython 时,使用 Microdot 更为常见,因为它占用的资源更少。我了解到 Microdot 是由 Miguel Grinberg 开发的,他是 Flask 最受欢迎的书籍之一的作者。这是一个很好的建议,我请 Claude 用 Microdot 重新编写 Web 服务器。

完成后,我在 Pico 上测试了服务器,它运行良好!但我还有一个想法,我问:

请帮我为 Microdot 编写 GET 函数,当以 /sensors 调用时,它将返回传感器列表,当以 /sensors/id 调用时,它将返回传感器的值。我认为这应该有助于可发现性。

这是另一个发现!Claude 告诉我一个名字很奇怪的概念,“HATEOAS”,代表超媒体作为应用程序状态的引擎。它解释了背后的想法,给出了示例,最后编写了服务器代码,该代码将响应 /sensors/leds 等路线,其中包含有关传感器和 LED 位置(屋顶、花园、门)、参数(LED 颜色、传感器校准)的信息,最重要的是,我应该使用它们来工作的链接。

这非常接近我需要的。

4、使用 LLM 生成 REST API 调用

现在,多亏了 Claude 的帮助,我有一个服务器,它可以用以下 JSON 响应 curl http://server/leds 之类的请求:

{
  "_links": {
    "filter_by_color": {
      "href": "/leds/filter?color={color}",
      "templated": true
    },
    "self": {
      "href": "/leds"
    },
    "filter_by_location": {
      "href": "/leds/filter?location={location}",
      "templated": true
    }
  },
  "data": {
    "1": {
      "color": "yellow",
      "location": "roof",
      "state": 0,
      "_links": {
        "on": {
          "href": "/leds/1/on"
        },
        "self": {
          "href": "/leds/1"
        },
        "off": {
          "href": "/leds/1/off"
        },
        "toggle": {
          "href": "/leds/1/toggle"
        }
      }
    },
    "2": {
      "color": "white",
      "location": "garden",
      "state": 0,
      "_links": {
        "on": {
          "href": "/leds/2/on"
        },
        "self": {
          "href": "/leds/2"
        },
        "off": {
          "href": "/leds/2/off"
        },
        "toggle": {
          "href": "/leds/2/toggle"
        }
      }
    }
  }
}

如果我从其他路由(例如 /sensors/motors)获取类似的 JSON,将它们发送到 LLM,并要求它将人工请求转换为 curl 命令,会怎么样?然后,我可以通过请求 Python 库将这些命令发送到服务器并与设备一起工作!

下一步是编写一个简单的 Python 脚本,该脚本将从服务器的根路由( /)获取初始链接,并探索所有链接以从中获取相同的 JSON。

脚本以这种方式收集服务器的 API 描述后,我创建了一个系统提示,其中包含来自服务器的所有链接的整个 JSON,并添加了请求:

你是 IoT API 助手。
将用户命令转换为 IoT 服务器的 curl 命令。
API 结构:{json.dumps(self.api_structure, indent=2)}
服务器 URL:{self.server_url}
仅使用 curl 命令进行响应,不做任何解释。

然后,我创建了一个简单的对话框,该对话框将以人类语言从用户那里获取命令,将其附加到提示,然后将其发送到 LLM。

对于此应用程序,我使用了 Anthropic 的 Haiku-3.5,因为它比更复杂的模型更快、更便宜。

5、将 JSON 响应翻译成人类语言

现在,系统已开始工作。我会发送一条消息,例如“打开黄色 LED”,它就会亮起。或者,“打开花园 LED”,花园中的白色 LED 就会亮起。我可以用普通语言问:“屋顶上的光照条件如何?”它用包含大量信息的 JSON 进行响应:

{
  "_links": {
    "config": {
      "href": "/sensors/2/config"
    },
    "self": {
      "href": "/sensors/2/value"
    },
    "all_sensors": {
      "href": "/sensors"
    },
    "sensor": {
      "href": "/sensors/2"
    }
  },
  "data": {
    "unit": "lux",
    "type": "light",
    "calibrated_value": 4114.6,
    "location": "roof",
    "id": "2",
    "raw_value": 41146
  }
}

这很好,但我想要更合理的人类语言而不是 JSON!LLM 再次拯救了我!这是 Haiku 的另一个提示:

将此 IoT API JSON 响应转换为简洁的人类语言,重点关注最重要的信息。
不要打印“这是简明摘要”或其他解释;只打印内容:

现在我的服务器的答案看起来像:

位于屋顶上的光传感器 #2 测量到 4,109.8 勒克斯,表明照明条件明亮。

6、首次公开演示

最近,我去了亚特兰大当地的 Python 聚会。我打算介绍并演示这个项目。不用说,我很紧张。

我在手机上启动了一个热点,将笔记本电脑连接到它,然后启动了 Pico。它表明它已连接到热点并获得了 IP 地址。现在,我必须更改我的对话程序以指向该地址。

对话开始:

物联网控制器启动。输入“退出”退出。
>>> 打开黄色 LED
LED 1 当前亮起,颜色为黄色,位于屋顶上。
>>> 打开电机
电机 1(直流类型)当前处于开启状态并位于屋顶上。
>>> 关闭电机
电机 #1 是位于屋顶的直流电机,目前已关闭。

到目前为止,一切顺利。当螺旋桨开始旋转时,公众很喜欢,并给了我一阵掌声。

我将键盘切换为西里尔字母并输入以下内容:

>>> выключи желтый led

“哇,这是俄语吗?”我听到观众的低语。

然后奇迹发生了。LED 熄灭了,我收到了以下消息:

位于屋顶的 LED 1 为黄色,目前处于关闭状态(状态 0)。

我问聚会组织者,“Pablo,你能用西班牙语告诉它打开 LED 吗?”

Pablo 拿起键盘输入:

>>> Por favor prender el LED amarillo
LED 1 当前处于打开状态(状态 1),颜色为黄色,位于屋顶上。
>>> Apaga la maldita led amarilla
LED 1 目前处于关闭状态,位于屋顶上,颜色为黄色。

“哇!”观众说道。

我解释说:“这个魔术完全是由 LLM 完成的。我没有在代码中做任何事情。它理解多种语言,并轻松地在它们与 REST 和 JSON 之间进行转换。请注意,当我用俄语跟它说话时,我使用了英文单词“LED”,它完全理解了我的话。”

7、经验教训

这个项目变成了一次意想不到的学习之旅。我从一个控制玩具屋的简单想法开始,但最终学到了:

  • MicroPython 及其与常规 Python 的区别
  • Microdot — 一个非常适合微控制器的轻量级 Web 框架
  • HATEOAS — 一个名称听起来像打喷嚏的 REST API 设计原则
  • LLM 在处理自然语言处理方面的令人难以置信的多功能性

最重要的是,我了解到像 Claude 这样的 AI 助手可以成为出色的编码伙伴。他们帮助编写代码,并向你介绍您可能没有发现的最佳实践和概念。

8、未来计划

当然,我开始寻找扩展项目的方法。而且,我从 Keyestudio 找到了一个巨大的 42 合 1 套件,里面有许多传感器和执行器。

说点什么并显示在 LCD 屏幕上不是很酷吗?气体传感器、加速度计、蜂鸣器和电机都在等着我把它们连接起来。

越来越严肃了。

当然,这只是一个为学习而创建的玩具项目。如果你想在现实生活中使用物联网,当然,你应该看看 Home Assistant。我就是这么做的,我想,“我可以用同样的方法来创建 Home Assistant 的 API 请求吗?”不用说,该项目已经为 LLM 实现了 API。“英雄所见略同”,我自豪地对自己说。😉

9、项目代码

如果你有兴趣构建自己的多语言智能玩具屋(或者只是想看看它是如何工作的),请查看 GitHub 上的项目:Geekhouse。欢迎随时贡献、提问或分享你的物联网冒险经历。

尝试使用你知道的任何语言,看看 LLM 是否可以将其转换为 REST API 调用!尝试其他 LLM;尝试在你的家庭实验室中运行本地 LLM。最有可能的是,使用本地 LLM 将使 LED 的打开和关闭速度更快。

10、结束语

我喜欢这个项目从我早期对 Alexa 等语音助手的实验发展到在物联网中使用 LLM。在这个项目中,我不仅使用 LLM 将人类转换为 JSON,还帮助我编写代码和学习新事物。LLM 确实是好帮手!


原文链接:Geekhouse: an LLM-based IoT project

汇智网翻译整理,转载请标明出处