# Achai **Repository Path**: chi-chen666/achai ## Basic Information - **Project Name**: Achai - **Description**: Achai 是一个基于 C 语言构建的高性能、轻量级 AI Agent 运行时环境。它专为嵌入式设备(如树莓派、IoT 网关)设计,支持 ReAct 认知架构、工具调用(Function Calling)、技能动态加载、本地和远程MCP服务以及 MQTT 远程控制。实现了线程池和内存池,生产级可用。 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-02-14 - **Last Updated**: 2026-03-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Achai (AI Agent in C) Achai 是一个基于 C 语言构建的高性能、轻量级 AI Agent 运行时环境。它专为嵌入式设备(如树莓派、IoT 网关)设计,支持 ReAct 认知架构、工具调用(Function Calling)、技能动态加载、本地和远程MCP服务以及 MQTT 远程控制。 ## ✨ 主要特性 * **轻量级运行时**: 纯 C 语言编写,低内存占用,适合嵌入式环境。 * **ReAct 架构**: 实现 "思考-行动-观察" (Think-Act-Observe) 循环,支持复杂任务拆解。 * **多模态交互**: 支持命令行交互 (REPL) 和 MQTT 远程指令控制。 * **工具与技能**: * **内置工具**: Shell 命令执行、文件读写、定时器、闹钟等。 * **动态技能**: 支持通过 `skills/` 目录动态加载外部技能配置。 * **IoT 控制**: 内置 IoT 管理模块,支持通过配置文件 (`iot_config.json`) 定义设备,并进行读写操作。 * **Web & MCP**: 集成 MCP 协议,支持连接本地或远程的 MCP 服务。 * **异步架构**: 基于 Reactor 模式的事件驱动设计,集成 Paho MQTT,实现非阻塞 I/O。 * **长短期记忆**: * **短期记忆**: JSON 文件实时存储最近对话。 * **长期记忆**: 基于 SQLite + Vector Search 的归档机制,自动总结并向量化存储重要信息。 * **模块化设计**: 支持多种 LLM 后端(目前支持火山引擎 Volcengine,架构上支持扩展)。 ## 🛠️ 编译指南 (Build) ### 前置依赖 请确保您的系统已安装以下工具和库: * **CMake** (>= 3.10) * **GCC** 或 **Clang** 编译器 * **Make** * **libcurl4-openssl-dev** (用于 HTTP 请求) * **pthread** (线程支持) * **libssl-dev** (用于 HTTPS/MQTT) * **zlib1g-dev** (用于数据压缩) ### 编译步骤 #### 1. 克隆项目 ```bash git clone cd achai ``` #### 2. 编译 使用提供的脚本进行一键编译: ```bash chmod +x build.sh ./build.sh ``` 编译成功后,可执行文件 `Achai` 将生成在 `build/` 目录下。 ### 调试模式 (可选) 如果需要开启调试符号及内存检查 (AddressSanitizer): ```bash # 修改 build.sh 中的 CMAKE_BUILD_TYPE cmake -DCMAKE_BUILD_TYPE=Debug .. make ``` ## 🧪 测试 (Testing) 本项目包含单元测试和集成测试,使用 CTest 进行管理。 ### 运行所有测试 在 `build` 目录下运行: ```bash ctest --output-on-failure ``` 或者: ```bash make test ``` ### 运行特定测试 您可以根据测试名称运行特定的测试套件: ```bash # 运行单元测试 (Unit Tests) ctest -R unit_tests # 运行网络模块测试 (Network Tests) ctest -R network_tests # 运行 MQTT 集成测试 (Integration Tests - 需要 MQTT Broker) ctest -R integration_mqtt ``` ### 测试说明 * **unit_tests**: 核心逻辑的单元测试,涵盖 Utils, Core, Agent, Skills 等模块。使用 Mock 模拟网络和 LLM 调用,无需外部依赖。 * **network_tests**: 网络客户端的逻辑测试,使用 Mock 驱动模拟 LLM 响应。 * **integration_mqtt**: MQTT 模块的集成测试。**注意**:此测试需要本地或配置的 MQTT Broker 处于运行状态,否则会失败。 ## ⚙️ 配置说明 (Configuration) Achai 使用 `.env` 文件进行配置。程序启动时会自动在当前目录、父目录或祖父目录查找 `.env` 文件。 请在项目根目录创建 `.env` 文件,并参考以下配置: ```ini # --- 基础配置 --- # 工作区目录 (默认: workspace) ACHAI_WORKSPACE=workspace # 技能目录 (默认: skills) ACHAI_SKILLS_DIR=skills # 日志级别 (0:User, 1:Process, 2:Debug, 3:Error) ACHAI_LOGGER=2 # 是否输出日志到控制台 (1:开启, 0:关闭) ACHAI_LOG_TO_CONSOLE=1 # --- LLM 模型配置 --- # LLM 提供商 (目前支持: volcengine) LLM_PROVIDER=volcengine # 模型接入点 ID (例如火山引擎的 Endpoint ID) LLM_MODEL_ID=ep-20240604055538-2q2h9 # API Key (格式: _API_KEY,大写) VOLCENGINE_API_KEY=your_api_key_here # --- 记忆与归档配置 --- # 触发归档的对话条数 (默认: 25) ACHAI_MEMORY_ARCHIVE_THRESHOLD=25 # 归档后保留的最近条数 (默认: 5) ACHAI_MEMORY_ARCHIVE_KEEP=5 # 归档时重叠的条数 (默认: 5) ACHAI_MEMORY_ARCHIVE_OVERLAP=5 # --- Embedding 配置 --- # Embedding 模型路径 (GGUF 格式) ACHAI_EMBEDDING_MODEL=models/embedding/bge-small-zh-v1.5-f32.gguf # 数据库文件路径 (默认: memory/achai.db) ACHAI_MEMORY_PATH=memory/achai.db # --- MQTT 配置 (IoT 集成) --- # MQTT Broker 地址 MQTT_HOST=localhost # MQTT 端口 MQTT_PORT=1883 # 客户端 ID MQTT_CLIENT_ID=achai_device_01 # 订阅的主题 (接收指令) MQTT_TOPIC_IN=achai/chat/in # 发布的主题 (发送回复) MQTT_TOPIC_OUT=achai/chat/out # (可选) MQTT 用户名和密码 # MQTT_USERNAME=user # MQTT_PASSWORD=pass # --- IoT 配置 (IoT) --- # IoT 配置文件路径 (默认: config/iot_config.json) ACHAI_IOT_CONFIG=config/iot_config.json # IoT 数据库路径 (默认: iot.db) ACHAI_IOT_DB=iot.db ``` ### IoT 配置文件 (iot_config.json) Achai 使用 `config/iot_config.json` 定义 IoT 设备。支持 **只读 (read)** 和 **只写 (write)** 两种权限。 **配置示例:** ```json { "devices": [ { "name": "living_room_temp", "topic": "achai/sensor/temp", "type": "float", "unit": "°C", "access": "read" }, { "name": "kitchen_light_control", "topic": "achai/kitchen/light/set", "type": "string", "unit": "mode", "access": "write" } ] } ``` * **access="read"**: 设备为只读(如传感器)。系统会自动订阅 `topic`,接收到的消息会存入本地数据库 `iot.db`。 * **access="write"**: 设备为只写(如控制器)。Agent 可以使用 `set_iot` 工具向 `topic` 发送指令,但不会订阅该主题,也不会将指令存入数据库。 * **type**: 支持 `int`, `float`, `bool`, `string`。系统会自动进行类型转换和校验。 ### MCP 服务配置 (mcp_config.json) Achai 支持通过 `mcp_config.json` 文件配置多个 MCP 服务器。支持 **Stdio** (本地进程) 和 **HTTP/SSE** (远程服务) 两种模式。 文件路径优先级: 1. 环境变量 `ACHAI_MCP_CONFIG` 指定的路径 2. 当前目录下的 `mcp_config.json` 3. 父目录或祖父目录下的 `mcp_config.json` **配置示例:** ```json { "mcpServers": { "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/files"], "env": { "NODE_ENV": "production" } }, "remote-agent": { "url": "http://localhost:8000/sse", "api_key": "sk-..." } } } ``` **配置字段说明:** * **Stdio 模式** (通过命令行启动本地服务): * `command`: (必填) 可执行命令或脚本路径。 * `args`: (可选) 命令行参数数组。 * `env`: (可选) 环境变量键值对对象。 * **HTTP 模式** (连接远程 SSE 服务): * `url`: (必填) 远程服务的 SSE 端点地址。 * `api_key`: (可选) 用于认证的 Bearer Token。 ## 🚀 使用说明 (Usage) ### 1. 启动 Agent 确保已配置好 `.env` 文件,然后在 `build` 目录下运行: ```bash ./Achai ``` 或者通过命令行参数指定模型: ```bash # 用法: ./Achai [provider] [model_id] ./Achai volcengine ep-2024xxxx ``` ### 2. 交互模式 启动后,您可以直接在终端输入自然语言指令与 Agent 交互: ```text User: 帮我设置一个 5 分钟后的闹钟 Achai: 好的,正在为您设置... [调用 set_timer 工具] Achai: 已为您设置好 5 分钟后的闹钟。 ``` ### 3. MQTT 远程控制 Achai 启动后会自动连接配置的 MQTT Broker。 * **发送指令**: 向 `achai/chat/in` 主题发布消息。 * **接收回复**: 订阅 `achai/chat/out` 主题获取 Agent 的响应。 ### 4. 目录结构 * `src/`: 源代码 * `tools/`: 工具定义与注册 * `definitions/`: 工具的具体实现代码 * `tool_list.c`: 工具注册列表 * `skills/`: 技能定义文件 (Markdown 格式) * `workspace/`: Agent 运行时产生的文件存储位置 * `memory/`: 长期记忆数据库存放位置 * `config/`: 配置文件存放位置 (如 iot_config.json) * `prompt/`: 系统提示词模板存放位置 * `logs/`: 运行时日志存放位置 * `models/`: 本地模型存放位置 (需自行下载模型文件) * `AGENTS.md`: 详细的开发与架构文档 ## 🛠️ 如何添加新工具 (How to Add Tools) Achai 支持扩展自定义工具。工具源代码位于项目根目录的 `tools/` 文件夹下。 ### 步骤 1: 创建工具实现文件 在 `tools/definitions/` 目录下创建一个新的 `.c` 文件(例如 `my_tool.c`),并使用 `DEFINE_TOOL` 宏实现工具逻辑。 ```c #include #include #include "utils/cJSON.h" #include "tools.h" // 引入基础工具定义 // 使用 DEFINE_TOOL 宏定义工具函数 // 自动生成函数签名: char* tool_my_add(cJSON* args) DEFINE_TOOL(my_add) { // 1. 解析参数 (假设 args 是 [1, 2]) // GET_ARG_INT(index, variable_name) GET_ARG_INT(0, num1); GET_ARG_INT(1, num2); // 2. 执行逻辑 // ... // 3. 返回结果 (自动处理内存分配) char buffer[128]; snprintf(buffer, sizeof(buffer), "%d + %d = %d", num1, num2, num1 + num2); RETURN_STRING(buffer); } ``` ### 步骤 2: 注册工具 打开 `tools/tool_list.c` 文件,在 `tools_register_all()` 函数中注册您的新工具。 1. 声明外部函数(或者在头文件中声明): ```c // Forward declaration char* tool_hello_world(cJSON* args); ``` 2. 调用 `tools_register`: ```c void tools_register_all(void) { // ... 其他工具 ... // 参数: 名称, 描述, 参数格式(JSON schema 字符串), 函数指针 tools_register( "hello_world", "Say hello to someone", "[\"name\"]", tool_hello_world ); } ``` ### 常用宏说明 * **DEFINE_TOOL(name)**: 定义工具函数 `tool_name`。 * **GET_ARG_STR(idx, var)**: 获取字符串参数,存入 `const char* var`。如果类型不匹配会自动返回错误。 * **GET_ARG_INT(idx, var)**: 获取整数参数,存入 `int var`。 * **RETURN_STRING(str)**: 返回字符串结果。 * **RETURN_INT(val)**: 返回整数结果(自动转字符串)。 * **RETURN_ERROR(msg)**: 返回错误信息。 ### 步骤 3: 重新编译 ```bash cd build make ``` 重启 Achai 后,Agent 即可感知并使用该工具。 ## 🔌 如何添加本地 MCP 服务 (How to Add Local MCP Server) 除了内置的 C 语言工具,Achai 还支持通过 **Model Context Protocol (MCP)** 集成外部工具服务。您可以编写 Python、Node.js 等语言的 MCP Server,并通过标准输入输出 (stdio) 与 Achai 通信。 ### 步骤 1: 创建 MCP Server 脚本 在项目根目录下创建一个新目录(例如 `MCP_local`),并在其中编写 Server 脚本(例如 `server.py`)。 该脚本需要实现基本的 MCP 协议 JSON-RPC 交互,主要处理以下方法: - `initialize`: 初始化握手 - `tools/list`: 返回工具列表 - `tools/call`: 执行工具调用 以下是一个 Python 实现示例: ```python import sys import json def main(): while True: try: # 读取标准输入 line = sys.stdin.readline() if not line: break req = json.loads(line) method = req.get("method") req_id = req.get("id") # 1. 处理初始化请求 if method == "initialize": resp = { "jsonrpc": "2.0", "id": req_id, "result": { "protocolVersion": "2024-11-05", "capabilities": {}, "serverInfo": {"name": "MyLocalServer", "version": "1.0"} } } print(json.dumps(resp)) sys.stdout.flush() # 2. 处理初始化通知 (无响应) elif method == "notifications/initialized": pass # 3. 返回工具列表 elif method == "tools/list": resp = { "jsonrpc": "2.0", "id": req_id, "result": { "tools": [ { "name": "weather_query", "description": "查询指定地点的天气", "inputSchema": { "type": "object", "properties": { "location": {"type": "string", "description": "城市名称"} }, "required": ["location"] } } ] } } print(json.dumps(resp)) sys.stdout.flush() # 4. 处理工具调用 elif method == "tools/call": params = req.get("params", {}) name = params.get("name") args = params.get("arguments", {}) # 兼容性处理:如果 args 是列表,取第一个元素 if isinstance(args, list) and len(args) > 0 and isinstance(args[0], dict): args = args[0] content = "" if name == "weather_query": loc = args.get("location", "未知地点") content = f"{loc} 的天气是:晴朗,25°C" else: content = f"未知工具: {name}" resp = { "jsonrpc": "2.0", "id": req_id, "result": { "content": [{"type": "text", "text": content}] } } print(json.dumps(resp)) sys.stdout.flush() # 5. 心跳检测 elif method == "ping": resp = {"jsonrpc": "2.0", "id": req_id, "result": {}} print(json.dumps(resp)) sys.stdout.flush() except json.JSONDecodeError: continue except Exception as e: continue if __name__ == "__main__": main() ``` ### 步骤 2: 配置 mcp_config.json 在项目根目录下创建或编辑 `mcp_config.json` 文件,注册您的本地 Server。 ```json { "mcpServers": { "local_mcp": { "command": "python3", "args": ["-u", "server.py"], "env": { "PYTHONPATH": "/absolute/path/to/achai/MCP_local", "LOG_LEVEL": "INFO" } } } } ``` > **注意**: `cwd` (工作目录) 建议使用绝对路径,确保 Achai 能正确找到脚本位置。`args` 中的 `-u` 参数对于 Python 很重要,它强制标准输出不缓存,保证通信实时性。 ### 步骤 3: 启动 Achai 配置完成后,正常启动 Achai: ```bash ./Achai ``` Achai 启动时会自动读取 `mcp_config.json`,启动配置的子进程,并加载其中定义的工具(如 `weather_query`)。您可以在对话中直接使用这些工具。 ## ☁️ 如何连接远程 MCP 服务 (How to Connect Remote MCP Server) 除了本地子进程,Achai 还支持通过 HTTP (SSE - Server-Sent Events) 协议连接远程运行的 MCP 服务器。这对于将重型计算任务卸载到云端或连接共享的 Agent 服务非常有用。 ### 步骤 1: 部署远程 MCP Server 远程 Server 需要支持 MCP 的 SSE 传输规范。您可以使用官方 SDK 或兼容框架部署。 例如,一个简单的 Node.js SSE Server 可能运行在 `http://myserver.com:8000/sse`。 ### 步骤 2: 配置 mcp_config.json 在 `mcp_config.json` 中添加 `url` 字段即可: ```json { "mcpServers": { "remote_math_solver": { "url": "http://192.168.1.100:8000/sse", "api_key": "optional-secret-token" } } } ``` * `url`: 远程服务的 SSE 端点。Achai 会先连接此端点接收事件,并通过 POST 请求发送指令。 * `api_key`: (可选) 如果远程服务需要鉴权,Achai 会将其放入 HTTP 请求头的 `Authorization: Bearer ` 中。 ### 步骤 3: 启动 Achai 启动后,Achai 会自动尝试连接该 URL。连接成功后,远程 Server 暴露的工具将自动注册到 Achai 的工具列表中。 ## 📝 开发手册 更多关于项目架构、代码结构和开发规范的详细信息,请参阅 [AGENTS.md](AGENTS.md)。 ## 📄 许可证 (License) 本项目基于 MIT 许可证开源。详情请参阅 [LICENSE](LICENSE) 文件。 Copyright (c) 2024-2025 Achai