2026-06-12 10:50:07 +08:00
|
|
|
|
# CamTalk
|
|
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
<div align="center">
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
**多模态实时 AI 视觉对话助手**
|
2026-06-14 23:59:00 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
用户通过摄像头和麦克风与 AI 交互,AI 理解视觉场景和语音输入后,以文字和语音形式给出自然回应
|
|
|
|
|
|
|
|
|
|
|
|
[](https://opensource.org/licenses/MIT)
|
|
|
|
|
|
[](https://go.dev/)
|
|
|
|
|
|
[](https://react.dev/)
|
|
|
|
|
|
[](https://www.typescriptlang.org/)
|
|
|
|
|
|
|
|
|
|
|
|
[路演视频](https://www.bilibili.com/video/BV1dDJK6cE5S/) • [在线体验](http://8.161.227.145:9000) • [文档](docs/README.md)
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
> ⚠️ **在线体验提示**:由于演示环境使用 HTTP 协议,需配置 Chrome 允许非 HTTPS 下访问摄像头/麦克风:
|
2026-06-14 23:59:00 +08:00
|
|
|
|
>
|
2026-06-22 14:35:53 +08:00
|
|
|
|
> 1. 访问 `chrome://flags/#unsafely-treat-insecure-origin-as-secure`
|
|
|
|
|
|
> 2. 启用该选项,并在输入框填入 `http://8.161.227.145:9000`
|
|
|
|
|
|
> 3. 点击 **Relaunch** 重启浏览器
|
2026-06-14 23:59:00 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
## ✨ 核心特性
|
2026-06-14 23:58:41 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
- 🎥 **多模态理解**:摄像头视觉 + 麦克风语音双输入,AI 理解完整场景
|
|
|
|
|
|
- 🗣️ **自然对话**:基于 VAD 的端到端语音交互,低延迟流式响应
|
|
|
|
|
|
- 🚀 **实时推送**:LLM 文本流 + TTS 音频流并行推送,感知延迟 < 0.5 秒
|
|
|
|
|
|
- 🎭 **情景模式**:自由对话、面试官、英语老师等多场景支持
|
|
|
|
|
|
- 💾 **对话历史**:自动保存会话,支持搜索、重命名、删除、时间分组
|
|
|
|
|
|
- 🔐 **安全认证**:JWT 双 token 轮转 + Refresh Token Rotation 防重放
|
|
|
|
|
|
- 📊 **三级存储**:Memory → Redis → PostgreSQL 自动降级,保障可靠性
|
|
|
|
|
|
- 🌐 **国际化**:支持中文、英文、日文界面
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
## 🏗️ 系统架构
|
|
|
|
|
|
|
|
|
|
|
|
CamTalk 采用**三层架构**:前端轻量预处理 → Go 网关智能编排 → 云端 AI 按需调用
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-14 23:59:00 +08:00
|
|
|
|
```mermaid
|
|
|
|
|
|
graph TB
|
2026-06-22 14:35:53 +08:00
|
|
|
|
subgraph Browser["🌐 浏览器客户端"]
|
|
|
|
|
|
UI["React UI 渲染"]
|
|
|
|
|
|
VAD["VAD 语音检测"]
|
|
|
|
|
|
Media["媒体采集"]
|
2026-06-14 23:59:00 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
subgraph Gateway["⚙️ Go 网关 (Eino Graph)"]
|
|
|
|
|
|
WS["WebSocket Handler"]
|
|
|
|
|
|
Auth["JWT 认证"]
|
|
|
|
|
|
Session["会话管理 (三级存储)"]
|
|
|
|
|
|
Orch["AI 编排器 (7节点DAG)"]
|
2026-06-14 23:59:00 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
subgraph AI["☁️ 云端 AI 服务"]
|
|
|
|
|
|
STT["STT (MiMo/Deepgram)"]
|
|
|
|
|
|
LLM["LLM (qwen3-vl-plus)"]
|
|
|
|
|
|
TTS["TTS (MiMo/OpenAI)"]
|
2026-06-14 23:59:00 +08:00
|
|
|
|
end
|
|
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
Browser <-->|"WebSocket<br/>(JWT + query/config)"| Gateway
|
|
|
|
|
|
Orch --> STT
|
|
|
|
|
|
Orch --> LLM
|
|
|
|
|
|
Orch --> TTS
|
2026-06-14 09:15:05 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
### AI 编排流水线(Eino Graph)
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
基于 [CloudWeGo Eino](https://github.com/cloudwego/eino) 框架的声明式 7 节点 DAG:
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
```
|
|
|
|
|
|
START → STT → History → ChatModel → Msg2Str → Splitter → TTS → Done → END
|
|
|
|
|
|
```
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
**核心优势**:
|
|
|
|
|
|
- **流式处理**:ChatModel 逐 token 推送,Callback AOP 机制实时转发客户端
|
|
|
|
|
|
- **句子级 TTS**:Splitter 实时切分句子,TTS 逐句并行合成,无需等待完整回复
|
|
|
|
|
|
- **类型安全**:Go 泛型 + 编译期检查,Graph 拓扑错误在编译时发现
|
|
|
|
|
|
|
|
|
|
|
|
## 🛠️ 技术栈
|
|
|
|
|
|
|
|
|
|
|
|
<table>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td><b>层级</b></td>
|
|
|
|
|
|
<td><b>技术选型</b></td>
|
|
|
|
|
|
<td><b>说明</b></td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td><b>前端</b></td>
|
|
|
|
|
|
<td>React 18 + TypeScript + Vite</td>
|
|
|
|
|
|
<td>组件化开发,类型安全,快速热更新</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td><b>VAD</b></td>
|
|
|
|
|
|
<td>@ricky0123/vad-web (ONNX Runtime)</td>
|
|
|
|
|
|
<td>浏览器端语音活动检测,零延迟</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td><b>后端</b></td>
|
|
|
|
|
|
<td>Go 1.25+ + Gin + gorilla/websocket</td>
|
|
|
|
|
|
<td>高并发 goroutine,长连接管理</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td><b>AI 编排</b></td>
|
|
|
|
|
|
<td>CloudWeGo Eino Graph</td>
|
|
|
|
|
|
<td>声明式 DAG,Stream 模式,Callback AOP</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td><b>STT</b></td>
|
|
|
|
|
|
<td>MiMo ASR(默认)/ Deepgram</td>
|
|
|
|
|
|
<td>实时语音识别,多语言支持</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td><b>LLM</b></td>
|
|
|
|
|
|
<td>DashScope qwen3-vl-plus</td>
|
|
|
|
|
|
<td>多模态推理(通过 eino-ext OpenAI 接入)</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td><b>TTS</b></td>
|
|
|
|
|
|
<td>MiMo TTS(默认)/ OpenAI TTS</td>
|
|
|
|
|
|
<td>自然语音合成</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td><b>存储</b></td>
|
|
|
|
|
|
<td>PostgreSQL 15 + Redis 7</td>
|
|
|
|
|
|
<td>三级存储架构:Memory → Redis → PG</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td><b>认证</b></td>
|
|
|
|
|
|
<td>JWT (HS256) + bcrypt</td>
|
|
|
|
|
|
<td>双 token 轮转 + Refresh Token Rotation</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td><b>配置</b></td>
|
|
|
|
|
|
<td>Viper + godotenv</td>
|
|
|
|
|
|
<td>YAML + .env + 环境变量覆盖</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td><b>日志</b></td>
|
|
|
|
|
|
<td>Zap</td>
|
|
|
|
|
|
<td>高性能结构化日志 + Trace ID 追踪</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
|
|
## 📁 项目结构
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
CamTalk/
|
2026-06-22 14:35:53 +08:00
|
|
|
|
├── frontend/ # 🌐 浏览器客户端
|
2026-06-14 09:15:05 +08:00
|
|
|
|
│ └── src/
|
|
|
|
|
|
│ ├── components/ # UI 组件
|
2026-06-20 20:17:16 +08:00
|
|
|
|
│ │ ├── LandingPage/ # 登录着陆页 + LoginModal
|
2026-06-14 09:15:05 +08:00
|
|
|
|
│ │ ├── CameraManager/ # 摄像头流采集
|
2026-06-22 14:35:53 +08:00
|
|
|
|
│ │ ├── MicManager/ # 麦克风音频采集 + VAD
|
|
|
|
|
|
│ │ ├── WebSocketManager/ # WS 连接生命周期
|
|
|
|
|
|
│ │ ├── ChatPanel/ # 消息展示 + 流式回复
|
2026-06-20 20:17:16 +08:00
|
|
|
|
│ │ ├── SessionSidebar/ # 对话历史侧边栏
|
2026-06-22 14:35:53 +08:00
|
|
|
|
│ │ └── ConfigPanel/ # 配置面板(主题/TTS/语言/场景)
|
2026-06-14 09:15:05 +08:00
|
|
|
|
│ ├── hooks/ # 自定义 Hooks
|
2026-06-22 14:35:53 +08:00
|
|
|
|
│ │ ├── useVisionSession.ts # 核心会话 Hook (~500 行)
|
2026-06-20 20:17:16 +08:00
|
|
|
|
│ │ ├── useSessionList.ts # 对话列表管理
|
2026-06-14 09:15:05 +08:00
|
|
|
|
│ │ └── useObservationMode.ts # 观察模式
|
|
|
|
|
|
│ ├── lib/ # 工具库
|
2026-06-22 14:35:53 +08:00
|
|
|
|
│ │ ├── websocket.ts # WebSocket 单例(心跳/重连/订阅)
|
|
|
|
|
|
│ │ ├── api.ts # REST 客户端(401拦截+刷新)
|
|
|
|
|
|
│ │ ├── auth.tsx # AuthProvider(JWT 自动刷新)
|
|
|
|
|
|
│ │ ├── ttsPlayer.ts # TTS 流式播放队列
|
|
|
|
|
|
│ │ └── i18n/ # 国际化(zh-CN/en-US/ja-JP)
|
2026-06-14 09:15:05 +08:00
|
|
|
|
│ └── types/ # TypeScript 类型定义
|
2026-06-22 14:35:53 +08:00
|
|
|
|
├── backend/ # ⚙️ Go 网关
|
|
|
|
|
|
│ ├── cmd/server/ # 服务入口(main.go)
|
2026-06-14 09:15:05 +08:00
|
|
|
|
│ └── internal/
|
2026-06-22 14:35:53 +08:00
|
|
|
|
│ ├── eino/ # 🔥 Eino Graph 编排层(7节点DAG)
|
|
|
|
|
|
│ │ ├── graph.go # Graph 构建与编译
|
|
|
|
|
|
│ │ ├── adapter.go # EinoOrchestrator 适配器
|
|
|
|
|
|
│ │ ├── callback.go # LLM token 推送回调
|
|
|
|
|
|
│ │ ├── state.go # 跨节点状态管理
|
|
|
|
|
|
│ │ └── nodes_*.go # STT/History/Splitter/TTS/Done 节点
|
|
|
|
|
|
│ ├── session/ # 会话管理(TieredManager 三级存储)
|
|
|
|
|
|
│ ├── store/ # 持久化层(Repository 接口 + PG/内存实现)
|
|
|
|
|
|
│ │ ├── user_pg.go # PostgreSQL 实现
|
|
|
|
|
|
│ │ └── cached_user.go # Redis 缓存装饰器
|
|
|
|
|
|
│ ├── auth/ # 认证(JWT/bcrypt/中间件)
|
2026-06-14 09:15:05 +08:00
|
|
|
|
│ ├── ai/ # AI 服务抽象层
|
2026-06-20 20:17:16 +08:00
|
|
|
|
│ │ ├── llm/ # LLM 提示词与场景
|
|
|
|
|
|
│ │ ├── stt/ # STT 服务(MiMo/Deepgram)
|
|
|
|
|
|
│ │ └── tts/ # TTS 服务(MiMo/OpenAI)
|
2026-06-14 09:15:05 +08:00
|
|
|
|
│ ├── ws/ # WebSocket Handler
|
2026-06-20 20:17:16 +08:00
|
|
|
|
│ ├── api/ # REST API(Auth/Conversation)
|
2026-06-22 14:35:53 +08:00
|
|
|
|
│ ├── config/ # 配置管理(Viper)
|
|
|
|
|
|
│ └── logger/ # 日志(Zap + Trace ID)
|
|
|
|
|
|
├── migrations/ # 📊 数据库迁移(嵌入式 SQL)
|
|
|
|
|
|
├── docs/ # 📚 设计文档
|
|
|
|
|
|
│ ├── 01-架构设计.md
|
|
|
|
|
|
│ ├── 02-接口文档.md
|
|
|
|
|
|
│ ├── 08-Eino框架与编排设计.md
|
|
|
|
|
|
│ ├── 10-鉴权体系.md
|
|
|
|
|
|
│ └── 13-日志追踪.md
|
|
|
|
|
|
├── deploy.sh # 🐳 部署脚本(Docker Compose)
|
|
|
|
|
|
├── docker-compose.yml # 容器编排配置
|
|
|
|
|
|
└── CLAUDE.md # 🤖 Claude Code 开发指引
|
2026-06-14 09:15:05 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
## 🚀 快速开始
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
|
|
|
|
|
### 前置条件
|
|
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
- **Node.js** >= 18
|
|
|
|
|
|
- **Go** >= 1.25
|
|
|
|
|
|
- **PostgreSQL** >= 15(可选 Docker)
|
|
|
|
|
|
- **Redis** >= 7(可选,用于缓存加速)
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
### 1. 克隆项目
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-06-22 14:35:53 +08:00
|
|
|
|
git clone https://github.com/yourusername/CamTalk.git
|
|
|
|
|
|
cd CamTalk
|
2026-06-14 09:15:05 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
### 2. 配置环境变量
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 复制环境变量模板
|
|
|
|
|
|
cp backend/.env.example backend/.env
|
|
|
|
|
|
|
|
|
|
|
|
# 编辑 .env 文件,填入以下必需配置:
|
|
|
|
|
|
# - CAMTALK_AUTH_JWT_SECRET(使用 openssl rand -hex 32 生成)
|
|
|
|
|
|
# - CAMTALK_STORAGE_DSN(PostgreSQL 连接字符串)
|
|
|
|
|
|
# - CAMTALK_AI_LLM_API_KEY(DashScope API Key)
|
|
|
|
|
|
# - CAMTALK_AI_STT_API_KEY(MiMo/Deepgram API Key)
|
|
|
|
|
|
# - CAMTALK_AI_TTS_API_KEY(MiMo/OpenAI API Key)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 启动后端
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd backend
|
2026-06-22 14:35:53 +08:00
|
|
|
|
|
|
|
|
|
|
# 安装依赖
|
2026-06-14 09:15:05 +08:00
|
|
|
|
go mod download
|
2026-06-22 14:35:53 +08:00
|
|
|
|
|
|
|
|
|
|
# 运行数据库迁移(自动创建表)
|
|
|
|
|
|
go run ./cmd/server migrate
|
|
|
|
|
|
|
|
|
|
|
|
# 启动服务(监听 :8080)
|
|
|
|
|
|
go run ./cmd/server
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 启动前端
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
cd frontend
|
|
|
|
|
|
|
|
|
|
|
|
# 安装依赖
|
|
|
|
|
|
npm install
|
|
|
|
|
|
|
|
|
|
|
|
# 启动开发服务器(http://localhost:5173)
|
|
|
|
|
|
npm run dev
|
2026-06-14 09:15:05 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
### 5. 访问应用
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
打开浏览器访问 [http://localhost:5173](http://localhost:5173),注册账号后即可开始使用。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 🐳 Docker 快速部署(生产环境)
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-06-22 14:35:53 +08:00
|
|
|
|
# 一键启动全部服务(frontend + backend + postgres + redis)
|
|
|
|
|
|
./deploy.sh up
|
|
|
|
|
|
|
|
|
|
|
|
# 停止服务
|
|
|
|
|
|
./deploy.sh down
|
|
|
|
|
|
|
|
|
|
|
|
# 查看日志
|
|
|
|
|
|
./deploy.sh logs
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
部署完成后访问 [http://localhost:9000](http://localhost:9000)
|
|
|
|
|
|
|
|
|
|
|
|
### 配置优先级
|
|
|
|
|
|
|
2026-06-14 09:15:05 +08:00
|
|
|
|
```
|
2026-06-22 14:35:53 +08:00
|
|
|
|
环境变量 > config.{APP_ENV}.yaml > config.yaml > .env
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
通过 `APP_ENV=prod` 切换生产环境配置(启用限流 + 严格 CORS)
|
|
|
|
|
|
|
|
|
|
|
|
## 📡 WebSocket 协议
|
|
|
|
|
|
|
|
|
|
|
|
连接地址:`ws://localhost:8080/ws?token=<jwt>&conversation_id=<uuid>`
|
|
|
|
|
|
|
|
|
|
|
|
所有消息为 JSON 文本帧,统一信封格式:
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
interface BaseMessage {
|
|
|
|
|
|
type: string;
|
|
|
|
|
|
request_id?: string;
|
|
|
|
|
|
timestamp?: number;
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 客户端 → 服务端
|
|
|
|
|
|
|
|
|
|
|
|
| 消息类型 | 说明 | 示例 |
|
|
|
|
|
|
|---------|------|------|
|
|
|
|
|
|
| `query` | 发送视觉+语音查询 | `{type: "query", image: "base64...", audio: "base64..."}` |
|
|
|
|
|
|
| `config` | 更新会话配置 | `{type: "config", scenario: "interviewer", language: "en"}` |
|
|
|
|
|
|
| `interrupt` | 中断当前响应 | `{type: "interrupt", request_id: "xxx"}` |
|
|
|
|
|
|
| `ping` | 心跳保活 | `{type: "ping"}` |
|
|
|
|
|
|
|
|
|
|
|
|
### 服务端 → 客户端
|
|
|
|
|
|
|
|
|
|
|
|
| 消息类型 | 说明 | 触发时机 |
|
|
|
|
|
|
|---------|------|---------|
|
|
|
|
|
|
| `connected` | 连接成功 | WebSocket 握手后 |
|
|
|
|
|
|
| `stt_result` | STT 识别结果 | STT 节点完成 |
|
|
|
|
|
|
| `llm_chunk` | LLM 文本增量 | ChatModel 逐 token(Callback) |
|
|
|
|
|
|
| `llm_done` | LLM 推理完成 | Done 节点执行 |
|
|
|
|
|
|
| `tts_audio` | TTS 音频片段 | TTS 节点逐句合成 |
|
|
|
|
|
|
| `error` | 错误通知 | 任意节点失败 |
|
|
|
|
|
|
| `pong` | 心跳响应 | 响应 `ping` |
|
|
|
|
|
|
|
|
|
|
|
|
**心跳机制**:
|
|
|
|
|
|
- 客户端每 30 秒发送 `ping`
|
|
|
|
|
|
- 服务端 60 秒无消息自动断连
|
|
|
|
|
|
- 断连后自动重连(指数退避 1s → 30s)
|
|
|
|
|
|
|
|
|
|
|
|
完整协议定义见 [docs/02-接口文档.md](docs/02-接口文档.md)
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
## 🔐 认证体系
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
CamTalk 采用 **JWT 双 token 轮转 + Refresh Token Rotation** 安全机制:
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
### 双 Token 设计
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
| Token | 有效期 | 存储位置 | 用途 |
|
|
|
|
|
|
|-------|-------|---------|------|
|
|
|
|
|
|
| `access_token` | 120 分钟 | 前端内存(推荐)/ localStorage | 访问受保护资源 |
|
|
|
|
|
|
| `refresh_token` | 7 天 | httpOnly Cookie(推荐)/ localStorage | 刷新 access_token |
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
### Refresh Token Rotation
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
每次刷新 token 时:
|
|
|
|
|
|
1. 验证 `refresh_token` 签名和有效期
|
|
|
|
|
|
2. 查询数据库中的 SHA256 哈希
|
|
|
|
|
|
3. **如果哈希不存在** → 检测到 token 复用 → **吊销该用户所有 token**
|
|
|
|
|
|
4. 删除旧 refresh_token,生成新 token pair
|
|
|
|
|
|
5. 返回新 access_token + refresh_token
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
**防重放攻击**:旧 refresh_token 立即失效,复用时触发全局吊销,强制所有设备重新登录。
|
|
|
|
|
|
|
|
|
|
|
|
### REST API 端点
|
|
|
|
|
|
|
|
|
|
|
|
- `POST /api/auth/register` — 用户注册
|
|
|
|
|
|
- `POST /api/auth/login` — 用户登录
|
|
|
|
|
|
- `POST /api/auth/refresh` — 刷新 token
|
|
|
|
|
|
- `POST /api/auth/logout` — 登出(需认证)
|
|
|
|
|
|
- `GET /api/conversations` — 获取对话列表(需认证)
|
|
|
|
|
|
- `POST /api/conversations` — 创建对话(需认证)
|
|
|
|
|
|
- `GET /api/health` — 健康检查
|
|
|
|
|
|
|
|
|
|
|
|
详细设计见 [docs/10-鉴权体系.md](docs/10-鉴权体系.md)
|
|
|
|
|
|
|
|
|
|
|
|
## 💾 三级存储架构
|
|
|
|
|
|
|
|
|
|
|
|
**TieredManager** 实现会话状态的三级存储,平衡性能与可靠性:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─────────────┐
|
|
|
|
|
|
│ L1 Memory │ ← 微秒级读写,进程内缓存
|
|
|
|
|
|
├─────────────┤
|
|
|
|
|
|
│ L2 Redis │ ← 毫秒级访问,跨实例共享
|
|
|
|
|
|
├─────────────┤
|
|
|
|
|
|
│ L3 PostgreSQL│ ← 持久化存储,数据可靠性
|
|
|
|
|
|
└─────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**特性**:
|
|
|
|
|
|
- ✅ **自动降级**:Redis 故障时自动切换到 Memory + PostgreSQL 模式
|
|
|
|
|
|
- ✅ **灵活配置**:支持单级(Memory)、双级(Memory + PG)、完整三级
|
|
|
|
|
|
- ✅ **TTL 管理**:会话默认 30 分钟过期,自动清理
|
|
|
|
|
|
- ✅ **写穿透**:数据先写 L1,异步同步到 L2/L3
|
|
|
|
|
|
|
|
|
|
|
|
## 📊 数据库设计
|
|
|
|
|
|
|
|
|
|
|
|
系统使用 PostgreSQL 存储持久化数据:
|
|
|
|
|
|
|
|
|
|
|
|
### 核心表
|
|
|
|
|
|
|
|
|
|
|
|
| 表名 | 说明 | 关键字段 |
|
|
|
|
|
|
|------|------|---------|
|
|
|
|
|
|
| `users` | 用户账户 | `id (UUID)`, `username (UNIQUE)`, `password_hash (bcrypt)` |
|
|
|
|
|
|
| `sessions` | 对话会话 | `id (UUID)`, `user_id (FK)`, `title`, `config (JSONB)` |
|
|
|
|
|
|
| `messages` | 消息记录 | `id (BIGSERIAL)`, `session_id (FK)`, `role`, `content`, `tokens_used` |
|
|
|
|
|
|
| `refresh_tokens` | 刷新令牌 | `token_hash (PK, SHA256)`, `user_id (FK)`, `expires_at` |
|
|
|
|
|
|
|
|
|
|
|
|
**关系**:`users 1:N sessions 1:N messages`,`users 1:N refresh_tokens`
|
|
|
|
|
|
|
|
|
|
|
|
**迁移管理**:使用嵌入式 SQL 文件(`backend/migrations/`),应用启动时自动执行。
|
|
|
|
|
|
|
|
|
|
|
|
## 🛡️ 安全特性
|
|
|
|
|
|
|
|
|
|
|
|
- 🔒 **密码安全**:bcrypt (cost=10) 哈希,自动生成盐值
|
|
|
|
|
|
- 🔑 **Token 安全**:JWT HS256 签名,refresh_token SHA256 哈希存储
|
|
|
|
|
|
- 🚫 **防重放攻击**:Refresh Token Rotation + 复用检测自动吊销
|
|
|
|
|
|
- 🌐 **传输安全**:生产环境强制 HTTPS,开发环境 Vite proxy 同源代理
|
|
|
|
|
|
- 🚦 **限流保护**:令牌桶算法(生产环境启用),防暴力破解
|
|
|
|
|
|
- 🔍 **日志追踪**:全链路 Trace ID,请求/响应/错误统一记录
|
|
|
|
|
|
|
|
|
|
|
|
## 🌍 部署架构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─────────────┐
|
|
|
|
|
|
│ Nginx │ ← 反向代理(静态资源 + API + WebSocket)
|
|
|
|
|
|
└──────┬──────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
┌──────┴───────────────────┐
|
|
|
|
|
|
│ Go Gateway 集群 │
|
|
|
|
|
|
│ ├─ Gateway-1 │
|
|
|
|
|
|
│ ├─ Gateway-2 │
|
|
|
|
|
|
│ └─ Gateway-N │
|
|
|
|
|
|
└───┬────────────┬─────────┘
|
|
|
|
|
|
│ │
|
|
|
|
|
|
┌───┴────┐ ┌───┴────────┐
|
|
|
|
|
|
│ Redis │ │ PostgreSQL │
|
|
|
|
|
|
└────────┘ └────────────┘
|
|
|
|
|
|
│
|
|
|
|
|
|
┌───┴────────────────────┐
|
|
|
|
|
|
│ 外部 AI 服务 │
|
|
|
|
|
|
│ ├─ DashScope (LLM) │
|
|
|
|
|
|
│ ├─ MiMo (STT/TTS) │
|
|
|
|
|
|
│ └─ Deepgram (可选) │
|
|
|
|
|
|
└───────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**跨域策略**:Nginx 统一反代前后端到同一域名,无跨域问题。
|
|
|
|
|
|
|
|
|
|
|
|
**水平扩展**:Gateway 无状态设计,会话状态存储在 Redis/PostgreSQL,支持多实例部署。
|
|
|
|
|
|
|
|
|
|
|
|
## 📖 文档
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| [01-架构设计](docs/01-架构设计.md) | 三层架构、技术栈、数据库设计、部署方案 |
|
|
|
|
|
|
| [02-接口文档](docs/02-接口文档.md) | WebSocket 协议、REST API、AI 服务层、编排器、配置管理 |
|
|
|
|
|
|
## 📖 文档
|
|
|
|
|
|
|
|
|
|
|
|
### 核心设计文档
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
|
|
|
|
|
| 文档 | 内容 |
|
|
|
|
|
|
|------|------|
|
2026-06-20 20:17:16 +08:00
|
|
|
|
| [01-架构设计](docs/01-架构设计.md) | 三层架构、技术栈、数据库设计、部署方案 |
|
|
|
|
|
|
| [02-接口文档](docs/02-接口文档.md) | WebSocket 协议、REST API、AI 服务层、编排器、配置管理 |
|
2026-06-22 14:35:53 +08:00
|
|
|
|
| [08-Eino框架与编排设计](docs/08-Eino框架与编排设计.md) | Eino Graph 7 节点 DAG、节点实现、流式处理、Callback AOP |
|
|
|
|
|
|
| [10-鉴权体系](docs/10-鉴权体系.md) | JWT 双 token 轮转、Refresh Token Rotation、密码安全、中间件 |
|
|
|
|
|
|
| [11-令牌桶限流](docs/11-令牌桶限流.md) | 限流算法、配置策略、生产环境保护 |
|
|
|
|
|
|
| [13-日志追踪](docs/13-日志追踪.md) | Zap 日志、Trace ID 全链路追踪、日志级别 |
|
|
|
|
|
|
|
|
|
|
|
|
### 功能文档
|
|
|
|
|
|
|
|
|
|
|
|
| 文档 | 内容 |
|
|
|
|
|
|
|------|------|
|
2026-06-20 20:17:16 +08:00
|
|
|
|
| [03-技术选型](docs/03-技术选型.md) | AI 服务栈、持久化层、前端边缘处理选型 |
|
|
|
|
|
|
| [04-用户故事](docs/04-用户故事.md) | 用户场景与优先级 |
|
|
|
|
|
|
| [05-语音交互](docs/05-语音交互.md) | VAD → STT → LLM → TTS 全链路 |
|
|
|
|
|
|
| [06-视觉理解](docs/06-视觉理解.md) | 帧采样、关键帧检测、多模态输入 |
|
|
|
|
|
|
| [07-成本控制](docs/07-成本控制.md) | 采样策略、端云协同、模型分级 |
|
2026-06-22 14:35:53 +08:00
|
|
|
|
| [09-情景切换](docs/09-情景切换.md) | 情景模式设计与实现 |
|
|
|
|
|
|
| [12-自定义情景](docs/12-自定义情景.md) | 用户自定义情景功能(规划中) |
|
|
|
|
|
|
|
|
|
|
|
|
## 🤝 贡献指南
|
|
|
|
|
|
|
|
|
|
|
|
欢迎提交 Issue 和 Pull Request!
|
|
|
|
|
|
|
|
|
|
|
|
### 开发规范
|
|
|
|
|
|
|
|
|
|
|
|
- **提交信息**:遵循 [Conventional Commits](https://www.conventionalcommits.org/),中文描述(例:`feat: 添加 WebSocket 心跳`)
|
|
|
|
|
|
- **Go 代码**:遵循标准 Go 规范,使用 `golangci-lint` 检查
|
|
|
|
|
|
- **TypeScript 代码**:严格模式,使用 ESLint + Prettier
|
|
|
|
|
|
- **文档优先**:开发前先读 `docs/` 设计文档,代码与文档不一致时优先更新文档
|
|
|
|
|
|
|
|
|
|
|
|
### 本地开发环境
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
# 安装开发工具
|
|
|
|
|
|
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
|
|
|
|
|
|
|
|
|
|
|
|
# 运行代码检查
|
|
|
|
|
|
cd backend
|
|
|
|
|
|
golangci-lint run
|
|
|
|
|
|
|
|
|
|
|
|
# 运行测试
|
|
|
|
|
|
go test ./...
|
|
|
|
|
|
|
|
|
|
|
|
# 前端测试
|
|
|
|
|
|
cd frontend
|
|
|
|
|
|
npm test
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 🐛 问题反馈
|
|
|
|
|
|
|
|
|
|
|
|
遇到问题?请提交 [Issue](https://github.com/yourusername/CamTalk/issues),并提供以下信息:
|
|
|
|
|
|
|
|
|
|
|
|
- 操作系统版本
|
|
|
|
|
|
- Go / Node.js 版本
|
|
|
|
|
|
- 错误日志(后端日志 + 浏览器控制台)
|
|
|
|
|
|
- 复现步骤
|
|
|
|
|
|
|
|
|
|
|
|
## 📝 版权声明
|
|
|
|
|
|
|
|
|
|
|
|
MIT License © 2024 XEngineers
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
<div align="center">
|
|
|
|
|
|
|
|
|
|
|
|
**Built with ❤️ using Go, React, and AI**
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
[⬆️ 回到顶部](#camtalk)
|
2026-06-14 09:15:05 +08:00
|
|
|
|
|
2026-06-22 14:35:53 +08:00
|
|
|
|
</div>
|