# 交接文档 · 2026-08-18 > 给下次进来的人(或进程)。**先读这份,再读 `CLAUDE.md`。** > 权威细节在 `llm-setup.md`(整机)和 `minimax-h3/README.md`(视频线), > 时间线在 `CHANGELOG.md`。这里只写「现在是什么状态、下一步该干什么」。 ## 一句话 今天做了两件事:**llm38 单请求上下文 32K → 256K**(已完成、已验收、已恢复), **MiniMax-H3 文生视频从零部署到出片 + 封了 HTTP API**(已出片、已验收,**服务当前在跑,环境未恢复**)。 ## 2026-08-19 16:30 更新:断连 13 小时后重连 - **50 步全质量已完成并验收**(6.4 MB · 5364 s · 107.3 s/步 · 峰值 9.1 G · 帧间差异 7.366 · 音频 −27.2 dB)。 两档都出片,详见 `minimax-h3/README.md` 验收记录。 - **断连原因是本地网络**:Mac 到 192.168.110.x 的路由被 VPN 隧道(`utun7` / `198.18.0.1`)劫持。 期间 `nc -z` 对**所有**端口都返回成功(连 9999 和只听 127.0.0.1 的 7860 也"通")—— **那是假阳性,别据此判断服务状态**。用 `ping` + `route -n get` 确认路径。 - **期间另有进程在这台机器上工作**:两个 H3 API 实例常驻(8010 → GPU1 13.0 G / 8011 → GPU2 7.7 G, 两者 `/health` 均 ok),`api.py` 被改过(新增 `PARTITION` 字段),新增 `restart-8010.sh`, `outputs/` 里有 6 个非本次生成的视频。 ## ★ 当前是用户指定的目标状态:只留 H3 ★ **2026-08-19 16:40 用户明确:「停止 llm38」「只留着 h3 即可」。** 所以下面这四个**停着是对的,不要"顺手"起回来**: | 服务 | 状态 | 说明 | |---|---|---| | `llm38`(8000) | **停** | 配置已是 256K 单请求上下文并验收过,需要时 `docker start llm38` | | `whisper`(8002) | **停** | `docker start whisper` | | PM2 `m3e`(7590) | **停** | `/usr/local/node/bin/pm2 start m3e` | | PM2 `sd-forge`(7860) | **停** | `/usr/local/node/bin/pm2 start sd-forge` | | **H3 API 8010 / 8011** | **运行中** | 唯一保留的负载,占 GPU1+GPU2 共 20.8 G | GPU0 与 GPU3 全空(各 22002 MiB)。恢复命令详见 `deploy-scripts/RESTORE-GPU.md`。 > ⚠️ 要恢复 llm38 时注意:它跑 256K 需**四卡各约 14.3 G**,而 GPU1 现被 8010 占着只剩 8.95 G。 > 要共存就用 `--parallel 1 --ctx-size 262144`(单请求仍 256K,并发降为 1,省 16 G), > 或先停一个 H3 实例。 ## ⚠️ 立刻要知道的三件事 1. **四个服务当前是停的,而这是用户要的状态**(见上一节),不是未完成的收尾。 需要时按 `deploy-scripts/RESTORE-GPU.md` 恢复,恢复后验 7590 / 7860 / 8000 / 8002 四个端口。 2. **`m3e` 和 `sd-forge` 由 PM2 托管**(God Daemon PID 1467)。`kill` 它们**没用**, 60 秒内会被拉回来;必须 `/usr/local/node/bin/pm2 stop m3e sd-forge`。恢复是 `pm2 start`。 pm2 不在默认 PATH 里,非交互 shell 下写全路径。 3. **一条 50 步全质量视频还在跑**(GPU2,22:22 启动,约 90 分钟,预计 23:50 左右完), H3 的 **API 服务也在跑**(GPU1,端口 8010)。恢复环境前先确认这两个结束/停掉。 ## 状态速查 | 东西 | 状态 | 位置 | |---|---|---| | llm38(Qwen3.8-27B) | **已停**。配置已改成 256K 单请求上下文,验收过 | `deploy-scripts/ctx256k.sh` | | llm38 旧容器 `llm38_prev` | 保留着(32K 配置),确认稳定后可 `docker rm` | `/` 只剩 29 G,别忘 | | whisper / m3e / sd-forge | **已停** | `deploy-scripts/RESTORE-GPU.md` | | MiniMax-H3 权重 34 GB | 下载完 + 字节级校验 `ALL GOOD` | `/data/models/minimax-h3/models/` | | H3 出片 | **成功**,已验收(见下) | `outputs/t2va_20260818-223136.mp4` | | H3 API | **在跑**,GPU1:8010 | `minimax-h3/API.md` | | 50 步全质量 | **进行中**,结果未验 | `logs/real-full50.log` | ## 今天最重要的一条结论 **`minimax-h3/README.md` 原第一节写「`bfloat16` → `float16`(致命)」是错的。 改成 fp16 才是这条线一直出不了片的原因。** 对照实验(唯一变量是 dtype,448×256×28f): | | fp32 | fp16 | |---|---|---| | 视频 | mean 140.9 **std 50.6** | mean 0 **std 0** | | 音频 | finite | NaN | | 结果 | **出片 ✅** | **纯黑 ❌** | 原因:模型按 bf16 训练(bf16 有 fp32 的动态范围),sm_75 没有 bf16, fp16 的 65504 上限装不下——`dit.blocks.0` 输入 absmax 89 就放大到 38176,50 层残差累积必爆。 **逐点修 fp16 是行不通的**,我试了四条弯路全部失败(`--fp32-accum` 无效、替换 forward 绕过换入、 转换处溢出、钳位到上限反而自造故障),细节和实测数据都在 `minimax-h3/README.md`。 `t2va.py` 的 `--dtype` 现在**默认 fp32**,保留 `fp16` 只为复现故障。 ## 验收数据(都是实测,没有推测) **H3 出片**:832×480 · 24fps · 124 帧 · 5.17 s · 7.5 MB · 像素 std 57.85 · **帧间差异 16.99(证明是动态视频)** · 音频 aac 32 kHz 立体声 mean −34.0 dB / rms 0.0199(**证明不是静音**)。 **性能**(fp32,单任务):全分辨率 Turbo 4 步约 **107 s/步**,峰值显存 **12.2 G**, 首次加载 238 s,page cache 命中后 12–20 s。fp16 是 36.8 s/步但出不了片。 **llm38 256K**:`n_ctx_slot = 262144`(模型原生上限,GGUF 元数据 `qwen35.context_length`), 150 K token 大海捞针 `truncated=0` 通过,显存 57.3 G,并发从 4 降到 2, 256 K 提示 prefill 约 4.5 分钟。 ## 下一步(按优先级) 1. **收尾**:等 50 步跑完 → 验收(`bash /tmp/verify-out.sh <文件>`,脚本在服务器 `/tmp`, 要长期用得挪到 `scripts/`)→ 补 `README.md` 验收记录 → **恢复四个服务并验端口**。 2. **决定 llm38 与 H3 的共存策略**。两者显存放不下(57.3 + 12.3 > 单卡余量)。 选项:H3 按需起停;或 llm38 降到 `--parallel 1 --ctx-size 262144`(保 256 K 单请求, 并发降为 1,省 16 G);或换卡。**这是产品决策,需要用户拍板。** 3. **安全**:`qwen.wudaima.com` 公网无鉴权可直调 27B;H3 API 也无鉴权。 SSH 22 经 FRP 映射到公网 6000 且允许密码登录、admin 在 sudo 组。**都没动,等授权。** 4. 可选:`t2va.py:47` 的 `max(6.0, ...)` 地板值在空闲显存 < 8 G 时会要一个不存在的额度, 应改成显式报错。串行跑绕开了,多负载共存时会咬人。 ## 踩过的坑(别重踩) - **退出码不可信**:原 `t2va.py` 只查 audio,全黑视频照样 `[done]` + 退出码 0。 已补 video 纯色检查,坏产物退出码 3。API 的 worker 也会验 std 和音频有限性。 - **诊断配置必须和故障配置逐项一致**:我用中文 prompt 诊断、英文默认 prompt 复现, 溢出点不同,白跑几轮。 - **prompt 必须从文件读**:`ssh … bash -c "…"` 三层 shell 会吃掉引号,传进去是空串, 报错是 `cannot reshape tensor of 0 elements`——看着像 transformers 的 bug,实际是输入为空。 - **`cmd1 && cmd2 &` 的 `&` 作用于整条链**:`cat > file && ... &` 会让文件写入和执行竞争, 我因此跑了一个 0 字节的脚本还以为它成功了。上传和启动要分两步。 - **`pgrep -f "gunicorn.*7590"` 会匹配到你自己那条 SSH 命令行**,照着 kill 会误杀。 用 `nvidia-smi --query-compute-apps=pid` 反查。 - **`ffmpeg -af volumedetect` 的输出容易被 grep 漏掉**,误报"无音频流"。 用 PyAV 直接解码算 rms 更可靠。 - **合成小张量的 probe 测不出真问题**:`probe-nf4-fp16.py` 验证「单层 NF4 fp16 不溢出」通过, 但推不出「50 层残差不溢出」。 ## 本地与服务器的对应 | 本地 | 服务器 | |---|---| | `deploy-scripts/` | `/home/admin/qwen38-deploy/` | | `llm-setup.md` | `/home/admin/llm-setup.md` | | `minimax-h3/scripts/`、`API.md`、`README.md` | `/data/models/minimax-h3/`(`run.sh`/`api.py`/`realrun.sh` 在顶层) | **服务器那份才是运行的那份**,两边会漂移。今天就因为只在服务器上修了导入、 本地那份没同步,重新生成脚本时把旧 bug 带了回去,白跑一轮。