另外,我为deepseekharness安装了记忆系统,让dsh也拥有跨会话长期记忆了。

另外,我为deepseekharness安装了记忆系统,让dsh也拥有跨会话长期记忆了。


硬件就不晒了,老机箱的配置,只换了显卡,原32GB内存再加了32GB内存。晒一张这个模型驱动deepseekharness的截图吧!
@Xiaoyong-S 是的,内存太小,现在购入大内存实在不划算,只能先将就一下了。
@johnnybegood 确实内存不多,只能IQ2的试试水。
我是一个本地大模型玩家,机器是一台 X570 平台:RTX PRO 4500 Blackwell(32GB)+ Ryzen 7 3700X + 60GB 内存。之前主力是 27B 级别的本地模型(SGLang),一直眼馋 Qwen3.8-Flash-Next 这个 125B 的 MoE——但 125B 意味着"没有 96GB 显存别想碰",直到 Strata 出现。
Strata(Niko1221/Strata,MIT 开源)是专为这一个模型写的推理引擎:把 24,576 个专家按三层摆放——热专家进显存、全部专家进内存、n-gram 查表进 SSD——让 12-32GB 的游戏卡也能跑 125B。10 月初它冲上 HN 首页(900+ 分),社区帖我也翻了个遍,国庆假期第六天,我花了一个下午把它从零装到能用。
最值得讲的一组数字:我这张 32GB 卡上,短对话 decode 跑出 189 tok/s;升级到 262K 满上下文后,用 24.5 万 token 的长文实测零崩溃、埋词召回 3/3 全中。安装全程约 50 分钟(含编译、68GB 模型下载与校验)。
这篇帖子把全流程、全部实测数据、踩过的坑、不要做的事一次写全。所有数字都附测法,欢迎复现。
最重要机制:125B 是怎么塞进 32GB 显存的
晚间更新:agent 对打补测 + 原主力退役表 1 · 最终成绩单
| 维度 | 结果 | 备注 |
|---|---|---|
| 模型 | Qwen3.8-Flash-Next IQ2_XS(125B 总参 / 6B 激活) | 68GB 权重,双文件 SHA256 对照官方全过 |
| 设备 | RTX PRO 4500 Blackwell 32GB 单卡 | 游戏卡/工作站卡通吃(本项目 NVIDIA/AMD 都支持) |
| 短对话速度 | decode 189 t/s(16K-32K 档) | 比官方 12GB 卡标线(79)高一倍多 |
| 长文速度 | 127K 上下文 186.8 t/s;245K 深度 85.1 t/s | 长上下文衰减系行业通性,官方同深度标线 ~53 |
| 上下文 | 262K 满血(模型原生上限) | 24.5 万 token 长文实测零崩溃 |
| 召回 | needle 全绿:32K/128K/250K 各深度 100% | 90% 深度埋词也能捞出来 |
| 思考模式 | 支持 off/low/medium/high | 陷阱题答对,思维链完整 |
| 资源占用 | 显存 ~33.2/34.2 GB(十进)、内存 47/60GB | 显存"看起来"97% 是设计(见机制节) |
| 稳定性 | 全程零崩溃(含 4 连发 24.5 万 token 压力) | 尚未做小时级长稳(见未测项) |
| agent 任务补充实测 | 13.3 秒完成真代码任务、一次过隐藏验收;对照原主力 27B 快 6.9× | 2026-10-06 晚补测,见文末更新 |
表 2 · 这次实践的流水账
| 环节 | 耗时 | 说明 |
|---|---|---|
| 硬件自检 | 1 分钟 | 官方自带 --check |
| CUDA 13.0 安装 | 15 分钟 | Ubuntu 26.04 需手动路径(见坑 1) |
| 引擎编译 | 5 分钟 | 撞 glibc 坑,修复后全绿(见坑 2) |
| 模型下载+校验 | 13 分钟 | 68GB,换国内源后 120MB/s(见坑 3) |
| 配置补全(MTP+打包) | 7 分钟 | 自动流程 |
| 启动+首答 | 2 分钟 | 35.5GB 以 3.08GiB/s 载入内存 |
| 全套实测 | 20 分钟 | 五档压测+召回+思考 |
| 262K 升级+验证 | 15 分钟 | 含 24.5 万 token 四次压力测试 |
| agent 对打补测 | 10 分钟 | 同题同协议 vs 原主力 27B,见文末更新 |
| 词 | 白话解释 |
|---|---|
| 量化(IQ2_XS) | 把模型权重压缩到约 2 比特的格式。体积省 8 倍,质量小损(不同压缩档质量不同,按内存选) |
| MTP 推测解码 | 模型自带的"抢答小助手"先猜后面几个词,大头模型一次核对——猜中就赚了,输出质量不变。实测约 1.6-1.8 倍加速 |
| 上下文 / 262K | 模型一次能"记住"的文本量。262K token ≈ 19 万汉字,够塞一整本长篇小说 |
| prefill / decode | 两个阶段的吐字速度:prefill = 读你发的内容(读入越慢首答越久);decode = 一个字一个字写答案的速度 |
| 项 | 值 |
|---|---|
| GPU | NVIDIA RTX PRO 4500 Blackwell,32GB GDDR7,驱动 595.91.07 |
| CPU | AMD Ryzen 7 3700X(8 核 16 线程,AVX2,无 AVX-512——官方说 AVX-512 机器更快,我这台是普通款) |
| 内存 | 60GB DDR4 |
| 磁盘 | NVMe SSD(模型放根盘,1.3TB 空闲) |
| 系统 | Ubuntu 26.04 |
| CUDA | 13.0(为编译引擎装的,与系统原有 12.9 共存) |
| 引擎 | Strata v0.1.39(源码编译) |
| 模型 | Qwen3.8-Flash-Next GSQ-RCO IQ2_XS(68GB,官方推荐档) |
| 上下文 | 262,144(模型原生拉满) |
️ 为什么选 IQ2_XS 而不是更高质量的 IQ3_S?——内存。60GB 机器上的安全档是 IQ2_XS(专家 35.5GB);IQ3_S 的 50GB 专家 + 系统会让 64GB 机器贴边。如果你有 96GB+ 内存,直接上 IQ3_S(质量更高,速度低一档)。社区有人实测过:更激进的量化(IQ3_S→IQ3_XXS)快 14-23%,但输出 token 是 2.7 倍(过度思考、反复返工),端到端反而慢 2.4 倍——所以别只看压缩率。
# 1. 克隆 + 硬件自检(不装任何东西,1 分钟)
git clone https://github.com/Niko1221/Strata.git && cd Strata
./setup.sh --check
# 期望末行:This PC can run Strata. 且列出各量化档的 RAM 适配
# 2. CUDA Toolkit 13.0(Ubuntu 22.04/24.04 可跳过——setup 自动装;
# 26.04 需手动,见我踩的坑 1/2)
# 3. 非交互安装(下载 68GB + 编译引擎,全程后台跑,可断点续传)
./setup.sh --yes --family qwen --model IQ2_XS --context 262144 --no-start
# ⚠️ 注意:改设置重跑时不要漏 --model(见我踩的坑 3)
# 4. 启动(前台进程,关闭即停)
./run-iq2_xs.sh
# 浏览器自动开 http://127.0.0.1:8080
几个设计上良心的地方(实测确认):
光能跑不算数,我把它接进了自己的三套体系(都实测通过):
| 集成 | 方式 | 实测 |
|---|---|---|
| systemd 服务化 | strata.service(user 级) |
️ 必须配 LimitMEMLOCK=infinity(专家要锁 35.5GB 内存,systemd 默认只给 8MiB);25 秒就绪 |
| 一键切换 | 个人切换脚本新增 strata 目标(现编号 1=strata) | 与 SGLang 27B / ComfyUI 显存互斥自动生效;切换实测:起 30s / 互切 75s / 切回 55s |
| dsh 客户端 | 新增 local-strata 渠道 | 关键配置:thinkingFormat: openai(它直接吃标准 reasoning_effort 字段);headless 实测 12.9 秒完成任务 |
最重要机制:125B 是怎么塞进 32GB 显存的很多人第一反应是"32GB 显存跑 125B?骗人的吧"。原理其实很朴素,官方 paper 讲得很清楚,我用厨房打个比方:
这台机器被当成一个"异构厨房"用:
| 层 | 放什么 | 我这台实配 |
|---|---|---|
灶台(VRAM 32GB) |
每道菜都要用的(注意力/路由器/输出头,约 3.5GB)+ 最热门的专家缓存——它自己会学你聊什么、动态换血 | 18,119 个专家常驻(约 26GB),命中率 95-99% |
| 🧺 备菜台(RAM 60GB) | 全部 24,576 个专家(35.5GB)——显卡没有的,CPU 当场算,和显卡同时干活 | 同时开 7 个 CPU 专家流水线 |
储物柜(SSD) |
一张 28.8GB 的 n-gram 查表,每次只读几行 | 走系统页面缓存,基本无感 |
三个关键设计(为什么能"同时"而不是"轮流"):
由此引出一个所有人都会误解的现象:我装好后看到显存占用 33.2/34.2 GB(97%)也慌了一下——这是设计状态,不是极限。引擎的策略就是"把剩余显存全部填成专家缓存换速度"(启动日志原话:"423 MiB of VRAM free with everything loaded")。我后来升级 262K 上下文实测:显存代价只有缓存缩 1%(18,314→18,119 槽)——因为长上下文的 KV 记忆主体放在内存里(+1GB),根本不吃显存。所以**"97% 占用"和"能开多大上下文"是两个独立问题**。
测法说明:全部用 OpenAI 兼容接口、streaming 计时、temperature=0、reasoning off(思考模式单独测)。长短文任务为"编号记录复述"类(含固定句式重复文本),这类任务对推测解码友好,数字偏乐观——预计真实代码/agent 任务会有出入,见未测项。每条数据都由我机器上的基准脚本自动采集。
表 3 · 五档压力实测(131K 配置时代)
| 实际 prompt tokens | prefill t/s | decode t/s | 召回判断题 |
|---|---|---|---|
| 5,501 | 2,789 | 142.2 | ![]() |
| 22,576 | 3,514 | 189.1 | ![]() |
| 46,966 | 5,291 | 189.0 | ![]() |
| 96,106 | 5,138 | 179.7 | ![]() |
| 127,561 | 8,828 | 186.8 | ![]() |
表 4 · 262K 满上下文验证(升级后实测)
| 项目 | 数据 |
|---|---|
| 245,308 token 深度压测 | prefill 3,263 t/s、decode 85.1 t/s、 零崩溃、 找回全部编号 |
| 244K 深度召回 | 3/3 找到(明细见表 5) |
| 升级后短任务复核 | 4K 档 144.5 t/s(与升级前持平,零损失) |
| 资源增量 | 内存 +1GB、显存缓存 -1%、重启 25 秒 |
表 5 · needle 召回测试(官方工具 needle_bench.py,埋词位置 10%/50%/90% 三档)
| 上下文长度 | 结果 | 耗时/次 |
|---|---|---|
| 32K | 3/3 |
5-10 秒 |
| 128K | 3/3 |
34-38 秒 |
| 250K | 3/3 |
73-77 秒 |
思考模式:经典陷阱题("17 只羊除了 9 只都跑了还剩几只")
答对,思维链走 reasoning_content 字段完整返回,总耗时 1.5 秒。
表 6 · 横向对照(同模型不同硬件)
| 机器 | 量化 | decode @128K | 来源 |
|---|---|---|---|
| 本机 RTX PRO 4500 32GB | IQ2_XS | 186.8 t/s | 本帖实测 |
| RTX 5090(同量化) | IQ2_XS | 165 t/s | 社区报告 |
| RTX 5070 12GB(官方基准机) | IQ2_XS | 63 t/s | 官方数据 |
| 同款 4500 32GB(512GB 内存机) | IQ3_S | 116 t/s | 社区报告 |
我这张卡能跑到 5090 之上,解释一下:32GB 显存对 IQ2_XS 这个体积的模型"缓存命中率"极高(95-99%),而 IQ2_XS 本身又是最轻的档——两个因素叠加。5090 那台跑的是同一量化但上下文策略不同。
症状:setup.sh 到第 4 步停住——"the CUDA Toolkit can be installed automatically on Ubuntu 22.04 / 24.04 only",要求手动装 CUDA 13.0。
根因:项目自动安装 CUDA 的路径只覆盖 22.04/24.04;26.04 太新。
修复:手动走等效路径(cuda-keyring 用 ubuntu2404 源 + apt install cuda-toolkit-13-0,约 6GB/10 分钟)。装完把系统默认 cuda 软链接恢复指向旧版(用 update-alternatives --set),不影响引擎——它从 nvcc 绝对路径找工作,不依赖全局软链。
症状:引擎编译第一步(CMake 探测编译器)就挂:error: exception specification is incompatible with that of previous function "rsqrtf"。
根因:Ubuntu 26.04 的 glibc 2.43 给 rsqrt/rsqrtf 加了 noexcept 标记,与 CUDA 13.0 头文件的旧声明打架——系统头文件级别的冲突,换编译器版本没用(网上有人说降级 gcc,实测无效)。
修复:llama.cpp 官方文档给的正解——给 CUDA 安装目录的头文件打一个小补丁(备份后,给 rsqrt/rsqrtf 两行声明加上 noexcept (true)),编译 5 分钟全绿。(项目仓库里 pinned 的 llama.cpp 文档正好写了这个 issue,而且是社区 issue 里维护者确认过的方案。)
症状:从 HuggingFace 官方源拉 68GB 模型,速度只有 0.2-4MB/s(我这出口走代理跨境),aria2 多线程也只能 2-4MB/s,按这个速度要 7 小时。
根因:不是工具问题,是到 HF 的线路慢(跨境瓶颈)。我测试对比过:内置下载器 0.2MB/s、aria2 八线程 2.6MB/s、hf-xet 3.8MB/s——都受限。
修复:换 ModelScope(国内源)——实测 120MB/s,68GB 只要 11 分钟。安全性与官方源等价:MS 的存储对象 ID 就是文件 SHA256 本体,且下载后我用双文件 SHA256 对照 HF 官方发布值全部一致。连 MTP 层(另一种张量范围下载)也切到了 MS 通道继续沿用。
结论:跨境的锅别让工具背。测速 → 换源 → 校验(SHA256 对齐官方),比折腾多线程参数高效得多。
症状:下载完成的 aria2 进程停在后台不退出(文件其实已完整)。
根因 + 修复:进程停在收尾阶段,发 SIGTERM 后正常退(文件+控制文件都已就绪,无损)。另发现一个坑:aria2 配置里有 enable-rpc=true(6800 端口),同一时刻只能跑一个 aria2 实例——并发调用第二个会绑定失败秒退;另外配置里的下载目录会覆盖当前目录,用 -d 显式指定才稳妥。
症状:测 262K 满上下文时,标称 131K 的测试集实际打进去 19.2 万 token,直接被服务端 400 拒绝——不是引擎的问题,是测试脚本按"每行 18 token"估算、中文实际每行 26+ token。
修复:按实测比例(×1.47)反推目标值重测。这也是所有做上下文测试的人都会踩的坑——永远以服务端返回的 prompt_tokens 为准,别信标称值。
别做 |
为什么 |
|---|---|
| 在 26.04 上为了 glibc 冲突折腾 gcc 版本/降级系统库 | 冲突在系统头文件层,换编译器没用;正解是打 CUDA 头补丁(5 分钟) |
| 给官方源硬扛慢速下载 | 换国内源 + SHA256 校验,600 倍速度差 |
| 看到显存 97% 就断定"开不了大上下文" | 97% 是设计(缓存填满换速度),262K 实测只多占 1% 缓存 |
跑 setup.sh --setup 改设置时不带 --model |
它会把流程理解成"装新模型",自动下推荐档(我这边撞到它自动开始下 IQ3_XXS 76GB,幸好及时终止清理) |
| 60GB 内存机硬上 IQ3_S / 强行 512K | 内存会贴边/换页,首答从 0.4 秒变分钟级;262K 是这台机器的甜蜜点 |
把 --ple-io ram(锁页)当必开项盲目抄 |
那是双卡大内存机的优化;我 60GB 机器装不下(专家+PLE 会爆),且社区 A/B 实测 SSD 版反而略快 |
复现清单(版本锁定):
| 组件 | 版本/来源 |
|---|---|
| 引擎 | Strata v0.1.39(GitHub 源码编译) |
| 模型 | ISTA-DASLab/Qwen3.8-Flash-Next-GSQ-RCO-GGUF,IQ2_XS 档(ModelScope 同源下载) |
| Web UI | http://127.0.0.1:8080(Chat/Monitor/About) |
| API | http://127.0.0.1:8080/v1(OpenAI 兼容;模型名任意) |
| 关键参数 | 131K 配置自动生成;262K 仅改 --max-context 一处 |
| 实测脚本 | 官方 needle_bench.py + 自建 streaming 计时基准(TTFT 首 token 时间戳法) |
未测项(诚实揭露):
--calibrate(官方 NVIDIA 自动调参)没跑——据说还能再快几个 %,留作下次折腾。
2026-10-06 晚间更新:agent 对打补测 + 我把原来的主力撤了表 3 的数据是复述型任务(我当时自己就标注了「数字偏乐观、agent 任务未测」)。晚上把这个未测项补上了——两个模型跑同一道真实的 agent 题:
题目:实现一个线程安全的 LRU + TTL 缓存模块(自动过期、异常校验),并自带 pytest 测试。
协议:同一提示词、temperature=0、两边都开 medium 思考(各按自己的接口形态)、交付给同一套隐藏验收测试(模型看不到)+ 最多两轮反馈修复。
测法:端到端计时(发请求→完整响应)、服务端 usage 计数、reasoning_content 字符数,全自动采集。
表 7 · agent 对打(同题同协议)
| 维度 | Strata IQ2_XS(125B) | 原主力 27B NVFP4 |
|---|---|---|
| 验收结果 | 一次通过(+自测全绿) |
一次通过(+自测全绿) |
| 端到端耗时 | 13.3 秒 | 91.2 秒(6.9×) |
| 输出量 | 2,057 tokens | 4,494 tokens |
| 思考量 | 1,021 字符 | 6,205 字符(6.1×) |
| 折算吞吐 | ~155 t/s | ~49 t/s |
| 产物质量 | 教科书级(OrderedDict + 锁 + 惰性过期) | 教科书级(同构实现,注释更密) |
两点观察:
️ 诚实声明:n=1、单题中等复杂度、超长任务链未测——这是方向性结论,不是终审。但它是真代码 + 隐藏验收,比复述型任务可信得多。
对打当晚就做了决定:SGLang 27B / A3B 全部退役,Strata 升为主力。动作:
一句话总结:125B 级别的模型,2026 年真的可以在单张 32GB 游戏卡上跑到近 190 tok/s、开满 262K 上下文、零崩溃——这不是"能跑"的 Demo,是日常可用的生产力。感谢 Niko1221 写出这个引擎,也感谢社区把坑都趟平了。
*本文所有数据来自作者机器实测(2026-10-06)
测试基准:本机 RTX PRO 4500 32GB,100K 上下文稳定档 / DSPARK 投机 / NVFP4 量化,agent 真实负载(开思考)稳态 decode 63-79 tok/s,no-spec 基线 49 tok/s。数据附实测方法,欢迎拉复验打脸。
| 指标 | 数值 | 说明 |
|---|---|---|
| Decode 吞吐 | 63-79 tok/s | agent 负载(开思考),DSPARK 投机 |
| no-spec 基线 | ~49 tok/s | 关投机对照(DSPARK 提速 ~29%) |
| 关思考纯生成 | ~47 tok/s | 短输出直答模式 |
| TTFT | 0.12-0.17s | 短上下文;session radix 命中 <1s 免 prefill |
| 上下文 | 100000 (100K) | 稳定档;131072+DSPARK 在 32GB 上 6K 即 OOM(血案见坑1) |
| KV 池 | 107077 tokens | fp8_e4m3,每 token 仅 32KB(hybrid 架构红利) |
| 可用显存 | ~1.57GB | 余量(OOM 崩溃时仅 0.049GB,30 倍差距) |
| 缓存命中上报 | 已开启 |
--enable-cache-report;agent(dsh)可显示真实命中率(实测 97% 前缀命中上报) |
| 真实 agent 会话 | 90 tok/s · 首 token 3.1s · 缓存命中 84% | dsh 5 轮 31 步真实会话(2026-09-09,UI 累计口径;口径辨析见「实测数据 > 真实 agent 会话」节) |
| 冷启(JIT 热后) | ~45s | CUDA graph capture 完成 |
| 首请求 | ~90s 一次性 | 首次 lazy init |
| 完整冷启(无 JIT 缓存) | 16-18min | CUDA graph capture 阶段占大头,属正常非卡死 |
| 名词 | 白话 |
|---|---|
| NVFP4 | NVIDIA 的 4-bit 浮点量化方案,Blackwell 原生支持,精度损失远小于整数量化 |
| Qwen3.8-27B | dense 27.8B 混合架构:64 层 = 48 层 Gated DeltaNet(线性注意力)+ 16 层 full attention |
| Gated DeltaNet | 线性注意力变体,无传统 KV cache——每 token KV 只占 32KB,长上下文显存成本骤降 |
| SGLang | LLM 推理引擎,RadixAttention 自动共享请求间公共前缀 |
| session radix cache | 同一会话多轮共享前缀缓存,agent 连续对话免重复 prefill |
| DSPARK | 投机解码新方案:独立小 draft 模型(1.4GB)并行预测,主模型验证;对 reasoning 思考链接受率高 |
| modelopt_fp4 | draft 模型量化格式(NVIDIA modelopt),DSPARK 必须配此格式 |
| intermediate buffer | DSPARK 验证 linear-attention state 的必需中间显存(2.25GB),不可省 |
| flashinfer_cutlass | SGLang 底层 kernel 后端;本机 dense 模型走 flashinfer 默认路径,JIT 编译是冷启大头 |
| 组件 | 版本 |
|---|---|
| GPU | RTX PRO 4500(sm_120,Blackwell 架构,12.0)32GB |
| CUDA | torch 2.13.0+cu130 wheel 自带(nvcc 13.4.46rc1 全家桶在 venv site-packages/nvidia/cu13) |
| SGLang | 0.5.19(~/.sglang-venv,python3.11) |
| torch | 2.13.0+cu130 |
| flashinfer-python | 0.6.18(随 sglang 自动装) |
| 主模型权重 | gittensor-model-hub/Qwen3.8-27B-NVFP4-RTX5090(17GB,NVFP4,无 MTP head、无 vision 加载) |
| draft 权重 | gittensor-model-hub/Qwen3.8-27B-DSpark-NVFP4(1.4GB,DSPARK 专用) |
️ 权重必须 gittensor-model-hub 版(modelopt 格式,SGLang 兼容);Unsloth NVFP4(compressed-tensors)SGLang 直接报不支持。
systemd 服务路径:~/.config/systemd/user/sglang-qwen27b.service(全文如下,可直接复制)
[Unit]
Description=SGLang Qwen3.8-27B-NVFP4 (100K/DSPARK/无视觉, 2026-09-08 定案)
After=network.target
[Service]
Type=simple
WorkingDirectory=%h
ExecStart=%h/.sglang-venv/bin/python -m sglang.launch_server --model-path %h/models/Qwen3.8-27B-NVFP4-RTX5090 --served-model-name qwen3.8-27B-NVFP4 --host 127.0.0.1 --port 8000 --context-length 100000 --mem-fraction-static 0.88 --max-running-requests 4 --mamba-ssm-dtype bfloat16 --kv-cache-dtype fp8_e4m3 --reasoning-parser qwen3 --tool-call-parser qwen3_coder --enable-session-radix-cache --enable-cache-report --speculative-algorithm DSPARK --speculative-draft-model-path %h/models/Qwen3.8-27B-DSpark-NVFP4 --speculative-dspark-block-size 7 --speculative-draft-model-quantization modelopt_fp4
# ⚠️ 环境三件套(缺一不可,见坑3):PATH 前缀 cuda-cc(gcc-12 symlink)+ cu13 bin;CUDA_HOME=cu13;LD_LIBRARY_PATH=cu13/lib + cudnn/cusparselt/nccl/nvshmem
Environment=PATH=%h/.local/bin/cuda-cc:%h/.sglang-venv/lib/python3.11/site-packages/nvidia/cu13/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Environment=CUDA_HOME=%h/.sglang-venv/lib/python3.11/site-packages/nvidia/cu13
Environment=LD_LIBRARY_PATH=%h/.sglang-venv/lib/python3.11/site-packages/nvidia/cu13/lib:%h/.sglang-venv/lib/python3.11/site-packages/nvidia/cudnn/lib:%h/.sglang-venv/lib/python3.11/site-packages/nvidia/cusparselt/lib:%h/.sglang-venv/lib/python3.11/site-packages/nvidia/nccl/lib:%h/.sglang-venv/lib/python3.11/site-packages/nvidia/nvshmem/lib
Environment=CUDA_VISIBLE_DEVICES=0
Restart=on-failure
RestartSec=10
[Install]
WantedBy=default.target
️ 不要加 --mamba-radix-cache-strategy no_buffer(与 overlap schedule 不兼容直接 crash loop,用默认 auto);不要加 --max-mamba-cache-size 20(intermediate 预占挤走 KV 池 ~2.8GB)。
启动 & 验证(长等待用 curl --retry,勿 shell 手写循环):
systemctl --user daemon-reload
systemctl --user start sglang-qwen27b.service
curl -s -m 3 --retry 90 --retry-delay 10 --retry-all-errors http://127.0.0.1:8000/v1/models | head -c 300
llm-switch 集成:目标 1=sglang-qwen27b(echo 1 | llm-switch),与 sglang-a3b/ComfyUI 8000 端口互斥。
最重要的机制ctx 131072 + mem-fraction 0.90 + DSPARK 时,6K 前缀请求即 CUDA OOM(free 仅 49MB)→ scheduler SIGQUIT → 服务崩溃。显存账本:
| 组件 | 大小 | 说明 |
|---|---|---|
| 权重 NVFP4 | ~17GB | gittensor 版(含 vision tower 权重但 SGLang 不加载 vision) |
| DSPARK draft | 1.4GB | 独立小模型 |
| Mamba intermediate | 2.25GB | DSPARK 验证 state 必需(auto→extra_buffer) |
| ssm+conv state | ~1.2GB | 48 层线性注意力状态池 |
| KV 池 fp8 | ~3.4GB | 107077 tokens × 32KB/token |
| CUDA graph | ~1.4GB | prefill + verify/decode |
关键数字:每 token KV 仅 32KB(16/64 层 full-attn 才要传统 KV,48 层线性注意力走 state 池)——100K 满需求 ~3.2GB,131K 满需求 ~4.2GB,差距不大;真正的杀手是 DSPARK 的 draft 1.4GB + intermediate 2.25GB 预占。mem-fraction 0.90 时预分配过满,运行时 free≈0,任何请求峰值即爆。
100K + mem-fraction 0.88 = 甜点区:KV 池 107077(≥100K + radix 余量)+ available 1.57GB(30 倍余量)。实测 30K 上下文稳定、NRestarts=0。
若要回 131072:唯一路径是去掉 DSPARK(释放 draft+intermediate 共 ~3.65GB → 池 174681),但速度 63→49 tok/s,稳定性换速度,想清楚再动。
--speculative-draft-model-quantization modelopt_fp4(README 裸格式在部分环境报不兼容)
️ gittensor README 的 85.8/161.7 tok/s 是 RTX 5090(1792 GB/s 带宽)参考值,4500 带宽减半——本机实测约其一半(no-spec 49→DSpark 63),勿拿 README 数字当本机预期SGLang 默认不加载 vision encoder;--language-model-only 对本模型架构会 ValueError。视觉任务走云端多模态 API(mimo-v2.5 等),本地只管文本——显存省 ~2GB。
方法:连续请求看 SGLang 日志 gen throughput (token/s);短输出直答另测。
实测区间:63-79 tok/s(DSPARK,思考链长短波动)
no-spec 对照:~49 tok/s
关思考纯生成:~47 tok/s
本配置 2026-09-08 起作为 dsh agent 日常现役模型(~/.dsh/settings.yaml → qwen3.8-27B-NVFP4),持续稳定运行(NRestarts=0)。真实 5 轮 31 步会话(本会话累计快照,随会话增长数值小幅漂移):
LLM 合计 9分8秒 · 工具调用 30.7s
90 tok/s UI 口径:Σ输出 tokens ÷ Σ纯 decode 时长(firstToken→completed,不含 prefill/排队/等待;4 轮快照 88,随会话增长小幅上浮)
首 token 平均 3.1s UI 口径:每请求 (firstTokenTime − stepStart) 全请求平均
缓存命中 84% UI 口径:cacheReadTokens ÷ 输入 tokens(1.3M 输入中约 1.1M 免重复 prefill)
输入 1.3M tok · 输出 40.9K tok(5 轮累计;单请求上下文逐轮增长,末轮远超此前 30K 实测档)
️ 口径辨析(复验请以下列 SGLang 日志为准):UI 的 90 tok/s ≠ SGLang 日志 gen throughput 63-79 tok/s。前者是客户端「纯 decode 窗口」(首 token 到完成,不含 prefill/排队/混合采样窗口),数值高于日志档属口径使然;后者是服务端采样窗口、复验基准。两口径不矛盾,勿互相打脸。首 token 平均 3.1s(4 轮快照 3.5s)被后轮长上下文 prefill 拉高(短上下文冷/热 0.107-0.17s 仍成立),属预期行为非劣化。
缓存命中上报已打通(2026-09-08 晚):服务端加 --enable-cache-report 后,响应 usage.prompt_tokens_details.cached_tokens 真实回填,agent(dsh)可显示真实命中率(实测 987 token 前缀第 2 轮起 cached=960,97%)。
️ 该参数默认 False——不加时 ptd 恒 null,agent 显示「缓存命中 0%」是读不到字段的盲区不是 radix 失效(旧版文档的坑8 即此,现已由参数解决)。DSPARK 投机不影响上报(字段来自 radix 前缀命中统计,与 decode 侧投机无关)。验证法仍可用:同前缀两连发对比 TTFT(实测 25K 前缀:冷 5.7s → 命中 0.107s)。| 状态 | 占用 |
|---|---|
| 启动后稳态 | ~30.4GB / 32GB |
| 可用显存 | ~1.57GB |
| KV 池 | 107077 tokens(fp8_e4m3) |
| 权重 | ~17GB(主)+ 1.4GB(draft) |
6K 前缀请求即 CUDA OOM,scheduler SIGQUIT 服务崩。反复调参浪费数小时后定案:不是 ctx 大,是 mem-fraction 0.90 预分配过满 + DSPARK 三件套(draft 1.4GB + intermediate 2.25GB + graph 1.4GB)挤压。解法:100K + 0.88(见机制1)。教训:新参数先复刻历史验证基线跑通,再逐档上调,别一上来顶目标配置。
首次部署无 JIT 缓存时 CUDA graph capture 阶段日志静默、GPU util 低波动——差点被 kill。判定:进程 ALIVE + 显存 ~29.7GB + 无 traceback = 正常。就绪探测用 curl --retry 90(见上),不要用 shell 手写循环 + 短超时误判 DOWN。
SGLang JIT(flashinfer)依赖链全在 venv 的 site-packages/nvidia/cu13(nvcc 13.4.46rc1 全家桶),不是系统 CUDA:
~/.local/bin/cuda-cc/ 放 gcc/g++ → gcc-12 symlink,PATH 前缀site-packages/nvidia/cu13(含 nvcc + 头 + lib);指向系统 /usr/local/cuda(12.9)会编译出链接 libcublasLt.so.12 的产物 → sm_120 fp8 初始化失败 bmm_fp8_internal_cublaslt failedcu13/lib(无 lib64、无 libcublasLt.so 无版本 symlink)→ JIT 找不到 -lcudart/-lcublasLt,需 ln -sfn lib lib64 + 补 5 个无版本 symlink;pip 重装 nvidia-cuda-* 后 symlink 会丢,需重补--prerelease=allow 装 SGLang 可能拉 nvcc 13.4.46rc1 + 头 13.0 → CUDA compiler and CUDA toolkit headers are incompatible。解法:nvcc/crt/runtime 全套统一 13.4.46rc1Unsupported .version 9.4,13.0.x 全线不行,必须 13.4rcUnsloth NVFP4(compressed-tensors 混合精度)SGLang 报 No compressed-tensors compatible scheme was found;必须 gittensor-model-hub 版(modelopt 格式,含 No-MTP/LMHead4 变体可选)。下载 hf download 勿 | tail 吞退出码(假成功空目录血案)。
--speculative-algorithm DSPARK + --speculative-draft-model-path + --speculative-draft-model-quantization modelopt_fp4 + --speculative-dspark-block-size 7。少 quantization 或 block-size 不对 → draft 加载失败或验证路径报错。draft 用 gittensor-model-hub/Qwen3.8-27B-DSpark-NVFP4,不是 MTP head 版。
--mamba-radix-cache-strategy 与 --max-mamba-cache-size 是负优化开关no_buffer:与 overlap schedule 不兼容 → AssertionError crash loop(需 --disable-overlap-schedule 才能用,别碰)--max-mamba-cache-size 20:intermediate 预占从 KV 池挤走 ~2.8GB(池 174681→99102),KV 不足dsh 等 agent harness 显示「缓存命中 0%」——根因是 SGLang 启动参数 --enable-cache-report 默认 False:响应 usage.prompt_tokens_details 恒 null 不回填 cached_tokens,harness 读不到字段(pi-ai 解析链只认 ptd.cached_tokens / prompt_cache_hit_tokens / 顶层 cached_tokens)。不是 radix 失效,TTFT 验证法可确认缓存实际在工作。
修复(2026-09-08 实测闭环):unit ExecStart 加 --enable-cache-report → 重启 → 第二轮起同前缀请求返回 cached_tokens: N(987 token 前缀实测 cached=960,97%),dsh UI 命中率显示真实值。DSPARK 投机不影响该字段。排查链:curl 直连看响应 ptd 是否 null → null 即未开上报。
Unexpected message role.(developer role 坑)dsh(DeepSeek 官方 harness)对配置了 reasoning 的模型把 system prompt 发成 role:"developer"(pi-ai 逻辑:useDeveloperRole = model.reasoning && compat.supportsDeveloperRole,DeepSeek API 认 developer,本地 Qwen3.6 模板不认直接 400)。症状:dsh 所有请求失败报 CONTEXT_WINDOW_EXCEEDED: 400 status code (no body),但 curl 直连 SGLang 完全正常——tcpdump 抓包见响应体 Unexpected message role.。
修复:dsh ~/.dsh/settings.yaml 的 local-qwen 每个模型条目 compat 块加 supportsDeveloperRole: false(role 回落 system),重启 dsh.service 即恢复:
compat:
supportsDeveloperRole: false # 本地 Qwen 模板不认 developer role
thinkingFormat: chat-template
chatTemplateKwargs:
enable_thinking: {$var: thinking.enabled}
reasoning_effort: {$var: thinking.effort, omitWhenOff: true}
preserve_thinking: true
Qwen3.8 jinja 模板只认 xhigh/high/medium/low,max 直接 500。agent 配置 reasoning_effort 用 xhigh 封顶(本地 override 键大小写双套 low/medium 细调)。
| 操作 | 为什么 |
|---|---|
| ctx 直接顶 131072 + DSPARK | 6K 即 OOM 崩溃(坑1) |
| mem-fraction 设 0.90+ | 预分配过满,运行时 free≈0,任何峰值即爆 |
加 --max-mamba-cache-size |
intermediate 预占挤走 KV 池(坑7) |
用 --mamba-radix-cache-strategy no_buffer |
crash loop(坑7) |
| 用 Unsloth NVFP4 权重 | SGLang 不兼容(坑5) |
| 拿 gittensor README 速度当本机预期 | 5090 带宽参考,4500 减半(机制2) |
| 期待本地模型带视觉 | 无 vision encoder,视觉走云端 API(机制3) |
| 手动 shell 循环判就绪 | 冷启 16-18min 会误判 DOWN;用 curl --retry |
| tail 吞 hf download 退出码 |
假成功空目录 |
| 给 agent 配 reasoning_effort=max | 模板 500(坑10) |
服务端不加 --enable-cache-report |
agent 侧缓存命中永远 0%(坑8) |
# 1. 创建虚拟环境(python3.11)
python3.11 -m venv ~/.sglang-venv
# 2. 安装 SGLang 0.5.19 + flashinfer(自动依赖 cu130 wheel)
~/.sglang-venv/bin/pip install sglang==0.5.19 --prerelease=allow
# 验证:nvcc 13.4.46rc1 全家桶在 site-packages/nvidia/cu13(坑4)
# 3. 补 JIT 编译环境
# gcc-12 symlink(nvcc 不认 gcc 15)
mkdir -p ~/.local/bin/cuda-cc && cd ~/.local/bin/cuda-cc
ln -sf "$(which gcc-12)" gcc && ln -sf "$(which g++-12)" g++
# cu13/lib64 + 无版本 .so symlink(pip 布局缺这两个)
cd ~/.sglang-venv/lib/python3.11/site-packages/nvidia/cu13
ln -sfn lib lib64
cd lib && for f in libcudart.so.13 libcublas.so.13 libcublasLt.so.13 libnvrtc.so.13 libcuda.so; do
ln -sfn "$f" "${f%.13}"; ln -sfn "$f" "${f%%.so*}.so" 2>/dev/null
done; cd -
# 4. 下载权重(gittensor 官方,勿 | tail 吞退出码)
hf download gittensor-model-hub/Qwen3.8-27B-NVFP4-RTX5090 --local-dir ~/models/Qwen3.8-27B-NVFP4-RTX5090
hf download gittensor-model-hub/Qwen3.8-27B-DSpark-NVFP4 --local-dir ~/models/Qwen3.8-27B-DSpark-NVFP4
# 5. 写入 systemd 服务(最终配置节全文)到 ~/.config/systemd/user/sglang-qwen27b.service
# ⚠️ 环境三件套 Environment 行是启动成败关键(坑3),逐字复制
# 6. 启动(冷启 16-18min 属正常,见坑2)
systemctl --user daemon-reload
systemctl --user start sglang-qwen27b.service
curl -s -m 3 --retry 90 --retry-delay 10 --retry-all-errors http://127.0.0.1:8000/v1/models | head -c 300
# 7. 验证
curl -s http://127.0.0.1:8000/v1/models | python3 -m json.tool # id=qwen3.8-27B-NVFP4, max_model_len=100000
# 8. 压测(纯文本 max_tokens 给足 ≥512,思考模型占 token)
curl -s http://127.0.0.1:8000/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model":"qwen3.8-27B-NVFP4","messages":[{"role":"user","content":"详细解释量子计算原理"}],"max_tokens":2048}' | python3 -m json.tool
~/.hermes/config.yaml:providers.local-qwen.models[0].context_length = 100000~/.dsh/settings.yaml:llm-pi-ai.providers.local-qwen 模型条目 contextWindow = 100000(A3B 条目保持 131072),且每个模型条目 compat 块必须含 supportsDeveloperRole: false(见坑9——dsh 对 reasoning 模型默认发 developer role,本地 Qwen 模板不认会 400)# llm-switch.sh TARGETS 表已含:1=sglang-qwen27b / 2=sglang-a3b / 3=comfyui / 4=stop
echo 1 | llm-switch # 切到 27B
echo 4 | llm-switch # 停止全部
| 项目 | 原因 |
|---|---|
| 4 路并发满载压力 | 现役单用户 agent 场景,max-running-requests 4 未同时打满 |
| 100K 满长度压测 | 实测 30K 稳定,未灌满 100K 连续长会话(2026-09-09 真实会话末轮单请求上下文按累计输入估算已达 40K+ 级且稳定,仍未灌满) |
| 超 100K 上下文 + 去 DSPARK 方案 | 理论上池 174681 可行,用户拍板前不动 |
| EAGLE/MTP 投机 | gittensor 权重已移除 MTP head;EAGLE 需额外 draft 未测 |
| multi-GPU/tensor parallel | 单卡场景 |
| stream vs non-stream 吞吐差异 | 未单独 benchmark |
| 8 路并发 | 显存不足(draft+intermediate 挤压),未尝试 |
本文档写于 2026-09-08,基于本机 RTX PRO 4500 32GB 实测(llama.cpp/vLLM 引擎同日退役后的 SGLang 终局配置)。硬件不同数据会有差异,仅供参考。方法论框架见 Hermes llm-serving 技能(M1-M8 全流程),本配置为 2026-09-08 深夜 OOM 实证后定案的稳定档。
2026-09-08 深夜更新:① ExecStart 加
--enable-cache-report(缓存命中真实上报打通,坑8 由"盲区无解"改"参数解决")② 新增坑9(dsh developer role 400,settings.yaml compat 加supportsDeveloperRole: false)③ 原坑9 顺延为坑10。2026-09-09 更新:本配置现为 dsh agent 日常现役模型(settings.yaml → qwen3.8-27B-NVFP4,NRestarts=0 稳定运行)。新增「真实 agent 会话(dsh UI 口径)」实测:5 轮 31 步,90 tok/s(UI 累计口径,4 轮快照 88)/ 首 token 平均 3.1s / 缓存命中 84%(输入 1.3M tok · 输出 40.9K tok);90 与 63-79 的口径差异、首 token 解释见该节。核心配置与坑位全部不变。整体用下来,感觉驱动dsh是非常丝滑,不太适合驱动hermes(如果显存有至少48GB,应该没问题)。相比llama,我的感觉是更适合聊天,sglang才适合驱动agent,仅代表个人观点。
@2024fatwolf55 技能是个好东东,而且hermes能自动把固定流程存为技能,这点确实不错!
@2024fatwolf55 我之前就部署成功过,沉淀到技能中去了,deepseek调用技能处理会很快。没有技能的话,时间会要得久一点。
@Botio-Kuo 确实,看来标称1M上下文的模型,有些模型真的只是标称,远远达不到1M长上下文,这方面,还是deepseek是实打实的1M上下文,对于长任务的理解和处理是最优秀的。
刚刚用hermes来一条龙部署cloudflare workers and pages,为了省钱,用的mimo-v2.5,弄了半个小时,在有技能的情况下,给我整得稀烂,没办法,熬到6点后,切deepseek-v4-flash,5分钟不到,搞定!哎,差距真是有点大啊,要是deepseek能回到涨价前就好了,这个模型实在是好用啊!
@imbiplaza-ASUS 不客气!
@ran-z ● 介绍下你自己
Initializing agent...
────────────────────────────────────────
─
Hermes ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
我是你的个人 AI 助手,跑在本地 Qwen3.8-27B(llama.cpp,4500 显卡,67 t/s)。
核心能力:
工作风格:你拍板我执行,不废话不绕弯,实测验证不猜。
有什么要干的?
────────────────────────────────────────
● 显示本机软硬件环境
────────────────────────────────────────
┊
$ echo "=== CPU ===" + 26 commands 0.3s [exit 1]
┊
$ lscpu | grep "型号名称" + 3 commands 0.1s
─
Hermes
硬件
CPU: AMD Ryzen 7 3700X 8核 (3.6/4.4 GHz)
内存: 64GB DDR4 (60Gi 可用) + 127Gi Swap
GPU: NVIDIA RTX PRO 4500 Blackwell 32GB GDDR7
驱动 595.84, 当前占用 25.9GB, 93% 利用率, 51°C
主板: Gigabyte X570 GAMING X
存储
系统盘: NVMe 1.8TB (LVM) 已用 261G / 1.5T 可用 15%
数据盘: NVMe 938GB /mnt/ssd1 已用 538G / 353G 可用 61%
RAID: md0 RAID1 1.8TB /mnt/raid1 已用 586M 1%
系统
OS: Ubuntu 26.04.1 LTS, kernel 7.0.0-30-generic
主机名: aqbjqtd-X570-GAMING-X
Python: 3.14.4
Docker: 29.1.3
CUDA: 12.9 (编译) + 13.3 (运行时, ComfyUI 用)
四档推理深度(关/低/中/高)全量生效实测 · 可直接复制配置 · 踩坑记录
这篇是写给另一台机器上的 Hermes 看的操作文档:照着做就能把本地 Qwen3.8-27B(含 UC 版)完整配置进 DeepSeek Harness(dsh),四档推理深度全部真实生效。
前提:llama.cpp 的 llama-server 已经在 127.0.0.1:8000 跑起来(
--jinja --reasoning on --reasoning-preserve),dsh web 已装好。本文只讲「把模型加进 dsh」这一步。
| 项目 | 结果 |
|---|---|
| 配置位置 | ~/.dsh/settings.yaml 的 llm-pi-ai.providers 下加 provider |
| 模型条目 | qwen3.8-27B + qwen3.8-27B-UC 两个 |
| 推理深度 | 关/低/中/高 四档全部真实生效(抓包验证) |
| 关键 | 光配 reasoningEfforts 不够,必须配 compat 块 |
| 一句话 | reasoning_effort: "none" 关不掉 Qwen3.8 的思考,必须走 chat_template_kwargs.enable_thinking: false |
最终配置效果(tcpdump 抓包实测):
enable_thinking: false(思考彻底关闭,秒回)enable_thinking: true, reasoning_effort: "low"(思考最简短)enable_thinking: true, reasoning_effort: "medium"enable_thinking: true, reasoning_effort: "xhigh"(官方最高档)| 名词 | 白话解释 |
|---|---|
| dsh | DeepSeek Harness,DeepSeek 官方开源的 agent harness,dsh web 是它的 Web UI(本机 127.0.0.1:3080) |
| llama.cpp / llama-server | 本地跑 GGUF 模型的推理引擎,提供 OpenAI 兼容 API(/v1/chat/completions) |
| reasoningEfforts | dsh 里给每个模型声明的「推理深度档位 → 端点参数」映射表 |
| thinkingFormat | dsh 的 compat 配置,决定「把推理档位翻译成哪种端点的请求格式」 |
| chat_template_kwargs | llama.cpp 端点认识的请求字段,Qwen3.8 的 jinja 模板用 enable_thinking 控制是否思考 |
| enable_thinking | Qwen3.8 模板真正的思考开关。false = 不思考,true = 思考 |
打开 ~/.dsh/settings.yaml,在 llm-pi-ai.providers 下加入(或合并到已有的 qwen provider 里):
llm-pi-ai:
providers:
qwen-local:
displayName: qwen-local
apiKeyEnv: QWEN_LOCAL_API_KEY # 任意命名,~/.dsh/.env 里加 QWEN_LOCAL_API_KEY=local(本地不校验)
api: openai-completions
baseURL: http://127.0.0.1:8000/v1
models:
- id: qwen3.8-27B
name: qwen3.8-27B
contextWindow: 153600
maxTokens: 32768
reasoningEfforts:
'off': none
low: low
medium: medium
high: xhigh # ⚠️ 必须是 xhigh!Qwen3.8 模板不认 high,会直接 500
compat:
thinkingFormat: chat-template # ⚠️ 必须是 chat-template,不是 qwen-chat-template!
chatTemplateKwargs:
enable_thinking: {$var: thinking.enabled}
reasoning_effort: {$var: thinking.effort, omitWhenOff: true}
preserve_thinking: true
- id: qwen3.8-27B-UC
name: qwen3.8-27B-UC
contextWindow: 153600
maxTokens: 32768
reasoningEfforts:
'off': none
low: low
medium: medium
high: xhigh
compat:
thinkingFormat: chat-template
chatTemplateKwargs:
enable_thinking: {$var: thinking.enabled}
reasoning_effort: {$var: thinking.effort, omitWhenOff: true}
preserve_thinking: true
然后:
# 1. 备份
cp ~/.dsh/settings.yaml ~/.dsh/settings.yaml.bak.$(date +%Y%m%d-%H%M%S)
# 2. .env 补 apiKeyEnv 对应的变量(本地端点不校验 key 值,任意非空即可)
echo 'QWEN_LOCAL_API_KEY=local' >> ~/.dsh/.env
# 3. 默认模型指向本地(可选,按需)
# agent-default-model:
# provider: qwen-local
# model: qwen3.8-27B-UC
# reasoningEffort: 'off' # ⚠️ off 必须带引号!
# 4. 重启
systemctl --user restart dsh-web.service
sleep 6
systemctl --user is-active dsh-web.service # 期望 active
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3080/ # 期望 200
从 Qwen3.8 GGUF 里直接提取的 jinja 模板源码:
{%- if enable_thinking is undefined or enable_thinking is true %}
{%- set resolved_reasoning_effort = reasoning_effort|default('xhigh') %}
{%- if resolved_reasoning_effort not in ('xhigh', 'medium', 'low') %}
{{- raise_exception('Unexpected reasoning effort ' ~ reasoning_effort ~ '. Supported types are xhigh (default), medium, and low.') }}
{%- endif %}
none 不是合法档位 → 顶层 API 传 reasoning_effort: none 时被 llama.cpp 归一化剥掉(不传给模板),模板走默认 xhigh 满档思考——实测 none 思考最长(4631 字符)high 不是合法档位 → 若直接把 high 塞进 chat_template_kwargs.reasoning_effort 传给模板,模板 raise_exception → HTTP 500(实测确认)enable_thinking: false;低 → low;中 → medium;高 → xhighchat-template 而不是 qwen-chat-templatedsh 源码(pi-ai 的 openai-completions.js)里有两个 Qwen 分支:
// qwen-chat-template 分支:只发开关,不带 effort → 低/中/高三档没区别!
else if (compat.thinkingFormat === "qwen-chat-template" && model.reasoning) {
params.chat_template_kwargs = {
enable_thinking: !!options?.reasoningEffort,
preserve_thinking: true,
};
}
// chat-template 分支:走 buildChatTemplateKwargs → 支持 $var 占位符,带 effort!
else if (compat.thinkingFormat === "chat-template" && model.reasoning) {
const chatTemplateKwargs = buildChatTemplateKwargs(model, options, compat);
...
}
qwen-chat-template 分支只发 enable_thinking 开关(低/中/高都变成「开思考」+ 默认 xhigh 满档),必须用 chat-template 分支 + chatTemplateKwargs 里的 $var: thinking.effort 才能把档位传下去。
$var 是 dsh 官方占位符chatTemplateKwargs 的 value 支持两种写法:
string / number / boolean / null{$var: "thinking.enabled"} 或 {$var: "thinking.effort", omitWhenOff: true}thinking.effort 解析逻辑(dsh 源码 resolveChatTemplateKwargValue):
thinkingLevelMap → 发对应值omitWhenOff: true 让它不发(思考由 enable_thinking: false 关掉)症状:dsh 里把推理深度设「关」,模型还在不停思考。
根因:dsh 走通用分支发 reasoning_effort: "none",但 Qwen3.8 模板不认 none → 默认 xhigh 满档思考。实测 reasoning_effort=none 思考最长(4631 字符)。
修复:配 compat 走 chat-template 分支,发 chat_template_kwargs.enable_thinking: false(实测思考归零)。
reasoning_effort: {} 空对象 → 整个 provider 挂掉,模型从 dsh 消失症状:NO_ADAPTER: no adapter registered for provider "qwen-local",dsh 里模型全没了。
根因:dsh 的 schema(chatTemplateKwarg)只接受 string/number/boolean/null/带必填 $var 的对象。空对象 {} 校验失败 → 整个 provider 被拒。
修复:reasoning_effort 用 {$var: thinking.effort, omitWhenOff: true}。
血泪:改完必须验证——dsh --profile headless '测试' 能回话才算真活。
off 重写成布尔 false症状:用 Python yaml 库改 settings.yaml 后,reasoningEffort: off 变成 reasoningEffort: false。
根因:PyYAML 按 YAML 1.1 解析,off/on/yes/no 是布尔关键字;dsh 用 js-yaml 按 YAML 1.2 解析,off 是字符串。
修复:写回时显式带引号 'off',改完 grep 检查 reasoningEffort 行。
血泪:'off' 键也要带引号——PyYAML 会把 off: none 的键 off 解析成布尔 False。
high 档直接 500症状:选「高」档,请求 500 错误。
根因:模板只认 xhigh/medium/low,high 触发 raise_exception。
修复:reasoningEfforts.high 映射到 xhigh(官方最高档)。
# 1. 服务健康
systemctl --user is-active dsh-web.service # active
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3080/ # 200
# 2. headless 实测(能回话 = provider 真活着)
dsh --profile headless '27乘以43等于多少?一行答案。'
# 期望:秒回「1161」这类答案(不是 NO_ADAPTER)
# 3. 四档抓包验证(可选但推荐)
# 临时改 agent-default-model.reasoningEffort 到 off/low/medium/high 各测一次
sudo tcpdump -i lo -A -s 0 'tcp port 8000' > /tmp/dsh_cap.txt &
dsh --profile headless '27乘以43等于多少?'
grep -o 'chat_template_kwargs[^,}]*' /tmp/dsh_cap.txt
# 期望:off → enable_thinking:false
# 低 → reasoning_effort:"low",中 → "medium",高 → "xhigh"
curl -s http://127.0.0.1:8000/v1/models 返回模型列表(llama-server 活着)ls ~/.dsh/settings.yaml + systemctl --user is-active dsh-web.servicecp ~/.dsh/settings.yaml ~/.dsh/settings.yaml.bak.$(date +%Y%m%d-%H%M%S)echo 'QWEN_LOCAL_API_KEY=local' >> ~/.dsh/.env(apiKeyEnv 对应变量,本地不校验值)systemctl --user restart dsh-web.servicedsh --profile headless '测试' 回话注意:dsh 的
--dump-config输出 profile 树,不含 llm-pi-ai 的 model 条目——grep 不到模型条目属正常,不能用来验证模型级配置。验证用第 6 节的方法。
实测日期:2026-08-30 · 环境:Ubuntu + llama.cpp(CUDA 12.9)+ Qwen3.8-27B Q4_K_XL / Q4_K_P · dsh web :3080 · 全文配置均经抓包与 headless 实测验证
@ran-z HiCache 的实际价值
坦白说,HiCache 在单用户场景下最大的价值不是"跑更大上下文",而是多会话 KV 复用免 prefill。
GPU 上直接跑 ~101K tokens(全速)
超出部分由 HiCache L2 从 RAM 换入(有延迟)
重启服务后,之前的 KV 从 L2 恢复,不用重新 prefill
多会话切换时,不活跃会话的 KV 换到 RAM,活跃的留在 VRAM
对比 llama.cpp 的 150K 全 VRAM 方案:
llama.cpp 速度更快(全在 GPU 上,零搬运延迟)
SGLang HiCache 胜在会话复用(重启免 prefill)
看到论坛 neo 大佬分享的 SGLang HiCache 三层 KV 缓存(VRAM→RAM→NVMe),很感兴趣。核心卖点是:显存里的 KV Cache 放不下时,把暂时不用的 KV "搬到内存/磁盘",需要时再取回来——重启后 190K 上下文直接加载免 prefill。
我的环境:RTX PRO 4500 Blackwell 32GB + 64GB RAM + X570 主板。之前一直用 llama.cpp 跑 Qwen3.8-27B(Q4 量化,150K ctx,MTP 投机解码)。今天折腾了一下午,把 SGLang HiCache 跑通了,记录一下过程和踩的坑。
SGLang 0.5.18 + RadixArk Qwen3.8-27B-NVFP4 + HiCache L2 32GB 在 32GB Blackwell 单卡跑通
关键数据:
Unsloth 的 NVFP4 用 compressed-tensors 格式 + FP8 lm_head,SGLang 加载报错。必须用 RadixArk/Qwen3.8-27B-NVFP4(NVIDIA Model Optimizer/modelopt 格式)。
hf download RadixArk/Qwen3.8-27B-NVFP4 --local-dir ~/models/sglang/Qwen3.8-27B-NVFP4
不加 --reasoning-parser qwen3 的话,thinking 标签会残留在 content 里,reasoning_content 字段为 None。加了之后正确分离:
reasoning: "The user said hi - a simple greeting..."
content: "Hi there! How can I help?"
python3.12 -m venv ~/.sglang-venv
source ~/.sglang-venv/bin/activate
pip install --upgrade pip && pip install uv
uv pip install --prerelease=allow sglang
hf download RadixArk/Qwen3.8-27B-NVFP4 --local-dir ~/models/sglang/Qwen3.8-27B-NVFP4
约 21GB,3 个 safetensors 分片。
python -m sglang.launch_server \
--model-path ~/models/sglang/Qwen3.8-27B-NVFP4 \
--served-model-name qwen3.8-27B-NVFP4 \
--host 127.0.0.1 --port 8000 \
--enable-hierarchical-cache \
--hicache-size 32 \
--tp 1 \
--mem-fraction-static 0.85 \
--max-running-requests 1 \
--context-length 131072 \
--reasoning-parser qwen3 \
--tool-call-parser qwen3_coder
参数说明:
--hicache-size 32:L2 缓存分配 32GB host RAM--context-length 131072:128K 上下文上限--mem-fraction-static 0.85:GPU 内存分配比例--reasoning-parser qwen3:分离 thinking 和 content--tool-call-parser qwen3_coder:支持工具调用[Unit]
Description=SGLang Qwen3.8-27B-NVFP4 with HiCache L2/L3 KV Cache
After=network.target
[Service]
Type=simple
WorkingDirectory=%h
ExecStart=%h/.sglang-venv/bin/python -m sglang.launch_server \
--model-path %h/models/sglang/Qwen3.8-27B-NVFP4 \
--served-model-name qwen3.8-27B-NVFP4 \
--host 127.0.0.1 --port 8000 \
--enable-hierarchical-cache --hicache-size 32 \
--tp 1 --mem-fraction-static 0.85 --max-running-requests 1 \
--context-length 131072 \
--reasoning-parser qwen3 --tool-call-parser qwen3_coder
Environment=CUDA_VISIBLE_DEVICES=0
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=default.target
| 组件 | 大小 |
|---|---|
| 模型权重 (NVFP4) | 20.14 GB |
| Mamba SSM state | 2.67 GB (18 slots) |
| Mamba conv state | 0.05 GB |
| KV Cache (fp8, 101K tokens) | 3.10 GB |
| GPU 剩余 | ~4.69 GB |
| HiCache L2 (host RAM) | 32 GB |
| 系统总占用 | ~46 GB / 64 GB |
坦白说,HiCache 在单用户场景下最大的价值不是"跑更大上下文",而是多会话 KV 复用免 prefill。
对比 llama.cpp 的 150K 全 VRAM 方案:
| 上下文范围 | 性能 |
|---|---|
| <101K tokens | 全速(KV 全在 GPU) |
| 101K-128K | HiCache L2 换入,decode 有额外延迟 |
| 128K+ | 明显变慢(每步 PCIe 搬运 ~100ms+) |
建议设 128K 上限,日常控制在 100K 以内。
L3(NVMe 磁盘缓存)在命令里加 --hicache-storage-backend file 即可开启。实测 NVMe 顺序读 ~3.5-7GB/s,延迟 ~100μs,对 decode 来说太慢了——从 NVMe 取 KV 做 prefill 比直接重算慢不了多少,实际价值有限。L2 RAM 缓存才是重点。
有人会问:SGLang 能不能也上 MTP 加速?答案是32GB 单卡上标准版不行,但有专门的轻量化 checkpoint 可以。
RadixArk 版权重 20.14GB,GPU 剩余 ~4.69GB。MTP 额外需要:
理论上 4.69GB 够放,但实际上 Unsloth 官方明确说了:
"SGLang 0.5.18(NEXTN/MTP 在 32 GB 上无法有效适配)。在 32 GB 下,额外尺寸会占用 KV pool,因此无法容纳原生 256k。"
根因是 MTP 会和 HiCache 的内存分配冲突——HiCache 需要预留 host memory pool,MTP 需要额外的 draft model 状态,两者抢同一块剩余空间。
社区有人(gittensor-model-hub)做了一个专门适配 RTX 5090 32GB 的优化 checkpoint:
但没必要,三个原因:
llama.cpp 已经有 MTP 了——我的标准版 UD-Q4_K_XL + MTP n=2 跑到 67 t/s,这是验证过的稳定方案。SGLang + MTP 在 896 GB/s 带宽上不会更快(RTX 5090 1792 GB/s 才能跑到 180 t/s)。
HiCache 价值被 MTP 吃掉——加 MTP 后 GPU 内存更紧张,HiCache L2 分配空间被压缩,多会话复用的优势打折扣。
社区 checkpoint 质量不确定——gittensor 不是官方也不是大厂,模型质量和长期维护都不确定。你之前定的铁律是"模型必须官方源版本"。
32GB 卡上 SGLang + NVFP4 的最优定位就是多会话 KV 复用,不追求 MTP 加速。MTP 投机解码留给 llama.cpp(那边已经验证稳定)。
两者互补:
论坛版主 Terry 用 4090D 48GB 跑了类似方案,形成直接对比:
| 维度 | Terry (4090D 48GB) | 本机 (RTX PRO 4500 32GB) |
|---|---|---|
| 模型格式 | FP8 (28.5GB) | NVFP4 (20.1GB) |
| HiCache L2 | 24GB(64GB 系统不够开 32) | 32GB |
| GPU KV | 270K tokens | 101K tokens |
| 上下文 | 262K(满配) | 128K |
| MTP | NEXTN 5步/6draft |
无 |
| 性能 | 63-76 t/s (thinking-off) | ~55 t/s |
关键发现:
--hicache-size 后 tok/s "掉得太厉害,直接打折"——RAM 换入延迟不是无感的SGLang HiCache 是个不错的方案,但 32GB 单卡有几个硬约束:
32GB 卡的最优组合:llama.cpp + GGUF + MTP 做日常推理(67 t/s),SGLang + NVFP4 + HiCache 做多会话 KV 复用(重启免 prefill)。两者互补,不互相替代。
48GB 卡(4090D/RTX Pro 5000)可以全开:FP8 + MTP + HiCache + 262K 上下文,体验接近在线模型。
如果你有 48GB+ 的卡,HiCache 的价值会更大——更多 KV 留在 GPU 上,L2 作为冷备,MTP 也能跑得动。32GB 单卡的话,这个组合已经够用了。
看来unsloth的模型及其优化在固件bug不能解决的情况下,还是尽可能把参数调优到各种机器都能顺利运行了:
测试完成,六级全部通过,零崩溃。结果在 /tmp/ctx-stress-27b-20260822-010212.md。
关键数据(实际 prompt_tokens 比名义目标更深,因中文填充每行 token 数高于预估):
| 档位 | 实际深度 | 耗时 | prefill | /health |
|---|---|---|---|---|
| 4K | 5.5K | 8.5s | 652 t/s | ok |
| 8K | 11K | 9.3s | 1206 t/s | ok |
| 16K | 22K | 16s | 1411 t/s | ok |
| 32K | 47K | 34s | 1372 t/s | ok |
| 64K | 96K | 81s | 1192 t/s | ok |
| 128K | 194K | 224s | 870 t/s | ok |
结论: