7.6 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
CamTalk — 多模态实时 AI 视觉对话助手(摄像头 + 麦克风 + 视觉 + 语音 AI)
文档优先原则: 开发前先读
docs/设计文档,以文档为准;若代码与文档不一致,优先更新文档(尤其接口文档)。详细设计见docs/01-13系列文档。注意:docs/Eino/框架文档内容庞大(~75 个文件),仅在需要了解 Eino Graph/节点/Callback 等框架细节时才读取。
常用命令
# === 前端(frontend/ 目录)===
npm run dev # Vite 开发服务器(http://localhost:5173,代理 /ws 和 /api 到 :8080)
npm run build # 生产构建(tsc -b && vite build,输出到 dist/)
npm run lint # ESLint 代码检查
npm run preview # 预览生产构建
# === 后端(backend/ 目录)===
go run ./cmd/server # 启动服务(监听 :8080,启动时自动执行数据库迁移)
golangci-lint run # Go 代码检查
# 后端测试
go test ./... # 单元测试
go test -tags=integration ./... # 集成测试(需要 PostgreSQL)
go test -v -run TestXxx ./path/ # 运行单个测试
# === Docker 部署 ===
./deploy.sh build # 构建 Docker 镜像
./deploy.sh up # 启动服务(4 容器:frontend/backend/postgres/redis)
./deploy.sh down # 停止服务
./deploy.sh logs # 查看日志(可加服务名:./deploy.sh logs backend)
./deploy.sh status # 查看服务状态
架构
三层系统:前端(React + Vite)→ Go 网关(Gin + WebSocket + Eino Graph AI 编排)→ AI 服务(DashScope LLM, MiMo STT/TTS)
AI 编排流水线(Eino Graph 7 节点 DAG):STT → History → ChatModel → Msg2Str → Splitter → TTS → Done。LLM token 通过 Callback 实时推送,TTS 逐句并行合成。
会话存储(TieredManager):L1 Memory → L2 Redis → L3 PostgreSQL 三级存储,30 分钟 TTL,Redis 故障自动降级。
鉴权:JWT 双 token 轮转(Access 120min + Refresh 7d),重放攻击检测(DB hash 校验),Redis 缓存装饰器。
技术栈
前端:React 18 + TypeScript + Vite,VAD(@ricky0123/vad-web),ONNX Runtime,国际化(zh-CN / en-US / ja-JP)
后端: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
CI/CD:Gitea Actions(.gitea/workflows/deploy.yml),push main/v2 自动构建部署到自建 aliyun runner
前端测试:暂无(package.json 无 test 脚本,无测试框架配置)
配置体系
配置优先级:环境变量 > config.{APP_ENV}.yaml > config.yaml > 代码默认值
配置文件位于 backend/config/:
config.yaml— 基础配置(dev 默认值)config.dev.yaml— 开发环境覆盖(可选)config.prod.yaml— 生产环境覆盖(可选)
环境切换:APP_ENV=dev|prod(dev 默认,prod 启用限流 + 严格 CORS + Release 模式)
敏感信息(API Key、JWT Secret、数据库密码)只能通过环境变量或 .env 文件注入,不写入 YAML 配置文件。核心环境变量(参考 backend/.env.example):
| 变量 | 说明 |
|---|---|
CAMTALK_AI_LLM_API_KEY |
LLM API Key(DashScope) |
CAMTALK_AI_STT_API_KEY |
STT API Key(MiMo/Deepgram) |
CAMTALK_AI_TTS_API_KEY |
TTS API Key(MiMo/OpenAI) |
CAMTALK_AUTH_JWT_SECRET |
JWT 签名密钥 |
CAMTALK_STORAGE_DSN |
PostgreSQL 连接字符串 |
CAMTALK_REDIS_ADDR |
Redis 地址 |
CAMTALK_REDIS_PASSWORD |
Redis 密码 |
数据库迁移
迁移 SQL 文件位于 backend/migrations/(001_*.up.sql 等),通过 Go //go:embed 嵌入二进制(见 backend/migrations/embed.go)。应用启动时自动执行未应用的迁移,无需手动运行迁移命令。迁移通过 schema_migrations 表追踪执行状态。
回滚脚本为同目录下的 *.down.sql 文件,需手动执行。
协议与 API
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),订阅模式,自动重连 - WebSocket 地址自动从当前页面协议/主机推导,也可通过
VITE_WS_URL环境变量显式指定(如wss://api.example.com/ws)
REST API:/api/auth/*(注册/登录/刷新/登出),/api/conversations/*(CRUD + 消息分页),/api/scenarios/*(用户自定义情景 CRUD),/api/health
错误码:INVALID_MESSAGE, SESSION_NOT_FOUND, RATE_LIMITED, IMAGE_TOO_LARGE, LLM_TIMEOUT, STT/TTS/LLM_ERROR, INVALID_TOKEN 等
关键文件路径
后端核心:
backend/cmd/server/main.go— 入口,依赖注入与启动流程(存储→AI 服务→Graph→路由→Server)backend/internal/eino/— Eino Graph 编排层(graph.go 构建、adapter.go 适配、callback.go 推送、state.go 状态、nodes_*.go 各节点实现)backend/internal/session/tiered.go— 三级会话存储(TieredManager)backend/internal/store/— 持久化层(Repository 接口 + PG 实现 + Redis 缓存装饰器)- Repository 模式:接口定义在
user.go/session.go/message.go,PG 实现在*_pg.go,Redis 缓存装饰器在cached_user.go
- Repository 模式:接口定义在
backend/internal/ws/handler.go— WebSocket 连接管理(升级→认证→收发循环→清理)backend/internal/ai/— AI 服务抽象层(llm/stt/tts 各子目录,统一Service接口)backend/internal/auth/— JWT/bcrypt/中间件backend/internal/ratelimit/— 令牌桶限流(内存/Redis 两种后端)backend/migrations/— 嵌入式 SQL 迁移文件(embed.go + *.sql)
前端核心:
frontend/src/hooks/useVisionSession.ts— 核心会话 Hook(~500 行,编排整个采集→发送→接收→播放流程)frontend/src/lib/websocket.ts— WebSocket 客户端单例(心跳/重连/订阅模式)frontend/src/lib/auth.tsx— AuthProvider(JWT 自动刷新 + React Context)frontend/src/lib/api.ts— REST 客户端(401 拦截 + token 刷新)frontend/src/lib/ttsPlayer.ts— 流式 TTS 音频播放队列frontend/src/lib/i18n/— 国际化(zh-CN / en-US / ja-JP)frontend/src/components/— UI 组件(LandingPage/CameraManager/MicManager/WebSocketManager/ChatPanel/SessionSidebar/ConfigPanel/VideoPreview 等)frontend/vite.config.ts— VAD 模型文件自动复制 + ONNX WASM MIME 处理 + 代理配置
编码规范
- Go:标准规范,
context.Context超时控制,sync.RWMutex并发保护,json:"snake_case"标签,编译期接口检查var _ Interface = (*Impl)(nil) - TypeScript:严格模式,接口定义数据模型,WebSocket 消息用可辨识联合类型(
type字段区分) - 存储层模式:Repository 接口 + PostgreSQL 实现 + Redis 缓存装饰器(
CachedUserRepository包装模式) - CORS:禁止后端代码/配置文件配置 CORS,统一由代理层处理(开发环境 Vite proxy,生产环境 Nginx)
- 提交信息:Conventional Commits,中文描述(如
feat: 添加 WebSocket 心跳) - 禁止自动 push:除非用户明确要求
- 文档优先:开发前先读
docs/设计文档,代码与文档不一致时优先更新文档