fix: CI/CD 部署固定到 /root/camtalk 目录,确保 compose 能正确管理容器生命周期
This commit is contained in:
@@ -14,8 +14,13 @@ jobs:
|
||||
- name: Install Docker CLI
|
||||
run: apk add --no-cache docker-cli docker-cli-compose
|
||||
|
||||
- name: Sync to deploy directory
|
||||
run: |
|
||||
mkdir -p /root/camtalk
|
||||
rsync -a --delete --exclude='.env' --exclude='pgdata' --exclude='redisdata' ./ /root/camtalk/
|
||||
|
||||
- name: Build and Deploy
|
||||
run: |
|
||||
chmod +x deploy.sh
|
||||
./deploy.sh build
|
||||
./deploy.sh restart
|
||||
chmod +x /root/camtalk/deploy.sh
|
||||
/root/camtalk/deploy.sh build
|
||||
/root/camtalk/deploy.sh restart
|
||||
|
||||
116
CamTalk-演讲稿.md
116
CamTalk-演讲稿.md
@@ -1,116 +0,0 @@
|
||||
## CamTalk — 多模态实时 AI 视觉对话助手 · 演讲稿
|
||||
|
||||
> 面向面试官,预计 10-15 分钟。建议配合架构图或项目文档做演示。
|
||||
|
||||
---
|
||||
|
||||
### 开场(约 1 分钟)
|
||||
|
||||
各位好,今天我想和大家分享一个我主导设计和开发的项目——**CamTalk**,一个多模态实时 AI 视觉对话助手。
|
||||
|
||||
简单来说,用户打开浏览器,对着摄像头,用语音提问,AI 就能同时"看到"画面、"听到"语音,然后用文字和语音自然地回应。整个过程不需要打字,就像一个面对面的助手。
|
||||
|
||||
做这个项目的初衷其实很直接——现在的大模型已经具备多模态能力,但大多数产品还是"上传一张图、输入一段文字"的交互方式。我认为真正的多模态交互应该是**无感的**——用户只需要说话,AI 自己去理解视觉场景,就像两个人面对面聊天一样。
|
||||
|
||||
---
|
||||
|
||||
### 系统架构(约 3 分钟)
|
||||
|
||||
CamTalk 采用三层架构:**前端做轻量预处理,后端做智能编排,云端 AI 服务按需调用**。
|
||||
|
||||
**前端**是 React 18 加 TypeScript,跑在浏览器里。它负责三件事:摄像头和麦克风的采集,边缘侧的预处理——比如语音活动检测和关键帧过滤,以及 UI 渲染。通过 WebSocket 与后端通信。
|
||||
|
||||
**后端**是 Go 写的网关服务,用 Gin 框架做 HTTP 路由,gorilla/websocket 处理长连接。它是整个系统的"大脑",负责会话管理、AI 编排,以及和各家 AI 服务的对接。每个 WebSocket 连接对应一个 goroutine,天然适合这种长连接场景。
|
||||
|
||||
**AI 服务层**是可插拔的。LLM 默认用 GPT-4o,通过 OpenAI 兼容接口可以随时切换成通义千问等国产模型。语音识别默认 Deepgram,语音合成默认 OpenAI TTS,同时也支持小米的 MiMo 系列作为备选。
|
||||
|
||||
有人可能会问:为什么不直接让前端调用 AI API?这里有三点考虑。第一是**安全性**,API Key 不应该暴露在客户端。第二是**统一管控**,速率限制、成本监控、模型路由这些逻辑集中在网关层更好维护。第三是**可扩展性**,未来加缓存、做负载均衡、多实例部署,都在网关层解决。
|
||||
|
||||
部署方面,我们设计了 Nginx 做同源反向代理,前端静态资源和后端 API 在同一个域名下,天然解决跨域问题。Go 网关可以水平扩展,通过 Redis 共享会话状态。目前也已经配置好了 Docker Compose 一键部署方案,包含前端、后端和 PostgreSQL 三个容器。
|
||||
|
||||
---
|
||||
|
||||
### 核心交互流程(约 3 分钟)
|
||||
|
||||
我想重点讲一下一次完整的交互流程,因为它串起了整个系统最核心的技术挑战。
|
||||
|
||||
用户对着摄像头说了一句话,比如"这是什么花"。首先是**前端**的 VAD——语音活动检测模块——在浏览器端实时检测用户何时开始说话、何时说完。这一步完全在端侧完成,用的是 @ricky0123/vad-web,基于 WebRTC VAD 算法。好处是:用户不说话时不需要上传任何音频,节省约 70% 的无效带宽。
|
||||
|
||||
VAD 检测到语音结束后,前端会同时做两件事:把音频编码成 PCM 格式,以及从摄像头捕获当前画面,一起通过 WebSocket 发给后端。
|
||||
|
||||
后端收到后,启动一个 **AI 编排管道**(我们叫它 Orchestrator)。第一步,把音频发给 STT 服务做语音识别,拿到文字结果。第二步,把识别出的文字、摄像头画面以及对话历史,一起打包发给多模态 LLM 做推理。LLM 以流式方式逐 token 输出。第三步,也是最关键的优化——我们不等待 LLM 输出完再调用 TTS,而是做**句子级切分**:LLM 每输出一个完整句子,就立即送入 TTS 合成并推送给客户端。
|
||||
|
||||
所以客户端的体验是这样的:文字一个 token 一个 token 地出现,几乎同时语音就开始播放了。用户**先看到文字、紧接着听到语音**,感知延迟可以控制在 0.5 秒以内。整个端到端的目标延迟是 1.5 到 2 秒。
|
||||
|
||||
这个"LLM 文本流和 TTS 音频流并行推送"的设计,是我们降低感知延迟最关键的手段。
|
||||
|
||||
---
|
||||
|
||||
### 成本控制(约 2 分钟)
|
||||
|
||||
做实时多模态应用,成本是最容易失控的地方。我在设计之初就把成本控制作为架构级别的考量。
|
||||
|
||||
最直观的例子是视觉链路:如果按 1fps 全量发送画面给 LLM,一个用户每天用 10 分钟,一天就是 60 万帧的 token 消耗,1000 个用户时成本完全不可控。
|
||||
|
||||
我们的核心策略叫**端云协同**——把适合的计算前置到客户端。
|
||||
|
||||
在视觉侧,我们做了三个优化:一是降低采样频率,空闲时 5 秒一帧,用户说话时 1 秒一帧;二是关键帧过滤,通过 Canvas 像素比较计算帧间相似度,画面没有显著变化就不发送;三是只在用户提问时捕获画面,而不是持续上传视频流。
|
||||
|
||||
在语音侧,VAD 在浏览器端检测,只上传有效语音片段,环境噪音和静默时段完全不消耗带宽。
|
||||
|
||||
在推理侧,我们规划了模型分级策略——简单识别类问题走 GPT-4o-mini,深度分析走 GPT-4o,复杂推理走 o1。同时对话历史做了裁剪,前端保留最近 10 轮,后端保留 20 轮,限制每轮的固定 token 开销。
|
||||
|
||||
这些策略综合下来,预估月成本可以从无优化的约 5000 美元降到 300 到 500 美元,降幅大约 90%。
|
||||
|
||||
---
|
||||
|
||||
### 工程设计与取舍(约 2 分钟)
|
||||
|
||||
除了技术实现,我想分享几个设计上的取舍。
|
||||
|
||||
**存储方案的分阶段设计**。MVP 阶段我们用进程内存存会话状态,快速验证核心功能。但代码层面我们已经通过 Repository 接口模式做了抽象——HistoryRepository、UsageRepository 这些接口定义好了,底层实现可以是 Memory、Redis 或 PostgreSQL,通过配置切换。目前 Redis 实现已经就绪,PostgreSQL 的 schema 也设计好了,包括 sessions、messages、usage_daily 三张表。这种渐进式设计让我们既能快速交付,又为后续扩展留好了空间。
|
||||
|
||||
**文档驱动开发**。项目里有一套完整的设计文档,涵盖架构、接口协议、技术选型、成本控制等。我们遵循"文档优先"原则——实现功能前先写设计文档,实现和文档不一致时优先更新文档。这在团队协作中特别重要,接口契约清晰,前后端可以并行开发。
|
||||
|
||||
**WebSocket 协议的可靠性设计**。客户端每 30 秒发心跳,服务端 60 秒没收到心跳就断开。断线后用指数退避加抖动重连——1 秒、2 秒、4 秒、8 秒,最大 30 秒。消息用统一信封格式,所有消息都带 type 字段做类型分发。
|
||||
|
||||
---
|
||||
|
||||
### 用户故事与产品规划(约 2 分钟)
|
||||
|
||||
最后讲一下产品层面的思考。用户故事我按 P0 到 P2 分了三个优先级。
|
||||
|
||||
P0 是 MVP 必做的四个场景:AI 识别画面中的物体、语音对话无需打字、AI 能看到摄像头画面、AI 用语音回答。这四个跑通了,核心价值就成立了。
|
||||
|
||||
P1 是体验增强:AI 主动观察画面变化并提示重要事件、识别画面中的文字做 OCR、以及多轮对话的上下文记忆。
|
||||
|
||||
P2 是进阶探索:比如视障用户的无障碍辅助——AI 实时描述周围环境并提示障碍物,画面中外语内容的实时翻译,以及"观察模式"和"对话模式"的切换。
|
||||
|
||||
优先级判断用两个维度交叉评估:用户价值和实现成本。P0 是高价值且成本合理的,P1 是高价值但成本较高的,P2 是探索性的,验证后再投入。
|
||||
|
||||
目前还有几个功能创意在规划中,包括视频录制、对话翻译、对话总结、手动对话输入,以及对话情景选择——比如面试官模式、英语老师模式、辩论赛模式等。
|
||||
|
||||
---
|
||||
|
||||
### 总结(约 1 分钟)
|
||||
|
||||
总结一下,CamTalk 这个项目有几个我比较满意的设计点。
|
||||
|
||||
第一是**架构清晰**:三层分离,每层职责明确,前端做轻量预处理,后端做智能编排,AI 服务可插拔。
|
||||
|
||||
第二是**体验导向**:从用户感知延迟倒推技术方案,流式并行推送、句子级切分、端侧 VAD 这些手段都是围绕"让对话像真人一样自然"这个目标设计的。
|
||||
|
||||
第三是**成本意识**:从架构层面就融入了成本控制,端云协同、智能采样、模型分级,不是等功能做完再去优化成本。
|
||||
|
||||
第四是**工程成熟度**:接口抽象、文档驱动、渐进式存储升级,为项目的长期演进留好了空间。
|
||||
|
||||
以上就是 CamTalk 项目的整体介绍。谢谢大家,有什么问题我们可以一起讨论。
|
||||
|
||||
---
|
||||
|
||||
> **附:讲解提示**
|
||||
>
|
||||
> - 如果面试官追问技术深度,可以展开讲 Orchestrator 的管道实现细节(goroutine 并发、context 取消、句子切分算法)或 VAD 参数调优。
|
||||
> - 如果追问产品思维,可以展开讲用户故事的优先级判断逻辑,以及观察模式和对话模式的差异设计。
|
||||
> - 如果追问可扩展性,可以讲 Redis 共享会话、多 Gateway 水平扩展、模型路由器的规划。
|
||||
> - 如果追问成本数据,可以给出具体的 token 消耗计算过程和各种优化手段的量化效果。
|
||||
@@ -57,7 +57,7 @@ redis:
|
||||
|
||||
auth:
|
||||
# jwt_secret 通过环境变量 CAMTALK_AUTH_JWT_SECRET 设置
|
||||
access_ttl: 15 # Access Token 过期时间(分钟)
|
||||
access_ttl: 120 # Access Token 过期时间(分钟)
|
||||
refresh_ttl: 10080 # Refresh Token 过期时间(分钟),7 天
|
||||
|
||||
log:
|
||||
|
||||
Reference in New Issue
Block a user