From c55201a03a7eb604638743ffdb1f8b23a2b712e1 Mon Sep 17 00:00:00 2001 From: AskaEth Date: Mon, 22 Jun 2026 21:17:14 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E6=B8=85=E7=90=86=E4=B8=8D=E5=BA=94?= =?UTF-8?q?=E8=B7=9F=E8=B8=AA=E7=9A=84=E6=96=87=E6=A1=A3=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gitignore 规范: 仅 docs/api/ 和 docs/deploy/ 纳入版本管理 移除: 架构分析/开发规划/备份迁移等规划类文档 Co-Authored-By: Claude --- docs/cyrene-project-architecture-analysis.md | 856 ------------------- docs/dev-plan/12-next-phase-optimization.md | 290 ------- docs/pg-backup-migration.md | 99 --- 3 files changed, 1245 deletions(-) delete mode 100644 docs/cyrene-project-architecture-analysis.md delete mode 100644 docs/dev-plan/12-next-phase-optimization.md delete mode 100644 docs/pg-backup-migration.md diff --git a/docs/cyrene-project-architecture-analysis.md b/docs/cyrene-project-architecture-analysis.md deleted file mode 100644 index 9c283b1..0000000 --- a/docs/cyrene-project-architecture-analysis.md +++ /dev/null @@ -1,856 +0,0 @@ -# Cyrene AI 项目架构与功能分析文档 - -> **日期**:2026-05-23 -> **分支**:`dev` -> **项目根目录**:`d:\Project\Code\Uni\Cyrene` - ---- - -## 目录 - -1. [项目概览](#一项目概览) -2. [总体架构](#二总体架构) -3. [后端服务详解](#三后端服务详解) - - [AI-Core (8081) — 对话引擎](#31-ai-core-8081--对话引擎) - - [Gateway (8080) — API 网关](#32-gateway-8080--api-网关) - - [Memory-Service (8091) — 记忆系统](#33-memory-service-8091--记忆系统) - - [工具系统 (pkg/plugins + AI-Core)](#34-工具系统-pkgplugins--ai-core-集成) - - [IoT-Debug-Service (8083) — 模拟设备](#35-iot-debug-service-8083--模拟设备) - - [Voice-Service (8093) — 语音服务](#36-voice-service-8093--语音服务) - - [Proto (占位)](#37-proto-占位) -4. [前端详解](#四前端详解) - - [技术栈](#41-技术栈) - - [状态管理](#42-状态管理) - - [组件树](#43-组件树) - - [自定义 Hooks](#44-自定义-hooks) - - [API 模块](#45-api-模块) - - [WebSocket 消息流](#46-websocket-消息流) -5. [ethend (9090) — 调试工具](#五ethend-9090--调试工具) -6. [对话管线详解](#六对话管线详解) -7. [数据库设计](#七数据库设计) -8. [安全性](#八安全性) -9. [已知限制与改进方向](#九已知限制与改进方向) - ---- - -## 一、项目概览 - -Cyrene(昔涟)是一个 AI 数字伴侣系统,以 React SPA 为前端,Go 微服务集群为后端,通过 PostgreSQL 持久化数据和 pgvector 向量搜索实现长期记忆。系统以虚拟角色"昔涟"的固定人格与用户对话,支持 IoT 智能家居操控、定时提醒、知识库管理、自动化规则引擎、语音识别/合成、图片分析、互联网搜索 (SearXNG) 等功能。 - -| 维度 | 数据 | -|------|------| -| 后端语言 | Go 1.24 | -| 前端框架 | React 18.3 + TypeScript 5.6 + Vite 6.0 | -| 数据库 | PostgreSQL (pgvector 向量扩展) | -| LLM 模型 | 多模型配置系统 (models.json),支持多 Provider/多用途路由回退链 | -| WebSocket 库 | gorilla/websocket (Go), 原生 WebSocket (浏览器) | -| HTTP 框架 | Gin (Gateway), net/http (其他服务) | -| 状态管理 | Zustand 4.5 | -| CSS 框架 | Tailwind CSS 3.4 | -| 包管理器 | pnpm | -| Go 代理 | GOPROXY=https://goproxy.cn,direct | - ---- - -## 二、总体架构 - -``` -┌──────────────────────────────────────────────────────────────┐ -│ Browser (React SPA) │ -│ localhost:5173 (dev) / 生产由 Gateway 托管静态文件 │ -└───────────┬──────────────────────────────────┬───────────────┘ - │ WebSocket (ws://gateway:8080/ws/chat) - │ + REST API (gateway:8080/api/v1/*) - ▼ -┌──────────────────────────────────────────────────────────────┐ -│ Gateway (:8080) │ -│ Gin Router → JWT Auth → Rate Limiter → Handlers │ -│ WebSocket Hub: 会话状态/消息缓存/IoT广播 │ -│ 规则引擎: 定时/事件触发自动化 │ -└───┬──────────┬──────────┬──────────┬─────────────┘ - │ SSE │ HTTP │ HTTP │ HTTP - ▼ ▼ ▼ ▼ -┌────────┐ ┌────────┐ ┌────────┐ ┌──────────────┐ -│AI-Core │ │Memory │ │Voice │ │IoT Debug │ -│ :8081 │ │:8091 │ │:8093 │ │ :8083 │ -│ │ │ │ │ │ │ │ -│编排器 │ │PGVector│ │whisper │ │8个模拟设备 │ -│意图分析 │ │语义搜索│ │edge-tts│ │toggle/set/ │ -│子会话 │ │去重衰减│ │TTS回退│ │history API │ -│人格系统 │ │ │ │ │ │传感器波动 │ -│思考引擎 │ │ │ │ │ │ │ -│工具调用 │ │ │ │ │ │ │ -└────┬───┘ └────┬───┘ └────┬───┘ └──────────────┘ - │ │ │ │ - └──────────┴──────────┴──────────┘ - │ - ┌───────▼───────┐ - │ PostgreSQL │ - │ + pgvector │ - └───────────────┘ -``` - -**核心数据流**:用户消息 → Gateway WebSocket → AI-Core SSE → 编排器并行处理(意图分析 → 子会话分派 → LLM 合成 → 审查拆分) → Gateway 解析 → WebSocket 逐条返回前端。 - ---- - -## 三、后端服务详解 - -### 3.1 AI-Core (:8081) — 对话引擎 - -**目录**:`backend/ai-core/` -**入口**:[cmd/main.go](backend/ai-core/cmd/main.go) -**包数量**:11 个内部包,约 40 个 `.go` 文件 - -#### 3.1.1 启动流程 - -1. 加载 `.env` 环境变量 -2. 初始化人格加载器(`persona.NewLoader`)——从 `internal/persona/` 目录读取 YAML 配置 -3. 初始化 LLM 适配器:优先加载 `models.json` → `ModelSelector`;无配置文件时回退到 `.env` -4. 初始化记忆系统(`memory.NewStore` + `NewRetriever` + `NewExtractor`)——PostgreSQL 持久化 -5. 初始化会话历史存储(`context.NewConversationStore`)——内存缓存,上限 50 条 -6. 初始化 IoT 客户端(`tools.NewIoTClient`)——连接 IoT Debug Service -7. 注册 13 个 LLM 可调用工具(`tools.NewRegistry`) -8. 启动后台思考引擎(`background.NewThinker`) -9. 构建编排器 v2.0(`orchestrator.NewOrchestrator`) -10. 注册 HTTP 端点:`/api/v1/chat`(SSE)、`/api/v1/memory/search`、`/api/v1/memory`(CRUD)、`/api/v1/health` - -#### 3.1.2 包结构 - -| 包 | 文件 | 职责 | -|----|------|------| -| `orchestrator/` | `orchestrator.go`, `intent_analyzer.go`, `synthesizer.go` | 对话编排 v2.0:意图分析→子会话分派→综合生成 | -| `subsession/` | `manager.go`, `registry.go`, `general_provider.go`, `memory_provider.go`, `iot_provider.go`, `review_provider.go` | 子会话框架:4 个提供者并行执行 | -| `llm/` | `adapter.go`, `openai.go`, `stream.go`, `selector.go` | LLM 抽象层:OpenAI 兼容协议、流式输出、断句器、多模型路由选择器 | -| `config/` | `loader.go` | 模型配置加载器:只读加载 models.json | -| `memory/` | `store.go`, `retriever.go`, `extractor.go`, `client.go` | 记忆系统:存储/检索/提取/HTTP 客户端 | -| `persona/` | `loader.go`, `injector.go` | 人格管理:YAML 加载、系统提示构建、风格注入 | -| `tools/` | `registry.go`, `calculator_tool.go`, `datetime_tool.go`, `crypto_tool.go`, `file_tool.go`, `http_tool.go`, `iot_client.go`, `iot_control_tool.go`, `iot_tools.go`, `json_tool.go`, `markdown_tool.go`, `random_tool.go`, `text_tool.go`, `web_fetch.go`, `web_search.go` | 工具系统:13 个 LLM 可调用工具 + IoT 客户端 | -| `context/` | `builder.go` | 上下文构建器:会话历史/人格/子会话结果组合为 LLM 提示 | -| `background/` | `thinker.go` | 后台思考引擎:事件驱动(chat 后/沉默)自主思考 | -| `model/` | `message.go`, `session.go`, `sub_session.go`, `memory.go` | 共享数据模型:消息、会话、子会话、记忆 | - -#### 3.1.3 Orchestrator v2.0 管线 - -``` -用户输入 → ProcessInput() - ├─ 1. 意图分析 (intentAnalyzer.Analyze) - │ ├─ isStrongIoTCommand() 快速通道 (0s) - │ ├─ isGreeting() 快速通道 (0s) - │ └─ LLM 意图分析 (fallback) - ├─ 2. 加载人格配置 → BuildSystemPrompt - ├─ 3. 子会话分派 (subManager.Dispatch) - │ ├─ general_provider (通用对话意图) - │ ├─ memory_provider (记忆检索) - │ ├─ iot_provider (IoT 设备查询/操控) - │ └─ review_provider (审查拆分) - │ 快速通道: greeting/纯聊天 → 跳过所有子会话 - ├─ 4. 200ms 超时等待子会话结果 - ├─ 5. Synthesizer 流式生成 (ChatWithTools + 最多5轮工具调用循环) - ├─ 6. 流式输出 delta → SSE - ├─ 7. parseReviewMessages() 审查拆分 → StreamReview SSE - ├─ 8. 断句信息 → StreamSegments SSE - ├─ 9. StreamDone → [DONE] - └─ 10. 后处理: 缓存回复 + 异步记忆提取 -``` - -**快速通道条件**: -- IoT 命令:`controlWords ∩ msg AND deviceWords ∩ msg` → 跳过 LLM 意图分析(节省 2-3s) -- 纯问候/聊天无 IoT 无 Memory:跳过所有子会话分派 - -**`parseReviewMessages()`** — 括号匹配状态机: -- 输入:`"(歪着头看你) 叶酱,客厅灯早就开着啦♪..."` -- 输出:`[{type: "action", content: "歪着头看你"}, {type: "chat", content: "叶酱,客厅灯早就开着啦♪..."}]` -- 支持 `()` 和 `()` 两种括号 -- `splitReviewLongMessage()`:80 字符智能断句(句号/感叹号/问号/逗号边界) - -#### 3.1.4 Intent Analyzer - -**文件**:[intent_analyzer.go](backend/ai-core/internal/orchestrator/intent_analyzer.go) - -**快速通道关键词**: -```go -controlWords = ["打开", "关闭", "关掉", "关上", "调到", "设置", "开关", "调节", "调高", "调低", "开一下", "关一下"] -deviceWords = ["灯", "空调", "窗帘", "电视", "风扇", "加湿器", "插座", "门锁", "传感器"] -``` - -**意图类型**:`iot_control`, `iot_query`, `greeting`, `chat`, `story`, `memory_trigger`, `knowledge`, `task` - -#### 3.1.5 IoT Provider (子会话) - -**文件**:[iot_provider.go](backend/ai-core/internal/subsession/iot_provider.go) - -- `Execute()`:收集所有 device-action 对 → 批量执行 -- 上下文窗口:±30 字节 + 全文回退逻辑 -- 操作检测:`hasOpen`/`hasClose` 布尔值判断 -- 通过 `personaDir` 字段加载 IoT 回复人格配置 - -#### 3.1.6 后台思考引擎 - -- 事件驱动:`TriggerPostChatThink()` 在每次对话后触发 -- 沉默触发:用户长时间不活动 -- 思考内容可持久化到 memory-service - ---- - -### 3.2 Gateway (:8080) — API 网关 - -**目录**:`backend/gateway/` -**入口**:[cmd/main.go](backend/gateway/cmd/main.go) -**包数量**:8 个内部包,约 30 个 `.go` 文件 - -#### 3.2.1 启动流程 - -1. 加载配置 (`config.Load`) -2. 确保上传目录 `./uploads/` 存在 -3. 初始化 7 个持久化 Store(降级:连接失败不影响启动) -4. 种子数据:自动创建 admin 用户 + 清理旧 admin 用户 -5. 初始化 WebSocket Hub + 闲置会话清理 + IoT 广播 -6. 初始化规则引擎 -7. 配置 Gin 路由 → 启动 HTTP 服务 -8. 启动提醒/简报调度器 - -#### 3.2.2 路由表 - -**公开路由**: -| 方法 | 路径 | 说明 | -|------|------|------| -| GET | `/api/v1/health` | 健康检查 | -| POST | `/api/v1/auth/register` | 注册(限流) | -| POST | `/api/v1/auth/login` | 登录(限流) | - -**需认证路由** (JWT + Rate Limit): -| 方法 | 路径 | Handler | -|------|------|---------| -| POST | `/api/v1/auth/refresh` | authHandler | -| POST | `/api/v1/sessions` | sessionHandler.Create | -| GET | `/api/v1/sessions` | sessionHandler.List | -| DELETE | `/api/v1/sessions` | sessionHandler.DeleteAll | -| GET | `/api/v1/sessions/:id` | sessionHandler.Get | -| DELETE | `/api/v1/sessions/:id` | sessionHandler.Delete | -| GET | `/api/v1/sessions/:id/messages` | sessionHandler.GetMessages | -| DELETE | `/api/v1/sessions/:id/messages` | sessionHandler.ClearMessages | -| GET | `/api/v1/sessions/:id/export` | sessionHandler.ExportSession | -| GET | `/api/v1/messages/search` | sessionHandler.SearchMessages | -| GET | `/api/v1/memory/search` | memoryHandler.Query | -| GET | `/api/v1/memory` | memoryHandler.List | -| POST | `/api/v1/memory` | memoryHandler.Add | -| DELETE | `/api/v1/memory` | memoryHandler.Delete | -| POST | `/api/v1/notifications/push` | notificationHandler.Push | -| GET/POST/PUT/DELETE | `/api/v1/reminders*` | reminderHandler | -| GET/POST | `/api/v1/briefings*` | briefingHandler | -| POST/GET | `/api/v1/voice/*` | voiceHandler | -| POST/GET/DELETE | `/api/v1/files/*` | fileHandler | -| GET/POST/PUT/DELETE | `/api/v1/automation/rules*` | automationHandler | -| GET/POST/PUT/DELETE | `/api/v1/automation/scenes*` | automationHandler | -| POST/GET/PUT/DELETE | `/api/v1/knowledge/*` | knowledgeHandler | -| POST/GET | `/api/v1/images/*` | imageHandler | - -**WebSocket**: -| 路径 | 说明 | -|------|------| -| `GET /ws/chat?token=xxx&session_id=xxx` | WebSocket 升级(仅限 admin 用户) | - -**内部服务** (Internal Service Token): -| 方法 | 路径 | 说明 | -|------|------|------| -| POST | `/api/v1/internal/notify` | 内部通知推送 | - -**Webhook** (Webhook Auth): -| 方法 | 路径 | 说明 | -|------|------|------| -| POST | `/api/v1/webhook/generic` | 通用 Webhook | -| POST | `/api/v1/webhook/discord` | Discord Webhook | - -#### 3.2.3 WebSocket Hub - -**文件**:[hub.go](backend/gateway/internal/ws/hub.go) - -核心数据结构: -- `clients map[*Client]bool` — 所有活跃连接 -- `userClients map[string]map[*Client]bool` — 按用户索引 -- `sessions map[string]*SessionState` — 会话状态追踪 -- `conversationCache sync.Map` — 对话缓存(最多 50 条/session) - -功能: -- 客户端注册/注销(优雅清理,两阶段广播) -- 按用户/会话精准推送 -- 闲置会话自动标记(超过 idleTimeout 无活动 → state="idle") -- IoT 设备状态广播:每 10 秒轮询 IoT Debug Service 并推送给所有客户端 -- 对话缓存:`CacheMessage()` / `GetConversation()` / `GetSessionHistory()` - -#### 3.2.4 消息持久化 - -**WebSocket handler** ([chat_handler.go](backend/gateway/internal/handler/chat_handler.go)) 的 `streamResponse()`: - -1. 用户消息**立即**持久化到 DB(在 WebSocket 发送前) -2. AI 回复**流式**接收 SSE,逐 delta 转发 WebSocket -3. `review_messages` 解析后每条独立持久化(role="action"/"assistant") -4. 最终完整文本也持久化一次 - -#### 3.2.5 Store 层 - -| Store | 文件 | 功能 | -|-------|------|------| -| `SessionStore` | `session_store.go` | 会话 CRUD、消息持久化、搜索 | -| `UserStore` | `user_store.go` | 用户注册/查询/列表/删除 | -| `ReminderStore` | `reminder_store.go` | 提醒 CRUD | -| `BriefingStore` | `briefing_store.go` | 每日简报 CRUD | -| `AutomationStore` | `automation_store.go` | 自动化规则/场景 CRUD | -| `FileStore` | `file_store.go` | 文件上传/管理 | -| `KnowledgeStore` | `knowledge_store.go` | 知识库/文档管理 | - -#### 3.2.6 规则引擎 - -**文件**:[rule_engine.go](backend/gateway/internal/engine/rule_engine.go) - -- 事件驱动自动化:定时触发 / Webhook 触发 -- 场景执行:一组规则的批量触发 -- 通过 WebSocket 向用户推送通知 - ---- - -### 3.3 Memory-Service (:8091) — 记忆系统 - -**目录**:`backend/memory-service/` -**入口**:[cmd/main.go](backend/memory-service/cmd/main.go) -**文件数**:6 个 Go 文件 - -#### 3.3.1 包结构 - -| 包 | 文件 | 职责 | -|----|------|------| -| `cmd/` | `main.go` | HTTP 服务入口 | -| `internal/config/` | `config.go` | 配置加载 | -| `internal/model/` | `memory.go` | 记忆数据模型 | -| `internal/store/` | `store.go` | PostgreSQL + pgvector 存储层 | -| `internal/service/` | `memory_service.go` | 业务逻辑层 | -| `internal/handler/` | `memory_handler.go` | HTTP 处理器 | - -#### 3.3.2 记忆数据模型 - -``` -MemoryEntry { - ID, UserID, Content, Category, Priority, - Embedding (pgvector 1536维), - CreatedAt, UpdatedAt, DecayFactor, AccessCount, LastAccessedAt -} -``` - -#### 3.3.3 核心功能 - -- **语义搜索**:pgvector 余弦相似度检索 top-N 相关记忆 -- **去重**:Jaccard 相似度检测,合并高相似度记忆 -- **衰减机制**:`DecayFactor` 随时间衰减,低权重记忆被清理 -- **记忆巩固**:高访问频率记忆自动提升优先级 -- **CRUD API**:创建/查询/列表/删除 - -#### 3.3.4 HTTP API - -| 端点 | 方法 | 说明 | -|------|------|------| -| `/api/v1/memories` | POST | 创建记忆 | -| `/api/v1/memories?user_id=xxx` | GET | 列表 | -| `/api/v1/memories/:id` | GET | 获取 | -| `/api/v1/memories/:id` | DELETE | 删除 | -| `/api/v1/memories/search?user_id=xxx&q=xxx&limit=10` | GET | 语义搜索 | -| `/api/v1/thinking/logs` | POST | 记录思考日志 | -| `/api/v1/health` | GET | 健康检查 | - ---- - -### 3.4 工具系统 (pkg/plugins + AI-Core 集成) - -> **迁移说明:** tool-engine (8092) 已移除。工具注册与调用整合到 `pkg/plugins` 共享模块,由 AI-Core 直接管理。 - -**目录**:`backend/pkg/plugins/` -**核心**:[pkg/plugins/manager/registry.go](backend/pkg/plugins/manager/registry.go) -**插件数**:11 个共享插件 + 5 个 AI-Core 专属工具 - -#### 3.4.1 16 个 LLM 可调用工具 - -**共享插件** (`pkg/plugins/`): - -| 工具 | 目录 | 功能 | -|------|------|------| -| calculator | `calculator/` | 数学表达式求值 | -| datetime | `datetime/` | 日期时间计算/格式化 | -| text | `text/` | 文本处理(统计/转换/截断) | -| crypto | `crypto/` | 哈希/加解密 | -| random | `random/` | 随机数/字符串生成 | -| markdown | `markdown/` | Markdown 渲染 | -| json | `json/` | JSON 解析/查询/格式化 | -| file | `file/` | 文件读写/列表 | -| http | `http/` | HTTP 请求(GET/POST 等) | -| web_search | `web_search/` | SearXNG 网络搜索 (DuckDuckGo 兜底) | -| web_fetch | `web_fetch/` | 网页内容提取 | - -**AI-Core 专属工具** (`ai-core/internal/tools/`): - -| 工具 | 功能 | -|------|------| -| iot_query | IoT 设备状态查询 | -| iot_control | IoT 设备操控 | -| host_exec | 主机命令执行 (沙箱) | -| host_file | 主机文件操作 (沙箱) | -| host_system | 主机系统信息 | -| vision_analyze | 图片视觉分析/OCR | -| knowledge_search | 知识库 RAG 检索 | -| knowledge_ingest | 知识库文档导入 | - -#### 3.4.2 ToolRegistry 调用审计 - -[registry.go](backend/pkg/plugins/manager/registry.go) — 内存环形缓冲区 (500 条) 记录工具调用的参数/结果/耗时/成功率。API 端点: -- `GET /api/v1/tools/calls` — 分页查询,支持按工具名过滤 -- `GET /api/v1/tools/calls/stats` — 按工具聚合的成功率/平均耗时 - -#### 3.4.3 主聊天流程工具调用 - -`Synthesizer` 通过 `ChatWithTools` 向 LLM 传递工具定义,支持最多 5 轮工具调用循环。后台思考器使用相同机制。 - ---- - -### 3.5 IoT-Debug-Service (:8083) — 模拟设备 - -**目录**:`backend/iot-debug-service/` -**单文件服务**:[cmd/main.go](backend/iot-debug-service/cmd/main.go)(626 行) - -#### 3.5.1 模拟设备列表 - -| ID | 名称 | 类型 | 可操作性 | -|----|------|------|---------| -| `light-livingroom` | 客厅灯 | light | toggle, brightness, color | -| `light-bedroom` | 卧室灯 | light | toggle, brightness, color | -| `ac-livingroom` | 客厅空调 | ac | toggle, temperature, mode | -| `ac-bedroom` | 卧室空调 | ac | toggle, temperature, mode | -| `curtain-livingroom` | 客厅窗帘 | curtain | toggle, position | -| `sensor-temperature` | 温度传感器 | sensor | 只读 | -| `sensor-humidity` | 湿度传感器 | sensor | 只读 | -| `lock-door` | 智能门锁 | lock | toggle, battery | - -#### 3.5.2 API - -| 端点 | 方法 | 说明 | -|------|------|------| -| `/api/v1/devices` | GET | 列出所有设备(不含历史) | -| `/api/v1/devices/{id}` | GET | 获取单个设备(含最近 10 条历史) | -| `/api/v1/devices/{id}/toggle` | POST | 切换开关状态 | -| `/api/v1/devices/{id}/set` | POST | 设置属性 `{field, value}` | -| `/api/v1/devices/{id}/history` | GET | 获取操作历史 | - -#### 3.5.3 特性 - -- **线程安全**:`sync.RWMutex` 保护所有设备操作 -- **传感器波动**:每 30 秒自动模拟温度 ±0.2°C / 湿度 ±1% 随机波动 -- **属性设置**:声明式控制,支持中文值("开"/"关")和布尔值 -- **操作历史**:记录每次变更的字段、旧值、新值、时间戳 - ---- - -### 3.6 Voice-Service (:8093) — 语音服务 - -**目录**:`backend/voice-service/` -**入口**:[cmd/main.go](backend/voice-service/cmd/main.go) -**文件数**:6 个 Go 文件 - -#### 3.6.1 STT (语音识别) - -- **引擎**:whisper.cpp(本地运行) -- **前处理**:ffmpeg 音频格式转换 -- **支持语言**:中文(`zh`) - -#### 3.6.2 TTS (语音合成) - -三级回退策略: -1. **edge-tts**(首选)— Microsoft Edge TTS API,音质最好 -2. **espeak-ng**(回退)— 离线 TTS,无需网络 -3. **静默 WAV 生成器**(最终回退)— 生成等长静音音频,保证用户体验不中断 - ---- - -### 3.7 Proto (占位) - -`backend/proto/` — 目前仅包含 `.gitkeep`,为未来的 Protobuf/gRPC 通信预留。 - ---- - -## 四、前端详解 - -**目录**:`frontend/web/` -**入口**:[main.tsx](frontend/web/src/main.tsx) → [App.tsx](frontend/web/src/App.tsx) - -### 4.1 技术栈 - -| 技术 | 版本 | 用途 | -|------|------|------| -| React | 18.3 | UI 框架 | -| TypeScript | 5.6 | 类型系统 | -| Vite | 6.0 | 构建工具 | -| Zustand | 4.5 | 状态管理 | -| Tailwind CSS | 3.4 | 样式 | -| 原生 WebSocket | — | 实时通信 | -| SpeechSynthesis API | — | TTS 朗读 | -| SpeechRecognition API | — | STT 语音输入 | - -### 4.2 状态管理 (Zustand) - -| Store | 文件 | 职责 | -|-------|------|------| -| `authStore` | `authStore.ts` | 用户认证状态、token 管理 | -| `chatStore` | `chatStore.ts` | 消息列表、流式状态、IoT 设备状态、后台思考状态、历史分页 | -| `sessionStore` | `sessionStore.ts` | 会话列表、当前会话、消息加载、导出 | -| `notificationStore` | `notificationStore.ts` | 站内通知列表、已读管理 | -| `personaStore` | `personaStore.ts` | 昔涟人格配置、心情状态 | - -### 4.3 组件树 - -``` -App -├── ErrorBoundary -└── AppLayout - ├── Header (Logo, 连接状态, 搜索按钮) - ├── Sidebar (会话列表, 新建对话) - ├── ChatContainer - │ ├── MessageList - │ │ ├── MessageBubble (用户/助手消息) - │ │ │ ├── CyreneAvatar (昔涟头像) - │ │ │ ├── ImageLightbox (图片灯箱) - │ │ │ ├── AIMessageActions (朗读按钮) - │ │ │ └── ActionMessageBubble (动作消息: 居中/斜体/灰色) - │ │ └── TypingIndicator (输入中动画) - │ ├── IoTStatusBar (设备状态条) - │ └── ChatInput (输入框/附件/发送) - ├── AutomationPanel (自动化规则管理) - ├── BriefingPanel (每日简报) - ├── FilePanel (文件管理) - ├── KnowledgePanel (知识库管理) - ├── ReminderPanel (提醒管理) - └── SearchModal (全局搜索) -``` - -### 4.4 自定义 Hooks - -| Hook | 文件 | 功能 | -|------|------|------| -| `useWebSocket` | `useWebSocket.ts` | WebSocket 连接生命周期、指数退避自动重连、消息路由 | -| `useChat` | `useChat.ts` | 消息发送逻辑 | -| `useAuth` | `useAuth.ts` | 认证状态管理 | -| `useSession` | `useSession.ts` | 会话切换、历史加载 | -| `useSpeechRecognition` | `useSpeechRecognition.ts` | 浏览器语音识别封装 | -| `useSpeechSynthesis` | `useSpeechSynthesis.ts` | 浏览器 TTS 封装 | -| `usePWA` | `usePWA.ts` | PWA 安装/更新 | - -#### 4.4.1 WebSocket 重连策略 - -- **指数退避**:初始 1s,每次翻倍,最大 30s -- **jitter**:在 `[delay/2, delay]` 范围内随机,避免惊群 -- **最大重试**:10 次后放弃并提示用户刷新 -- **会话恢复**:重连后自动发送 `history` 消息恢复后端上下文 - -### 4.5 API 模块 - -| 模块 | 文件 | 对应后端 | -|------|------|---------| -| `client` | `client.ts` | Axios 实例、JWT 拦截器 | -| `auth` | `auth.ts` | `/api/v1/auth/*` | -| `sessions` | `sessions.ts` | `/api/v1/sessions/*` | -| `memory` | `memory.ts` | `/api/v1/memory/*` | -| `reminders` | `reminders.ts` | `/api/v1/reminders/*` | -| `briefings` | `briefings.ts` | `/api/v1/briefings/*` | -| `voice` | `voice.ts` | `/api/v1/voice/*` | -| `files` | `files.ts` | `/api/v1/files/*` | -| `automation` | `automation.ts` | `/api/v1/automation/*` | -| `knowledge` | `knowledge.ts` | `/api/v1/knowledge/*` | - -### 4.6 WebSocket 消息流 - -**客户端 → 服务端**: -```typescript -{ type: "message", content: "你好", mode: "text", session_id: "xxx", timestamp: 123 } -{ type: "history", session_id: "xxx" } -{ type: "voice_input", audio_data: "base64..." } -``` - -**服务端 → 客户端**: -| type | 触发时机 | 前端处理 | -|------|---------|---------| -| `stream_chunk` | AI 流式逐字输出 | `appendToLastMessage` 累积 | -| `stream_end` | 流式输出结束 | `finishStreaming` 标记完成 | -| `response` | 审查后的独立消息 (action/chat) | `addMessage` 添加独立气泡 | -| `history_response` | 会话恢复/历史请求 | 仅在无消息时加载 | -| `review` | 旧版审查消息 | 逐条 `addMessage` | -| `multi_message` | 多段消息 | 逐段 `addMessage` | -| `stream_segments` | 断句信息 | 逐段 `addMessage` | -| `device_update` | IoT 设备状态广播 (10s) | `setIoTDevices` 更新状态栏 | -| `background_thinking` | 后台思考状态变化 | `setBackgroundThinkingStatus` | -| `notification` | 系统通知/提醒 | `addNotification` + 浏览器桌面通知 | -| `error` | 服务端错误 | 系统消息气泡 | - ---- - -## 五、ethend (:9090) — 调试工具 - -**目录**:`ethend/` -**类型**:Node.js Express 应用 - -### 5.1 服务管理 - -| 端点 | 方法 | 功能 | -|------|------|------| -| `/api/services` | GET | 列出所有服务状态 | -| `/api/services/:id/build` | POST | 编译服务 (go build -o main.exe) | -| `/api/services/:id/start` | POST | 启动服务 | -| `/api/services/:id/stop` | POST | 停止服务 | -| `/api/services/:id/restart` | POST | 重启服务 | -| `/api/services/:id/logs` | GET | 获取服务日志 | -| `/api/services/:id/memory` | GET | 获取进程内存 | - -### 5.2 其他功能 - -- **IoT 管理**:设备列表/状态切换 -- **记忆管理**:记忆搜索/CRUD -- **性能监控**:CPU/内存使用率 -- **数据库管理**:表结构检查、迁移执行 -- **WebSocket 状态**:连接数/会话列表 -- **健康检查轮询**:每秒检测所有服务可达性 - -### 5.3 关键配置 - -**构建命令**([config.js](ethend/src/config.js)): -```javascript -buildCommand: 'go', -buildArgs: ['build', '-o', isWin ? 'main.exe' : 'main', './cmd/main.go'], -goBin: GO_BIN -``` - -所有 Go 服务统一编译为 `main.exe`(Windows),ethend 通过 `./main` 启动。**自定义二进制名称不会被 ethend 识别。** - ---- - -## 六、对话管线详解 - -### 6.1 完整请求时序 - -``` -Browser (React) Gateway AI-Core - │ │ │ - ├─ WebSocket: {type:"message"} ──┤ │ - │ ├─ POST /api/v1/chat ──────►│ - │ │ (SSE streaming) │ - │ │ ├─ 意图分析 (0-1.4s) - │ │ ├─ 并行子会话 - │ │ │ ├─ memory (检索) - │ │ │ ├─ iot (查询/操控) - │ │ │ └─ general (意图) - │ │ ├─ LLM 合成 (3-4s) - │ │ ├─ parseReviewMessages - │ │ │ - │ │◄── SSE: delta ────────────┤ - │◄── WS: stream_chunk ──────────┤ │ - │◄── WS: stream_chunk ... ──────┤ │ - │ │◄── SSE: review_messages ──┤ - │◄── WS: response (action) ─────┤ (200ms delay) │ - │◄── WS: response (chat) ───────┤ │ - │ │◄── SSE: [DONE] ──────────┤ - │◄── WS: stream_end ────────────┤ │ -``` - -### 6.2 性能数据 - -| 场景 | 总响应 | 意图分析 | 子会话 | LLM 合成 | -|------|--------|---------|--------|---------| -| "你好呀" | ~3.9s | 0s | 跳过 | 3.9s | -| "打开客厅灯" | ~2.6s | 0s | IoT+Memory | ~2.6s | -| "关掉客厅灯" | ~2.6s | 0s | IoT+Memory | ~2.6s | -| "打开卧室灯和卧室空调" | ~3.0s | 0s | IoT+Memory | ~3.0s | -| "看看设备状态" | ~5.3s | 1.4s | IoT+Memory | ~3.9s | -| "你还记得我喜欢什么吗?" | ~4-5s | LLM | Memory+General | ~3-4s | - -LLM 合成(deepseek-v4-flash)是主要延迟来源,约占 60-80% 的总响应时间。 - -### 6.3 E2E 消息流示例 - -``` -用户: "帮我把客厅灯打开" - → Gateway WS → AI-Core SSE - → Intent: iot_control (快速通道, 0s) - → Dispatch: memory + general + iot + review (并行) - → IoT: 查询 8 个设备 → 匹配客厅灯 → 已开状态 - → Synthesize: 综合上下文 → LLM 生成回复 - → parseReviewMessages: - action: "歪着头看你" - chat: "叶酱,客厅灯早就开着啦♪ 你是不是工作太累看花了眼呀?" - → Gateway: 200ms 间隔逐条推送 WebSocket response - → Frontend: ActionMessageBubble + MessageBubble 分别渲染 -``` - ---- - -## 七、数据库设计 - -### 7.1 PostgreSQL 连接 - -所有服务共用 PostgreSQL 数据库 `cyrene_ai`,通过 `DB_URL` 环境变量配置: -``` -postgres://cyrene:cyrene_pass@localhost:5432/cyrene_ai?sslmode=disable -``` - -### 7.2 主要表结构 - -| 表 | 管理方 | 用途 | -|----|--------|------| -| `users` | Gateway | 用户认证 | -| `sessions` | Gateway | 会话记录 | -| `messages` | Gateway | 对话消息(role, content, timestamp) | -| `memories` | Memory-Service | 记忆存储(含 pgvector embedding) | -| `reminders` | Gateway | 定时提醒 | -| `briefings` | Gateway | 每日简报 | -| `automation_rules` | Gateway | 自动化规则 | -| `automation_scenes` | Gateway | 自动化场景 | -| `files` | Gateway | 文件元数据 | -| `knowledge_bases` | Gateway | 知识库 | -| `knowledge_documents` | Gateway | 知识文档 | -| — (工具调用日志) | AI-Core (内存) | 环形缓冲区 500 条,无 DB 持久化 | - -### 7.3 已知缺项 - -- `messages` 表 `msg_type` 通过后端 ServerMessage 自动填充(含 markdown/code),但数据库层面未持久化该字段,历史消息查询依赖 role 判断 - ---- - -## 八、安全性 - -| 层面 | 实现 | -|------|------| -| 认证 | JWT (HS256),默认永不过期 | -| 密码存储 | bcrypt 哈希 | -| 会话隔离 | 按 userID + sessionID 双重隔离 | -| 限流 | 认证端点:5次/分钟/IP;API 端点:10 req/s + 突发 20 | -| CORS | 可配置的来源白名单 | -| HTTP 框架 | Gin 的生产模式(ReleaseMode)+ Recovery 中间件 | -| WebSocket 安全 | JWT token 验证 + admin-only 主对话 | -| 内部服务 | Internal Service Token 认证 | - ---- - -## 九、已知限制与改进方向 - -### 当前限制 - -1. **LLM 合成延迟**(3-4s):deepseek-v4-flash 调用是主要瓶颈,合成阶段无法被快速通道绕过 -2. **"开" 字歧义**:无法将单独的 "开" 加入快速通道("开心"/"开始" 产生误判),"开灯" 等短命令仍走 LLM -3. **msg_type 数据库持久化**:后端 ServerMessage 已自动填充 msg_type(含 markdown/code),但数据库 messages 表未存储该字段 -4. **Node.js v24 Windows 原生 WebSocket bug**:频繁建立连接可能触发 libuv `UV_HANDLE_CLOSING` 断言 -5. **流式审查**:`parseReviewMessages()` 需要等 LLM 合成完成后才能执行,无法实时拆分 -6. **`frontend/packages/shared/`** 和 **`backend/proto/`** 为空占位 - -### 建议改进方向 - -1. **LLM 响应缓存**:对相似问候/常见 IoT 命令引入语义缓存 -2. **数据库迁移**:为 messages 表添加 `msg_type` 列以持久化消息类型(当前仅 ServerMessage 传输层携带) -3. **流式审查**:在 LLM 合成过程中实时识别并分段发送 action/chat -4. **Protobuf 通信**:填充 `backend/proto/` 目录,服务间改用 gRPC -5. **WebSocket 兼容**:生产环境使用 `ws` npm 包替代原生 WebSocket -6. **前端集成测试**:Playwright/CDP 端到端测试 - ---- - -## 附:快速参考 - -### 服务端口一览 - -| 服务 | 端口 | 技术 | -|------|------|------| -| Gateway | 8080 | Gin + WebSocket | -| AI-Core | 8081 | net/http + SSE | -| IoT Debug | 8083 | net/http | -| Memory | 8091 | net/http + pgvector | -| Voice | 8093 | net/http + whisper.cpp | -| Frontend (dev) | 5173 | Vite | -| ethend | 9090 | Express | - -### 常用命令 - -```bash -# 构建所有 Go 服务 -cd backend/ai-core && GOWORK=off go build -o main.exe ./cmd/main.go -cd backend/gateway && GOWORK=off go build -o main.exe ./cmd/main.go -# ... 其他服务同理 - -# 或通过 ethend API -curl -X POST http://localhost:9090/api/services/ai-core/build -curl -X POST http://localhost:9090/api/services/gateway/build - -# 启动前端开发服务器 -cd frontend/web && pnpm dev - -# E2E 测试 -node test/test_final_e2e.mjs -``` - -### 环境变量 (.env) - -位于 `.env`,基础设施与 LLM 回退配置: -``` -POSTGRES_HOST=localhost -POSTGRES_PORT=5432 -POSTGRES_USER=cyrene -POSTGRES_PASSWORD=cyrene_pass -POSTGRES_DB=cyrene_ai -JWT_SECRET=xxx -ADMIN_USERNAME=admin -ADMIN_PASSWORD=xxx - -# Phase 6: 以下 LLM 变量作为 models.json 不存在时的回退 -LLM_API_URL=https://api.deepseek.com/v1 -LLM_API_KEY=sk-xxx -LLM_MODEL=deepseek-v4-flash -LLM_FALLBACK_MODEL=deepseek-v4-flash -``` - -### 模型配置 (models.json) - -Phase 6 新增,位于 `backend/models.json`(`.gitignore` 已排除)。格式: - -```json -{ - "version": "1.0", - "providers": { - "deepseek": { - "name": "deepseek", - "base_url": "https://api.deepseek.com", - "api_key": "sk-xxx", - "timeout_sec": 120, - "max_retries": 3 - } - }, - "models": { - "primary_chat": { - "id": "primary_chat", - "name": "deepseek-v4-flash", - "provider": "deepseek", - "description": "主对话模型", - "tags": ["chat", "fast"], - "params": { "temperature": 0.8, "max_tokens": 2048 }, - "enabled": true - } - }, - "routing": { - "chat": { - "purpose": "chat", - "fallback_chain": ["primary_chat", "fallback_chat"], - "required": false - } - } -} -``` - -**配置管理 API**(Gateway admin,ethend 代理提供 UI): - -| Method | Path | Description | -|--------|------|-------------| -| GET/POST/DELETE | `/api/v1/admin/models/providers/:name` | Provider CRUD | -| GET/POST/DELETE | `/api/v1/admin/models/models/:id` | Model CRUD | -| GET/POST/DELETE | `/api/v1/admin/models/routing/:purpose` | Routing CRUD | - -**向后兼容**:如果 `models.json` 不存在,`ModelSelector` 自动回退到 `.env` 的 4 个 LLM 变量,行为与 Phase 5 及之前完全一致。 diff --git a/docs/dev-plan/12-next-phase-optimization.md b/docs/dev-plan/12-next-phase-optimization.md deleted file mode 100644 index 79680ff..0000000 --- a/docs/dev-plan/12-next-phase-optimization.md +++ /dev/null @@ -1,290 +0,0 @@ -# 12 — 下一阶段优化大纲 - -> **日期**:2026-06-22 -> **来源**:对照 Cyrene 人格、记忆及功能拓展架构设计文档,逐项比对现状后梳理 -> **状态**:大纲,待拆分为详细实施计划 - ---- - -## 目录 - -1. [P0 — 自主思考分层](#1-p0--自主思考分层) -2. [P1 — LLM 可自主操作提醒与日程](#2-p1--llm-可自主操作提醒与日程) -3. [P2 — 对话后处理补全](#3-p2--对话后处理补全) -4. [P3 — 群聊并发(协会议话)](#4-p3--群聊并协会议话) -5. [P4 — 多平台前缀统一抽象](#5-p4--多平台前缀统一抽象) -6. [P5 — 工具子会话增强](#6-p5--工具子会话增强) -7. [实施顺序建议](#7-实施顺序建议) - ---- - -## 1. P0 — 自主思考分层 - -### 现状 - -所有后台思考(periodic / silence / post_chat / startup)共用同一个 LLM 模型和同一套 system prompt。高频短思考(如每分钟检查状态)和低频深度反思(如每 5 分钟整理记忆)没有区分,浪费 token。 - -### 目标 - -``` -┌─────────────┐ 唤醒 ┌─────────────┐ -│ 简单思考 │ ──────────────► │ 复杂思考 │ -│ (下位模型) │ │ (思考模型) │ -│ 高频/轻量 │ │ 低频/深度 │ -│ 例: 每分钟 │ │ 例: 每5分钟 │ -└──────┬───────┘ └──────┬───────┘ - │ 可调用工具 │ 可调用工具 - │ 可主动消息 │ 可主动消息 - │ 可追加继续 │ 可追加继续 - ▼ ▼ - 共享 ProactiveGuard 频率控制 -``` - -### 要点 - -- **模型配置**:简单思考用 fast/flash 模型(temperature 0.3),复杂思考用 thinking 模型(temperature 0.7) -- **周期**:简单思考 30-60s / 复杂思考 300s(可配置) -- **唤醒**:简单思考可判定"需要深思"→ 触发一次复杂思考 -- **追加**:两种思考都允许 `continue` 信号追加(当前只有 post_chat 可追加) -- **后处理**:每次复杂思考结束后触发记忆整理 - -### 涉及文件 - -| 文件 | 改动 | -|------|------| -| `background/thinker.go` | Thinker 拆分为 SimpleThinker + DeepThinker 或增加双模式循环 | -| `config/loader.go` → `models.json` | 新增 `simple_think` / `deep_think` 路由 | -| `background/thinker.go` → `buildThinkingSystemPrompt` | 简单/复杂两套 prompt | - ---- - -## 2. P1 — LLM 可自主操作提醒与日程 - -### 现状 - -Gateway 有 Reminder CRUD API,但 LLM 无法调用——没有注册 `reminder_create` / `reminder_update` / `schedule_query` 工具。昔涟不能在思考中说"明天早上 8 点提醒开拓者开会",因为这句话无法转化为实际的定时提醒。 - -### 目标 - -在 AI-Core 的 ToolRegistry 中新增 3-4 个提醒/日程工具,LLM 可在对话中或自主思考中调用。 - -### 要点 - -- **工具列表**: - - `reminder_create(time, content, repeat?)` → 创建提醒 - - `reminder_list()` → 列出当前用户的提醒 - - `reminder_delete(id)` → 删除提醒 - - `schedule_query(date)` → 查询某一天的日程 -- **实现方式**:HTTP 调用 Gateway `/api/v1/reminders` API(已有后端 CRUD) -- **自主思考可调用**:加入 `AutonomousToolPolicy.AllowedTools` 白名单 -- **防止阻塞**:配置 `THINK_SCHEDULE_WINDOW` 环境变量,在提醒时间窗口内确保简单思考被唤醒 - -### 涉及文件 - -| 文件 | 改动 | -|------|------| -| `ai-core/internal/tools/reminder_tool.go` | **新建** — 3-4 个 reminders 工具 | -| `ai-core/cmd/main.go` | 注册提醒工具到 ToolRegistry | -| `background/thinker.go` → `AutonomousToolPolicy` | 允许提醒工具在自主思考中调用 | - ---- - -## 3. P2 — 对话后处理补全 - -### 3.1 自主思考后触发记忆整理 - -**现状**:记忆提取(`ExtractMemoriesOnly`)只在 `platform_silent` 和正常对话后触发。自主思考(periodic/silence/startup)结束后不触发。 - -**目标**:复杂思考结束后自动调用一次记忆整理。 - -**涉及文件**:`background/thinker.go` → `performThink` 的结尾逻辑 - -### 3.2 对话后思考可追加 - -**现状**:`post_chat` 思考支持追加(`allowContinuation` + `triggerReason == "post_chat"`),但 `periodic` / `silence` 不支持。 - -**目标**:所有思考类型都支持 `continue` 信号追加,通过 `MaxContinuationRounds` 限制防止死循环。 - -**涉及文件**:`background/thinker.go` → 思考循环的 `allowContinuation` 条件 - ---- - -## 4. P3 — 群聊并发(协会议话) - -### 现状 - -一个 session 的消息处理是严格线性的。当多个 QQ 用户同时在群里 @ 昔涟时: -- 消息按到达顺序排队 -- 每条的 LLM 合成延迟 3-4s -- 第 3 条消息要等前面 2 条处理完才开始回复(6-8s 延迟) - -### 目标 - -``` -主会话 (session_id=platform_qq_) - │ - ├─ 消息A → 主会话处理 (LLM 合成中...) - │ - ├─ 消息B (主会话繁忙) → 协会议话 B (独立 LLM 合成) - │ └─ 完成 → 结果写入主会话上下文 - │ - └─ 消息C (主会话繁忙) → 协会议话 C (独立 LLM 合成) - └─ 完成 → 结果写入主会话上下文 -``` - -### 要点 - -- **并发检测**:收到新消息时,检查主会话是否正在处理(`isProcessing` 标记) -- **协会议话**:独立 goroutine + 独立 LLM 调用,共享主会话的对话历史 -- **结果合并**:协会议话完成后,回复通过 platform-bridge 发送,上下文摘要写回主会话 -- **数量限制**:最多 3 个协会议话并行,超出则排队 -- **身份一致性**:每个协会议话携带相同的 persona config + 群聊上下文 - -### 涉及文件 - -| 文件 | 改动 | -|------|------| -| `ai-core/orchestrator/orchestrator.go` | ProcessInput 增加并发检测 + 协会议话创建 | -| `ai-core/orchestrator/concurrent_handler.go` | **新建** — 协会议话管理器 | -| `platform-bridge/cmd/main.go` | 可能需要支持协会议话的回复路由 | - ---- - -## 5. P4 — 多平台前缀统一抽象 - -### 现状 - -QQ 平台标识(`【QQ群聊:xxx】`、`【QQ私聊:xxx】`)硬编码在 `thinker.go` 的 `buildThinkingUserPrompt` 里,`extractProactiveMessage` 里的 `qqTargetRe` 也只匹配 QQ。如果要接入 Telegram / Discord / 企业微信,需要在多个位置添加硬编码。 - -### 目标 - -将"平台前缀"抽象为一个统一的 `PlatformRouteFormat` 接口,每个 adapter 注册时声明自己的格式。 - -### 要点 - -- `PlatformRouteFormat` 接口: - - `ProactiveMarker(chatType, channelID, atUserID string) string` — 主动消息标记格式 - - `ChannelPrefix(channelID string) string` — 消息来源前缀(如 `【QQ群聊:xxx】`) -- 注册在 `PlatformAdapter` 接口扩展中 -- thinker prompt 和 extractProactiveMessage 从 router 获取当前已注册的格式列表 -- 后向兼容:QQ 当前行为不变 - -### 涉及文件 - -| 文件 | 改动 | -|------|------| -| `platform-bridge/bridge/adapter.go` | PlatformAdapter 接口扩展 | -| `platform-bridge/bridge/router.go` | GetRouteFormats() 方法 | -| `platform-bridge/handler/bridge_handler.go` | API 端点暴露格式信息 | -| `ai-core/background/thinker.go` | 从 bridge 获取格式替代硬编码 | -| `ai-core/cmd/main.go` | 启动时拉取格式配置 | - ---- - -### 5.1 P4.1 — 同平台多账号支持 - -#### 现状 - -Platform-Bridge 已支持同一平台注册多个 adapter 实例(如 `qq-main`, `qq-secondary`),但 ai-core 侧的 key 系统用 platform 类型字符串(`"qq"`)而非 adapter config name: - -| 位置 | 当前 key | 问题 | -|---|---|---| -| `botUIDs` | `"qq"` → UID | 多个 OBv11 账号只能存一个 UID | -| `ProactiveTarget.Platform` | `"qq"` | 主动消息不知道发给哪个 adapter | -| `platform_qq_xxx` session ID | `"qq"` | ✅ 正确,同群聊多账号应共享上下文 | - -#### 目标 - -将 ai-core 内部的 platform 标识从"协议类型"改为"adapter 实例名",使多个同平台账号独立工作。 - -#### 要点 - -- **platform-bridge `forwardToAICore`**:source.platform 传 adapter config name(`"qq-main"`)而非 `"qq"` -- **ai-core `SetBotUID`**:key 改为 adapter name,允许多个同平台 Bot -- **`ProactiveTarget.Platform`**:传 adapter name,platform-bridge 直接用它查 router -- **platform-bridge `sendProactive` handler**:直接用 platform 字段作为 adapter name -- **`PlatformFormat` 注册表**:key 保持 platform 类型(`"qq"`),格式与协议绑定,不绑定账号 -- **session ID prefix**:保持 `platform_qq_`,同群聊多账号共享上下文 - -#### 涉及文件 - -| 文件 | 改动 | -|---|---| -| `platform-bridge/cmd/main.go` | forwardToAICore 传 adapter name | -| `platform-bridge/internal/handler/bridge_handler.go` | sendProactive 直接用 platform 查 adapter | -| `ai-core/cmd/main.go` | SetBotUID key 用 adapter name | -| `ai-core/background/thinker.go` | ProactiveTarget + botUIDs 适配 | - ---- - -## 6. P5 — 工具子会话增强 - -### 6.1 子会话返回时间戳 - -**现状**:子会话结果(SubSessionResult)没有记录创建时间和结束时间。 - -**目标**:每个子会话结果增加 `CreatedAt` / `FinishedAt` 字段。 - -**涉及文件**:`model/sub_session.go` + 各 provider 的 `Execute()` 方法 - -### 6.2 工具调用不阻塞主会话 - -**现状**:`Synthesizer.ChatWithTools` 的 LLM 工具调用循环(最多 5 轮)在主 goroutine 中执行,长工具调用(如 `web_search` + `web_fetch` 链)会阻塞流式输出。 - -**目标**:工具调用结果通过 channel 异步返回,Synthesizer 先输出等待提示(如"让我查一下..."),收到结果后再继续流式生成。 - -**涉及文件**:`orchestrator/synthesizer.go` — `ChatWithTools` 的调用模型改为 publish/subscribe - ---- - -## 7. 实施顺序建议 - -``` -Phase A (本节可做) ───────────────────────────── ✅ 已完成 - P2.2 对话后思考可追加 ~10 行改动 - P2.1 自主思考后触发记忆整理 ~5 行改动 - P5.1 子会话返回时间戳 ~20 行改动 - -Phase B (需要跨服务协调) ─────────────────────── ✅ 已完成 - P1 LLM 可自主操作提醒与日程 新建 1 文件 + 注册工具 - P0 自主思考分层 重构 thinker 核心循环 - -Phase C (架构级改动) ─────────────────────────── - P4 QQ→OBv11 重命名 + PlatformFormat 抽象 ✅ 已完成 - P4.1 同平台多账号支持 跨 ai-core + platform-bridge ← 当前 - P3 群聊并发(协会议话) 跨 ai-core + platform-bridge - -Phase D (后续优化) ───────────────────────────── - P5.2 工具调用不阻塞主会话 改造 synthesizer 调用模型 -``` - ---- - -## 附:与架构设计文档的对照清单 - -| # | 设计要求 | 状态 | 对应章节 | -|---|---------|------|---------| -| 1 | 基础出人格库 | ✅ | — | -| 2 | 故事背景知识库 | ✅ | — | -| 3 | 多优先级自主增删改记忆 | ⚠️ 缺自主删改 | 待定 | -| 4 | 用户手动增删改知识库 | ✅ | — | -| 5 | IoT 功能调用知识库 | ✅ | — | -| 6 | 插件功能调用知识库 | ✅ | — | -| 7 | 定时任务模块 | ❌ | P1 | -| 8 | 定时任务自主增删改 | ❌ | P1 | -| 9 | 日程自主增删改 | ❌ | P1 | -| 10 | 简单思考(高频下位模型) | ❌ | P0 | -| 11 | 复杂思考(低频思考模型) | ⚠️ 有但未分层 | P0 | -| 12 | 简单思考可唤醒复杂思考 | ❌ | P0 | -| 13 | 两种思考均可追加 | ⚠️ 仅 post_chat | P2.2 | -| 14 | 两种思考均可调用工具 | ✅ | — | -| 15 | 主动通讯(客户端+平台) | ✅ | — | -| 16 | 思考后触发记忆整理 | ❌ | P2.1 | -| 17 | 回复一句一句发 | ✅ | — | -| 18 | 工具调用不阻塞主会话 | ⚠️ 部分阻塞 | P5.2 | -| 19 | 工具子会话返回时间戳 | ❌ | P5.1 | -| 20 | 群聊并发协会议话 | ❌ | P3 | -| 21 | 多平台消息前缀 | ⚠️ QQ 硬编码 | P4 | -| 22 | 多平台发送方式 | ✅ | — | - -> 共 22 项设计要求:✅ 已完成 9 项,⚠️ 部分完成 5 项,❌ 未实现 8 项。 diff --git a/docs/pg-backup-migration.md b/docs/pg-backup-migration.md deleted file mode 100644 index ed55d7f..0000000 --- a/docs/pg-backup-migration.md +++ /dev/null @@ -1,99 +0,0 @@ -# PostgreSQL 备份与迁移 - -## 备份脚本 - -`scripts/pg-backup.sh` 封装了 `pg_dump` / `psql`,跨任何 PG 版本兼容。 - -```bash -./scripts/pg-backup.sh backup # 备份 -./scripts/pg-backup.sh restore # 从最新备份恢复 -./scripts/pg-backup.sh restore <文件路径> # 恢复指定备份 -``` - -备份文件写入 `backups/cyrene_YYYYMMDD_HHMMSS.sql`,自动保留最近 7 个。 - -## PG 大版本升级(16 → 17 等) - -生产环境用 `docker-compose.yml`,开发环境用 `docker-compose.dev.yml`。 - -```bash -# === 步骤 1:备份 === -./scripts/pg-backup.sh backup - -# === 步骤 2:停服并清理 === -docker compose -f docker-compose.dev.yml down - -# 删旧 volume,确保新 PG 从干净状态初始化(可选但推荐) -docker volume rm cyrene_cyrene_pg_data - -# === 步骤 3:修改镜像版本 === -# docker-compose.dev.yml 中: -# image: pgvector/pgvector:pg16 → image: pgvector/pgvector:pg17 - -# === 步骤 4:启动新 PG === -docker compose -f docker-compose.dev.yml up -d postgres - -# 等 healthcheck 通过 -docker ps --filter name=cyrene_postgres - -# === 步骤 5:恢复数据 === -./scripts/pg-backup.sh restore - -# === 步骤 6:启动全栈 === -docker compose -f docker-compose.dev.yml up -d -``` - -## 版本间切换(dev.db.yml ↔ dev.yml) - -两个文件的 volume 名和容器名已对齐,直接切换即可,数据自动继承: - -```bash -# 从轻量版切到全服务版 -docker compose -f docker-compose.dev.db.yml down -docker compose -f docker-compose.dev.yml up -d - -# 反向切回 -docker compose -f docker-compose.dev.yml down -docker compose -f docker-compose.dev.db.yml up -d -``` - -原有的 `cyrene_*_data` volume 会被新容器直接挂载,无需恢复。 - -## 跨服务器迁移 - -```bash -# 源服务器 -./scripts/pg-backup.sh backup -scp backups/cyrene_*.sql user@target:/path/to/backups/ - -# 目标服务器 -./scripts/pg-backup.sh restore backups/cyrene_*.sql -``` - -## 常见问题 - -### 新版 PG 启动后不接受旧 volume - -`pg_upgrade` 要求 in-place 升级必须用 PG 自带的升级工具,不能直接挂旧数据目录。如果没删旧 volume 导致启动失败: - -```bash -docker logs cyrene_postgres # 会提示 data directory incompatible -docker compose down -docker volume rm cyrene_cyrene_pg_data -docker compose up -d -./scripts/pg-backup.sh restore -``` - -### 备份文件过大 - -`pg_dump` 产生的 `.sql` 文件包含全部数据,如果数据库过大可以考虑: - -```bash -# 仅导出结构,不导出日志/缓存表 -docker exec cyrene_postgres pg_dump -U cyrene -d cyrene_ai \ - --schema-only > schema.sql - -# 按表分别导出 -docker exec cyrene_postgres pg_dump -U cyrene -d cyrene_ai \ - -t memories -t sessions -t users > core_tables.sql -```