前言

本文手把手教你把 MimiClaw 部署到 ESP32-S3系列开发板上,并对接国内大模型(以阿里云百炼 Qwen 为例),适合 0 基础小白,部分步骤参考了Mimiclaw 快速体验指南 - 芯电厂MimiClaw 项目中添加一个新的大语言模型 提供商 - 哔哩哔哩的教程。


目录

  1. 准备工作

  2. 克隆 MimiClaw 仓库

  3. 安装 ESP-IDF 开发环境

  4. 修改配置文件(核心步骤)

  5. 编译烧录

  6. 常见问题


1. 准备工作

需要的硬件

  • ESP32-S3-WROOM-1 开发板

  • USB-C 数据线

  • 电脑(Windows 系统)

需要的软件

  • Git(用于克隆仓库)

  • 阿里云百炼账号(获取 API Key)

  • 飞书机器人(可选,用于和 MimiClaw 对话)


2. 克隆 MimiClaw 仓库

首先,在 D 盘创建一个文件夹(比如 D:\mimiclaw),然后打开 cmd,输入:

cd /d D:\
git clone git@github.com:memovai/mimiclaw.git

克隆完成后,你会看到 D:\mimiclaw 文件夹下有很多文件。


3. 安装 ESP-IDF 开发环境

3.1 下载离线安装包

访问这个链接下载 ESP-IDF 安装管理器和完整离线包: https://dl.espressif.cn/dl/eim/?tab=offline

点击“Download”下载这两个文件:

  • ESP-IDF 安装管理器(ESP-IDF Installation Manager)

  • 完整离线套餐:archive_vv5.5.3_windows-x64.zst

3.2 安装 ESP-IDF

  1. 打开下载好的 ESP-IDF 安装管理器

  2. 点击"从存档安装"(Install from archive)

  3. 选择刚才下载的 archive_vv5.5.3_windows-x64.zst 压缩包

  4. 更改安装路径到 D 盘(比如 D:\ESP-IDF

  5. 点击"开始安装"

3.3 配置工具链

安装完成后,你会看到:

  • D:\ESP-IDF\v5.5.3\esp-idf 文件夹

  • C:\Espressif 文件夹(里面有 dist 和 tools)

重要步骤

  1. 先不要管 C:\Espressif

  2. Win + R 键,输入 cmd 打开命令行

  3. 输入:

    cd /d D:\ESP-IDF\v5.5.3\esp-idf
    install.bat
  4. 这个脚本会在 C:\Users\你的用户名\.espressif 下创建 dist 和 tools 文件夹,但安装过程可能很慢

  5. 关闭命令行窗口,我们直接复制已有的文件

  6. C:\Espressif 下的 dist 和 tools 两个文件夹复制到 C:\Users\你的用户名\.espressif 内(点击替换相同类型的文件)

  7. 再次按 Win + R,输入 cmd,输入:

    cd /d D:\ESP-IDF\v5.5.3\esp-idf
    install.bat
  8. 等待安装完成后,输入:

    export.bat
  9. 验证环境:

    idf.py --version

如果没有报错,说明 ESP-IDF 环境配置成功!


4. 修改配置文件

我们需要修改mimiclaw文件夹下的 3 个文件:

  1. main\mimi_secrets.h - 存放私密配置

  2. main\mimi_config.h - 全局配置

  3. main\llm\llm_proxy.c - 大模型代理逻辑


4.1 修改 mimi_secrets.h(以配置qwen3.5-flash模型接口为例)

位置D:\mimiclaw\main\mimi_secrets.h

原始文件内容

/* Anthropic API */
#define MIMI_SECRET_API_KEY         ""
#define MIMI_SECRET_MODEL           ""
#define MIMI_SECRET_MODEL_PROVIDER  "anthropic"

修改后的内容

/* Anthropic API */
#define MIMI_SECRET_API_KEY         "sk-你的阿里云百炼API Key"
#define MIMI_SECRET_MODEL           "qwen3.5-flash"
#define MIMI_SECRET_MODEL_PROVIDER  "qwen"

修改说明

配置项

修改内容

原因

MIMI_SECRET_API_KEY

填入你的阿里云百炼 API Key

用于认证大模型

MIMI_SECRET_MODEL

改成 qwen3.5-flash

使用阿里云的 Qwen 模型

MIMI_SECRET_MODEL_PROVIDER

改成 qwen

告诉程序使用 Qwen 大模型


4.2 修改 mimi_config.h,新增#define MIMI_QWEN_API_URL

位置D:\mimiclaw\main\mimi_config.h

原始文件修改前(约第 85-94 行):

/* LLM */
#define MIMI_LLM_DEFAULT_MODEL       "claude-opus-4-5"
#define MIMI_LLM_PROVIDER_DEFAULT    "anthropic"
#define MIMI_LLM_MAX_TOKENS          4096
#define MIMI_LLM_API_URL             "https://api.anthropic.com/v1/messages"
#define MIMI_OPENAI_API_URL          "https://api.openai.com/v1/chat/completions"

修改后的内容

/* LLM */
#define MIMI_LLM_DEFAULT_MODEL       "qwen3.5-flash"
#define MIMI_LLM_PROVIDER_DEFAULT    "qwen"
#define MIMI_LLM_MAX_TOKENS          4096
#define MIMI_QWEN_API_URL            "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"
//新增了:#define MIMI_QWEN_API_URL
#define MIMI_LLM_API_URL             "https://api.anthropic.com/v1/messages"
#define MIMI_OPENAI_API_URL          "https://api.openai.com/v1/chat/completions"

修改说明

配置项

修改内容

原因

MIMI_LLM_DEFAULT_MODEL

改成 qwen3.5-flash

默认使用 Qwen 模型

MIMI_LLM_PROVIDER_DEFAULT

改成 qwen

默认 provider 为 qwen

新增 MIMI_QWEN_API_URL

添加阿里云 API 地址

指定 Qwen 的 API 端点

新增的代码解释

  • MIMI_QWEN_API_URL:阿里云百炼的 OpenAI 兼容接口地址

  • 后面我们会在 llm_proxy.c 中使用这个 URL


4.3 修改 llm_proxy.c(最复杂的部分)

位置D:\mimiclaw\main\llm\llm_proxy.c

这是最复杂的部分,我们需要添加 Qwen 的完整支持。


4.3.1 添加 Qwen 的 Provider 判断函数

修改位置:约第 185 行附近

原始代码

static bool provider_is_openai(void)
{
    return strcmp(s_provider, "openai") == 0;
}

修改后的代码

static bool provider_is_openai(void)
{
    return strcmp(s_provider, "openai") == 0;
}

static bool provider_is_qwen(void)
{
    return strcmp(s_provider, "qwen") == 0;
}

修改原因:添加一个函数,用来判断当前使用的是不是 Qwen 大模型。


4.3.2 修改 llm_api_url() 函数

修改位置:约第 190 行

原始代码

static const char *llm_api_url(void)
{
    return provider_is_openai() ? MIMI_OPENAI_API_URL : MIMI_LLM_API_URL;
}

修改后的代码

static const char *llm_api_url(void)
{
    if (provider_is_qwen()) {
        return MIMI_QWEN_API_URL;
    }
    return provider_is_openai() ? MIMI_OPENAI_API_URL : MIMI_LLM_API_URL;
}

修改原因:当使用 Qwen 时,告诉程序去访问阿里云的 API 地址。


4.3.3 修改 llm_api_host() 函数

修改位置:约第 195 行

原始代码

static const char *llm_api_host(void)
{
    return provider_is_openai() ? "api.openai.com" : "api.anthropic.com";
}

修改后的代码

static const char *llm_api_host(void)
{
    if (provider_is_qwen()) {
        return "dashscope.aliyuncs.com";
    }
    return provider_is_openai() ? "api.openai.com" : "api.anthropic.com";
}

修改原因:告诉程序 Qwen 的服务器域名是阿里云的域名。


4.3.4 修改 llm_api_path() 函数

修改位置:约第 200 行

原始代码

static const char *llm_api_path(void)
{
    return provider_is_openai() ? "/v1/chat/completions" : "/v1/messages";
}

修改后的代码

static const char *llm_api_path(void)
{
    if (provider_is_qwen()) {
        return "/compatible-mode/v1/chat/completions";
    }
    return provider_is_openai() ? "/v1/chat/completions" : "/v1/messages";
}

修改原因:指定 Qwen API 的具体路径。


4.3.5 修改 llm_http_direct() 函数(认证部分)

修改位置:约第 268 行

原始代码

if (provider_is_openai()) {
    if (s_api_key[0]) {
        char auth[LLM_API_KEY_MAX_LEN + 16];
        snprintf(auth, sizeof(auth), "Bearer %s", s_api_key);
        esp_http_client_set_header(client, "Authorization", auth);
    }
}

修改后的代码

if (provider_is_openai() || provider_is_qwen()) {
    if (s_api_key[0]) {
        char auth[LLM_API_KEY_MAX_LEN + 16];
        snprintf(auth, sizeof(auth), "Bearer %s", s_api_key);
        esp_http_client_set_header(client, "Authorization", auth);
    }
}

修改原因:Qwen 使用和 OpenAI 一样的 Bearer 认证方式,所以需要把 Qwen 也加入这个判断。


4.3.6 修改 llm_http_via_proxy() 函数(代理模式)

修改位置:约第 296 行

原始代码

if (provider_is_openai()) {
    hlen = snprintf(header, sizeof(header),
        "POST %s HTTP/1.1\r\n"
        "Host: %s\r\n"
        "Content-Type: application/json\r\n"
        "Authorization: Bearer %s\r\n"
        "Content-Length: %d\r\n"
        "Connection: close\r\n\r\n",
        llm_api_path(), llm_api_host(), s_api_key, body_len);
}

修改后的代码

if (provider_is_openai() || provider_is_qwen()) {
    hlen = snprintf(header, sizeof(header),
        "POST %s HTTP/1.1\r\n"
        "Host: %s\r\n"
        "Content-Type: application/json\r\n"
        "Authorization: Bearer %s\r\n"
        "Content-Length: %d\r\n"
        "Connection: close\r\n\r\n",
        llm_api_path(), llm_api_host(), s_api_key, body_len);
}

修改原因:在使用代理模式时,Qwen 也需要和 OpenAI 一样的请求头。


4.3.7 修改 llm_chat_tools() 函数(请求格式)

修改位置:约第 562 行

原始代码

if (provider_is_openai()) {
    cJSON_AddNumberToObject(body, "max_completion_tokens", MIMI_LLM_MAX_TOKENS);
} else {
    cJSON_AddNumberToObject(body, "max_tokens", MIMI_LLM_MAX_TOKENS);
}

if (provider_is_openai()) {
    cJSON *openai_msgs = convert_messages_openai(system_prompt, messages);
    cJSON_AddItemToObject(body, "messages", openai_msgs);

    if (tools_json) {
        cJSON *tools = convert_tools_openai(tools_json);
        if (tools) {
            cJSON_AddItemToObject(body, "tools", tools);
            cJSON_AddStringToObject(body, "tool_choice", "auto");
        }
    }
}

修改后的代码

if (provider_is_openai() || provider_is_qwen()) {
    cJSON_AddNumberToObject(body, "max_completion_tokens", MIMI_LLM_MAX_TOKENS);
} else {
    cJSON_AddNumberToObject(body, "max_tokens", MIMI_LLM_MAX_TOKENS);
}

if (provider_is_openai() || provider_is_qwen()) {
    cJSON *openai_msgs = convert_messages_openai(system_prompt, messages);
    cJSON_AddItemToObject(body, "messages", openai_msgs);

    if (tools_json) {
        cJSON *tools = convert_tools_openai(tools_json);
        if (tools) {
            cJSON_AddItemToObject(body, "tools", tools);
            cJSON_AddStringToObject(body, "tool_choice", "auto");
        }
    }
}

修改原因:Qwen 兼容 OpenAI 的请求格式,所以用相同的消息转换函数和参数。


4.3.8 修改响应解析部分

修改位置:约第 638 行

原始代码

if (provider_is_openai()) {
    cJSON *choices = cJSON_GetObjectItem(root, "choices");
    // ... 解析响应
}

修改后的代码

if (provider_is_openai() || provider_is_qwen()) {
    cJSON *choices = cJSON_GetObjectItem(root, "choices");
    // ... 解析响应
}

修改原因:Qwen 的响应格式也和 OpenAI 兼容,所以用相同的解析逻辑。


5. 编译烧录

终于到最后一步了!

5.1 激活 ESP-IDF 环境

Win + R,输入 cmd,打开命令行:

cd /d D:\ESP-IDF\v5.5.3\esp-idf
export.bat

5.2 进入项目目录

cd D:\mimiclaw

5.3 清理旧构建(可选)

如果之前编译过,建议运行这条命令清理一下:

idf.py fullclean

5.4 设置目标芯片

idf.py set-target esp32s3

这个命令会自动编译。

5.5 烧录并查看串口监视器

idf.py flash monitor


显示如上信息则说明烧录成功了。

5.6 配置飞书和WIFI

以下展示通过CLI 的方式配置mimiclaw。
首先,在串口监视器下输入:

help

如上所示,串口监视器会返回所有配置mimiclaw 的命令。

我们可以分别输入:

set_wifi 你的wifi名称 你的wifi密码

注意:可以填入你的手机热点WiFi和密码,但WiFi频段必须要2.4Ghz 才能连接。

set_feishu_creds 飞书app_id 飞书app_secret

可在飞书开放平台获取,具体如何配置飞书机器人,可参考Mimiclaw 快速体验指南 - 芯电厂的教程。

最后,检查所有配置是否完成,输入:

config_show

配置完成。

5.7 测试飞书通信


 


6. 常见问题

6.1 提示 "No bot token configured"

如果你不用 Telegram,在 mimi.c 中注释掉这两行:

// ESP_ERROR_CHECK(telegram_bot_init());
// ESP_ERROR_CHECK(telegram_bot_start());

6.2 提示 "You didn't provide an API key"

  1. 检查 mimi_secrets.h 中的 API Key 是否正确

  2. 通过串口 CLI 重新设置:

    mimi> set_api_key 你的API Key
    mimi> set_model_provider qwen
    mimi> set_model qwen3.5-flash

6.3 404 错误

检查 mimi_config.h 中的 MIMI_QWEN_API_URL 是否正确,应该是:

https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions

总结

恭喜你!现在你的 ESP32-S3 已经成功部署了 MimiClaw,并且可以使用阿里云百炼的 Qwen 大模型了!

通过飞书机器人给 ESP32 发消息,试试吧!


注意:本文以 Qwen 为例,如果你想用火山引擎或混元,修改方式类似,只需要:

  1. mimi_config.h 中添加对应的 API URL

  2. llm_proxy.c 中添加对应的 provider 判断

  3. 调整消息格式(如果需要)

希望这篇教程对你有帮助!有问题欢迎在评论区留言!

Logo

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

更多推荐