Spaces:
Runtime error
Runtime error
Merge branch 'main' of https://huggingface.co/spaces/build-small-hackathon/PregoPal
Browse files- docs/技术调研_与并行工作路径.md +277 -0
docs/技术调研_与并行工作路径.md
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 技术调研 & 并行工作方案:MiniCPM-o 全双工语音升级(路线 A)
|
| 2 |
+
|
| 3 |
+
> 日期:2026-06-10
|
| 4 |
+
> 状态:技术调研完成,方案待 agent 执行
|
| 5 |
+
> 参考来源:MiniCPM-V-Cookbook(llama.cpp 部署 + llama.cpp-omni 全双工语音)
|
| 6 |
+
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
## 一、当前状态速查
|
| 10 |
+
|
| 11 |
+
| 项目 | 值 |
|
| 12 |
+
|------|-----|
|
| 13 |
+
| API URL | `https://andrew-jiabin--prego-pal-minicpm-serve.modal.run` |
|
| 14 |
+
| GPU | T4 (16GB VRAM) |
|
| 15 |
+
| 运行时 | **llama-cpp-python** (预编译 wheel, CUDA 12.1) |
|
| 16 |
+
| 模型 | MiniCPM-o-4_5-Q4_K_M.gguf (~5GB) + vision mmproj |
|
| 17 |
+
| 音频 | **不支持**(仅挂载了 vision mmproj) |
|
| 18 |
+
| 端点 | `/v1/chat/completions`, `/v1/embeddings`, `/v1/vision`(冗余) |
|
| 19 |
+
|
| 20 |
+
## 二、核心发现:为什么当前架构不支持全双工语音
|
| 21 |
+
|
| 22 |
+
### 2.1 软件层限制
|
| 23 |
+
|
| 24 |
+
```
|
| 25 |
+
当前架构:
|
| 26 |
+
Modal ASGI → llama-cpp-python (Python binding)
|
| 27 |
+
└── ggml-org/llama.cpp 主线
|
| 28 |
+
└── mmproj= 只支持单个投影层 (vision)
|
| 29 |
+
└── 无 audio mmproj 参数
|
| 30 |
+
└── 无 token2wav 集成
|
| 31 |
+
└── 无 WebRTC 实时流
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
| 能力 | 当前 (`llama-cpp-python`) | 需要的 (`llama.cpp-omni`) |
|
| 35 |
+
|------|--------------------------|---------------------------|
|
| 36 |
+
| 同时加载 vision + audio + tts mmproj | ❌ 只支持 1 个 | ✅ 支持多个 |
|
| 37 |
+
| 全双工实时语音 (`CPP_MODE=duplex`) | ❌ | ✅ WebRTC 原语 |
|
| 38 |
+
| TTS 端点 `/v1/audio/speech` | ❌ | ✅ OpenAI 兼容 |
|
| 39 |
+
| 流式语音输出 (streaming WAV) | ❌ | ✅ |
|
| 40 |
+
| 声音克隆 (voice cloning) | ❌ | ✅ |
|
| 41 |
+
| 语音 token 识别 (S2T) | ❌ | ✅ |
|
| 42 |
+
|
| 43 |
+
### 2.2 VRAM 预算——T4 16GB 完全够用
|
| 44 |
+
|
| 45 |
+
| 组件 | 文件 | 大小 |
|
| 46 |
+
|------|------|------|
|
| 47 |
+
| 主模型 (LLM) | `MiniCPM-o-4_5-Q4_K_M.gguf` | ~5.0 GB |
|
| 48 |
+
| 视觉投影层 | `vision/MiniCPM-o-4_5-vision-F16.gguf` | ~1.1 GB |
|
| 49 |
+
| 音频投影层 (S2T) | `audio/MiniCPM-o-4_5-audio-F16.gguf` | ~0.6 GB |
|
| 50 |
+
| TTS 模型 | `tts/MiniCPM-o-4_5-tts-F16.gguf` | ~1.1 GB |
|
| 51 |
+
| 声学投影层 | `tts/MiniCPM-o-4_5-projector-F16.gguf` | ~14 MB |
|
| 52 |
+
| Token2Wav | encoder + flow + hifigan2 + cache 共 4 文件 | ~0.9 GB |
|
| 53 |
+
| KV Cache (8K ctx) | 运行时 | ~1.5 GB |
|
| 54 |
+
| **总计** | | **~10.2 GB** |
|
| 55 |
+
|
| 56 |
+
**结论:T4 16GB 跑全双工语音 + 视觉 + 文本完全可行,还剩 ~5.8GB 余量。**
|
| 57 |
+
|
| 58 |
+
---
|
| 59 |
+
|
| 60 |
+
## 三、升级路线:从 llama-cpp-python → llama.cpp-omni
|
| 61 |
+
|
| 62 |
+
### 3.1 架构变化
|
| 63 |
+
|
| 64 |
+
```
|
| 65 |
+
升级前:
|
| 66 |
+
FastAPI ←→ llama-cpp-python (Python binding, 单 mmproj)
|
| 67 |
+
|
| 68 |
+
升级后:
|
| 69 |
+
FastAPI ←→ subprocess: llama-server (OpenBMB/llama.cpp-omni, 多 mmproj + token2wav)
|
| 70 |
+
├── -m Q4_K_M.gguf (主模型)
|
| 71 |
+
├── --mmproj vision.gguf (视觉)
|
| 72 |
+
├── --mmproj audio.gguf (音频, S2T)
|
| 73 |
+
├── --voxcpm2-base-lm tts.gguf (TTS)
|
| 74 |
+
├── --voxcpm2-acoustic projector.gguf (声学投影)
|
| 75 |
+
└── token2wav/ (encoder + flow + hifigan2 + cache)
|
| 76 |
+
```
|
| 77 |
+
|
| 78 |
+
### 3.2 新增端点
|
| 79 |
+
|
| 80 |
+
| 端点 | 方法 | 功能 |
|
| 81 |
+
|------|------|------|
|
| 82 |
+
| `/v1/chat/completions` | POST | 文本 + 多模态(图片/音频),支持 streaming |
|
| 83 |
+
| `/v1/audio/speech` | POST | TTS:文本 → 语音 WAV/PCM |
|
| 84 |
+
| `/v1/audio/speech/stream` | POST | 流式 TTS |
|
| 85 |
+
| `/v1/audio/transcriptions` | POST | STT:语音 → 文本(需 audio mmproj 挂载后可用) |
|
| 86 |
+
| `/v1/embeddings` | POST | 文本嵌入 |
|
| 87 |
+
| `/v1/models` | GET | 模型列表 |
|
| 88 |
+
| `/health` | GET | 健康检查(含音视频组件状态) |
|
| 89 |
+
| `/v1/voxcpm2/init` | POST | 动态加载/切换 TTS 模型 |
|
| 90 |
+
|
| 91 |
+
### 3.3 全双工流程
|
| 92 |
+
|
| 93 |
+
```
|
| 94 |
+
浏览器/客户端 Modal (T4)
|
| 95 |
+
│ │
|
| 96 |
+
│── WebRTC offer ──────────────────→│
|
| 97 |
+
│←─ WebRTC answer ──────────────────│
|
| 98 |
+
│ │
|
| 99 |
+
│── Opus 音频帧 ───────────────────→│ llama.cpp-omni
|
| 100 |
+
│ │ ├── audio mmproj: 语音 → 文本
|
| 101 |
+
│ │ ├── LLM: 推理
|
| 102 |
+
│ │ └── token2wav: 文本 → 语音
|
| 103 |
+
│←─ Opus 音频帧 ────────────────────│
|
| 104 |
+
│ │
|
| 105 |
+
│── 图片/文字 ─────────────────────→│ vision mmproj + LLM
|
| 106 |
+
│←─ 文本/语音 ──────────────────────│
|
| 107 |
+
```
|
| 108 |
+
|
| 109 |
+
---
|
| 110 |
+
|
| 111 |
+
## 四、并行工作方案(可分给多个 agent)
|
| 112 |
+
|
| 113 |
+
### Agent 1(你):编译 & 部署 llama.cpp-omni 到 Modal
|
| 114 |
+
|
| 115 |
+
**文件:`modal_deploy/deploy_omni.py`**(新建,不动现有 `deploy.py`)
|
| 116 |
+
|
| 117 |
+
#### 步骤:
|
| 118 |
+
|
| 119 |
+
1. **修改 Docker 镜像**:从 `pip install llama-cpp-python` → 在 Image 中 `git clone OpenBMB/llama.cpp-omni && cmake && make`
|
| 120 |
+
```python
|
| 121 |
+
_omni_image = (
|
| 122 |
+
Image.debian_slim(python_version="3.11")
|
| 123 |
+
.apt_install("curl", "git", "build-essential", "cmake", "libcurl4-openssl-dev",
|
| 124 |
+
"libsndfile1", "libasound2-dev")
|
| 125 |
+
.pip_install("fastapi", "uvicorn[standard]", "httpx", "numpy", "Pillow", "soundfile")
|
| 126 |
+
.run_commands(
|
| 127 |
+
"git clone --depth 1 https://github.com/OpenBMB/llama.cpp-omni /llama.cpp-omni",
|
| 128 |
+
"cd /llama.cpp-omni && cmake -B build -DGGML_CUDA=ON -DCMAKE_BUILD_TYPE=Release",
|
| 129 |
+
"cd /llama.cpp-omni && cmake --build build -j$(nproc) --target llama-server llama-mtmd-cli",
|
| 130 |
+
)
|
| 131 |
+
)
|
| 132 |
+
```
|
| 133 |
+
|
| 134 |
+
2. **新增 `serve_omni()` ASGI 函数**:
|
| 135 |
+
- 启动 `llama-server` 子进程:
|
| 136 |
+
```bash
|
| 137 |
+
/llama.cpp-omni/build/bin/llama-server \
|
| 138 |
+
-m /models/MiniCPM-o-4_5-gguf/MiniCPM-o-4_5-Q4_K_M.gguf \
|
| 139 |
+
--mmproj /models/MiniCPM-o-4_5-gguf/vision/MiniCPM-o-4_5-vision-F16.gguf \
|
| 140 |
+
--mmproj /models/MiniCPM-o-4_5-gguf/audio/MiniCPM-o-4_5-audio-F16.gguf \
|
| 141 |
+
--voxcpm2-base-lm /models/MiniCPM-o-4_5-gguf/tts/MiniCPM-o-4_5-tts-F16.gguf \
|
| 142 |
+
--voxcpm2-acoustic /models/MiniCPM-o-4_5-gguf/tts/MiniCPM-o-4_5-projector-F16.gguf \
|
| 143 |
+
--host 127.0.0.1 --port 8081 \
|
| 144 |
+
-ngl 99 -c 8192 \
|
| 145 |
+
--no-mmap \
|
| 146 |
+
--jinja \
|
| 147 |
+
--reasoning-budget -1
|
| 148 |
+
```
|
| 149 |
+
- FastAPI 代理 `llama-server`(纯文本/嵌入直接转发,多模态构造标准 OpenAl content 格式)
|
| 150 |
+
- 健康检查包含音视频组件状态验证
|
| 151 |
+
|
| 152 |
+
3. **Volume 确认**:验证 Volume 中是否有所有必需文件(vision, audio, tts, token2wav-gguf)
|
| 153 |
+
|
| 154 |
+
4. **测试**:
|
| 155 |
+
- `modal run modal_deploy.deploy_omni::test_inference` → 文本 + 图片理解
|
| 156 |
+
- `modal run modal_deploy.deploy_omni::test_audio` → TTS 生成
|
| 157 |
+
- `modal run modal_deploy.deploy_omni::test_multimodal` → 图片+文本联合
|
| 158 |
+
|
| 159 |
+
5. **部署**:`modal deploy modal_deploy.deploy_omni`
|
| 160 |
+
|
| 161 |
+
#### 关键踩坑提醒:
|
| 162 |
+
|
| 163 |
+
| 坑 | 解决方案 |
|
| 164 |
+
|----|---------|
|
| 165 |
+
| CMake 找不到 CUDA | Modal T4 已有 CUDA 驱动,cmake -DGGML_CUDA=ON 即可 |
|
| 166 |
+
| `libcurl4-openssl-dev` 必须安装 | 否则 LLAMA_CURL=ON 编译失败 |
|
| 167 |
+
| `llama-server` 的 `--mmproj` 可以传多次 | vision + audio 各传一次 |
|
| 168 |
+
| `--no-mmap` 必需 | Modal tmpfs 不支持 mmap |
|
| 169 |
+
| token2wav 文件需要放在模型目录的 `token2wav-gguf/` 子目录 | llama-server 自动查找 |
|
| 170 |
+
| 编译时间 ~10-15 分钟 | 首次 deploy 后 Docker 层缓存,下次热更新 < 1min |
|
| 171 |
+
|
| 172 |
+
---
|
| 173 |
+
|
| 174 |
+
### Agent 2:升级客户端 `client.py` 支持全双工语音
|
| 175 |
+
|
| 176 |
+
**文件:`modal_deploy/client.py`**(修改现有文件)
|
| 177 |
+
|
| 178 |
+
#### 改动:
|
| 179 |
+
|
| 180 |
+
1. **修复 bug**:`describe_image()` 第 157 行 `result.get("response", ...)` → `result["choices"][0]["message"]["content"]`
|
| 181 |
+
2. **新增 TTS 方法**:
|
| 182 |
+
```python
|
| 183 |
+
def text_to_speech(self, text, voice="default", stream=False) -> bytes:
|
| 184 |
+
"""TTS: 文本 → WAV 音频字节"""
|
| 185 |
+
```
|
| 186 |
+
3. **新增 STT 方法**:
|
| 187 |
+
```python
|
| 188 |
+
def speech_to_text(self, audio_bytes, audio_format="wav") -> str:
|
| 189 |
+
"""STT: 音频 → 文本"""
|
| 190 |
+
```
|
| 191 |
+
注意:STT 需要确认 llama.cpp-omni 的 `/v1/audio/transcriptions` 端点是否可用(需 audio mmproj)
|
| 192 |
+
4. **新增全双工对话方法**(如果需要 WebRTC 前端集成):
|
| 193 |
+
```python
|
| 194 |
+
def duplex_chat(self, audio_stream, ...) -> AsyncGenerator:
|
| 195 |
+
"""全双工:边说边听,返回音频流"""
|
| 196 |
+
```
|
| 197 |
+
|
| 198 |
+
---
|
| 199 |
+
|
| 200 |
+
### Agent 3:确认 Volume 模型文件 & 补传
|
| 201 |
+
|
| 202 |
+
**检查清单**:
|
| 203 |
+
|
| 204 |
+
```bash
|
| 205 |
+
# 确认 Volume 中有哪些文件
|
| 206 |
+
modal volume ls minicpm-o-4_5-models /MiniCPM-o-4_5-gguf
|
| 207 |
+
|
| 208 |
+
# 必需的全部文件:
|
| 209 |
+
# ✅ MiniCPM-o-4_5-Q4_K_M.gguf
|
| 210 |
+
# ✅ vision/MiniCPM-o-4_5-vision-F16.gguf
|
| 211 |
+
# ✅ audio/MiniCPM-o-4_5-audio-F16.gguf
|
| 212 |
+
# ✅ tts/MiniCPM-o-4_5-tts-F16.gguf
|
| 213 |
+
# ✅ tts/MiniCPM-o-4_5-projector-F16.gguf
|
| 214 |
+
# ✅ token2wav-gguf/encoder.gguf
|
| 215 |
+
# ✅ token2wav-gguf/flow_extra.gguf
|
| 216 |
+
# ✅ token2wav-gguf/flow_matching.gguf
|
| 217 |
+
# ✅ token2wav-gguf/hifigan2.gguf
|
| 218 |
+
# ✅ token2wav-gguf/prompt_cache.gguf
|
| 219 |
+
```
|
| 220 |
+
|
| 221 |
+
**缺失文件补传**:
|
| 222 |
+
```bash
|
| 223 |
+
modal volume put minicpm-o-4_5-models \
|
| 224 |
+
./models/MiniCPM-o-4_5-gguf/audio /MiniCPM-o-4_5-gguf/audio
|
| 225 |
+
|
| 226 |
+
modal volume put minicpm-o-4_5-models \
|
| 227 |
+
./models/MiniCPM-o-4_5-gguf/tts /MiniCPM-o-4_5-gguf/tts
|
| 228 |
+
|
| 229 |
+
modal volume put minicpm-o-4_5-models \
|
| 230 |
+
./models/MiniCPM-o-4_5-gguf/token2wav-gguf /MiniCPM-o-4_5-gguf/token2wav-gguf
|
| 231 |
+
```
|
| 232 |
+
|
| 233 |
+
---
|
| 234 |
+
|
| 235 |
+
### Agent 4:docs & README 更新
|
| 236 |
+
|
| 237 |
+
**文件:`README.md` §11**(更新端点表、部署架构)
|
| 238 |
+
|
| 239 |
+
**文件新建:`docs/API接口规范_v3_全双工.md`**(完整 API 文档)
|
| 240 |
+
|
| 241 |
+
---
|
| 242 |
+
|
| 243 |
+
## 五、时间估算
|
| 244 |
+
|
| 245 |
+
| 阶段 | 预估时间 | 并行? |
|
| 246 |
+
|------|---------|-------|
|
| 247 |
+
| Agent 3: Volume 文件检查 & 补传 | 10-30 min | ✅ 可立即开始 |
|
| 248 |
+
| Agent 1: 编译 llama.cpp-omni 镜像 | 15-30 min | ✅ 可与 Agent 3 并行 |
|
| 249 |
+
| Agent 1: 写 `deploy_omni.py` | 30-60 min | 等待编译完成后 |
|
| 250 |
+
| Agent 1: 测试文本+视觉+TTS | 10-20 min | |
|
| 251 |
+
| Agent 2: ��级 `client.py` | 15-30 min | ✅ 可与 Agent 1 并行 |
|
| 252 |
+
| Agent 4: 写文档 | 15-20 min | ✅ 可与 Agent 1 并行 |
|
| 253 |
+
| Agent 1: `modal deploy` | 5-10 min | |
|
| 254 |
+
| **总计(并行后)** | **~1-1.5 小时** | |
|
| 255 |
+
|
| 256 |
+
---
|
| 257 |
+
|
| 258 |
+
## 六、风险 & 备用方案
|
| 259 |
+
|
| 260 |
+
| 风险 | 概率 | 影响 | 缓解 |
|
| 261 |
+
|------|------|------|------|
|
| 262 |
+
| `llama.cpp-omni` 的 multi-mmproj 同时加载 audio+vision+TTS 在 T4 上 OOM | 低 | 高 | 可先只启用 vision+TTS,audio 后续加 |
|
| 263 |
+
| token2wav 子目录问题导致 TTS 不工作 | 中 | 中 | 先确认路径结构,Cookbook 有明确说明 |
|
| 264 |
+
| WebRTC 集成复杂度过高 | 高 | 中 | 黑客松先做非 WebRTC 版本(普通 HTTP TTS+STT),全双工后续迭代 |
|
| 265 |
+
| 编译耗时过长导致冷启动慢 | 中 | 低 | Docker 层缓存;容器 keep_warm 参数 |
|
| 266 |
+
|
| 267 |
+
---
|
| 268 |
+
|
| 269 |
+
## 七、立即可以开始的并行任务
|
| 270 |
+
|
| 271 |
+
1. **Agent 3**(无需等待):立即 `modal volume ls` 检查模型文件完整性
|
| 272 |
+
2. **Agent 2**(独立):立即修复 `client.py` 的 `describe_image()` bug + 新增 TTS/STT 方法
|
| 273 |
+
3. **Agent 1**(本 agent):`deploy_omni.py` 编写 + `modal deploy`
|
| 274 |
+
|
| 275 |
+
---
|
| 276 |
+
|
| 277 |
+
*文档生成时间:2026-06-10 | 由 PregoPal Cline (deploy agent) 编写*
|