Files
Cyrene/docs/cyrene-project-architecture-analysis.md
AskaEth 46441335c0 refactor: 统一 .env 配置 — 合并 backend/.env + .docker.env 到根目录
- Go 服务 godotenv.Load("../.env") → godotenv.Load("../../.env")
- ethend.sh/config.js 读取路径改为根目录 .env
- 删除 .docker.env.example 和 backend/.env.example,统一为 .env.example
- Docker compose 默认读取根 .env,无需 --env-file
- 同步更新全部文档

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 10:12:54 +08:00

35 KiB
Raw Permalink Blame History

Cyrene AI 项目架构与功能分析文档

日期2026-05-23
分支dev
项目根目录d:\Project\Code\Uni\Cyrene


目录

  1. 项目概览
  2. 总体架构
  3. 后端服务详解
  4. 前端详解
  5. 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
包数量11 个内部包,约 40 个 .go 文件

3.1.1 启动流程

  1. 加载 .env 环境变量
  2. 初始化人格加载器(persona.NewLoader)——从 internal/persona/ 目录读取 YAML 配置
  3. 初始化 LLM 适配器:优先加载 models.jsonModelSelector;无配置文件时回退到 .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.0orchestrator.NewOrchestrator
  10. 注册 HTTP 端点:/api/v1/chatSSE)、/api/v1/memory/search/api/v1/memoryCRUD)、/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

快速通道关键词

controlWords = ["打开", "关闭", "关掉", "关上", "调到", "设置", "开关", "调节", "调高", "调低", "开一下", "关一下"]
deviceWords  = ["灯", "空调", "窗帘", "电视", "风扇", "加湿器", "插座", "门锁", "传感器"]

意图类型iot_control, iot_query, greeting, chat, story, memory_trigger, knowledge, task

3.1.5 IoT Provider (子会话)

文件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
包数量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

核心数据结构:

  • 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) 的 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

  • 事件驱动自动化:定时触发 / Webhook 触发
  • 场景执行:一组规则的批量触发
  • 通过 WebSocket 向用户推送通知

3.3 Memory-Service (:8091) — 记忆系统

目录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
插件数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 — 内存环形缓冲区 (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.go626 行)

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
文件数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.tsxApp.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 消息流

客户端 → 服务端

{ 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):

buildCommand: 'go',
buildArgs: ['build', '-o', isWin ? 'main.exe' : 'main', './cmd/main.go'],
goBin: GO_BIN

所有 Go 服务统一编译为 main.exeWindows),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 已知缺项

  • messagesmsg_type 通过后端 ServerMessage 自动填充(含 markdown/code),但数据库层面未持久化该字段,历史消息查询依赖 role 判断

八、安全性

层面 实现
认证 JWT (HS256),默认永不过期
密码存储 bcrypt 哈希
会话隔离 按 userID + sessionID 双重隔离
限流 认证端点:5次/分钟/IPAPI 端点: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

常用命令

# 构建所有 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 已排除)。格式:

{
  "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
    }
  }
}

配置管理 APIGateway adminethend 代理提供 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 及之前完全一致。