CLAUDE.md 9.95 KB

CLAUDE.md

本目录是公司 GPU 服务器 192.168.110.67(4 × RTX 2080 Ti 22G)的工作区。真正的服务和模型都在那台远程机器上,这里只放手册、脚本和记录。

目前有两条并行的工作线:

目录 工作线 状态
llm-setup.md / deploy-scripts/ / CHANGELOG.md LLM 推理服务(llama.cpp,对外 8000 端口) Qwen3.8-27B 已上线
minimax-h3/ MiniMax-H3 FL2VA 文生视频+音频(NF4 量化,sm_75) 探查/调试中

两条线共用同一批 GPU,改动前先 nvidia-smi 看余量——LLM 服务常驻约 29 GB / 88 GB,剩下的才是可用的。下面第「硬件的三条硬限制」一节对两条线都适用(尤其 bf16 不可用这条,minimax-h3/scripts/probe-turing-caps.py 就在探这个)。

接入

ssh admin@192.168.110.67        # 密码 P@ssw0rd

没装 sshpass。建议用 ControlMaster 复用连接(socket 路径必须短,否则超 Unix domain socket 长度限制):

# 一次性建连(用 expect 喂密码),之后所有命令走复用 socket 免密
ssh -o ControlMaster=yes -o ControlPath=~/.ssh/cm67 -o ControlPersist=30m -N admin@192.168.110.67 &
ssh -o ControlPath=~/.ssh/cm67 admin@192.168.110.67 '<命令>'

sudo 用 echo "P@ssw0rd" | sudo -S -p "" <命令>。注意 /data 是 root 属主,admin 直接 mkdir 会失败。

不在公司局域网时(在家、出差),192.168.110.67 连不通,见 remote-access-from-home.md—— 公网 HTTP 隧道(qwen.wudaima.com)能用,但公网 SSH 隧道(22→6000)2026-08-21 实测不通, 详见该文档和 docs/todo/ssh-public-tunnel-broken.md。

先读这个

HANDOFF.md 是每次进来的入口——现在是什么状态、哪些服务停着、下一步该干什么、 已经踩过哪些坑。它比本文件更新得勤,因为它记的是"此刻"。

权威文档

llm-setup.md 是这台机器的完整运维手册——模型清单、启动命令、显存核算、回滚流程、FRP/nginx 映射、硬件限制全在里面。动手前先读它,不要凭记忆回答。

⚠️ 本地这份是服务器上 /home/admin/llm-setup.md 的副本,两边会漂移。 以服务器上那份为准(SSH 进去的人读的是它)。同步:

# 从服务器拉最新
ssh -o ControlPath=~/.ssh/cm67 admin@192.168.110.67 'cat /home/admin/llm-setup.md' > llm-setup.md
# 推回服务器(改完本地后)
cat llm-setup.md | ssh -o ControlPath=~/.ssh/cm67 admin@192.168.110.67 'cat > /home/admin/llm-setup.md'

硬件的三条硬限制

细节见 llm-setup.md 第二、三节,这里只列最容易白费功夫的:

  1. 4 × RTX 2080 Ti = Turing / compute capability 7.5。装不了 FP8 模型(原生需 Ada 8.9+,vLLM 的 fp8_marlin 回退也需 Ampere 8.0+),不支持 bf16。 LLM 走 GGUF + llama.cpp 是唯一实际路径。扩散/视频模型不受此限——PyTorch + bitsandbytes NF4 在 sm_75 上实测可用,见 minimax-h3/。 bf16 的坑比想象中深:sm_75 上 bf16 没有任何高效 attention kernel,PyTorch 不报错、静默掉到 MATH 后端物化整个注意力矩阵,长序列表现为莫名 OOM。全链路改 fp16 才行。
  2. llama.cpp build 有下限。qwen35 架构需 ≥ b10450,低于此加载正常、显存正常、tok/s 正常、但输出全是乱码。上线前必须 --version 查 build 号。
  3. 网络:huggingface.co 与 ghcr.io 的 blob 层都不通,改用 hf-mirror.com 和 ghcr.nju.edu.cn。出口带宽约 5.9 MB/s 封顶,并行下载不会更快,只会互相抢——下载必须用 curl -C - 断点续传 + setsid nohup 脱离 SSH 会话。

目录约定(迁移工作内容时按此放)

一个工作负载一个顶层目录,目录名 = 服务/模型的短名。目录内固定三样:

<workload>/
  README.md      # 这个负载是什么、跑在哪张卡、怎么起、怎么停、怎么回滚
  scripts/       # 服务器上对应目录的副本(保持文件名一致,方便双向 diff)
  notes.md       # 可选:踩坑记录、被推翻的假设、实测数据

顶层只放跨负载的东西:本文件、CHANGELOG.md(按时间倒序,一次变更一节)、llm-setup.md(整机手册)。

迁移进来的工作必须补三件事,否则等于没迁:

  1. 在下面「当前负载」表里加一行(占哪张卡、多少显存、对外端口)。
  2. 在 CHANGELOG.md 顶部加一节,写清结果、被推翻的假设、实测数据——CHANGELOG 的价值在踩坑记录,不在流水账。
  3. 说明脚本对应服务器上的哪个绝对路径。本地全是副本,服务器上那份才是运行的那份,会漂移。

当前负载

目录 跑什么 卡 显存 对外
deploy-scripts/ Qwen3.8-27B-Q5_K_M(llama.cpp,容器 llm38) 0-3 分片 57.3 GB(256K 上下文,2 槽位) 8000 → qwen.wudaima.com
minimax-h3/ MiniMax-H3 FL2VA/Ref2VA NF4 文生视频,api.py 常驻四实例(GPU0-3,端口 8010-8013)+ gateway.py 调度层(端口 8000) 四卡各一进程 单卡 fp32 峰值约 9-14 GB(视时长/分辨率),另占 CPU 内存约 32 GB/worker 8000(内部,gateway.py)
h3-console/ H3 Web 管理台:上传/生成/预览三界面 + 任务持久化 + fl2va/ref2va 弹性调度器。两个进程共享同一份 sqlite/assets:8080(局域网直连,BASE_PATH 空,开弹性调度器)+ 8081(H3_CONSOLE_BASE_PATH=/console,不开调度器,专供公网子路径用) 不占显存(自己不跑模型,管理 minimax-h3 的四卡) — 局域网 http://192.168.110.67:8080;公网 http://qwen.wudaima.com/console(frp locations=/console 分流,gateway.wudaima.com 那条独立域名确认走不通,缺口在 frp 服务端 60.205.214.169,见 CHANGELOG)
(常驻) whisper GPU3 3.2 GB —

排卡前先 nvidia-smi 看实际余量:GPU3 被 whisper 占着,llama.cpp 默认 tensor-split 按总显存而非剩余显存均分,起新负载不加 -ts 容易把公网服务挤 OOM。

⚠️ 2026-08-18 上下文提到 256K 后余量大幅收紧:四卡合计已用 61.4 / 88 GB,只剩约 26 GB,GPU2 最紧只剩 5.4 GB。minimax-h3 按「空闲显存 − 2 GB」自适应,等于它的可用显存被同步压缩了。两条线同时跑之前先看 nvidia-smi。

部署脚本

deploy-scripts/ 下是服务器 /home/admin/qwen38-deploy/ 的副本:

脚本 作用
cutover.sh 切换到 Qwen3.8(校验完整性 → 停旧容器 → 起新容器 → 等健康)
restore.sh 一键回滚到 Qwen3.6,约 3-5 分钟
download.sh 断点续传下载模型
pull2.sh 从 NJU 代理拉镜像并 retag
ctx256k.sh 把单请求上下文切到 256K(旧容器改名保留,失败自动回滚)
ggufmeta.py 读 GGUF 元数据(查模型原生上下文上限、层数、KV 头维度)——别凭记忆猜上下文上限,跑这个

回滚依赖三样东西,都不要删:镜像 tag llamacpp-rollback:b9570、模型文件 /data/models/Qwen/Qwen3.6-27B-GGUF/、脚本 restore.sh。

MiniMax-H3 脚本

minimax-h3/scripts/ 对应服务器 /data/models/minimax-h3/scripts/(run.sh 在 /data/models/minimax-h3/run.sh)。权威文档是 minimax-h3/README.md——为什么官方示例 照抄跑不起来、Turing 的 dtype/attention/量化实测结论、多卡为什么只能做独立 worker。

其中 probe-*.py 四件套是当初得出兼容性结论的探测脚本。 换硬件或升级 torch / bitsandbytes 后,先跑这四个再动别的。

当前状态(2026-08-18)

对外服务 http://qwen.wudaima.com(仅 HTTP,无鉴权),经 FRP 指向本机 8000,跑 Qwen3.8-27B-Q5_K_M。

上下文:单请求 256K(--parallel 2 --ctx-size 524288,每槽 262144)。256K 是模型原生上限——GGUF 元数据 qwen35.context_length = 262144,不是 128K;早期文档里的 128K 是低估。已用 150K token 大海捞针实测通过(truncated=0)。代价是并发从 4 降到 2,且 256K 提示光 prefill 约 4.5 分钟。

回滚:docker rm -f llm38 && docker rename llm38_prev llm38 && docker start llm38(约 15 秒)。旧容器 llm38_prev 停着保留,稳定后再删(/ 只剩 29 GB)。

⚠️ 已知安全问题:公网可无鉴权直调 27B 推理;SSH 22 端口经 FRP 映射到公网 6000 且允许密码登录、admin 在 sudo 组。

这是一台测试机(2026-08-18 用户明确)

这台机器的用途就是测试各种模型,不是生产环境。 显存不够时直接停 llm38 给别的负载让路是允许的、也是预期做法,不需要为此设计复杂的共存方案。

这条推翻了本文件早期版本里「8000 是对公网服务的,停服务是对外可见动作」的前提。不要再把显存争抢当成需要精巧规避的约束——串行跑就行:

docker stop llm38     # 让出 ~57 GB,四卡各回到约 21 GB 空闲
# ... 跑 minimax-h3 / 别的模型 ...
docker start llm38    # 跑完起回来,约 15 秒

副作用:这样测出来的数字才是干净的(不被抢占扭曲),比在争抢状态下测更有参考价值。

操作纪律

  • 改动线上服务前先确认回滚路径可用。停服务本身不敏感(测试机),但起不回来会很麻烦。
  • 大文件下载和镜像拉取一律后台跑(setsid nohup),不要占着前台等。
  • 不要凭记忆回答这台机器的事。 先读 llm-setup.md 和 CHANGELOG.md——里面记的坑(build 号下限、FP8 不可行、MTP 不激活)都是已经花过时间验证的,重复踩一遍是纯浪费。
  • 多个进程可能同时在这个目录里干活。改共享文件(本文件、CHANGELOG.md、llm-setup.md)用追加/局部编辑,不要整文件覆写。