69ba8887ff
- 新建 README.md,整合项目架构、命令、配置、数据流 - 删除 6 个冗余/过时 md 文档 - save_summary_to_db 委托 db::models::save_summary,避免 SQL 重复 - #[allow(dead_code)] 标注 serde 反序列化字段和预留 API - 移除未使用的 re-export (Summarizer, Message, Role, StreamChunk) - 修复 README 中 manage_memos 风险等级和缺失的 AMAP_KEY 配置
241 lines
10 KiB
Markdown
241 lines
10 KiB
Markdown
# 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 <id> --text <msg>` | 手动发送消息 |
|
||
| `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 <URL>` | 提取网页正文 |
|
||
| `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<user_id, Vec<mem>>)
|
||
├── 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 | 审批确认码加密 |
|