12浏览
查看: 12|回复: 12

[项目] 【MimiClaw 嵌入式 AI Agent】ESP32-S3 从零搭建多端互联智能体

[复制链接]
## 摘要

本文基于自主开发的嵌入式 AI Agent 项目 MimiClaw(运行于 ESP32-S3 开发板),系统记录了整个开发周期中的架构设计、模块集成、典型故障及解决思路。MimiClaw 已实现多消息渠道接入(飞书、Telegram、WebSocket)、DeepSeek LLM 代理、博查搜索(联网检索工具)、技能系统、双电机差速驱动、WS2812 灯光控制、WiFi 配网与 OTA 预留等核心功能。文章详细阐述了消息总线设计、内存管理、外设驱动集成、网络异常处理、任务调度等关键环节的真实踩坑经验,并提供可直接复用的代码模板与最佳实践,旨在为从事嵌入式 AI Agent、边缘计算、机器人控制开发的工程师提供高价值参考。

真实硬件清单:ESP32-S3 开发板(8MB PSRAM)、9 颗 WS2812 LED(GPIO48)、双电机驱动模块(差速驱动)、可选串口调试线。

核心服务:DeepSeek LLM API(负责对话生成与推理决策)+ 博查搜索 API(提供联网信息检索能力),当前两者均存在网页解析失败问题,包括相关排查方案。

【MimiClaw 嵌入式 AI Agent】ESP32-S3 从零搭建多端互联智能体图1

驴友花雕  高级技神
 楼主|

发表于 2 小时前

【MimiClaw嵌入式AI Agent】ESP32-S3 从零搭建多端互联智能体

## 1. 项目背景:从“养一只 AI 小虾”到多端智能体

MimiClaw 的命名源自 “Miniature Intelligent Mobile & Interactive Cobot with Lightweight AI Wizard”,其定位是一款可部署在极低成本硬件上的轻量级 AI Agent。该项目可通过飞书、Telegram 等常用 IM 平台与用户交互,并能执行电机移动、灯光反馈等物理动作,实现“思考-搜索-行动”的完整闭环。

整个项目精准契合边缘 AI 落地的三大核心趋势:
(1)云端 LLM + 边缘执行:ESP32-S3 仅运行调度逻辑与工具调用,LLM 推理通过代理请求云端 DeepSeek API,兼顾智能性与实时性,避免边缘设备资源不足的瓶颈。
(2)多模态交互渠道:通过统一消息总线,同步支持飞书、Telegram、WebSocket 三种交互方式,后续可快速扩展至钉钉、微信等平台,降低多渠道接入成本。
(3)技能可插拔 + 联网搜索:借助 tool_registry 和 skill_loader 实现技能动态加载,结合博查搜索 API 赋予 Agent 联网检索真实世界实时信息的能力,弥补 LLM 知识截止日期的局限。

本文基于26天开发周期产出的36篇博客,完整记录了从裸机开发到完整 Agent 部署的全部弯路与教训。以下重点展开 DeepSeek LLM 接入与博查搜索工具集成两个核心模块的工程实践,同步融入当前 API 解析失败的排查思路。



回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 2 小时前

【MimiClaw嵌入式AI Agent】ESP32-S3 从零搭建多端互联智能体

## 2. 系统架构与模块划分

2.1 总体架构图(文字描述)

【MimiClaw 嵌入式 AI Agent】ESP32-S3 从零搭建多端互联智能体图1

2.2 核心模块职责

【MimiClaw 嵌入式 AI Agent】ESP32-S3 从零搭建多端互联智能体图2

回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 1 小时前

【MimiClaw嵌入式AI Agent】ESP32-S3 从零搭建多端互联智能体

本帖最后由 驴友花雕 于 2026-4-20 17:45 编辑

## 3. DeepSeek LLM 代理实现

3.1 为什么选择 DeepSeek?
在嵌入式 AI Agent 的 LLM 选型上,需要权衡以下几个维度:
- 成本:DeepSeek API 定价远低于 OpenAI 同类模型,适合开发测试与长期运行。
- 性能:推理速度快,响应延迟低(通常 1-3 秒),不阻塞 Agent 循环。
- 中文支持:原生中文理解与生成能力优秀,适合国内开发者场景。
- 兼容性:API 格式与 OpenAI 兼容,可复用成熟的 HTTP 客户端代码。

3.2 DeepSeek API 调用实现
参考官方文档,DeepSeek 提供标准的 OpenAI 兼容 API 接口。在 ESP-IDF 环境下,使用 esp_http_client 组件实现请求发送与响应接收。当前 API 地址(https://api.deepseek.com/v1/chat/completions)出现解析失败报错,需优先排查接口可用性、网络连接及证书配置问题。

  1. // llm_proxy.h 核心接口
  2. typedef struct {
  3.     char *api_key;
  4.     char *model;      // deepseek-chat / deepseek-reasoner
  5.     char *base_url;   // https://api.deepseek.com/v1/chat/completions
  6.     uint32_t timeout_ms;
  7.     bool stream;      // 是否启用流式输出
  8. } deepseek_config_t;
  9. esp_err_t deepseek_chat_completion(deepseek_config_t *config,
  10.                                    const char *system_prompt,
  11.                                    const char *user_message,
  12.                                    char **response);
复制代码

3.3 HTTP 请求与 JSON 解析实现
  1. // llm_proxy.c 核心实现片段
  2. static esp_err_t build_request_json(const char *system_prompt,
  3.                                      const char *user_message,
  4.                                      char **out_json) {
  5.     cJSON *root = cJSON_CreateObject();
  6.     cJSON_AddStringToObject(root, "model", "deepseek-chat");
  7.    
  8.     cJSON *messages = cJSON_CreateArray();
  9.     cJSON *sys_msg = cJSON_CreateObject();
  10.     cJSON_AddStringToObject(sys_msg, "role", "system");
  11.     cJSON_AddStringToObject(sys_msg, "content", system_prompt);
  12.     cJSON_AddItemToArray(messages, sys_msg);
  13.    
  14.     cJSON *user_msg = cJSON_CreateObject();
  15.     cJSON_AddStringToObject(user_msg, "role", "user");
  16.     cJSON_AddStringToObject(user_msg, "content", user_message);
  17.     cJSON_AddItemToArray(messages, user_msg);
  18.    
  19.     cJSON_AddItemToObject(root, "messages", messages);
  20.     cJSON_AddNumberToObject(root, "temperature", 0.7);
  21.     cJSON_AddNumberToObject(root, "max_tokens", 2048);
  22.    
  23.     *out_json = cJSON_Print(root);
  24.     cJSON_Delete(root);
  25.     return ESP_OK;
  26. }
复制代码


回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 1 小时前

【MimiClaw嵌入式AI Agent】ESP32-S3 从零搭建多端互联智能体

3.4 踩坑与解决方案(含 API 解析失败补充)

踩坑 1:SSL 证书验证失败
现象:ESP32 调用 DeepSeek API 时返回 SSL/TLS 握手失败。
原因:ESP32 的 mbedTLS 默认不包含 DeepSeek 服务端的根证书。
解决:
- 在 menuconfig 中启用 CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
- 将 DeepSeek API 域名添加到证书 bundle 白名单
- 或使用 esp_http_client_config_t 中的 skip_cert_common_name_check(仅限开发环境)

踩坑 2:PSRAM 与 JSON 解析内存不足
现象:调用 DeepSeek API 时,JSON 响应解析失败,返回 DeserializationError::NoMemory。
原因:DeepSeek 返回的响应可能超过 4KB,默认的静态 JSON 缓冲区不足。
解决:将 JSON 文档对象分配在 PSRAM 中。

  1. // 将 JsonDocument 分配在 PSRAM
  2. JsonDocument *doc = new (std::nothrow) JsonDocument();
  3. if (doc == NULL) {
  4.     // 回退到栈上分配
  5. }
复制代码

踩坑 3:流式输出阻塞 Agent 循环
现象:启用 stream: true 后,DeepSeek 的流式响应导致 Agent 循环被阻塞。
解决:在独立任务中处理流式响应,通过队列将完整响应发送回 Agent。

踩坑 4:API Key 硬编码风险
教训:将 API Key 硬编码在固件中既不安全也难以更新。
解决方案:
- 将 API Key 存储在 NVS 或 SPIFFS 的配置文件中。
- 通过 Serial CLI 命令动态更新 API Key,无需重新烧录固件。


踩坑 5:请求超时与重试机制缺失
现象:网络波动时,DeepSeek API 请求超时导致 Agent 无响应。
解决方案:实现指数退避重试机制(最多 3 次),并在重试失败时返回友好的错误提示。

踩坑 6:API 网页解析失败(新增)
现象:调用 DeepSeek API(https://api.deepseek.com/v1/chat/completions)时,系统提示“网页解析失败,可能是不支持的网页类型,请检查网页或稍后重试”。
可能原因:API 接口地址变更、网络连接异常(如 ESP32 未正常联网)、API 访问权限不足(如 API Key 无效)、请求头配置错误。
排查方向:
- 检查 WiFi 连接状态,确保 ESP32 能正常访问外网。
- 验证 DeepSeek API 地址是否正确,查询官方文档确认接口是否有更新。
- 检查 API Key 有效性,确认是否已开通对应接口权限。
- 简化请求参数,发送最小化合法请求,排查是否为请求体格式错误导致解析失败。

回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 1 小时前

【MimiClaw嵌入式AI Agent】ESP32-S3 从零搭建多端互联智能体

## 4. 博查搜索工具集成

4.1 为什么选择博查搜索?
博查(Bocha)是国内领先的 AI 搜索引擎 API 服务,为 LLM 和 AI Agent 提供联网搜索能力:
- 数据安全:国内合规服务,数据不出境。
- 内容安全:符合国内内容审核要求,有合规的内容过滤机制。
- 响应快速:平均响应时间 < 1 秒。
- 结果丰富:返回网页标题、URL、摘要、发布时间、网站名称等结构化信息。
- 成本低廉:单条搜索最低 0.001 元。
- 语义重排序:支持 Bocha Semantic Reranker,使搜索结果对 LLM 更友好。

4.2 博查搜索 API 调用实现
当前博查搜索 API 地址(https://api.bochaai.com/v1/web-search)出现解析失败报错,需同步排查接口可用性、网络及配置问题,以下为标准实现代码。

  1. // tools/tool_websearch.h
  2. typedef struct {
  3.     char *api_key;
  4.     char *query;
  5.     bool summary;        // 是否返回摘要
  6.     int count;           // 返回结果数量,最大 50
  7.     char *freshness;     // 时间范围:noLimit / oneDay / oneWeek / oneMonth / oneYear
  8.     char *include_sites; // 限定搜索网站,用 | 分隔
  9.     char *exclude_sites; // 排除搜索网站
  10. } bocha_search_params_t;
  11. esp_err_t bocha_web_search(bocha_search_params_t *params, char **result_json);
复制代码

4.3 HTTP 请求实现

  1. // tools/tool_websearch.c 核心实现
  2. static esp_err_t bocha_http_request(bocha_search_params_t *params, char **response) {
  3.     esp_http_client_config_t config = {
  4.         .url = "https://api.bochaai.com/v1/web-search",
  5.         .timeout_ms = 10000,
  6.         .keep_alive_enable = true,
  7.     };
  8.     esp_http_client_handle_t client = esp_http_client_init(&config);
  9.    
  10.     // 设置请求头
  11.     char auth_header[256];
  12.     snprintf(auth_header, sizeof(auth_header), "Bearer %s", params->api_key);
  13.     esp_http_client_set_header(client, "Authorization", auth_header);
  14.     esp_http_client_set_header(client, "Content-Type", "application/json");
  15.     esp_http_client_set_method(client, HTTP_METHOD_POST);
  16.    
  17.     // 构建请求体
  18.     cJSON *root = cJSON_CreateObject();
  19.     cJSON_AddStringToObject(root, "query", params->query);
  20.     cJSON_AddBoolToObject(root, "summary", params->summary);
  21.     cJSON_AddNumberToObject(root, "count", params->count);
  22.     if (params->freshness) {
  23.         cJSON_AddStringToObject(root, "freshness", params->freshness);
  24.     }
  25.     char *post_data = cJSON_Print(root);
  26.     esp_http_client_set_post_field(client, post_data, strlen(post_data));
  27.    
  28.     // 执行请求
  29.     esp_err_t err = esp_http_client_perform(client);
  30.     if (err == ESP_OK) {
  31.         int content_length = esp_http_client_get_content_length(client);
  32.         if (content_length > 0) {
  33.             *response = malloc(content_length + 1);
  34.             esp_http_client_read_response(client, *response, content_length);
  35.             (*response)[content_length] = '\0';
  36.         }
  37.     }
  38.    
  39.     free(post_data);
  40.     cJSON_Delete(root);
  41.     esp_http_client_cleanup(client);
  42.     return err;
  43. }
复制代码

4.4 注册为 Agent 工具

  1. // tools/tool_registry.c 注册函数
  2. void tool_registry_register_all(void) {
  3.     // ... 其他工具注册 ...
  4.    
  5.     tool_register(&(tool_t){
  6.         .name = "web_search",
  7.         .description = "搜索互联网获取实时信息,返回包含标题、链接和摘要的搜索结果",
  8.         .parameters = "{"type":"object","properties":{"query":{"type":"string","description":"搜索关键词"}}}",
  9.         .handler = websearch_tool_handler
  10.     });
  11. }
复制代码


回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 1 小时前

【MimiClaw嵌入式AI Agent】ESP32-S3 从零搭建多端互联智能体

4.5 踩坑与解决方案(含 API 解析失败补充)

踩坑 1:JSON 响应过大导致内存溢出
现象:博查搜索返回 50 条结果时,JSON 响应体可能超过 20KB,ESP32 内存不足。
解决方案:
- 使用流式 JSON 解析(deserializeJson(doc, client.getStream())),避免将整个响应加载到字符串中。
- 启用 PSRAM 存储 JSON 文档:JsonDocument doc; doc.reserve(32768)。
- 限制 count 参数不超过 10 条,减少单次搜索的内存占用。
-
踩坑 2:中文搜索关键词 URL 编码问题
现象:搜索中文关键词时,API 返回空结果。
原因:ESP32 的 esp_http_client 对中文未进行 URL 编码。
解决:使用 esp_http_client_set_post_field 以 POST 方式发送 JSON 请求体,中文直接放在 JSON 字符串中。

踩坑 3:并发搜索请求阻塞系统
现象:多个用户同时请求搜索时,Agent 循环被长时间阻塞。
解决:将搜索请求放入独立任务执行,使用消息队列通知 Agent 搜索结果。

踩坑 4:API Key 余额不足导致搜索失败
现象:搜索请求返回 HTTP 402,You do not have enough money。
解决方案:在 Serial CLI 中添加 check_balance 命令,定期检查余额并预警。

踩坑 5:搜索结果摘要包含特殊字符导致 JSON 解析失败
现象:博查返回的摘要中包含换行符或转义字符,导致 Agent 解析失败。
解决:使用 cJSON 自动处理字符串转义,或在使用前对摘要内容进行清理。

踩坑 6:API 网页解析失败(新增)
现象:调用博查搜索 API(https://api.bochaai.com/v1/web-search)时,系统提示“网页解析失败,可能是不支持的网页类型,请检查网页或稍后重试”。
可能原因:与 DeepSeek API 解析失败类似,主要包括接口地址变更、网络连接异常、API Key 无效、请求格式错误、博查服务临时故障。

排查方向:
- 确认 ESP32 外网连接正常,可通过 ping 命令测试博查 API 域名连通性。
- 核对博查 API 官方文档,确认接口地址、请求方法、请求头是否有更新。
- 检查 API Key 是否正确,是否已完成实名认证、余额充足。
- 简化请求参数(如仅传递 query 和 api_key),测试基础请求是否能正常响应。

回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 1 小时前

【MimiClaw嵌入式AI Agent】ESP32-S3 从零搭建多端互联智能体

## 5. DeepSeek + 博查搜索联合工作流

5.1 ReAct 循环设计
MimiClaw 的 Agent 循环采用 ReAct(Reasoning + Acting) 模式:

  1. 用户消息 → AgentLoop → 构造 Prompt(含历史会话 + 可用工具描述)→
  2. 调用 DeepSeek API → 解析响应 →
  3.     ├─ 若为普通回复 → 直接返回给用户
  4.     └─ 若为工具调用 → 执行对应工具(如 web_search)→ 将结果返回给 DeepSeek → 生成最终回复
复制代码


5.2 系统 Prompt 设计(工具调用引导)
为了让 DeepSeek 正确识别何时需要联网搜索,系统 Prompt 需包含工具说明:

你是 MimiClaw,一个智能助手。你可以使用以下工具:
1. web_search(query) - 搜索互联网获取实时信息。当你需要了解最新信息、新闻、事实或用户查询涉及的知识超出你的知识截止日期时,请调用此工具。
2. set_led(r,g,b) - 设置 RGB LED 颜色。
3. motor_control(motor, direction) - 控制电机。

请按以下格式输出工具调用:

<tool_call>{"name":"web_search","arguments":{"query":"搜索关键词"}}</tool_call>

5.3 完整交互示例
用户:今天深圳的天气怎么样?
Agent:调用 web_search(query="深圳 今天 天气")
博查返回:[网页结果...]
DeepSeek:今天深圳晴天,气温 22-28℃,适合出行。
Agent:今天深圳晴天,气温 22-28℃,适合出行。

5.4 联合工作流的踩坑

踩坑 1:LLM 返回格式不稳定导致工具调用失败
现象:DeepSeek 返回的工具调用 JSON 格式不符合预期(缺少引号、字段名错误)。
解决方案:
- 在系统 Prompt 中给出严格的格式示例。
- 实现容错解析:支持 {"name":"web_search","arguments":{"query":"..."}} 和 {"tool":"web_search","query":"..."} 两种格式。
- 解析失败时重新调用 DeepSeek 并要求纠正格式。

踩坑 2:搜索无结果时 LLM 仍然“编造”答案
现象:博查搜索返回空结果,DeepSeek 仍然生成了一个看似合理的虚假答案。
解决方案:
- 在工具返回结果中明确标识 success: false 或 results: []。
- 修改系统 Prompt,要求当搜索结果为空时明确告知用户“未找到相关信息”。

踩坑 3:DeepSeek 推理时间 + 博查搜索时间叠加导致超时
现象:用户等待时间超过 10 秒,体验差。
解决方案:
- 在飞书/Telegram 回复中先发送“正在思考...”的提示。
- 使用流式输出,逐字返回 DeepSeek 的生成内容。
- 将博查搜索的超时设置为 5 秒,超时后返回部分结果。

回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 1 小时前

【MimiClaw嵌入式AI Agent】ESP32-S3 从零搭建多端互联智能体

## 6. WiFi 配网与配置管理

6.1 WiFi 自动连接实现

  1. // wifi/wifi_manager.c 核心配置
  2. typedef struct {
  3.     char ssid[64];
  4.     char password[64];
  5. } wifi_credential_t;
  6. esp_err_t wifi_manager_init(void) {
  7.     // 从 NVS 读取已保存的 WiFi 凭证
  8.     wifi_credential_t cred;
  9.     if (nvs_read_credential(&cred) == ESP_OK) {
  10.         // 自动连接
  11.         return wifi_manager_connect(cred.ssid, cred.password);
  12.     }
  13.     return ESP_ERR_NOT_FOUND;  // 未配置,进入配网模式
  14. }
复制代码

6.2 WiFi 配置模板
为了方便批量部署,支持预置 WiFi 配置模板:

  1. // wifi_config_template.h
  2. #ifndef WIFI_CONFIG_TEMPLATE_H
  3. #define WIFI_CONFIG_TEMPLATE_H
  4. // 预置 WiFi 配置(首次烧录时使用,可被 NVS 覆盖)
  5. #define DEFAULT_WIFI_SSID     "your_wifi_ssid"
  6. #define DEFAULT_WIFI_PASSWORD "your_wifi_password"
  7. // 备用 WiFi 配置
  8. #define BACKUP_WIFI_SSID      "backup_wifi"
  9. #define BACKUP_WIFI_PASSWORD  "backup_password"
  10. #endif
复制代码

6.3 踩坑与解决方案
踩坑 1:WiFi 断线后无法自动重连
解决方案:注册 WiFi 断连事件,触发自动重连。

  1. esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED,
  2.                                      wifi_event_handler, NULL, NULL);
复制代码

踩坑 2:WiFi 连接超时导致系统卡死
解决方案:设置超时(30 秒),超时后进入配网模式。

  1. if (wifi_manager_wait_connected(30000) != ESP_OK) {
  2.     ESP_LOGW(TAG, "WiFi timeout, entering onboarding");
  3.     wifi_onboard_start(WIFI_ONBOARD_MODE_CAPTIVE);
  4. }
复制代码


回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 1 小时前

【MimiClaw嵌入式AI Agent】ESP32-S3 从零搭建多端互联智能体

## 7. 单元测试与验证方案

7.1 DeepSeek 代理单元测试

  1. // test_llm_proxy.c
  2. void test_deepseek_chat(void) {
  3.     deepseek_config_t config = {
  4.         .api_key = "your-api-key",
  5.         .model = "deepseek-chat",
  6.         .timeout_ms = 10000,
  7.         .stream = false,
  8.     };
  9.    
  10.     char *response = NULL;
  11.     esp_err_t ret = deepseek_chat_completion(&config,
  12.                                              "You are a helpful assistant.",
  13.                                              "Hello, who are you?",
  14.                                              &response);
  15.     TEST_ASSERT_EQUAL(ESP_OK, ret);
  16.     TEST_ASSERT_NOT_NULL(response);
  17.     ESP_LOGI("TEST", "DeepSeek response: %s", response);
  18.     free(response);
  19. }
复制代码

7.2 博查搜索工具单元测试

  1. // test_tool_websearch.c
  2. void test_bocha_websearch(void) {
  3.     bocha_search_params_t params = {
  4.         .api_key = "your-bocha-api-key",
  5.         .query = "ESP32 开发教程",
  6.         .summary = true,
  7.         .count = 5,
  8.         .freshness = "oneMonth",
  9.     };
  10.    
  11.     char *result = NULL;
  12.     esp_err_t ret = bocha_web_search(¶ms, &result);
  13.     TEST_ASSERT_EQUAL(ESP_OK, ret);
  14.     TEST_ASSERT_NOT_NULL(result);
  15.    
  16.     // 验证返回结果包含必要字段
  17.     cJSON *root = cJSON_Parse(result);
  18.     TEST_ASSERT_NOT_NULL(root);
  19.     TEST_ASSERT_NOT_NULL(cJSON_GetObjectItem(root, "webPages"));
  20.    
  21.     cJSON_Delete(root);
  22.     free(result);
  23. }
复制代码

7.3 端到端集成测试

  1. // test_agent_loop.c
  2. void test_agent_with_websearch(void) {
  3.     // 模拟用户消息
  4.     mimi_msg_t msg = {
  5.         .channel = MIMI_CHAN_TEST,
  6.         .chat_id = "test",
  7.         .content = strdup("今天的科技新闻有哪些?"),
  8.     };
  9.     message_bus_push_inbound(&msg);
  10.    
  11.     // 等待 Agent 处理(超时 15 秒)
  12.     mimi_msg_t reply;
  13.     message_bus_pop_outbound(&reply, 15000);
  14.     TEST_ASSERT_NOT_NULL(reply.content);
  15.     ESP_LOGI("TEST", "Agent reply: %s", reply.content);
  16.    
  17.     // 验证回复包含搜索相关信息
  18.     TEST_ASSERT_TRUE(strstr(reply.content, "科技") != NULL ||
  19.                      strstr(reply.content, "新闻") != NULL);
  20. }
复制代码


回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 1 小时前

【MimiClaw嵌入式AI Agent】ESP32-S3 从零搭建多端互联智能体

## 8. 核心经验与避坑速查表

汇总 MimiClaw 项目开发全流程典型问题、根本原因、解决方案及对应模块,重点标注当前 DeepSeek 与博查搜索 API 解析失败相关排查要点,方便开发调试快速查阅。

【MimiClaw 嵌入式 AI Agent】ESP32-S3 从零搭建多端互联智能体图2
【MimiClaw 嵌入式 AI Agent】ESP32-S3 从零搭建多端互联智能体图1

回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 1 小时前

【MimiClaw嵌入式AI Agent】ESP32-S3 从零搭建多端互联智能体

## 9. AI 落地的洞察:嵌入式 Agent 的三大实践原则

通过 MimiClaw 项目,我们可以提炼出适用于资源受限边缘设备的 AI Agent 设计准则:

9.1 云端大脑 + 边缘小脑 + 联网搜索
云端 LLM(DeepSeek):负责复杂推理、对话生成、工具选择。
边缘执行:实时响应、低延迟控制(电机、LED)、网络容灾。
联网搜索(博查):赋予 Agent 实时信息检索能力,弥补 LLM 知识截止日期的局限。
本项目体现:ESP32-S3 仅做轻量调度,DeepSeek Proxy 将请求转发至云端 API,同时集成博查搜索作为工具,实现“思考→行动→验证”的完整闭环(当前需先解决 API 解析失败问题)。

9.2 工具即技能(Tool as Skill)
将硬件操作和外部服务抽象为统一的工具接口,Agent 可通过自然语言调用。
代码实现:

  1. tool_registry_register("set_led", led_set_rgb)
  2. tool_registry_register("move", motor_differential)
  3. tool_registry_register("web_search", bocha_web_search)
复制代码

优势:用户可以说“请搜索今天的最新科技新闻”,Agent 自动调用博查搜索工具,将结果返回给 DeepSeek 后生成回复。

9.3 多渠道归一化
通过内部消息总线屏蔽不同 IM 的差异,Agent 核心只处理 mimi_msg_t。
扩展性:新增钉钉机器人只需实现 channel_send 和 channel_recv,并注册到 outbound_dispatch_task。
这些原则使得 MimiClaw 成为一个真正可落地的边缘 AI 原型——它不仅能“思考”,还能“搜索信息”和“执行动作”。


回复

使用道具 举报

驴友花雕  高级技神
 楼主|

发表于 1 小时前

【MimiClaw嵌入式AI Agent】ESP32-S3 从零搭建多端互联智能体

## 10. 后续优化方向

基于当前代码框架,以下工作可进一步提升实用性:
(1)OTA 固件更新:当前未实现,但已预留 SPIFFS 分区,可增加 ota_service 模块,从 HTTP 服务器拉取新固件。
(2)技能脚本热加载:skill_loader 目前仅支持 C 编译工具,可改为支持 Lua 或 MicroPython 脚本,让用户自定义行为。
(3) 低功耗模式:使用 ESP32-S3 的 light sleep,在无消息时关闭 WiFi 和电机驱动,将功耗降至 5mA 以下。
(4)本地 TinyML:在 PSRAM 中部署轻量级关键词唤醒模型(如使用 Edge Impulse SDK),实现语音触发,减少对 IM 的依赖。
(5)博查搜索语义重排序:集成 Bocha Semantic Reranker,使搜索结果按与用户问题的语义相关度排序,提升 LLM 对搜索结果的利用率。
(6)DeepSeek Reasoner 模型探索:尝试使用 deepseek-reasoner 模型,在复杂推理场景下获得更准确的工具调用决策。
(7) API 异常处理优化:针对当前 DeepSeek 和博查 API 解析失败问题,增加完善的异常捕获和重试机制,提升系统稳定性。

## 11. 结论

本文基于真实运行的 MimiClaw 项目源代码,系统回顾了在 ESP32-S3 上构建嵌入式 AI Agent 的完整过程——从内存配置、消息总线设计、多 IM 渠道接入,到 DeepSeek LLM 代理、博查搜索工具集成、双电机驱动、WS2812 灯光控制。

文中所有踩坑案例均来自实际调试记录,提供的解决方案可直接复用于类似项目。需特别注意,当前 DeepSeek LLM API(https://api.deepseek.com/v1/chat/completions)与博查搜索 API(https://api.bochaai.com/v1/web-search)均出现网页解析失败报错,需优先排查网络、接口地址、API 权限等问题,确保核心服务正常运行。

DeepSeek 接入核心要点:
- API 调用采用标准 OpenAI 兼容格式,响应通过流式或非流式返回。
- SSL 证书配置是 ESP32 端的常见障碍,需提前配置好 mbedTLS。
- PSRAM 是处理大 JSON 响应的关键,务必启用。
- 需重点排查 API 解析失败问题,确保接口可用性。

博查搜索接入核心要点:
- API 采用 RESTful 格式,支持丰富的搜索参数(时间范围、网站过滤等)。
- 控制 count 参数 ≤ 10,避免内存溢出。
- 使用流式 JSON 解析替代 getString(),大幅降低内存占用。
- 同步排查 API 解析失败问题,确保联网搜索功能正常。

26 天,36 篇博客,最终交付的代码量(仅 mimi.c 主文件)已达 200+ 行,整个工程超过 3000 行。MimiClaw 证明了:即使是在主频 240MHz、可用 RAM 仅 512KB 的 ESP32-S3 上,依然可以构建一个具备云端 LLM 能力、联网搜索能力、可执行物理动作、支持多端交互的智能 AI Agent。

最后,以代码中那行硬编码电机测试作为结束的隐喻:

  1. ESP_LOGI(TAG, ">>> Testing left motor forward 2 seconds <<<");
复制代码

MimiClaw 不仅学会了“思考”,学会了“搜索信息”,还学会了“行动”。这才是嵌入式 AI 真正迷人的地方。

【MimiClaw 嵌入式 AI Agent】ESP32-S3 从零搭建多端互联智能体图1

【MimiClaw 嵌入式 AI Agent】ESP32-S3 从零搭建多端互联智能体图2


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2026 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail