Files
CamTalk/docs/01-架构设计.md
hhs 032de796c8 docs: 重构文档结构,规范编号并整合冗余内容
## 主要变更

### 文档重构(减少 1199 行,-23%)
- 01-架构设计.md: 503→369 行 (-27%),删除 DDL/配置示例,精简鉴权/存储描述
- 02-接口文档.md: 1313→570 行 (-57%),删除 Go 接口/Orchestrator 实现/配置管理
- 07-成本控制.md: 65→59 行 (-9%),代码块替换为文件引用

### 文档编号规范化
- 08-功能创意.md → 删除(内容整合到 README.md "功能扩展方向")
- 10-Eino框架与编排设计.md → 08-Eino框架与编排设计.md
- 情景切换.md → 09-情景切换.md
- 12-鉴权体系.md → 10-鉴权体系.md
- 13-令牌桶限流.md → 11-令牌桶限流.md

### 交叉引用更新
- 01-架构设计.md: 更新对鉴权体系/令牌桶限流的引用为新编号
- README.md: 更新文档索引表、推荐阅读顺序、新增功能扩展方向

### 删除过时文档
- 09-技术名词解释.md(内容已整合到 03-技术选型.md)
- 10-Eino重构方案.md(历史记录,已完成)
- 11-Eino框架技术文档.md(已合并到 08)
- 情景切换功能完整文档.md(已规范化为 09)

## 重构原则
- 架构文档聚焦系统结构,移除实现细节
- 接口文档保留纯契约,删除内部实现
- 编号连续(01-11),语义清晰
- 通过交叉引用连接相关文档,避免重复
2026-06-21 14:48:03 +08:00

13 KiB
Raw Permalink Blame History

架构设计

项目概述

CamTalk 是一款多模态实时 AI 视觉对话助手。用户通过摄像头和麦克风与 AI 交互AI 理解视觉场景和语音输入后,以文字和语音形式给出自然回应。

核心挑战在于三个维度之间的张力:

维度 关键问题
视觉理解 如何准确理解摄像头画面中的人物、物体、场景?
语音交互 如何让对话像真人交流一样自然、低延迟?
成本控制 实时视频流 + LLM 推理,如何避免账单爆炸?

系统架构

三层架构:前端做轻量预处理,后端做智能编排,云端 AI 服务按需调用

graph TB
    subgraph Browser["浏览器客户端"]
        UI["UI 渲染层<br/>React 18 + TypeScript"]
        Edge["边缘预处理层<br/>VAD / 关键帧检测"]
        Media["媒体采集层<br/>Camera / Microphone"]
    end

    subgraph Gateway["Go 网关"]
        WS["WebSocket Handler<br/>连接管理 / 消息分发"]
        Session["Session Manager<br/>会话状态 / 对话历史"]
        Orch["AI Orchestrator<br/>Eino Graph 声明式编排"]
        Auth["Auth 模块<br/>JWT / bcrypt"]
        REST["REST API<br/>健康检查 / 对话管理"]
        Store["Store 层<br/>Repository 接口"]
    end

    subgraph AI["云端 AI 服务"]
        STT["STT<br/>Deepgram / MiMo ASR"]
        LLM["LLM<br/>GPT-4o / 通义千问"]
        TTS["TTS<br/>OpenAI TTS / MiMo TTS"]
    end

    subgraph Storage["存储层"]
        Mem["Memory<br/>进程内缓存"]
        Redis["Redis<br/>会话状态"]
        PG["PostgreSQL<br/>持久化存储"]
    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 API1API Key 安全性2统一的速率限制和成本管控3多模型路由逻辑集中在一处便于维护。

核心交互流程

一次完整的"用户提问 → AI 回答"流程:

sequenceDiagram
    participant B as 浏览器
    participant G as Go 网关Eino Graph
    participant S as STT
    participant L as LLMChatModel
    participant T as TTS

    B->>B: VAD 检测到语音结束
    B->>G: query {image, audio}
    Note over G: EinoOrchestrator 启动 Graph.Stream()

    G->>S: STT Lambda音频 → 文本
    S-->>G: 识别文本
    G-->>B: stt_result {text}

    G->>G: History Lambda组装提示词 + 历史 + 多模态消息

    G->>L: ChatModel Node流式推理
    loop LLM 流式输出Callback OnEndWithStreamOutput
        L-->>G: token delta
        G-->>B: llm_chunk {delta}
    end

    G->>G: Msg2Str + Splitter Lambda句子切分
    G->>T: TTS Lambda逐句合成
    T-->>G: 音频 chunk
    G-->>B: tts_audio {audio}

    G->>G: Done Lambda发送完成通知
    G-->>B: llm_done {full_text, tokens}
    G-->>B: tts_audio {final: true}

关键优化Eino Graph 以 Stream 模式运行ChatModel 的 token 流通过 Callback 的 OnEndWithStreamOutput 实时推送到客户端(llm_chunk),同时 Splitter 节点将 token 流切分为句子TTS 节点逐句合成并推送音频。LLM 文本流和 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 / PostgreSQL 三级存储 进程内存零依赖Redis 支持多实例PG 持久化。TieredManager 自动降级
AI 编排 CloudWeGo Eino Graph 声明式 DAG 编排Stream 模式Callback AOP
持久化存储 PostgreSQL 对话历史、用户数据、会话元数据
配置管理 Viper + godotenv 支持 YAML + .env + 环境变量覆盖
日志 Zap 高性能结构化日志

AI 服务

能力 默认方案 备选方案
多模态 LLM DashScope qwen3-vl-plus GPT-4o 等 OpenAI 兼容模型
语音识别 STT MiMo ASR小米 Deepgram
语音合成 TTS MiMo TTS小米 OpenAI TTS

Go 网关的 AI 服务层统一封装不同服务商的调用接口,通过配置切换 provider。LLM 通过 Eino 框架的 eino-ext/components/model/openai 组件接入,支持任何 OpenAI 兼容接口。

后端模块

graph LR
    subgraph Entry["入口层"]
        Main["main.go<br/>依赖注入 / 启动"]
    end

    subgraph Transport["传输层"]
        WSH["WebSocket Handler<br/>连接管理 / 认证"]
        APH["REST API Handlers<br/>Auth / Conversation / Health"]
    end

    subgraph Business["业务层"]
        SM["Session Manager<br/>会话生命周期"]
        ORCH["EinoOrchestrator<br/>Eino Graph 编排"]
        AS["Auth Service<br/>注册/登录/刷新/登出"]
    end

    subgraph Eino_Layer["Eino 编排层"]
        PG["PipelineGraph<br/>7 节点 DAG"]
        CB["Callback Handler<br/>LLM token 推送"]
        ST["PipelineState<br/>跨节点状态"]
    end

    subgraph AI_Layer["AI 服务层"]
        STT_S["STT Service<br/>MiMo / Deepgram"]
        LLM_S["ChatModel<br/>eino-ext OpenAI 兼容"]
        TTS_S["TTS Service<br/>MiMo / OpenAI"]
    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 --> PG
    PG --> CB
    PG --> ST
    PG --> STT_S
    PG --> LLM_S
    PG --> TTS_S
    SM --> MR
    SM --> SR
    AS --> UR
模块 职责
WebSocket Handler 管理客户端连接生命周期JWT 认证conversation_id 恢复,单播消息推送
Session Manager 维护用户会话状态、对话历史三级存储架构30 分钟 TTL
Eino 编排层 基于 CloudWeGo Eino Graph 的声明式 AI 编排7 节点 DAG 流水线Stream 模式调用
AI Orchestrator EinoOrchestrator 适配器,包装 Eino Graph 实现 Orchestrator 接口
AI Service Layer AI 服务抽象层,多 provider 支持Deepgram/MiMo/OpenAI 等)
Auth 用户认证与授权JWT 双 token 轮转bcrypt 密码哈希
Store 持久化存储层Repository 接口与实现(内存 + PostgreSQL
REST API 健康检查、认证、对话管理端点
Logger Zap 结构化日志
Models 数据模型定义
Migrations 数据库版本化迁移
Model Router 根据请求类型选择 AI 模型(待实现)
Rate Limiter 令牌桶限流,详见 11-令牌桶限流.md

前端组件

组件 职责
LandingPage 未登录时的着陆页,内嵌 LoginModal 登录/注册弹窗
CameraManager 摄像头流采集
MicManager 麦克风音频采集
EdgeProcessor VAD + 关键帧检测
WebSocketManager WebSocket 连接生命周期管理
ChatPanel 消息展示、流式回复、文本输入、场景选择
VideoPreview 摄像头画面预览
SessionSidebar 左侧对话列表(搜索、重命名、删除、时间分组)
ConfigPanel 右侧配置面板主题、TTS 开关、detail level、语言、场景、登出
Toast 轻量通知提示

核心 HookuseVisionSession() 封装完整的视觉对话会话摄像头、VAD、WebSocket、消息状态、认证、场景模式useSessionList() 通过 REST API 管理对话列表 CRUD。

前端会话状态模型(三态)

前端 UI 存在三个会话状态,由 isConnectedisCameraOn 联合决定:

┌──────────┐    startSession()    ┌──────────┐
│  initial  │ ──────────────────→ │  video   │
│  初始态    │                     │  视频通话  │
└──────────┘                      └──────────┘
      ↑                                │
      │ stopSession()            stopVideo()
      │                                │
      │                                ▼
      │                         ┌──────────┐
      └──────────────────────── │ textOnly │
                                │ 文字对话  │
                                └──────────┘
                                      │
                                startSession()
                                      │
                                      ▼
                                ┌──────────┐
                                │  video   │
                                └──────────┘
状态 条件 WebSocket 摄像头 消息 文字输入
initial !isConnected && messages.length === 0 断开 关闭 可用(自动连接)
video isConnected && isCameraOn 连接 开启 可用
textOnly isConnected && !isCameraOn 连接 关闭 保留 可用
  • stopVideo():停止摄像头/麦克风/VAD保持 WebSocket 连接和消息历史,用户可继续文字对话
  • stopSession():完全断开 WebSocket、清空消息、重置状态回到初始态

数据库设计

ER 关系

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
    }

系统采用关系型数据库存储持久化数据,包括用户账户、对话会话、消息记录和刷新令牌。数据库表定义详见 backend/migrations/ 目录下的 SQL 迁移文件。

存储策略

系统采用三级存储架构TieredManager实现会话状态管理平衡性能与可靠性

  • L1 Memory:进程内缓存,提供微秒级读写性能
  • L2 Redis:分布式缓存层,支持多实例部署,提供毫秒级访问
  • L3 PostgreSQL:持久化存储层,确保数据可靠性

会话数据按 TTL默认 30 分钟)在三级存储间流转,支持 Redis 故障时自动降级到 Memory + PostgreSQL 模式。配置灵活可根据部署规模选择单级Memory、双级Memory + PostgreSQL或完整三级存储方案。

认证设计

系统采用 JWT 双 token 轮转认证机制,结合 bcrypt 密码哈希和 Refresh Token Rotation 安全策略。

核心机制包括:双 token 轮转access_token 15 分钟 + refresh_token 7 天、密码安全bcrypt cost=10、token 安全SHA256 哈希存储、复用检测、WebSocket 连接认证(基于 access_token 的 HTTP Upgrade 校验)等。认证流程、安全机制、配置要求等详细设计见 10-鉴权体系.md

部署架构

系统采用分层部署架构,支持单实例和多实例水平扩展:

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无需硬编码端口。