From a04275cc76f1cb93dcf4e75d56227bb64e195a3e Mon Sep 17 00:00:00 2001
From: hhs <386998068@qq.com>
Date: Fri, 19 Jun 2026 15:31:52 +0800
Subject: [PATCH] =?UTF-8?q?docs:=20=E6=8C=89=E5=8A=9F=E8=83=BD=E6=A8=A1?=
=?UTF-8?q?=E5=9D=97=E9=87=8D=E6=9E=84=E6=96=87=E6=A1=A3=E7=BB=93=E6=9E=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 新建 01-架构设计.md:合并项目概述+系统架构+持久化设计,含 Mermaid 架构图、模块图、时序图、ER 图、部署图
- 新建 02-接口文档.md:合并接口文档+持久化 API+用户模块 API,统一格式去重
- 重编号 03~09,去掉状态标注,规划中功能标记为待实现
- 删除 PLAN_BACKEND.md、PLAN_USER_MODULE.md 及冗余文档
---
docs/01-架构设计.md | 389 +++++++
docs/01-项目概述.md | 28 -
docs/{03-接口文档.md => 02-接口文档.md} | 788 +++----------
docs/02-系统架构.md | 256 -----
docs/{04-技术选型.md => 03-技术选型.md} | 12 +-
docs/{05-用户故事.md => 04-用户故事.md} | 0
docs/{06-语音交互.md => 05-语音交互.md} | 2 +-
docs/{07-视觉理解.md => 06-视觉理解.md} | 0
docs/{08-成本控制.md => 07-成本控制.md} | 10 +-
docs/{10-功能创意.md => 08-功能创意.md} | 0
docs/11-持久化与用户系统设计.md | 751 ------------
docs/PLAN_BACKEND.md | 223 ----
docs/PLAN_USER_MODULE.md | 1381 -----------------------
docs/README.md | 56 +-
14 files changed, 606 insertions(+), 3290 deletions(-)
create mode 100644 docs/01-架构设计.md
delete mode 100644 docs/01-项目概述.md
rename docs/{03-接口文档.md => 02-接口文档.md} (61%)
delete mode 100644 docs/02-系统架构.md
rename docs/{04-技术选型.md => 03-技术选型.md} (97%)
rename docs/{05-用户故事.md => 04-用户故事.md} (100%)
rename docs/{06-语音交互.md => 05-语音交互.md} (97%)
rename docs/{07-视觉理解.md => 06-视觉理解.md} (100%)
rename docs/{08-成本控制.md => 07-成本控制.md} (90%)
rename docs/{10-功能创意.md => 08-功能创意.md} (100%)
delete mode 100644 docs/11-持久化与用户系统设计.md
delete mode 100644 docs/PLAN_BACKEND.md
delete mode 100644 docs/PLAN_USER_MODULE.md
diff --git a/docs/01-架构设计.md b/docs/01-架构设计.md
new file mode 100644
index 0000000..f770b43
--- /dev/null
+++ b/docs/01-架构设计.md
@@ -0,0 +1,389 @@
+# 架构设计
+
+## 项目概述
+
+CamTalk 是一款**多模态实时 AI 视觉对话助手**。用户通过摄像头和麦克风与 AI 交互,AI 理解视觉场景和语音输入后,以文字和语音形式给出自然回应。
+
+核心挑战在于三个维度之间的张力:
+
+| 维度 | 关键问题 |
+|------|---------|
+| 视觉理解 | 如何准确理解摄像头画面中的人物、物体、场景? |
+| 语音交互 | 如何让对话像真人交流一样自然、低延迟? |
+| 成本控制 | 实时视频流 + LLM 推理,如何避免账单爆炸? |
+
+## 系统架构
+
+三层架构:**前端做轻量预处理,后端做智能编排,云端 AI 服务按需调用**。
+
+```mermaid
+graph TB
+ subgraph Browser["浏览器客户端"]
+ UI["UI 渲染层
React 18 + TypeScript"]
+ Edge["边缘预处理层
VAD / 关键帧检测"]
+ Media["媒体采集层
Camera / Microphone"]
+ end
+
+ subgraph Gateway["Go 网关"]
+ WS["WebSocket Handler
连接管理 / 消息分发"]
+ Session["Session Manager
会话状态 / 对话历史"]
+ Orch["AI Orchestrator
STT→LLM→TTS 流式并行"]
+ Auth["Auth 模块
JWT / bcrypt"]
+ REST["REST API
健康检查 / 对话管理"]
+ Store["Store 层
Repository 接口"]
+ end
+
+ subgraph AI["云端 AI 服务"]
+ STT["STT
Deepgram / MiMo ASR"]
+ LLM["LLM
GPT-4o / 通义千问"]
+ TTS["TTS
OpenAI TTS / MiMo TTS"]
+ end
+
+ subgraph Storage["存储层"]
+ Mem["Memory
进程内缓存"]
+ Redis["Redis
会话状态"]
+ PG["PostgreSQL
持久化存储"]
+ end
+
+ Media --> Edge
+ Edge -->|"query (image+audio)"| WS
+ UI <-->|"WebSocket"| WS
+ WS --> Session
+ WS --> Orch
+ Orch --> STT
+ Orch --> LLM
+ Orch --> TTS
+ Session --> Store
+ Store --> Mem
+ Store --> Redis
+ Store --> PG
+ REST --> Session
+ WS --> Auth
+```
+
+> 为什么单独加一层 Go 网关,而不是让前端直连 AI API?1)API Key 安全性;2)统一的速率限制和成本管控;3)多模型路由逻辑集中在一处便于维护。
+
+## 核心交互流程
+
+一次完整的"用户提问 → AI 回答"流程:
+
+```mermaid
+sequenceDiagram
+ participant B as 浏览器
+ participant G as Go 网关
+ participant S as STT
+ participant L as LLM
+ participant T as TTS
+
+ B->>B: VAD 检测到语音结束
+ B->>G: query {image, audio}
+ G->>S: 音频流
+ S-->>G: 流式文本
+ G-->>B: stt_result {text}
+
+ G->>L: [图像 + 文本 + 上下文]
+ loop LLM 流式输出
+ L-->>G: token delta
+ G-->>B: llm_chunk {delta}
+ end
+ G-->>B: llm_done {full_text, tokens}
+
+ par LLM 输出的同时
+ G->>G: 句子切分器检测到完整句子
+ G->>T: 句子文本
+ T-->>G: 音频 chunk
+ G-->>B: tts_audio {audio}
+ end
+ G-->>B: tts_audio {final: true}
+```
+
+**关键优化**:LLM 文本流和 TTS 音频流**并行推送**——客户端先逐 token 展示文字,同时 TTS 逐句子合成并推送音频,用户感知延迟大幅降低。
+
+## 技术栈
+
+### 前端
+
+| 技术 | 选型 | 选择理由 |
+|------|------|---------|
+| 框架 | React 18 + TypeScript | 组件化开发,类型安全,生态成熟 |
+| 构建 | Vite | 开发热更新快,构建产物小 |
+| 实时通信 | WebSocket(原生 API) + 自封装连接管理 | 浏览器原生支持,封装心跳/重连/消息分发 |
+| 语音检测 | @ricky0123/vad-web | 基于 WebRTC VAD,纯前端零延迟 |
+| 媒体采集 | MediaDevices API | 浏览器原生摄像头/麦克风访问 |
+
+### 后端
+
+| 技术 | 选型 | 选择理由 |
+|------|------|---------|
+| 语言 | Go | 高并发 goroutine 模型,适合长连接管理 |
+| HTTP 框架 | Gin | 高性能 HTTP 路由,中间件生态成熟 |
+| WebSocket | gorilla/websocket | Go 生态最成熟的 WebSocket 库 |
+| 会话存储 | Memory(默认) / Redis | 进程内存零依赖,Redis 支持多实例部署 |
+| 持久化存储 | PostgreSQL | 对话历史、用户数据、会话元数据 |
+| 配置管理 | Viper + godotenv | 支持 YAML + .env + 环境变量覆盖 |
+| 日志 | Zap | 高性能结构化日志 |
+
+### AI 服务
+
+| 能力 | 默认方案 | 备选方案 |
+|------|---------|---------|
+| 多模态 LLM | GPT-4o | 通义千问等 OpenAI 兼容模型 |
+| 语音识别 STT | Deepgram | MiMo ASR(小米) |
+| 语音合成 TTS | OpenAI TTS | MiMo TTS(小米) |
+
+> Go 网关的 AI 服务层统一封装不同服务商的调用接口,通过配置切换 provider。
+
+## 后端模块
+
+```mermaid
+graph LR
+ subgraph Entry["入口层"]
+ Main["main.go
依赖注入 / 启动"]
+ end
+
+ subgraph Transport["传输层"]
+ WSH["WebSocket Handler
连接管理 / 认证"]
+ APH["REST API Handlers
Auth / Conversation / Health"]
+ end
+
+ subgraph Business["业务层"]
+ SM["Session Manager
会话生命周期"]
+ ORCH["Orchestrator
STT→LLM→TTS 编排"]
+ AS["Auth Service
注册/登录/刷新/登出"]
+ end
+
+ subgraph AI_Layer["AI 服务层"]
+ STT_S["STT Service
Deepgram / MiMo"]
+ LLM_S["LLM Service
OpenAI 兼容"]
+ TTS_S["TTS Service
OpenAI / MiMo"]
+ end
+
+ subgraph Data["数据层"]
+ UR["UserRepository"]
+ MR["MessageRepository"]
+ SR["SessionRepository"]
+ end
+
+ Main --> WSH
+ Main --> APH
+ Main --> SM
+ Main --> ORCH
+ Main --> AS
+
+ WSH --> SM
+ WSH --> ORCH
+ APH --> SM
+ APH --> AS
+ ORCH --> STT_S
+ ORCH --> LLM_S
+ ORCH --> TTS_S
+ SM --> MR
+ SM --> SR
+ AS --> UR
+```
+
+| 模块 | 职责 |
+|------|------|
+| WebSocket Handler | 管理客户端连接生命周期,JWT 认证,conversation_id 恢复,单播消息推送 |
+| Session Manager | 维护用户会话状态、对话历史。Memory(默认)/ Redis(可切换),30 分钟 TTL,Write-Through 到 PG |
+| AI Orchestrator | 编排 STT→LLM→TTS 流式并行管道,context 取消 + 超时控制 + 句子切分 |
+| AI Service Layer | AI 服务抽象层,多 provider 支持(Deepgram/MiMo/OpenAI 等) |
+| Auth | 用户认证与授权。JWT (HS256) 双 token 轮转,bcrypt 密码哈希,Gin 中间件 |
+| Store | 持久化存储层。UserRepository / MessageRepository / SessionRepository,内存 + PostgreSQL 双实现 |
+| REST API | 健康检查、认证、对话管理端点 |
+| Logger | Zap 结构化日志 |
+| Models | 数据模型定义 |
+| Migrations | 数据库版本化迁移,嵌入式 SQL 文件自动执行 |
+| Model Router | 根据请求类型选择 AI 模型(待实现) |
+| Rate Limiter | 令牌桶限流(待实现) |
+
+## 前端组件
+
+| 组件 | 职责 |
+|------|------|
+| AuthPage | 登录/注册表单 |
+| CameraManager | 摄像头流采集 |
+| MicManager | 麦克风音频采集 |
+| EdgeProcessor | VAD + 关键帧检测(Canvas 像素比较) |
+| WebSocketManager | WS 连接生命周期管理 |
+| ChatPanel | 消息展示、流式回复、文本输入、场景选择 |
+| VideoPreview | 摄像头画面预览 |
+| SessionSidebar | 左侧抽屉式对话列表(搜索、重命名、删除) |
+| ConfigPanel | 右侧抽屉式配置面板(主题、TTS 开关、detail level、语言、场景、账户) |
+| Toast | 轻量通知提示(3 秒自动消失) |
+
+核心 Hook:`useVisionSession()` 封装一次完整的视觉对话会话(摄像头、VAD、WebSocket、消息状态、认证、场景模式)。
+
+## 数据库设计
+
+### ER 关系
+
+```mermaid
+erDiagram
+ users ||--o{ sessions : "1:N"
+ users ||--o{ refresh_tokens : "1:N"
+ sessions ||--o{ messages : "1:N"
+
+ users {
+ uuid id PK
+ varchar username UK
+ varchar password_hash
+ timestamptz created_at
+ timestamptz updated_at
+ }
+
+ sessions {
+ uuid id PK
+ uuid user_id FK
+ varchar title
+ jsonb config
+ timestamptz created_at
+ timestamptz updated_at
+ }
+
+ messages {
+ bigserial id PK
+ uuid session_id FK
+ varchar role
+ text content
+ integer tokens_used
+ timestamptz created_at
+ }
+
+ refresh_tokens {
+ bigserial id PK
+ uuid user_id FK
+ varchar token_hash UK
+ timestamptz expires_at
+ timestamptz created_at
+ }
+```
+
+### 表结构
+
+```sql
+-- 用户表
+CREATE TABLE users (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ username VARCHAR(64) NOT NULL UNIQUE,
+ password_hash VARCHAR(256) NOT NULL,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now()
+);
+
+-- 会话表
+CREATE TABLE sessions (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
+ title VARCHAR(128) DEFAULT '新对话',
+ config JSONB DEFAULT '{}',
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now()
+);
+
+-- 消息表
+CREATE TABLE messages (
+ id BIGSERIAL PRIMARY KEY,
+ session_id UUID NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
+ role VARCHAR(16) NOT NULL,
+ content TEXT NOT NULL,
+ tokens_used INTEGER DEFAULT 0,
+ created_at TIMESTAMPTZ DEFAULT now()
+);
+
+-- 刷新令牌表
+CREATE TABLE refresh_tokens (
+ id BIGSERIAL PRIMARY KEY,
+ user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
+ token_hash VARCHAR(256) NOT NULL UNIQUE,
+ expires_at TIMESTAMPTZ NOT NULL,
+ created_at TIMESTAMPTZ DEFAULT now()
+);
+```
+
+### 存储策略
+
+| 场景 | 存储方案 | 说明 |
+|------|---------|------|
+| 默认 | Memory(进程内) | 零依赖,快速启动。MemoryManager 支持 Write-Through 到 PG |
+| 持久化 | Memory + PostgreSQL | 通过 `storage.driver: postgres` 启用,MemoryManager 注入 PG Repository |
+| 多实例 | Redis(独立) | 通过配置切换到 RedisManager,适合多实例部署 |
+
+冷热分离:Redis/Memory 存"热数据"(当前对话上下文,微秒级读写),PostgreSQL 存"冷数据"(历史记录)。MemoryManager 的 Write-Through 机制确保每次 AppendMessage 同时写入 PG,重启后可从 PG 恢复会话。
+
+## 认证设计
+
+```mermaid
+sequenceDiagram
+ participant C as 客户端
+ participant G as Go 网关
+ participant DB as PostgreSQL
+
+ Note over C,DB: 注册流程
+ C->>G: POST /api/auth/register {username, password}
+ G->>G: bcrypt hash 密码
+ G->>DB: INSERT users
+ G->>G: 生成 access_token + refresh_token
+ G->>DB: 存 SHA256(refresh_token)
+ G-->>C: {user, access_token, refresh_token}
+
+ Note over C,DB: 登录流程
+ C->>G: POST /api/auth/login {username, password}
+ G->>DB: 查 users by username
+ G->>G: bcrypt.CompareHashAndPassword
+ G->>G: 生成 token pair
+ G->>DB: 存 SHA256(refresh_token)
+ G-->>C: {user, access_token, refresh_token}
+
+ Note over C,DB: Token 刷新(轮转)
+ C->>G: POST /api/auth/refresh {refresh_token}
+ G->>G: 校验签名和过期
+ G->>DB: 验证 hash 存在
+ G->>DB: 撤销旧 refresh_token
+ G->>G: 生成新 token pair
+ G->>DB: 存新 refresh_token hash
+ G-->>C: {access_token, refresh_token}
+```
+
+**Token 策略**:access_token 15 分钟有效,refresh_token 7 天有效。refresh 时旧 token 失效(轮转),防止重放攻击。
+
+**WebSocket 认证**:连接地址 `ws://host/ws?token=&conversation_id=`。HTTP Upgrade 前校验 token,失败返回 401。
+
+## 部署架构
+
+```mermaid
+graph TB
+ User["用户浏览器"] --> Nginx
+
+ subgraph Nginx["Nginx 反向代理"]
+ Static["/ → 前端静态资源"]
+ API["/api/* → Go Gateway"]
+ WS_Proxy["/ws → Go Gateway"]
+ end
+
+ subgraph Gateway_Pool["Go Gateway 实例"]
+ G1["Gateway-1"]
+ G2["Gateway-2"]
+ GN["Gateway-N"]
+ end
+
+ Nginx --> G1
+ Nginx --> G2
+ Nginx --> GN
+
+ G1 --> Redis
+ G2 --> Redis
+ GN --> Redis
+
+ G1 --> PG_DB["PostgreSQL"]
+ G2 --> PG_DB
+ GN --> PG_DB
+
+ G1 --> AI_Services["AI Services(外部 API)"]
+ G2 --> AI_Services
+ GN --> AI_Services
+```
+
+**跨域策略**:Nginx 将前端(`/`)、REST API(`/api/*`)、WebSocket(`/ws`)统一反代到同一域名,浏览器无跨域问题。
+
+**开发环境**:前端 Vite :5173 通过 `server.proxy` 转发 `/ws` 和 `/api` 到后端 :8080,无需硬编码端口。
diff --git a/docs/01-项目概述.md b/docs/01-项目概述.md
deleted file mode 100644
index 8a5a2c9..0000000
--- a/docs/01-项目概述.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# 项目概述
-
-## 概述
-
-开发一款**多模态实时对话应用**——通过摄像头与麦克风捕获用户的视觉场景与语音输入,由 AI 理解并给出自然、流畅的回应。
-
-核心挑战在于三个维度之间的张力:
-
-| 维度 | 关键问题 | 详见 |
-|------|---------|------|
-| 视觉理解 | 如何准确理解摄像头画面中的人物、物体、场景? | `07-视觉理解.md` |
-| 语音交互 | 如何让对话像真人交流一样自然、低延迟? | `06-语音交互.md` |
-| 成本控制 | 实时视频流 + LLM 推理,如何避免账单爆炸? | `08-成本控制.md` |
-
-> 提升视觉精度意味着更高分辨率和更频繁的采样,但这会直接推高带宽和推理成本。架构设计需要在三者之间做好取舍。
-
-## 项目目标
-
-1. **用户故事规划**:明确"AI 能看、能听、能说"需要覆盖哪些场景 → `05-用户故事.md`
-2. **成本控制策略**:从架构设计层面融入运营成本意识 → `08-成本控制.md`
-
-## 交付物
-
-- 可运行的应用程序(摄像头 + 麦克风 → AI 回应)
-- 设计文档,覆盖:
- - 计划实现 vs 最终实现的用户故事
- - 成本控制技巧的构思 vs 实际采用的方案
- - 项目架构设计与技术选型
diff --git a/docs/03-接口文档.md b/docs/02-接口文档.md
similarity index 61%
rename from docs/03-接口文档.md
rename to docs/02-接口文档.md
index 1efe171..071a75e 100644
--- a/docs/03-接口文档.md
+++ b/docs/02-接口文档.md
@@ -2,11 +2,11 @@
## 概述
-前后端通信接口定义。以 WebSocket 承载实时对话,REST 端点支撑基础运维。持久化已通过 PostgreSQL 实现,MemoryManager 支持 Write-Through 模式。
+前后端通信接口定义。以 WebSocket 承载实时对话,REST 端点支撑基础运维。持久化通过 PostgreSQL 实现,MemoryManager 支持 Write-Through 模式。
**设计原则**:
- WebSocket 为主:所有对话数据走 WebSocket
-- REST 为辅:仅用于健康检查、会话管理等低频操作
+- REST 为辅:仅用于健康检查、认证、对话管理等低频操作
- 接口先行:先定义契约,再填充实现——前后端可并行开发
## 接口全景
@@ -20,7 +20,6 @@
/api/conversations/*
HTTP Client <--> GET /api/conversations/:id (历史消息)
/messages
- HTTP Client ~~> POST/DELETE /api/sessions (已废弃,保留兼容)
```
---
@@ -34,8 +33,6 @@
| `token` | 是 | JWT access_token,缺失或无效时返回 401 |
| `conversation_id` | 否 | 恢复已有对话;省略则创建新对话 |
-> 详见"REST API → WebSocket 认证变更"章节。
-
### 消息格式约定
所有 WebSocket 消息均为 JSON 文本帧,统一结构:
@@ -79,7 +76,7 @@ interface ConfigMessage {
tts_enabled?: boolean; // 是否开启语音合成,默认 true
detail_level?: "low" | "high"; // 图像精度,默认 "low"
language?: string; // 交互语言,默认 "zh-CN"
- scenario?: string; // 场景模式,可选值:free_chat / interviewer / english_teacher / debate / interpreter
+ scenario?: string; // 场景模式:free_chat / interviewer / english_teacher / debate / interpreter
};
}
```
@@ -175,7 +172,7 @@ interface TTSAudioMessage {
| 属性 | 值 | 说明 |
|------|------|------|
-| 编码 | `audio/mp3`(MP3) | 浏览器 `