docs: clarify realtime interaction positioning and capability status
This commit is contained in:
+44
-170
@@ -1,189 +1,63 @@
|
||||
# AI Video Assistant — 后端引擎
|
||||
# 后端运行时
|
||||
|
||||
参考 [dograh](../dograh),用 **pipecat** 作语音引擎的自建后端。目标是逐步长成
|
||||
类 dograh 平台,但**同时支持 WebRTC 和 WS 两种音频输出**。
|
||||
本目录提供 FastAPI 接入层、助手与模型资源管理,以及以 Pipecat 为核心的实时会话运行时。项目定位和完整能力状态见[仓库 README](../README.md)与[用户文档](../docs-user/status.mdx)。当前依赖版本以 [requirements.txt](requirements.txt) 为准。
|
||||
|
||||
## 双输出架构(核心)
|
||||
|
||||
pipecat 把"管线"和"输出方式"解耦:同一条 `STT→LLM→TTS` 管线可挂不同 transport。
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
浏览器 ──WebRTC──► /ws/voice ──┤ │
|
||||
│ run_pipeline(transport, cfg): │
|
||||
自定义/话务 ─WS──► /ws/stream ─┤ input→STT→LLM→TTS→output │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
- **WebRTC**(`/ws/voice`):浏览器,低延迟,带 NAT 穿透。`SmallWebRTCTransport`
|
||||
- **WS**(`/ws/stream`):裸音频流,服务端/话务/自定义客户端,无 ICE/TURN。`FastAPIWebsocketTransport`
|
||||
|
||||
加第三种输出(如 Twilio 电话)= 在 `services/pipecat/transports.py` 再加一个 `build_xxx_transport` + serializer,管线一行不用改。
|
||||
|
||||
## 目录结构(对齐 dograh 的 `api/`,便于生长)
|
||||
|
||||
```
|
||||
ai-video-backend/
|
||||
├── app.py # FastAPI 入口,挂路由 + CORS
|
||||
├── settings.py # 读 .env,仅存数据库/CORS/TURN 等运行设置
|
||||
├── models.py # AssistantConfig(对齐前端 AssistantForm)
|
||||
├── routes/ # 一个文件一组端点(对齐 dograh routes/)
|
||||
│ ├── health.py
|
||||
│ ├── voice_webrtc.py # WebRTC 信令
|
||||
│ └── voice_ws.py # WS 裸音频流
|
||||
├── services/
|
||||
│ └── pipecat/ # 引擎(对齐 dograh services/pipecat/)
|
||||
│ ├── service_factory.py # 建 STT/LLM/TTS(按 interface_type 分发)
|
||||
│ ├── transports.py # transport 工厂(加输出方式在此)
|
||||
│ └── pipeline.py # 管线拼装与运行(transport 无关)
|
||||
├── Dockerfile
|
||||
├── requirements.txt
|
||||
└── .env.example
|
||||
|
||||
# 平台长大后会再加(对齐 dograh):
|
||||
# db/ SQLAlchemy 模型 + 会话(助手/对话/向量)
|
||||
# schemas/ pydantic 请求响应
|
||||
# tasks/ 后台任务(转写、报表)—— 配 redis
|
||||
# services/storage.py 录音存储 —— 配 minio
|
||||
```
|
||||
|
||||
## 国产栈(全走 OpenAI 兼容,换栈只改 .env)
|
||||
|
||||
| 类型 | 默认 | 接入 |
|
||||
|------|------|------|
|
||||
| LLM | DeepSeek | 云端直连,只需 key |
|
||||
| STT | SenseVoice / FunASR | 本地 OpenAI 兼容转写服务 |
|
||||
| TTS | CosyVoice | 本地 OpenAI 兼容 TTS 服务 |
|
||||
|
||||
### 讯飞 ASR / TTS / SuperTTS
|
||||
|
||||
讯飞鉴权直接存入对应 `ModelResource.secrets`,接口参数存入 `ModelResource.values`:
|
||||
|
||||
- 普通语音识别:`interface_type=xfyun-asr`
|
||||
- 普通语音合成:`interface_type=xfyun-tts`
|
||||
- 超拟人语音合成:`interface_type=xfyun-super-tts`
|
||||
- `values.apiUrl` 保存讯飞 WebSocket URL,音色、语速等可选参数也放在 `values`
|
||||
- `secrets` 分别保存 `appId`、`apiKey`、`apiSecret`
|
||||
|
||||
## 接口定义驱动的模型注册表
|
||||
|
||||
LLM、ASR、TTS、Embedding、Realtime 使用同一套两层结构:
|
||||
## 请求如何进入运行时
|
||||
|
||||
```text
|
||||
assistant_model_bindings -> model_resources -> interface_definitions
|
||||
业务客户端 ── /v1/realtime WebSocket 或 /v1/realtime/calls WebRTC ──┐
|
||||
管理界面 ── /api/webrtc/offer、/ws/voice 或 /ws/stream ──────────┤
|
||||
▼
|
||||
协议适配 / Pipecat transport
|
||||
▼
|
||||
助手配置 + Pipeline 或 Realtime 模型
|
||||
```
|
||||
|
||||
- `interface_definitions`: 定义具体接入协议、能力和动态表单字段。
|
||||
- `model_resources`: 每条资源自带 `values/secrets`,不复用供应商账号。
|
||||
- `assistant_model_bindings`: 助手按能力选择模型资源。
|
||||
- **Pipeline**:ASR → LLM/外部 Agent → TTS;Pipecat 负责媒体帧、用户轮次、打断和服务编排。Pipeline 的 VAD 使用 Silero,轮次结束可选静音等待或 Local Smart Turn。
|
||||
- **Realtime**:端到端语音模型负责识别、生成和合成。当前 `create_realtime_service()` 只接通 `stepfun-realtime` 与 `qwen-audio-realtime`。轮次控制主要来自 Provider 配置。
|
||||
- **公开接口**:`/v1/realtime`、`/v1/realtime/calls`、`/v1/realtime/client_secrets`、`/v1/responses` 和 `/v1/models`。字段、事件和传输限制以[兼容矩阵](../docs-developer/openai-compatibility.mdx)为准。
|
||||
- **既有通道**:`/api/webrtc/offer`、`/ws/voice`、`/ws/stream` 仍供管理界面和已有集成使用;它们使用管理员鉴权,不采用公开 Realtime JSON 事件协议。
|
||||
|
||||
`interface_type` 是具体协议,例如 `xfyun-asr`、`xfyun-tts`、
|
||||
`xfyun-super-tts`,后端严格按它选择服务实现,不根据模型 ID 或 URL 猜测。
|
||||
## 模型资源与能力边界
|
||||
|
||||
API:
|
||||
`interface_definitions` 定义协议类型和表单字段,`model_resources` 保存每个资源的连接参数与凭证,`assistant_model_bindings` 决定助手使用哪些资源。运行时按 `interface_type` 创建服务,不根据 URL 或模型名自动推断协议。
|
||||
|
||||
- `/api/interface-definitions`: 前端读取字段定义并动态生成 Dialog。
|
||||
- `/api/model-resources`: 统一模型资源 CRUD,敏感字段逐项打码。
|
||||
| 类型 | 当前运行状态 |
|
||||
| --- | --- |
|
||||
| `openai-llm`、`openai-asr`、`openai-tts` 及已接通的讯飞接口 | Pipeline 可用;具体 Provider 仍需联调。 |
|
||||
| `stepfun-realtime`、`qwen-audio-realtime` | Realtime 可用;具体功能按 Provider 能力限制。 |
|
||||
| `openai-realtime`、`gemini-realtime` | **未接通运行时**。接口定义和种子资源仍在目录中,不能据此宣称模型可用。 |
|
||||
| 任意独立 VAD/EOU 模型 | **未实现**。目前是内置 Pipeline 策略或 Realtime Provider 自身的设置。 |
|
||||
|
||||
## 本地运行(用 uv,Python 3.12)
|
||||
后两项是[建议收敛的占位内容](../docs-user/status.mdx):在适配完成前,宜隐藏或标记不可用;移除已有资源定义前需考虑数据库记录。
|
||||
|
||||
## 主要目录
|
||||
|
||||
| 路径 | 用途 |
|
||||
| --- | --- |
|
||||
| `routes/openai_realtime.py`、`routes/openai_responses.py` | 公开 Realtime 与 Responses 入口。 |
|
||||
| `routes/voice_webrtc.py`、`routes/voice_ws.py` | 管理界面和旧通道入口。 |
|
||||
| `services/pipecat/pipeline.py` | Pipecat 会话编排。 |
|
||||
| `services/pipecat/service_factory.py`、`services/pipecat/turn_config.py` | 模型服务与 Pipeline 轮次策略。 |
|
||||
| `services/interface_catalog.py` | 接口定义目录。 |
|
||||
| `db/models.py`、`migrations/` | SQLAlchemy 数据模型与 Alembic 迁移。 |
|
||||
| `contracts/` | OpenAPI 与 Realtime 事件契约快照。 |
|
||||
|
||||
## 本地运行与验证
|
||||
|
||||
在仓库根目录启动 Docker 开发环境:
|
||||
|
||||
```bash
|
||||
cd ai-video/backend
|
||||
uv venv # 按 .python-version 用 3.12
|
||||
|
||||
# 阶段 A:只验证存储/CRUD(不装 pipecat,秒级)
|
||||
uv pip install fastapi "uvicorn[standard]" sqlalchemy asyncpg greenlet python-dotenv pydantic loguru
|
||||
# 阶段 B:做语音时再装全量(含 pipecat,需 3.10+)
|
||||
# uv pip install -r requirements.txt
|
||||
|
||||
cp .env.example .env # 只放数据库/CORS/TURN;模型 key 在模型资源里维护
|
||||
# 起 Postgres:在 ai-video/ 下 docker compose up -d postgres
|
||||
cd ..
|
||||
make db-migrate # 首次或表结构变更后执行 Alembic 迁移
|
||||
cd backend
|
||||
uv run --with-requirements requirements.txt uvicorn app:app --reload --port 8000
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
> pipecat 相关代码用**惰性导入**,所以阶段 A 不装 pipecat 也能启动并跑 `/api/*` 与 `/health`;
|
||||
> 只有真正连 `/ws/voice`、`/ws/stream` 时才需要全量依赖。
|
||||
>
|
||||
> 交互式 API 文档:启动后访问 http://localhost:8000/docs(手动戳 CRUD、定 schema 用)。
|
||||
API 容器启动时会执行 Alembic 迁移并同步接口定义。本机单独运行后端时,可用 `make db-init` 完成这两步;它需要本机安装 `uv`。需要演示助手和模型资源时,另运行 `make db-seed`;种子密钥是占位值,不能直接用于真实模型调用。`make db-seed` 还会更新示例助手的模型绑定,不要在已有生产配置上当作常规升级命令运行。
|
||||
|
||||
## 数据库迁移
|
||||
|
||||
表结构由 Alembic 管理,SQLAlchemy 模型在 `db/models.py`,迁移文件在
|
||||
`migrations/versions/`。
|
||||
后端地址是 `http://localhost:8000`,交互式 HTTP API 文档是 `/docs`。本地开发也可在 `backend/` 目录使用 `uv run --with-requirements requirements.txt uvicorn app:app --reload --port 8000`,需先准备数据库和环境变量。完整部署与 TURN 配置见[部署说明](../deploy/README.md)。
|
||||
|
||||
```bash
|
||||
cd ai-video
|
||||
make db-migrate # 升级到最新版
|
||||
make db-revision msg="add xxx" # 根据模型差异生成迁移
|
||||
make db-current # 查看当前库版本
|
||||
make test-backend
|
||||
make contract-check
|
||||
```
|
||||
|
||||
`interface_definitions` 的默认数据由 `services/interface_catalog.py` 维护,并通过
|
||||
启动时同步或 `make db-sync-interface-definitions` 写入数据库;模型资源、知识库和助手示例数据继续走 `db/seed_*.sql`。
|
||||
|
||||
## Docker(ai-video/docker-compose.yaml)—— 调试主路径
|
||||
|
||||
api 服务挂了源码 + `--reload`,前端用 npm dev + HMR,改代码都即时生效。
|
||||
|
||||
```bash
|
||||
cd ai-video
|
||||
docker compose up # 前台起 pg + api(:8000)+ ui(:3030),日志直出
|
||||
docker compose up -d # 后台起;看日志 docker compose logs -f api
|
||||
docker compose down # 停止全部
|
||||
|
||||
# 知识库依赖 RustFS;默认 compose 会一起启动。Redis 仍是可选服务。
|
||||
docker compose up -d postgres rustfs api ui
|
||||
docker compose --profile data up -d redis
|
||||
# 可选:公网部署(WebRTC 需 TURN)
|
||||
docker compose --profile remote up -d
|
||||
```
|
||||
|
||||
> 首次 `up` 会构建 api 镜像(装全量 `requirements.txt`,含 pipecat,较慢)。
|
||||
> 之后改 Python 代码靠 `--reload` 热更新,不用重建;只有改 `requirements.txt` 才 `docker compose build api`。
|
||||
|
||||
## 极简知识库 MVP
|
||||
|
||||
知识库入口为前端「组件 / 知识库」。使用前先在「组件 / 模型」配置并启用
|
||||
一个 Embedding 资源,然后:
|
||||
|
||||
1. 创建知识库并选择 Embedding 模型。
|
||||
2. 上传 PDF、DOCX、TXT、Markdown、CSV、JSON 或 HTML,或者直接添加文字。
|
||||
3. 文档状态会从 `pending` 变为 `processing`,最终进入 `ready` 或 `failed`。
|
||||
4. 失败记录会保留,可在页面重试;完成后可预览分块并使用「检索测试」验证召回。
|
||||
5. 在提示词助手的 pipeline 模式下选择知识库。每轮 LLM 推理前会自动检索并注入相关片段。
|
||||
|
||||
当前后台处理使用 FastAPI 进程内任务,适合 MVP。服务重启时未完成任务会转为失败,
|
||||
可在页面重试;需要多实例或高吞吐时再迁移到 Redis/ARQ worker。
|
||||
|
||||
## Prompt 动态变量
|
||||
|
||||
提示词助手的 Pipeline 与 Realtime 模式都支持在开场白和系统提示词中使用
|
||||
`{{ variable_name }}`。Pipeline 模式还支持在 HTTP 工具的 URL、Header 和 Body
|
||||
中引用变量。助手页维护变量类型、默认值和必填规则;调试面板在每次通话开始前
|
||||
传入会话值。Realtime 会把渲染后的提示词作为模型 instructions。
|
||||
|
||||
内置系统变量包括 `system__conversation_id`、`system__time`、
|
||||
`system__agent_turns` 和 `system__conversation_history`。客户端不能提交
|
||||
`system__*` 或 `secret__*`。HTTP 工具的密钥变量必须在工具的服务端密钥配置中
|
||||
以 `secret__` 开头声明,而且只能用于 Header。
|
||||
|
||||
HTTP 工具可通过“响应变量赋值”把 JSON 路径写回普通会话变量,例如:
|
||||
|
||||
```json
|
||||
{"order_status": "response.order.status"}
|
||||
```
|
||||
|
||||
后续轮次会使用新值重新渲染系统提示词。上线前执行 `make db-migrate`,应用
|
||||
`20260712_0007` 迁移。
|
||||
|
||||
## 待联调 / TODO
|
||||
|
||||
- [ ] 联调 Pipecat 1.3.0 语音链路与各 OpenAI 兼容服务
|
||||
- [ ] 起本地 SenseVoice / CosyVoice 的 OpenAI 兼容服务
|
||||
- [x] `realtime` 模式(StepFun StepAudio Realtime)
|
||||
- [x] `realtime` 模式(Alibaba Cloud Qwen-Audio 3.0 Realtime MVP)
|
||||
- [x] 前端 `DebugVoicePanel` 接 `/ws/voice`(参考 dograh `useWebSocketRTC.tsx`)
|
||||
- [ ] 加 DB 后:助手配置入库(目前随请求内联)
|
||||
开发计划中的生产可观测性、并发保护和可靠性工作尚未全部完成,见[单租户生产化计划](../docs-developer/development-plan.mdx)。
|
||||
|
||||
Reference in New Issue
Block a user