2026-06-12 16:49:01 +08:00
|
|
|
|
# CLAUDE.md
|
|
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
CamTalk — 多模态实时 AI 视觉对话助手(摄像头 + 麦克风 + 视觉 + 语音 AI)
|
2026-06-12 16:49:01 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
> **文档优先原则:** 开发前先读 `docs/` 设计文档,以文档为准;若代码与文档不一致,优先更新文档(尤其接口文档)。详细设计见 `docs/01-13` 系列文档。**注意**:`docs/Eino/` 框架文档内容庞大(~75 个文件),仅在需要了解 Eino Graph/节点/Callback 等框架细节时才读取。
|
2026-06-12 16:51:28 +08:00
|
|
|
|
|
2026-06-12 17:08:20 +08:00
|
|
|
|
## 架构
|
2026-06-12 16:49:01 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
三层系统:前端(React + Vite)→ Go 网关(Gin + WebSocket + Eino Graph AI 编排)→ AI 服务(DashScope LLM, MiMo STT/TTS)
|
2026-06-12 16:49:01 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
**AI 编排流水线**(Eino Graph 7 节点 DAG):`STT → History → ChatModel → Msg2Str → Splitter → TTS → Done`。LLM token 通过 Callback 实时推送,TTS 逐句并行合成。
|
2026-06-21 00:00:24 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
**会话存储**(TieredManager):L1 Memory → L2 Redis → L3 PostgreSQL 三级存储,30 分钟 TTL,Redis 故障自动降级。
|
2026-06-21 00:00:24 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
**鉴权**:JWT 双 token 轮转(Access 120min + Refresh 7d),重放攻击检测(DB hash 校验),Redis 缓存装饰器。
|
2026-06-12 16:49:01 +08:00
|
|
|
|
|
2026-06-12 17:08:20 +08:00
|
|
|
|
## 技术栈
|
2026-06-12 16:49:01 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
前端:React 18 + TypeScript + Vite,VAD(@ricky0123/vad-web),ONNX Runtime
|
|
|
|
|
|
后端:Go 1.25+, Gin, WebSocket, Viper, Zap, CloudWeGo Eino Graph
|
|
|
|
|
|
AI:DashScope qwen3-vl-plus, MiMo ASR/TTS(可切换 Deepgram/OpenAI TTS)
|
|
|
|
|
|
存储:PostgreSQL 15 + Redis 7
|
2026-06-21 00:00:24 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
## 快速启动
|
2026-06-21 00:00:24 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-06-21 14:48:03 +08:00
|
|
|
|
# 前端:npm run dev(Vite,代理 /ws 和 /api 到 :8080)
|
|
|
|
|
|
# 后端:go run ./cmd/server(监听 :8080)
|
|
|
|
|
|
# 生产:./deploy.sh up(4 容器:frontend/backend/postgres/redis)
|
2026-06-12 16:49:01 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
核心环境变量(`.env.example`):`CAMTALK_AI_LLM_API_KEY`, `CAMTALK_AI_STT_API_KEY`, `CAMTALK_AUTH_JWT_SECRET`, `CAMTALK_STORAGE_DSN`
|
2026-06-12 16:49:01 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
配置优先级:环境变量 > `config.{APP_ENV}.yaml` > `config.yaml`
|
|
|
|
|
|
环境切换:`APP_ENV=dev|prod`(dev 默认,prod 启用限流 + 严格 CORS)
|
2026-06-21 00:00:24 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
## 协议与 API
|
2026-06-21 00:00:24 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
**WebSocket**:`ws://localhost:8080/ws?token=<jwt>&conversation_id=<uuid>`
|
|
|
|
|
|
- 客户端:`query`(图像/音频 Base64), `config`, `interrupt`, `ping`
|
|
|
|
|
|
- 服务端:`connected`, `stt_result`, `llm_chunk`, `llm_done`, `tts_audio`, `error`, `pong`
|
|
|
|
|
|
- 心跳:客户端 30s ping,服务端 60s 超时断连;重连:指数退避 1s→30s
|
|
|
|
|
|
- 实现:`CamTalkWebSocket` 单例(`frontend/src/lib/websocket.ts`),订阅模式,自动重连
|
2026-06-20 13:24:53 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
**REST API**:`/api/auth/*`(注册/登录/刷新/登出),`/api/conversations/*`(CRUD + 消息分页),`/api/health`
|
2026-06-21 00:00:24 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
**错误码**:`INVALID_MESSAGE`, `SESSION_NOT_FOUND`, `RATE_LIMITED`, `IMAGE_TOO_LARGE`, `LLM_TIMEOUT`, `STT/TTS/LLM_ERROR`, `INVALID_TOKEN`, 等
|
2026-06-12 16:49:01 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
## 关键文件路径
|
2026-06-12 16:49:01 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
**后端核心**:
|
|
|
|
|
|
- `backend/internal/eino/` — Graph 定义、节点、Callback、Adapter、State
|
|
|
|
|
|
- `backend/internal/session/tiered.go` — 三级会话存储
|
|
|
|
|
|
- `backend/internal/store/` — Repository 实现(PG + 内存 + Redis 缓存)
|
|
|
|
|
|
- `backend/internal/ws/handler.go` — WebSocket 连接管理
|
|
|
|
|
|
- `backend/migrations/` — SQL 迁移文件
|
2026-06-21 00:00:24 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
**前端核心**:
|
|
|
|
|
|
- `frontend/src/hooks/useVisionSession.ts` — 核心会话 Hook(~500 行)
|
|
|
|
|
|
- `frontend/src/lib/websocket.ts` — WebSocket 客户端单例
|
|
|
|
|
|
- `frontend/src/lib/auth.tsx` — JWT 自动刷新 + AuthProvider
|
|
|
|
|
|
- `frontend/src/lib/api.ts` — REST 客户端(401 拦截 + token 刷新)
|
|
|
|
|
|
- `frontend/src/lib/ttsPlayer.ts` — 流式 TTS 音频播放队列
|
|
|
|
|
|
- `frontend/vite.config.ts` — VAD 模型文件自动复制 + 代理配置
|
2026-06-12 16:49:01 +08:00
|
|
|
|
|
2026-06-12 17:08:20 +08:00
|
|
|
|
## 编码规范
|
2026-06-12 16:49:01 +08:00
|
|
|
|
|
2026-06-21 14:48:03 +08:00
|
|
|
|
- **Go**:标准规范,`context.Context` 超时控制,`sync.RWMutex` 并发保护,`json:"snake_case"` 标签,编译期接口检查 `var _ Interface = (*Impl)(nil)`
|
|
|
|
|
|
- **TypeScript**:严格模式,接口定义数据模型,WebSocket 消息用可辨识联合类型(`type` 字段区分)
|
|
|
|
|
|
- **CORS**:禁止后端代码/配置文件配置 CORS,统一由代理层处理(开发环境 Vite proxy,生产环境 Nginx)
|
|
|
|
|
|
- **提交信息**:Conventional Commits,中文描述(如 `feat: 添加 WebSocket 心跳`)
|
|
|
|
|
|
- **禁止自动 push**:除非用户明确要求
|
|
|
|
|
|
- **文档优先**:开发前先读 `docs/` 设计文档,代码与文档不一致时优先更新文档
|