CLAUDE.md 13.6 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 已上线
raylight/ MiniMax-H3 文生视频(ComfyUI + Raylight 插件,4卡 FSDP 集群) 2026-08-22 起生产默认后端,minimax-h3/ 转热备份

两条线共用同一批 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
raylight/ 2026-08-22 起 h3-console 的默认后端:ComfyUI + Raylight 插件,4卡当一个 FSDP 集群跑 MiniMax-H3(不是4个独立worker,任何时刻只处理1个请求)。server.py(8100)对外契约兼容旧 gateway.py+api.py,管理常驻 ComfyUI 进程(8188,仅内部) 0-3 全部(FSDP集群) ⚠️「124帧会OOM」是旧结论,2026-08-22切SAGE_FP16后已推翻——0参考图时1344×768能撑412帧不OOM;但带参考图(ref2va/fl2va)时这份表不适用,2026-08-24实测同一份"1344×768×362帧×3参考图"配置5次4次失败,真实上限没测过,见 raylight/README.md「已知限制」第1条 8100(内部,h3-console 的 H3_GATEWAY_URL 指向这)
minimax-h3/ 代码已删除(2026-08-24),只剩权重/venv/日志。之前是 MiniMax-H3 FL2VA/Ref2VA NF4 文生视频的旧架构(api.py 四实例+gateway.py调度层,四卡各自独立worker)。先改名 .disabled-20260824 禁用,结果 2026-08-24 晚上还是被人手动 mv 回原名+手动启动过一次(跟 raylight 抢 GPU1,导致 console 短暂路由错乱),于是把 gateway.py/api.py/DiffSynth-Studio//scripts/等路由代码整个删掉(不只是改名),从根上杜绝再被手动复活。删前打包备份,见 CLAUDE.md「MiniMax-H3 脚本」一节。服务器 /data/models/minimax-h3/ 目录还在,但只剩 console/(h3-console 在用)、models/(53GB权重)、venv/、outputs/、logs/ 无(进程已停,代码已删) 权重仍在,如需复活须先从备份包恢复代码 无
h3-console/ H3 Web 管理台:上传/生成/预览三界面 + 任务持久化。两个进程共享同一份 sqlite/assets:8080(局域网直连,BASE_PATH 空)+ 8081(H3_CONSOLE_BASE_PATH=/console,专供公网子路径用)。2026-08-22 起两个实例的 H3_ENABLE_SUPERVISOR 都关了——fl2va/ref2va 弹性调度器(按partition flip某张卡)是给 minimax-h3 那套"4个独立worker"架构设计的,raylight 的FSDP集群架构下没有"单卡分区"这个维度,开着会出错 不占显存(自己不跑模型) — 局域网 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.2GB"这条 2026-08-24 确认是过期信息——当时机器上根本没有任何 带"whisper"字样的进程。实际常驻的是 stable-diffusion-webui-forge(PID对应/data/models/ stable-diffusion-webui-forge)和一个 embedding 服务(gunicorn:7590),跟这台服务器的 LLM/H3 两条工作线都无关,2026-08-24 一并停掉了(详见 CHANGELOG)。排卡前还是先 nvidia-smi 看实际 余量,不要照着这张表的旧数字猜,llama.cpp 默认 tensor-split 按总显存而非剩余显存均分, 起新负载不加 -ts 容易把公网服务挤 OOM——不过 LLM(llm38) 目前也已停(见上)。

⚠️ 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 脚本(⚠️ 2026-08-24 代码已删除,只剩备份压缩包)

minimax-h3/scripts/(含 probe-*.py 兼容性探测四件套、api.py/gateway.py 等路由代码) 本地仓库和服务器上都已经删除,不再是能直接跑的目录。删除原因:生产已全面切到 raylight/,2026-08-24 又发现这套旧代码被人手动复活过一次(跟 raylight 抢 GPU1),干脆连 代码一起删掉,杜绝再被误启动。

删之前打了包,换硬件或升级 torch / bitsandbytes 需要重新跑 probe-*.py 时,先从这里 解压出来:

  • 本地:~/Documents/lemonAI/2080tiserver-backups/minimax-h3-local-repo-backup-20260824.zip
  • 服务器实际删除内容(更全,含 DISABLED-README.md 等本地没有的文件):同目录 minimax-h3-code-backup-20260824.tar.gz

服务器上 /data/models/minimax-h3/ 目录本身还在,但只剩 console/(h3-console 正在用, 别动)、models/(53GB NF4 权重,没删)、venv/、outputs/(历史生成结果)、logs/。

当前状态(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-24 更新:LLM(llm38)和旧 H3(minimax-h3 的 gateway.py+api.py)都已下线,不占显存。 llm38 容器 docker ps -a 显示 6 天前就已经停了(Exited (0)),不是本次操作停的,只是文档一直 没更新——qwen.wudaima.com 现在实际上是打不通的,上面这段"对外服务中"的描述已经过期。 minimax-h3 的四个 worker(8010-8013)+ gateway.py(8000)是本次手动按端口 kill 停的, 停完反复自己又起来——一开始误以为是别的并发会话在手动重启,后来确认这台机器当时只有一个人 在用,排查出真正原因是 PM2(系统级进程管理器)在管另外两个不相关的服务(sd-forge/embedding), 已经 pm2 delete+pm2 save 处理掉;minimax-h3 本身的重启触发源没有查到,改用把 api.py/gateway.py 本体也改名的办法从根上堵死,完整排查过程见 CHANGELOG 2026-08-24 「更正」那条。现在这台机器上生产只跑 raylight/(h3-console 默认后端),代码/权重 都还在,两条线要拉回来都还是走各自的 start.sh/docker start llm38,没有删任何东西。

这是一台测试机(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)用追加/局部编辑,不要整文件覆写。