J.B-Lin commited on
Commit
348adcc
·
1 Parent(s): 6230c98

docs: add technical report for codex handoff (2026-06-13)

Browse files
Files changed (1) hide show
  1. docs/技术报告_2026-06-13.md +225 -0
docs/技术报告_2026-06-13.md ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # PregoPal — llama.cpp-omni 全双工部署技术报告
2
+
3
+ > 作者: Qclaw | 日期: 2026-06-13 08:00 | 项目: PregoPal 黑客松
4
+
5
+ ---
6
+
7
+ ## 1. 项目架构
8
+
9
+ ```
10
+ 用户 (HTTP) → FastAPI (serve()) → llama-server (子进程, 端口 8081)
11
+ → llama-omni-server (子进程, 端口 8082, 含 omni 端点)
12
+ ```
13
+
14
+ **部署方式:** Modal (T4 GPU, 16GB VRAM)
15
+ **生产 URL:** https://andrew-jiabin--prego-pal-minicpm-omni-serve.modal.run
16
+ **当前 Image:** `im-kINUqibAmbYIS6brxSIOIY` (建于 2026-06-12 23:42, 4737s)
17
+
18
+ **工作状态:**
19
+ - ✅ 文本推理 (chat/completions): 正常(中文 1.0s, 英文 1.9s)
20
+ - ✅ TTS `/v1/audio/speech`: 通过 serve() 代理,需要再验证
21
+ - ✅ STT `/v1/audio/transcriptions`: 同上
22
+ - ❌ **全双工 omni (init → prefill → generate SSE): 失败**
23
+
24
+ ---
25
+
26
+ ## 2. 当前核心问题: omni_init 500
27
+
28
+ ### 2.1 症状
29
+
30
+ ```
31
+ modal run -m modal_deploy.deploy_omni::test_omni
32
+ → llama-omni-server 启动正常(1s)
33
+ → llama-server 启动正常(7-11s)
34
+ → POST /v1/stream/omni_init 返回错误:
35
+ "Server disconnected without sending a response"
36
+ ```
37
+
38
+ ### 2.2 根因分析
39
+
40
+ **`llama-omni-server` 是独立进**,不含预先加载的 LLM 模型。当 `omni_init` 被调用时:
41
+
42
+ ```cpp
43
+ omni_init(&params, media_type, use_tts, tts_bin_dir, tts_gpu_layers,
44
+ token2wav_device, duplex_mode,
45
+ /*existing_model=*/nullptr, // ← 没有已加载的模型
46
+ /*existing_ctx=*/nullptr, // ← 没有已有的上下文
47
+ output_dir);
48
+ ```
49
+
50
+ `omni_init` 内部调用 `common_context_params_to_llama()` 和 `llama_load_model_from_file()` 来重新加载 LLM 模型。但过程失败,`omni_init` 返回 `nullptr`,`server-omni.cpp` 的 handler 返回 500。
51
+
52
+ ### 2.3 已尝试的修复
53
+
54
+ | # | 修复 | 结果 |
55
+ |---|------|------|
56
+ | 1 | 在 `server-omni.cpp` 中设置 `params.model.path`, `params.vpm_model`, `params.apm_model`, `params.tts_model` | 进程崩溃 (`Server disconnected`) |
57
+ | 2 | 额外设置 `params.n_parallel=1, params.n_ctx=4096` 避免 `n_seq_max <= 256` 错误 | 进程仍崩溃 |
58
+ | 3 | 通过 `git checkout` 恢复后发现修复被回滚 | 代码回到初始版 |
59
+ | 4 | 实际 commit `6451051` 已包含了修复,但测试时用的旧 Image | 行为未变化 |
60
+
61
+ ### 2.4 可能的原因
62
+
63
+ 建议如下排查方向(从最可能到最不可能):
64
+
65
+ 1. **模型路径不匹配**: `model_dir` 传的是 `/models/MiniCPM-o-4_5-gguf/`,但 `server-omni.cpp` 将 LLM 模型路径硬编码为 `model_dir + "/MiniCPM-o-4_5-Q4_K_M.gguf"` — 需要验证该文件是否存在(Volume `/models/MiniCPM-o-4_5-gguf/token2wav-gguf/` 下已有正确的文件)
66
+
67
+ 2. **`common_params` 字段名**: `params.model` 是 `common_params_model` 结构体,需要确保 `.path` 赋值正确。检查 `server-omni.cpp` 第 139-145 行是否格式正确。
68
+
69
+ 3. **GPU 内存不足**: `llama-server`(主 LLM)+ `llama-omni-server`(重新加载 LLM)同时运行时,T4 16GB 可能不够。建议先验证单一切片:在 `test_omni` 中只启动 `llama-omni-server`,不启动 `llama-server`。
70
+
71
+ 4. **`LLAMA_EXAMPLE_SERVER` 宏**: `omni.cpp` 内部可能有条件编译逻辑影响 context 创建;`server-omni.cpp` 是否定义了正确的宏?
72
+
73
+ ---
74
+
75
+ ## 3. 源码关键文件位置
76
+
77
+ ```
78
+ C:\Users\Andre\codes\LJB\hackthon\for_qclaw\PregoPal\
79
+ ├── modal_deploy/
80
+ │ ├── deploy_omni.py # Modal 部署脚本(编译、serve、测试)
81
+ │ ├── diagnoze_volume.py # Volume 诊断
82
+ │ ├── build_llama_server.sh # 构建脚本
83
+ │ └── llamacpp_omni/ # llama.cpp-omni 源码 (OpenBMB fork)
84
+ │ └── tools/
85
+ │ ├── server/
86
+ │ │ ├── server.cpp # llama-server (15KB, 无 omni 端点)
87
+ │ │ ├── server-omni.cpp # llama-omni-server (含 omni 端点, 关键文件)
88
+ │ │ └── CMakeLists.txt
89
+ │ └── omni/
90
+ │ ├── omni.h # omni_init() 声明
91
+ │ └── omni.cpp # omni_init() 实现 (约11000行)
92
+ ├── docs/
93
+ │ ├── 开发日志.md # 完整的开发历史
94
+ │ ├── 技术报告_2026-06-11.md # 跨天技术报告
95
+ │ ├── README_modal_deploy.md # 部署指南
96
+ │ └── 云端部署经验.md # 部署经验总结
97
+ ├── .git/ # Git 仓库 (Hugging Face)
98
+ └── tmp_*.py # 临时测试脚本(已删)
99
+ ```
100
+
101
+ ---
102
+
103
+ ## 4. Modal 容器环境
104
+
105
+ ### 4.1 预安装依赖
106
+
107
+ Modal Image (`_omni_image`) 包含:
108
+ - CUDA 12 + cuBLAS
109
+ - CMake + GCC
110
+ - Python 包: fastapi, httpx, numpy, soundfile, modal
111
+
112
+ ### 4.2 Volume 结构
113
+
114
+ Volume `minicpm-o-4_5-models` 挂载到 `/models/`:
115
+ ```
116
+ /models/
117
+ └── MiniCPM-o-4_5-gguf/
118
+ ├── MiniCPM-o-4_5-Q4_K_M.gguf (LLM, ~8GB)
119
+ ├── vision/
120
+ │ └── MiniCPM-o-4_5-vision-F16.gguf
121
+ ├── audio/
122
+ │ └── MiniCPM-o-4_5-audio-F16.gguf
123
+ ├── tts/
124
+ │ ├── MiniCPM-o-4_5-tts-F16.gguf
125
+ │ └── MiniCPM-o-4_5-projector-F16.gguf
126
+ └── token2wav-gguf/
127
+ ├── encoder.gguf
128
+ ├── flow_extra.gguf
129
+ ├── flow_matching.gguf
130
+ ├── hifigan2.gguf
131
+ └── prompt_cache.gguf
132
+ ```
133
+
134
+ ### 4.3 编译目标
135
+
136
+ 当前的 Image recipe 编译两个目标:
137
+ - `--target llama-server` (18KB wrapper, ~77min 含 CUDA kernels)
138
+ - `--target llama-omni-server` (261KB 独立二进制, 增量 ~2s)
139
+
140
+ **建议**: 保留两个目标,因为它们各自有独立作用。
141
+
142
+ ---
143
+
144
+ ## 5. Git 提交历史
145
+
146
+ ```
147
+ 6451051 (HEAD -> main) refactor: deprecate llama-omni-server...
148
+ e0c2f3a fix: set n_parallel=1, n_ctx=4096 before omni_init...
149
+ 4429886 test_omni: add stderr capture for omni-server when init fails
150
+ 22e5fff feat: add llama-omni-server support with full-duplex omni endpoints
151
+ ```
152
+
153
+ 注意 `6451051` 的提交实际上保留了 `llama-omni-server`(重构被回滚了),但本地文件经过了修改。
154
+
155
+ **远程仓库:** https://huggingface.co/spaces/build-small-hackathon/PregoPal
156
+
157
+ ---
158
+
159
+ ## 6. 建议 Codex 推进路线
160
+
161
+ ### Step 1: 诊断 omni_init 崩溃
162
+ 在本地(C++ 环境)编译 `llama-omni-server`,用 `gdb` 或加日志跟踪 `omni_init` 中的失败点。最直接的方法是:
163
+ - 在 `server-omni.cpp` 的 omni_init handler 中,在调用 `omni_init()` 前后加 `fprintf(stderr, ...)` 输出
164
+ - 或者在 `omni.cpp` 的 `omni_init()` 函数开头加日志
165
+
166
+ ### Step 2: 修复 omni_init
167
+ 常见修复方向:
168
+ - 确保 `common_params` 中所有路径正确(`params.model.path`, `params.mmproj.path`, `params.vpm_model` 等)
169
+ - 检查 `params.n_parallel` 和 `params.n_ctx` 是否被 `omni_init` 内部覆盖
170
+ - 尝试 `params.use_mmap = false`(与 `--no-mmap` 一致)
171
+
172
+ ### Step 3: 验证全双工流程
173
+ 修复后验证:
174
+ ```
175
+ POST /v1/stream/omni_init → 200 {success: true}
176
+ POST /v1/stream/prefill → 200 (audio/image prefill)
177
+ POST /v1/stream/decode → SSE (text + audio tokens)
178
+ ```
179
+
180
+ ### Step 4: 前端集成
181
+ 将前端的录音 → base64 PCM → HTTP POST 到 FastAPI → 代理到 llama-omni-server 的流程打通。
182
+
183
+ ---
184
+
185
+ ## 7. 环境说明
186
+
187
+ ### Windows 本机
188
+ - 项目目录: `C:\Users\Andre\codes\LJB\hackthon\for_qclaw\PregoPal\`
189
+ - Python: `C:\Users\Andre\miniconda3\python.exe` (环境: base)
190
+ - Modal: 已认证,Key 已配置
191
+ - 本机无法直接运行 `modal shell` (Windows 不支持)
192
+
193
+ ### Modal 容器内
194
+ - CPU: 4 vCPU
195
+ - GPU: Tesla T4 (16GB VRAM)
196
+ - RAM: 16GB
197
+ - OS: Linux (Modal 容器)
198
+ - Python: 3.12 (Modal 默认)
199
+
200
+ ### 编译参数
201
+ ```
202
+ -DGGML_CUDA=ON
203
+ -DGGML_CUDA_NO_VMM=ON
204
+ -DLLAMA_BUILD_SERVER=ON
205
+ -DLLAMA_BUILD_TESTS=OFF
206
+ -DLLAMA_BUILD_EXAMPLES=OFF
207
+ -DLLAMA_CUDA_FORCE_MMQ=ON
208
+ -DCMAKE_CUDA_ARCHITECTURES='75;89'
209
+ -DCMAKE_BUILD_TYPE=Release
210
+ ```
211
+
212
+ ---
213
+
214
+ ## 8. 当前瓶颈总结
215
+
216
+ | 模块 | 状态 | 难度 |
217
+ |------|------|------|
218
+ | llama-server 文本推理 | ✅ 通过 | — |
219
+ | llama-omni-server 编译 | ✅ 通过 | — |
220
+ | llama-omni-server omni_init | ❌ 崩溃 | 中等 |
221
+ | omni_init → prefill → decode | ❌ 未验证 | 未知 |
222
+ | 前端集成 (Gradio) | ❌ 未开始 | 简单 |
223
+ | 全双工真实测试 | ❌ 未开始 | 未知 |
224
+
225
+ **估计剩余工作量**: 3-5 天(含 debug + 集成 + 测试)