# iAs — 微信 AI 智能助手 Rust 实现的微信 iLink Bot,支持 DeepSeek AI 自动回复、内置工具调用、审批确认、定时任务和长期记忆。 ## 快速开始 ```bash # 1. 配置环境变量(或创建 .env 文件) export DEEPSEEK_API_KEY="sk-xxx" export DATABASE_URL="postgresql://..." # PostgreSQL 可选 # 2. 扫码登录微信 ias login # 3. 启动 AI 自动回复 ias listen --llm # 4. 后台运行(配合 systemd) ias service ``` ## 命令一览 | 命令 | 说明 | |------|------| | `ias login` | 扫码登录微信,认证信息存入 PostgreSQL / 本地文件 | | `ias listen --llm` | 启动长轮询 + AI 自动回复 | | `ias listen --echo` | 启动长轮询 + 原样回显 | | `ias listen` | 仅监听,不做回复 | | `ias send --to --text ` | 手动发送消息 | | `ias whoami` | 查看登录状态 | | `ias usage` | Token 用量统计(默认 7 天) | | `ias service` | 后台服务模式(日志 + systemd) | | `ias daemon` | 守护进程模式(daemon + worker 分离架构) | | `ias tool datetime` | 获取当前时间 | | `ias tool weather <城市>` | 查询天气 | | `ias tool search <关键词>` | 联网搜索 | | `ias tool fetch ` | 提取网页正文 | | `ias tool memos list/add/delete` | 管理备忘录 | | `ias tool amap poi-search/geocode/route-plan/travel-plan` | 高德地图服务 | ## 配置(环境变量) | 变量 | 必须 | 说明 | |------|------|------| | `DEEPSEEK_API_KEY` | ✅ | DeepSeek API 密钥 | | `DEEPSEEK_MODEL` | — | 模型名,默认 `deepseek-v4-flash` | | `DATABASE_URL` | — | PostgreSQL 连接串,无则降级文件存储 | | `WEIXIN_LLM_SYSTEM_PROMPT` | — | 自定义系统提示词 | | `TAVILY_API_KEY` | — | Tavily 搜索 API Key | | `QWEATHER_API_HOST` | — | 和风天气 API 地址 | | `QWEATHER_JWT_KEY_ID` | — | 和风天气 JWT Key ID | | `QWEATHER_JWT_PROJECT_ID` | — | 和风天气项目 ID | | `QWEATHER_JWT_PRIVATE_KEY_FILE` | — | 和风天气 Ed25519 私钥路径 | | `AMAP_WEBSERVICE_KEY` | — | 高德地图 Web 服务 Key(或 `AMAP_KEY`) | 加载顺序:`./.env` → `~/.ias/.env` → 环境变量 ## 架构 ``` ┌─────────────────────────────────────────────────┐ │ iAs CLI │ │ main.rs → clap 子命令路由 │ ├─────────────────────────────────────────────────┤ │ ┌──────────┐ ┌──────────┐ ┌───────────────┐ │ │ │ WeChat │ │ LLM │ │ Tools │ │ │ │ 长轮询 │ │ DeepSeek │ │ 内置工具 │ │ │ │ HTTP API │ │ 流式对话 │ │ 审批管理 │ │ │ └────┬─────┘ └────┬─────┘ └──────┬────────┘ │ │ │ │ │ │ │ ┌────┴──────────────┴───────────────┴────────┐ │ │ │ Context / Memory │ │ │ │ ChatSession · Token Budget · 摘要压缩 │ │ │ │ MemoryStore · 长期记忆 │ │ │ └──────────────────────┬──────────────────────┘ │ │ │ │ │ ┌──────────────────────┴──────────────────────┐ │ │ │ Database (PostgreSQL) │ │ │ │ auth · chat_records · llm_usage │ │ │ │ user_memories · pending_approvals │ │ │ │ session_summaries · scheduled_tasks │ │ │ └─────────────────────────────────────────────┘ │ ├─────────────────────────────────────────────────┤ │ Daemon / Worker IPC (可选) │ │ Unix Domain Socket · 帧协议 · 进程隔离 │ └─────────────────────────────────────────────────┘ ``` ## 核心数据流 ``` 微信消息到达 → 保存 inbound chat_records → 用户切换:加载历史 + 记忆 → 构建 LLM 上下文(token budget + 摘要注入) → Conversation.chat_with_tools() ├── LLM 流式回复 ├── 工具调用 → query_capabilities / call_capability │ ├── 上下文工具:read_memories / write_memory / read_summaries │ ├── 内置工具:datetime / weather / search / memos / fetch_page / amap │ └── High 风险工具 → 审批流程 └── 工具结果注入对话 → LLM 继续 → 保存 outbound chat_records + LLM usage → 微信发送回复 ``` ## 源码结构 ``` src/ ├── main.rs CLI 入口 + 命令实现 + 监听循环 + 工具执行器 ├── cli.rs clap 子命令定义(login/listen/send/tool 等) ├── logger.rs 日志初始化(终端 + 文件滚动) ├── state.rs 本地文件状态(auth.json / runtime.json,无DB时降级) ├── scheduler.rs 定时任务调度器 ├── context/ 上下文管理 │ ├── types.rs ChatSession(checkpoint/messages/summaries) │ ├── builder.rs Token budget 估算 + 上下文构建 + 摘要触发 │ └── tools.rs MemoryStore(HashMap>) ├── db/ 数据库 │ ├── mod.rs Database 连接池 + 迁移 │ └── models.rs CRUD(auth/chat/usage/summary) ├── llm/ 对话系统 │ ├── types.rs Message / Role / ToolCall / StreamChunk / Usage │ ├── provider.rs LlmProvider trait + SSE 解析 │ ├── deepseek.rs DeepSeek 流式客户端 │ └── conversation.rs Conversation(chat + chat_with_tools 工具循环) ├── tools/ 工具系统 │ ├── types.rs RiskLevel / SkillSpec / SkillResult / ExecutionContext │ ├── builtin.rs BuiltinRegistry 路由 │ ├── approval.rs ApprovalManager(确认码 + oneshot 通道) │ └── builtins/ 内置工具实现 │ ├── datetime.rs 日期时间 │ ├── weather.rs 和风天气(JWT + reqwest) │ ├── web_search.rs Tavily 搜索 │ ├── fetch_page.rs 网页抓取 │ ├── memos.rs 备忘录 │ └── amap.rs 高德地图(POI/地理编码/路径/旅游规划) ├── wechat/ 微信通道 │ ├── types.rs iLink API 协议类型 │ └── client.rs HTTP 客户端(login/poll/send/notify) ├── daemon.rs 守护进程(持有 WeChat + DB,spawn worker) ├── worker.rs Worker 进程(无状态 LLM 执行) └── ipc.rs Unix Domain Socket 帧协议 ``` ## 工具系统 ### LLM 可见工具 | 工具名 | 说明 | |--------|------| | `query_capabilities` | 列出所有可用工具及参数说明 | | `call_capability` | 按名称调用任意工具 | | `read_memories` | 读取用户长期记忆 | | `write_memory` | 写入长期记忆 | | `read_summaries` | 读取历史会话摘要 | ### 内置工具 | 工具 | 风险 | 说明 | |------|------|------| | `get_current_datetime` | Low | 获取北京时间 | | `query_weather` | Low | 和风天气查询 | | `web_search` | Low | Tavily 联网搜索 | | `fetch_page` | Low | 网页正文提取 | | `manage_memos` | Low | 备忘录增删查 | | `amap_*` | Low | 高德地图系列 | ### 审批流程 High 风险工具需要用户微信确认: ``` LLM 调用 High 工具 → 生成 6 位确认码 → SHA-256 入库 → 微信发送确认消息(含确认码) → 等待用户回复(最多 300s,3 次重试) → 匹配成功 → 执行工具 → 返回结果 → 匹配失败 / 超时 → 返回拒绝信息 ``` LLM 不感知确认码和审批过程,只看到最终的执行结果。 ## 上下文管理 - **Token Budget**:28K tokens,中/英文字符估算 - **Checkpoint**:摘要压缩点,之前的消息已压缩,之后完整保留 - **摘要触发**:token 溢出(overflow)或 12h 空闲(timeout) - **长期记忆**:LLM 按需通过 `read_memories` / `write_memory` 读写 - **用户隔离**:切换用户时清空 session,按需加载新用户历史 ## 数据库表 | 表 | 用途 | |----|------| | `app_state` | 认证信息 KV 存储 | | `chat_records` | 收发消息记录(message_id 去重) | | `llm_usage` | Token 用量统计(含缓存命中率) | | `user_memories` | 长期记忆(按 user_id) | | `pending_approvals` | 待审批记录(SHA-256 确认码) | | `session_summaries` | 会话摘要 | | `scheduled_tasks` | 定时任务 | ## 部署 ### systemd 服务 ```bash sudo cp systemd/ias.service /etc/systemd/system/ # 编辑 .env 文件确保 API Key 等环境变量已配置 sudo systemctl enable --now ias ``` ### 天气 API 密钥 将和风天气 Ed25519 密钥对放入 `qweather/` 目录: ``` qweather/ ├── ed25519-private.pem └── ed25519-public.pem ``` ## 依赖 | 依赖 | 用途 | |------|------| | tokio | 异步运行时 | | clap | CLI 参数解析 | | reqwest | HTTP 客户端 | | sqlx | PostgreSQL 驱动 + 迁移 | | serde / serde_json | 序列化 | | chrono | 时间处理 | | tracing | 结构化日志 | | async-trait | 异步 trait | | ed25519-dalek | 天气 API JWT 签名 | | scraper | 网页正文提取 | | sha2 / hex / rand | 审批确认码加密 |