文本与 LLM 模型
每种文本架构的下载与运行命令,随后按家族说明图像、音频与 PDF 输入、思考模式以及工具调用能力。
下载并运行
运行构建命令前,请先按平台安装并验证 .NET 10 SDK。第一个代码块是已验证的 Gemma 4 E4B 快速上手。所有代码块都使用 Hugging Face CLI(pip install -U huggingface_hub);其后的各家族代码块假定已完成完整源码构建。从仓库根目录运行;先把问题写入 prompt.txt,并按硬件把 ggml_cuda 换成 ggml_metal、ggml_vulkan 或 ggml_cpu。
约 30 秒快速上手:Gemma 4 E4B Q8_0(原生 GGML)
复制并运行这些命令约需 30 秒;7.48 GiB 的模型下载与首次 restore/构建耗时更长,取决于网络与机器。仓库基准已经验证 TensorSharp 的 E4B Q8_0 家族与执行路径;链接的公开 ggml-org 仓库是推荐下载源。下面的代码块面向 Linux + NVIDIA:
hf download ggml-org/gemma-4-E4B-it-GGUF gemma-4-E4B-it-Q8_0.gguf --local-dir models
TENSORSHARP_GGML_NATIVE_ENABLE_CUDA=ON dotnet build TensorSharp.slnx -c Release -p:TensorSharpSkipMlxNative=true
echo "请说明本地推理的价值。" > prompt.txt
# 纯文本不需要 mmproj。
dotnet run --project TensorSharp.Cli -c Release --no-build -- --model models/gemma-4-E4B-it-Q8_0.gguf \
--input prompt.txt --max-tokens 300 --backend ggml_cuda
dotnet run --project TensorSharp.Server.Host -c Release --no-build -- --model models/gemma-4-E4B-it-Q8_0.gguf \
--backend ggml_cuda
Apple Silicon 请省略 CUDA 环境变量并使用 ggml_metal;受支持的 Windows/Linux Vulkan GPU 请改为请求 TENSORSHARP_GGML_NATIVE_ENABLE_VULKAN=ON 并使用 ggml_vulkan。图像、视频或音频输入还需运行 hf download ggml-org/gemma-4-E4B-it-GGUF mmproj-gemma-4-E4B-it-Q8_0.gguf --local-dir models,并传入 --mmproj models/mmproj-gemma-4-E4B-it-Q8_0.gguf。服务端浏览器界面位于 http://localhost:5000/,存活检查为 /health。Windows PowerShell 与完整平台语法见快速开始。
DeepSeek V4.1 Flash(384 个路由专家,文本 + 图像/视频、思考、工具)
V4.1 并不是换了权重的 V4——它在每一次前向上都不同,把 GGUF 的架构名改成 deepseek4 是无效的。TensorSharp 为它准备了独立的原生计算图:四条残差流与延迟 hyper-connection 混合,每个注意力块带 128 token 的原始滑动窗口(前两层没有压缩注意力,接下来的 18 层压缩比为 2,最后 20 层为 1),带候选块过滤的 lightning indexer,以及在第 1 层与第 14 层注入的 Engram n-gram 特征。服务后端是 ggml_cuda。ggml_cpu 用标量回退实现跑同一套图,使得没有 GPU 也能验证该架构;ggml_vulkan 与 ggml_metal 需要 TS_DSV41_ALLOW_NON_CUDA_GPU=1,且每遇到一个架构专属算子就要一次主机往返;cpu 运行纯 C# 执行器——不用 ggml、不依赖原生库、也不需要 GPU——在一个小型合成夹具上按 2e-5 对齐 PyTorch 参考实现(这是架构层面的一致,而不是在真实 Q2_K 权重上的对齐),而且在这条路径上只能跑纯文本,因为视觉伴生模型是原生 ggml 组件;cuda 则用 Direct CUDA 引擎自己的内核运行 V4.1;两者都是正确性与可移植性路径,而非服务路径;mlx 会直接拒绝该检查点,而不是把 V4.1 的权重塞进并未实现它的图。
发布的 Q2_K 版本不能单独运行:它需要由官方仓库派生出的 Engram sidecar;图像还需要第二个准备好的文件——转换过程丢掉了视觉塔、aligner 与视觉路由偏置。
# 七个 Q2_K 分片,246.35 GiB,张量类型混合 Q2_K/Q3_K —— 需放在同一目录
python3 -m venv /tmp/dsv41-tools
/tmp/dsv41-tools/bin/python -m pip install numpy==2.0.2 tokenizers==0.22.2 huggingface_hub gguf
hf download vcruz305/DeepSeek-V4.1-Flash-GGUF \
--revision 8e0c4de3cb6519bfc11ed69dc87184b457a57bb5 \
--include "DeepSeek-V4.1-Flash-Q2_K-*.gguf" --local-dir models/deepseek41-q2
# 必需:由官方 config.json / tokenizer.json 派生的 Engram sidecar
/tmp/dsv41-tools/bin/python eng/dsv41-prepare.py models/deepseek41-q2 \
--repo deepseek-ai/DeepSeek-V4.1-Flash \
--revision dba1be0a40aa45a94ad051997016db3960a90277
# 可选:--mmproj 需要的约 970 MB 视觉伴随文件
/tmp/dsv41-tools/bin/python eng/dsv41-prepare-vision.py models/deepseek41-q2 \
--repository deepseek-ai/DeepSeek-V4.1-Flash \
--revision dba1be0a40aa45a94ad051997016db3960a90277
# 八卡服务 —— 这里的 --tp 是按层切分,不是张量并行
dotnet TensorSharp.Server.Host/bin/TensorSharp.Server.Host.dll \
--model models/deepseek41-q2/DeepSeek-V4.1-Flash-Q2_K-00001-of-00007.gguf \
--mmproj models/deepseek41-q2/deepseek41.vision.gguf \
--backend ggml_cuda --tp 8 --port 5000
同一仓库的十一个 Q4_K_M 分片(415 GiB)同样已测试,sidecar 步骤完全相同。在那里两张 Engram 表各自涨到 51.5 GiB,只能留在主机内存映射中而不再驻留 GPU,路由专家也需要在八张 46 GB 卡上卸载到 CPU——加载器会打印它需要的 --n-cpu-moe N 并直接拒绝启动,而不是在推理途中耗尽显存。
两张 Engram 表默认驻留 GPU,在图内用 get_rows 直接对量化行做 gather——因为 TensorSharp 保持检查点自身的量化格式:一行 256 个值的 Q2_K 只有 84 字节,两张 3.84 亿行的表合计 60.2 GiB。八卡 A40、每次都用冷提示词实测:驻留 GPU 为 prefill 532–541 / decode 35.6–35.9 tok/s;主机映射并用 TS_DSV41_ENGRAM_WARM=1 预热为 506–528 / 34.5–35.2;不预热则只有 207–221 / 28.0–29.2。驻留 GPU 还省掉了启动时 130 秒的整表预热,以及预热路径依赖的 60 GiB 主机页缓存。放置策略是保守的:如果把表放上 GPU 会逼出路由专家的 CPU 卸载,它们就留在主机映射上,并在启动时说明。
多 GPU 指的是按层切分。TS_DSV41_TP=N 可在同一批 GPU 上打开实验性的 routed-MoE 张量并行——gate/up 沿 FFN 中间维切分,down 沿输入维切分,partial 经主机中转的 F32 缓冲归约——而首次完整 Q2_K 实测比按层切分更慢。并发请求各有独立的序列槽位,但会回退到逐槽前向,因此这里的并发并不等于批处理的 GPU 吞吐。没有 V4.1 的 DSpark:V4 的草稿模型会被拒绝,而不是半加载。带音频的请求以 HTTP 400 拒绝,而不是被悄悄丢掉。哪些已实测、哪些明确未验证,见验证报告。
DeepSeek V4 Flash(284B MoE,文本、思考、工具、DSpark)
一个 284B 的专家混合模型,配备 128 token 的原始滑动窗口加块压缩注意力(官方宣称 1M 上下文)。它不走通用的逐算子前向:TensorSharp 通过三套专属的整模型执行器之一运行它 —— --backend cuda(Direct CUDA,不依赖 ggml)、--backend ggml_cuda / ggml_vulkan(原生 ggml),以及 --backend cpu(100% 纯 C#,零原生依赖)。三者都会把权重按层切分到所有可见 GPU,因此远大于单卡显存的模型依然跑得起来;--tp N(或 TS_DSV4_NGPU)用来限制使用几张卡。
# Q8 档位约需 160 GB 权重 —— 显存不足时改用更小的量化子目录
hf download unsloth/DeepSeek-V4-Flash-0731-GGUF --include "UD-Q8_K_XL/*" --local-dir models
hf download bleysg/DeepSeek-V4-Flash-DSpark-drafter-GGUF DSpark-drafter-Q2K-Q8-0731.gguf --local-dir models
# 普通 decode —— --model 指向第一个分片
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll \
--model models/UD-Q8_K_XL/DeepSeek-V4-Flash-0731-UD-Q8_K_XL-00001-of-00005.gguf \
--backend ggml_cuda --input prompt.txt --max-tokens 200
# DSpark 块级投机解码(decode 约 1.3-1.4×;需要贪心采样)
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll \
--model models/UD-Q8_K_XL/DeepSeek-V4-Flash-0731-UD-Q8_K_XL-00001-of-00005.gguf \
--backend ggml_cuda --draft-model models/DSpark-drafter-Q2K-Q8-0731.gguf \
--input prompt.txt --max-tokens 200 --temperature 0
# 通过 HTTP 服务,4 张 GPU,开启投机
dotnet TensorSharp.Server.Host/bin/TensorSharp.Server.Host.dll \
--model models/UD-Q8_K_XL/DeepSeek-V4-Flash-0731-UD-Q8_K_XL-00001-of-00005.gguf \
--backend ggml_cuda --tp 4 --draft-model models/DSpark-drafter-Q2K-Q8-0731.gguf
DSpark 每步起草一整块 token,主干用一次批量前向验证整块,因此贪心输出保持不变。在 CLI 上它需要纯 argmax 采样(任何 temperature、top-k/p 或惩罚项都会将其关闭);在服务端每一行验证都用该请求自己的采样器,因此可与任意采样设置组合。详见 DSpark 投机解码。
GLM 5.x(744B-A40B MoE,文本、思考、工具)
一个 744B 的混合专家模型——256 个路由专家 top-8 加一个共享专家——建立在 DeepSeek 稀疏注意力之上:带权重吸收的多头潜在注意力(MLA),使得缓存每 token 每层只占一行 576 宽的数据,再加上一个"lightning indexer"决定每个 query 可以看到哪些历史 token(自报 1M 上下文)。与 DeepSeek V4 一样,它不走通用的逐算子前向:--backend ggml_cuda / ggml_vulkan / ggml_cpu / ggml_metal 走原生整模型 ggml 执行器,把 226 GiB 权重按层切分到所有可见 GPU 上;而 --backend cpu(100% 纯 C#、无原生依赖)与 --backend cuda 走托管逐算子路径。MLX 跑不了它。多分片 GGUF 由 GgufFile 自己读取,所以 --model 指向第一片即可。下面的命令面向 GLM-5.2;GLM-5.3(非 Flash)共用同一条 glm-dsa 加载路径,其配方在其后单独给出。
# UD-IQ2_XXS 这一档约 226 GiB(6 个分片)——想要更大或更小可换一个量化目录
hf download unsloth/GLM-5.2-GGUF --include "UD-IQ2_XXS/*" --local-dir models
# 按层切分到所有可见 GPU —— --model 指向第一个分片
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll \
--model models/UD-IQ2_XXS/GLM-5.2-UD-IQ2_XXS-00001-of-00006.gguf \
--backend ggml_cuda --input prompt.txt --max-tokens 200
# 交互式 + 思考模式
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll \
--model models/UD-IQ2_XXS/GLM-5.2-UD-IQ2_XXS-00001-of-00006.gguf \
--backend ggml_cuda --interactive --think
# 显存不够?把前 N 层的路由专家留在系统内存里
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll \
--model models/UD-IQ2_XXS/GLM-5.2-UD-IQ2_XXS-00001-of-00006.gguf \
--backend ggml_cuda --n-cpu-moe 30 --input prompt.txt --max-tokens 200
# 以 HTTP 服务方式运行
dotnet TensorSharp.Server.Host/bin/TensorSharp.Server.Host.dll \
--model models/UD-IQ2_XXS/GLM-5.2-UD-IQ2_XXS-00001-of-00006.gguf \
--backend ggml_cuda
自报的 1M 上下文是上限而非承诺:1M token 的 MLA 缓存约 93 GiB,所以权重落盘之后加载器会去问各设备实际还剩多少显存,按「缓存加一整个 prefill 计算图」能装下的大小定上下文,并把选中的值打印出来。在 3× RTX PRO 6000 上用 GLM-5.2 实测,按层切分是 342,272 token,--n-cpu-moe 30 是 646,400,--tp 3 是 91,136(每个 rank 都要各自持有一份全长缓存)。想把某个长度变成硬性要求,就设 MAX_CONTEXT——放得下就照办,放不下会带着数字直接报错。
--tp N 这里也能用,但在 PCIe 互连的卡上它是容量特性而非速度特性:78 层里每层都要两次 all-reduce,占用的总线时间比拆分省下的算力还多,所以在 GLM-5.2 上 --tp 3 实测 pp2048 505.6 / tg64 17.6 tok/s,而按层切分是 915.9 / 43.9。并发靠原生的按序列槽位承载(每个请求拥有自己的 MLA 与索引器缓存),默认启用的批处理融合解码在 4 路并发下带来 1.81 倍总吞吐(在 GLM-5.2 上实测);设置 TS_BATCHED_FUSED_DECODE=0 可关闭。参见张量并行与连续批处理。
GLM-5.3(非 Flash)与 GLM-5.2 的 glm-dsa 块结构完全相同——79 个块(78 个主干块加一个 NextN 块)、256 个路由专家 top-8 外加一个共享专家、带 lightning indexer 的 MLA、rope base 8e6——所以它直接在 GLM-5.2 这条路径上加载,不需要新代码,也不需要新开关:同一个架构描述符同时服务 GLM-5.2、GLM-5.3 与 GLM-5.3-Flash,是不是 Flash 只由 general.architecture 上的一个布尔值决定。unsloth/GLM-5.3-GGUF 每种量化一个子目录,均为多分片——UD-Q2_K_XL 是 7 个分片、236.4 GiB。它仅文本,而且是双重意义上的仅文本:该仓库在任何量化下都没有发布 mmproj;就算给 glm-dsa 传了 --mmproj,也只会告警并忽略而不会报错,拿到的是一次纯文本运行而不是一次失败。--spec 会把 blk.78 上那个完整的 NextN 块加载进来,但该块没有自己的 nextn.shared_head_head.weight,只能借用主干的 LM head,而这颗 head 在 --tp 下是按列切分的——因此推测解码只在默认的按层切分(不传 --tp)时生效,而且这个开关必须在模型加载前就出现在命令行上。
# UD-Q2_K_XL 这一档约 236.4 GiB(7 个分片)——想要更大或更小可换一个量化目录
hf download unsloth/GLM-5.3-GGUF --include "UD-Q2_K_XL/*" --local-dir models
# 按层切分到所有可见 GPU —— --model 指向第一个分片
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll \
--model models/UD-Q2_K_XL/GLM-5.3-UD-Q2_K_XL-00001-of-00007.gguf \
--backend ggml_cuda --input prompt.txt --max-tokens 200
# NextN 推测解码 —— 只在默认的按层切分下生效,所以不要传 --tp
dotnet TensorSharp.Server.Host/bin/TensorSharp.Server.Host.dll \
--model models/UD-Q2_K_XL/GLM-5.3-UD-Q2_K_XL-00001-of-00007.gguf \
--backend ggml_cuda --spec
实测:8× A40 46 GB(无 NVLink)、GLM-5.3 UD-Q2_K_XL、10,531 token 提示、输出 300 token、3 次取中位数、整层放置:prefill 251.6 t/s、decode 20.48 t/s、加载 264 秒;同一台机器上 llama.cpp 是 decode 20.28 t/s、加载 753 秒——decode 打平,而加载这份 236.4 GiB 的检查点快 2.9 倍。真正的差距在首 token 时延:41.9 秒对 29.0 秒,约慢 1.4 倍(那一格 llama.cpp 没有记录 prompt token 数,因此不给出它的 prefill tok/s)。--tp N 在这里可以传,但只支持本地单进程,而且从未在 GLM-5.3 上跑过:每个 rank 都要持有一份完整复制的 KV 缓存,唯一有记录的算术是一次装不下——--tp 8 每个 rank 需要 41.7 GiB,而卡只有 46 GB。--tp-node-id / --tp-peers 则对整个 GLM 家族在建模型之前就直接拒绝。两个版本共用同一份GLM 模型卡。
GLM-5.3-Flash(320B MoE,文本 + 图像、思考、工具)
这个混合架构的后继型号走的是与 GLM-5.2 完全相同的原生整模型 ggml 执行器和同一个模型类——GGUF 架构 id 是 glm5next——只是在其上叠了四处架构改动。320B 参数,288 个路由专家 top-8 外加一个共享专家,46 个块 = 45 个主干块 + 1 个 NextN 块。45 个主干层里有 34 层是 KDA 线性注意力;另外 11 层是 NoPE MLA + DSA(文本塔里任何地方都没有 rope,512 宽的潜变量本身就是缓存行);索引器是池化的——4 格一池,top-k 2048 在池上取,再展开到池内成员;超连接是 ×4 流的 Sinkhorn 版本;所有 SwiGLU 都按上限 10 做钳位。KDA 的递归状态无法回退,因此只有当新提示恰好是缓存前缀的延长时才会复用该前缀。
# UD-Q2_K_XL 这一档约 101 GiB——想要更大或更小可换一个量化目录
hf download unsloth/GLM-5.3-Flash-GGUF --include "UD-Q2_K_XL/*" --local-dir models
hf download unsloth/GLM-5.3-Flash-GGUF mmproj-BF16.gguf --local-dir models
# 按层切分到所有可见 GPU —— --model 指向第一个分片
# (N 取决于你下载的那个量化目录里有多少个分片)
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll \
--model models/UD-Q2_K_XL/GLM-5.3-Flash-UD-Q2_K_XL-00001-of-0000N.gguf \
--backend ggml_cuda --input prompt.txt --max-tokens 200
# 图像理解 —— GLM-OCR ViT 以 mmproj-BF16.gguf 形式发布
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll \
--model models/UD-Q2_K_XL/GLM-5.3-Flash-UD-Q2_K_XL-00001-of-0000N.gguf \
--mmproj models/mmproj-BF16.gguf --image photo.png --input question.txt \
--max-tokens 300 --backend ggml_cuda
# 显存不够?把前 N 层的路由专家留在系统内存里
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll \
--model models/UD-Q2_K_XL/GLM-5.3-Flash-UD-Q2_K_XL-00001-of-0000N.gguf \
--backend ggml_cuda --n-cpu-moe 10 --input prompt.txt --max-tokens 200
# 以 HTTP 服务方式运行
dotnet TensorSharp.Server.Host/bin/TensorSharp.Server.Host.dll \
--model models/UD-Q2_K_XL/GLM-5.3-Flash-UD-Q2_K_XL-00001-of-0000N.gguf \
--mmproj models/mmproj-BF16.gguf --backend ggml_cuda
目前能跑的:不传 --tp 时按层切分到所有可见 GPU、--cpu-moe / --n-cpu-moe N 把专家放在主机内存、以服务形式运行时的原生按序列槽位,以及视觉——--image、多图提示与多轮图像会话,都走 GLM-OCR ViT。在 GGML GPU 后端上,传入 --tp N 与 GLM-5.2 一样选择仅支持本地单进程的原生张量并行:KDA / MLA head 与路由专家隐藏行切分,KDA 递归状态按 rank 持有。完整切分、每张本地 GPU 一个 rank、不启用 CPU MoE 或 tracing、且具备原生超连接内核时,按 rank 分段计算图会并发提交:路由 MoE 局部输出先归约,随后每个 rank 在本地计算并加入其复制的共享专家,再进入 Sinkhorn 超连接;超连接、池化 indexer、router、norm、稠密层与 embedding 保持不切分并按 rank 执行,output norm / LM head 留在 rank 0。CPU MoE、tracing、部分切分、超额 rank 或缺少原生超连接内核时选择组合调度器回退,其中共享专家只在 rank 0 运行一次;TS_GLM_TP_FUSED=0 可强制该诊断回退。GLM-5.2 与 GLM-5.3-Flash 的原生 TP 路径都只支持本地单进程,不支持分布式或跨节点。暂不支持:NextN/MTP 推测解码。
实测:2× RTX PRO 6000 Blackwell(96 GB)、GLM-5.3-Flash-UD-Q2_K_XL(101 GiB)、按层切分、两个引擎都用 n_ubatch 2048、背靠背运行:pp2048 llama.cpp 2070 t/s 对 TensorSharp 2014,pp16384 1690 对 1692,pp32768 1483 对 1446,tg64 36.6 对 73.5。prefill 双方相差不过几个百分点;decode 是 llama.cpp 的 2.0×。
它现在也能在 --backend cpu(100% 纯 C#、无原生依赖)上跑:glm5next 的 NoPE MLA(文本塔里没有 rope 半边,也就没有可切分的部分)以及它使用的 IQ2_XS / IQ4_XS 权重都已获得托管支持。但在这条路径上它明显落后于 GGML 后端:在 122 CPU 的机器上(22 token 提示、输出 16 token)实测 prefill 3.1 / decode 1.6 tok/s,而同文件同机器上的 ggml_cpu 是 17.7 / 3.9——prefill 约慢 5.7 倍,decode 约慢 2.4 倍,其中约 89% 的时间花在 MoE 专家路径上。请把它当作用于 A/B 的参考实现,而不是逐位对齐的实现:与 ggml_cpu 相比,prefill 的 logits 在 154880 词表上余弦相似度为 0.9567,贪心解码出的文本也不同——原生一侧排前两位的 logit 只差 0.11,而托管路径把两者的顺序调了个个儿。这与 2 bit 下专家选择的敏感性相符,但并不构成证明:0.96 低于更高精度 checkpoint 应有的 ~0.999,而当时没有更高精度的 GLM-5.3-Flash GGUF 可作对照。完整的实测数据、为此所做的四处修复与这一说明,见 GLM 模型卡。
Qwen 3.5 / 3.6(文本 + 图像、思维链、工具;3.6 支持 NextN MTP)
hf download unsloth/Qwen3.5-9B-GGUF Qwen3.5-9B-UD-Q4_K_XL.gguf --local-dir models
hf download unsloth/Qwen3.5-9B-GGUF mmproj-F16.gguf --local-dir models
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll --model models/Qwen3.5-9B-UD-Q4_K_XL.gguf --mmproj models/mmproj-F16.gguf \
--image photo.png --max-tokens 300 --backend ggml_cuda
dotnet TensorSharp.Server.Host/bin/TensorSharp.Server.Host.dll --model models/Qwen3.5-9B-UD-Q4_K_XL.gguf --mmproj models/mmproj-F16.gguf --backend ggml_cuda
Qwen 3.6 NextN 必须从保留该块的 -MTP- 仓库下载,并在服务端加入 --spec —— 该草稿头内嵌在主干 checkpoint 里,加载它要把额外权重调入显存,因此需要显式开启;基础仓库 GGUF 会剥离 NextN 块并回退到标准解码:
hf download unsloth/Qwen3.6-35B-A3B-MTP-GGUF Qwen3.6-35B-A3B-UD-Q4_K_M.gguf --local-dir models
dotnet TensorSharp.Server.Host/bin/TensorSharp.Server.Host.dll --model models/Qwen3.6-35B-A3B-UD-Q4_K_M.gguf --backend ggml_cuda --spec
Qwen 3.8 Flash Next(混合 MoE,文本 + 图像、思考;无法往返工具调用)
一个混合专家模型,GGUF 架构 id 为 qwen4exp:GatedDeltaNet 递归层与全注意力层交错(其中一部分还挂在 Qwen 稀疏注意力的索引器之后),一个 PLE n-gram 嵌入块,×4 的超连接流,以及 512 专家的 MoE。48 层,隐藏维度 2560,24 个 query 头 / 2 个 KV 头、head_dim 256,词表 248,320,每个 token 从 512 个专家里用 10 个,48 层中有 36 层带 GDN,PLE 在第 1 层。在各 ggml 后端上,整个 token(几乎)作为一张图跑完——嵌入、图内 PLE、全部 48 层、最后的混合器与 LM 头——并从按形状索引的已捕获图缓存中回放。视觉走 Qwen3.5-VL 塔,使用 (T,H,W) IMRoPE 位置,因此多图提示与多轮图像会话都可用;只要新提示恰好是缓存前缀的延长,跨轮的 KV 就会被复用(GDN 递归无法回退)。并发请求由按序列的状态持有者承载——每个请求拥有自己的注意力 KV 与索引器缓存、自己的 GDN 与 PLE 状态——因此请求之间的切换只是换一个引用。思考可用且始终开启。
工具状态:qwen4exp 的输出解析器目前无法返回结构化调用,因此不支持通用工具调用。TensorSharp 会对该家族隐藏内置 Agent Skills 与代码执行工具;选中某个 Agent Skill 时,其指令正文会作为回退直接内联到提示词,而不是通过 skills_read 获取。
# UD-Q2_K_XL 这一档约 73.4 GiB——想要更大或更小可换一个量化目录
hf download unsloth/Qwen3.8-Flash-Next-GGUF --include "UD-Q2_K_XL/*" --local-dir models
hf download unsloth/Qwen3.8-Flash-Next-GGUF mmproj-BF16.gguf --local-dir models
# 纯文本 —— --model 指向第一个分片
# (N 取决于你下载的那个量化目录里有多少个分片)
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll \
--model models/UD-Q2_K_XL/Qwen3.8-Flash-Next-UD-Q2_K_XL-00001-of-0000N.gguf \
--backend ggml_cuda --input prompt.txt --max-tokens 300
# 图像理解
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll \
--model models/UD-Q2_K_XL/Qwen3.8-Flash-Next-UD-Q2_K_XL-00001-of-0000N.gguf \
--mmproj models/mmproj-BF16.gguf --image photo.png --input question.txt \
--max-tokens 300 --backend ggml_cuda
# 两张 GPU:这里的 --tp N 走的是按层切分,不是张量并行
dotnet TensorSharp.Server.Host/bin/TensorSharp.Server.Host.dll \
--model models/UD-Q2_K_XL/Qwen3.8-Flash-Next-UD-Q2_K_XL-00001-of-0000N.gguf \
--mmproj models/mmproj-BF16.gguf --backend ggml_cuda --tp 2
qwen4exp 上的 --tp N 是按层切分:每张 GPU 持有一段连续的完整层。它不切分任何权重,所以并不是张量并行——而且这也是 llama.cpp 为该架构提供的同一种(且唯一的)多卡模式,它的 -sm row 会直接拒绝加载这个模型。请把它当作容量特性而非速度特性。在 2× A100-80GB、Qwen3.8-Flash-Next-UD-Q2_K_XL(73.4 GiB)上:单卡与双卡的贪心输出逐字节相同(SHA-256 一致);显存是 24.2 GB + 26.2 GB,而不是整个模型压在一张卡上;吞吐没有变化——两种跑法都是 prefill 约 1520–1550 t/s、decode 约 56 t/s。作为对照,llama.cpp 在同一台机器上单卡 pp1536 1094 / tg128 61.2,双卡 -sm layer 1200 / 61.5,同样是 prefill 涨约 10%、decode 不涨。启动时会打印实际走的是哪种模式,以及每张卡分到的层数与字节数;TS_Q4E_LAYER_SPLIT=20,28 可以用显式的每卡层数覆盖自动均衡(相当于 llama.cpp 的 --tensor-split),遇到无法满足的值会直接抛错而不是悄悄忽略——这很有用,因为自动均衡只按权重定价,看不到稍后才加载、并且会落在 GPU 0 上的视觉塔。
Bonsai Q1_0(仅文本,本地旁加载——无下载)
两个名字相同但架构不同的 Q1_0 文件:Bonsai-8B-Q1_0.gguf 是稠密 Qwen 3 解码器(qwen3),Bonsai-27B-Q1_0.gguf 是带 GatedDeltaNet 层的稠密 Qwen 3.5 混合架构(qwen35)。它们的 GGUF 元数据里既没有发布方 URL 也没有 license,因此 TensorSharp 只钉住确切字节数与 SHA-256,而不替它们编造——没有可 hf download 的东西。导入前请确认你有权使用该文件;钉住的取值见 Bonsai 卡片。
# Apple Silicon 上的 Bonsai 8B
MAX_CONTEXT=16384 KV_CACHE_DTYPE=f16 \
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll --model /path/to/Bonsai-8B-Q1_0.gguf \
--backend ggml_metal --input prompt.txt --max-tokens 256 --temperature 0.5 --top-k 20 --top-p 0.85
# Bonsai 27B;--think 可显示它的推理流
MAX_CONTEXT=32768 KV_CACHE_DTYPE=f16 \
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll --model /path/to/Bonsai-27B-Q1_0.gguf \
--backend ggml_metal --input prompt.txt --max-tokens 256 --think
Q1_0 是 GGML 张量类型 41——每 128 个值一块,存一个 F16 scale 加 128 个 1 bit 符号位,即每权重 1.125 bit——GGUF 读取器、原生绑定与托管回退路径都识别它。在 M5 Pro 上以同一文件与 llama.cpp 成对运行:8B pp128 为 1.05×、tg128 持平;27B 相对热漂移包夹后的 llama.cpp 基线为 pp512 1.03×、pp2048 1.04×、tg128 1.15×。TensorAgent 在 iOS 上也把两者列为仅导入条目。
GPT OSS(文本、始终思考、工具)
hf download ggml-org/gpt-oss-20b-GGUF gpt-oss-20b-MXFP4.gguf --local-dir models
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll --model models/gpt-oss-20b-MXFP4.gguf --input prompt.txt --max-tokens 400 --backend ggml_cuda
dotnet TensorSharp.Server.Host/bin/TensorSharp.Server.Host.dll --model models/gpt-oss-20b-MXFP4.gguf --backend ggml_cuda
Nemotron-H(文本;Omni 分发支持图像)
hf download bartowski/nvidia_Nemotron-H-8B-Reasoning-128K-GGUF nvidia_Nemotron-H-8B-Reasoning-128K-Q4_K_M.gguf --local-dir models
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll --model models/nvidia_Nemotron-H-8B-Reasoning-128K-Q4_K_M.gguf --input prompt.txt \
--think --max-tokens 400 --backend ggml_cuda
dotnet TensorSharp.Server.Host/bin/TensorSharp.Server.Host.dll --model models/nvidia_Nemotron-H-8B-Reasoning-128K-Q4_K_M.gguf --backend ggml_cuda
图像输入请改用上表 Nemotron 3 Nano Omni GGUF 与 mmproj-BF16.gguf。当前 GGUF 分发未附真实音频推理所需的 Parakeet audio mmproj。
Nemotron 3.5 Lightning 30B-A3B 走同一条 nemotron_h_moe 路径——23 层 Mamba-2 + 23 层 MoE + 6 层注意力,例如 unsloth/NVIDIA-Nemotron-3.5-Lightning-30B-A3B-GGUF 中的 NVIDIA-Nemotron-3.5-Lightning-30B-A3B-MXFP4_MOE.gguf(约 17 GB)。它是唯一可挂块级草稿器的 Nemotron:NVIDIA 的 DSpark 模块以 dflash 架构 GGUF 导出,用 --draft-model 加载,使它成为第一个运行块级投机解码的递归(Mamba-2)主干。→ 块级起草的原理
Hunyuan Dense(仅文本,单设备)
腾讯的稠密 Hunyuan 解码器——即 general.architecture 为 hunyuan-dense 的检查点,例如 Hy-MT2 系列。在该架构注册之前,这些官方文件会在加载阶段失败:加载器遇到未知架构选择失败关闭,而不是猜一套相近的图。文本计算图与 llama.cpp 的 hunyuan-vl 文本塔一致——RMSNorm、融合 QKV、NeoX RoPE,然后是 per-head Q/K RMSNorm、GQA 与 SwiGLU。QK-norm 在 RoPE 之后,与 Qwen 3.5 相反;搞反了不会加载失败,只会产出流畅但错误的文本,所以这两个 norm 是必需的,缺失即抛异常。
# 任何 general.architecture 为 hunyuan-dense 的 GGUF 都可以,选择依据不是文件名
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll \
--model models/<your-hunyuan-dense>.gguf \
--backend ggml_cuda --input prompt.txt --max-tokens 200
第一版:仅文本、单设备、走通用 per-op 路径,没有思考通道也没有工具解析器。多余的 GPU 会闲置,启动时会明说,而不用去猜。
Mistral 3(文本 + 图像)
hf download bartowski/mistralai_Mistral-Small-3.1-24B-Instruct-2503-GGUF mistralai_Mistral-Small-3.1-24B-Instruct-2503-Q4_K_M.gguf --local-dir models
hf download bartowski/mistralai_Mistral-Small-3.1-24B-Instruct-2503-GGUF mmproj-mistralai_Mistral-Small-3.1-24B-Instruct-2503-f16.gguf --local-dir models
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll --model models/mistralai_Mistral-Small-3.1-24B-Instruct-2503-Q4_K_M.gguf \
--mmproj models/mmproj-mistralai_Mistral-Small-3.1-24B-Instruct-2503-f16.gguf \
--image photo.png --max-tokens 300 --backend ggml_cuda
dotnet TensorSharp.Server.Host/bin/TensorSharp.Server.Host.dll --model models/mistralai_Mistral-Small-3.1-24B-Instruct-2503-Q4_K_M.gguf \
--mmproj models/mmproj-mistralai_Mistral-Small-3.1-24B-Instruct-2503-f16.gguf --backend ggml_cuda
Muse-Glimmer(文本 + 图像、思维链、工具、DFlash 起草)
hf download unsloth/Muse-Glimmer-30B-GGUF Muse-Glimmer-30B-UD-IQ2_XXS.gguf --local-dir models
hf download unsloth/Muse-Glimmer-30B-GGUF mmproj-Muse-Glimmer-30B-Q8_0.gguf --local-dir models
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll --model models/Muse-Glimmer-30B-UD-IQ2_XXS.gguf \
--input prompt.txt --max-tokens 256 --backend ggml_cuda
# 图像理解
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll --model models/Muse-Glimmer-30B-UD-IQ2_XXS.gguf \
--mmproj models/mmproj-Muse-Glimmer-30B-Q8_0.gguf --image photo.png --input question.txt \
--max-tokens 300 --backend ggml_cuda
# DFlash 投机解码(草稿 GGUF 可从同仓库下载)
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll --model models/Muse-Glimmer-30B-UD-IQ2_XXS.gguf \
--draft-model models/dflash-kquant.gguf --spec-draft 15 --input prompt.txt --backend ggml_cuda
DiffusionGemma(分块文本扩散)
hf download unsloth/diffusiongemma-26B-A4B-it-GGUF diffusiongemma-26B-A4B-it-Q4_K_M.gguf --local-dir models
dotnet TensorSharp.Cli/bin/TensorSharp.Cli.dll --model models/diffusiongemma-26B-A4B-it-Q4_K_M.gguf --input prompt.txt \
--max-tokens 256 --diffusion-steps 48 --diffusion-seed 0 --backend ggml_cuda
dotnet TensorSharp.Server.Host/bin/TensorSharp.Server.Host.dll --model models/diffusiongemma-26B-A4B-it-Q4_K_M.gguf --backend ggml_cuda
多模态支持
| 家族 | 输入 | 说明 |
|---|---|---|
| Gemma 4 | 图像 · 视频 · 音频 | 图像 PNG/JPEG/HEIC;视频 MP4(经 OpenCV 以 1 fps 采样);音频 WAV 16 kHz 单声道 / MP3 / OGG。E4B 投影器:mmproj-gemma-4-E4B-it-Q8_0.gguf。 |
| Qwen 3.5 / 3.6 | 图像 | 动态分辨率视觉编码器;9B / 3.6 仓库使用 mmproj-F16.gguf。 |
| Qwen 3.8 Flash Next | 图像 | Qwen3.5-VL 视觉塔,使用 (T,H,W) IMRoPE 位置;支持多图提示与多轮图像会话,新提示恰好延长缓存前缀时跨轮复用 KV。投影器:mmproj-BF16.gguf(同仓库)。 |
| GLM 5.x(5.3-Flash) | 图像 | GLM-OCR ViT——24 个块作为一张常驻设备的图跑完,投影后的行在原生执行器内部覆盖 <|image|> 占位。支持多图与多轮图像会话。投影器:mmproj-BF16.gguf(同仓库)。GLM-5.2 与 GLM-5.3(glm-dsa)均仅文本:GLM-5.3 仓库在任何量化下都未发布 mmproj,且给 glm-dsa 传入 --mmproj 只会告警并忽略、不会报错,因此仍是一次纯文本运行。只有 glm5next 接受投影器。 |
| Mistral 3 | 图像 | Pixtral 视觉编码器。投影器:mmproj-mistralai_Mistral-Small-3.1-24B-Instruct-2503-f16.gguf。 |
| Muse-Glimmer | 图像 | 50 层稀疏窗口 ViT,采用 2D RoPE 与 2×2 像素混洗;图像按 llama.cpp 相同的方式选定网格后直接拉伸(不填充、不切块)。投影器:mmproj-Muse-Glimmer-30B-Q8_0.gguf。 |
| Nemotron-H (Omni) | 图像 | RADIO / v2_vl ViT 编码器。传入匹配的 --mmproj;图像 token 在 <image> 占位处展开。当前 GGUF 分发未附真实音频推理需要的 Parakeet mmproj。 |
通过 CLI(--image、--video、--audio、--pdf)、Web UI 上传,或 HTTP API(Ollama 用 base64 images 数组,OpenAI 用 image_url data URI)发送文件。数字版 PDF 会提取文本;扫描版 PDF 会转换为页面图像并需要视觉模型。
思考 / 推理模式
具备思考能力的模型(Qwen 3.5/3.6、Qwen 3.8 Flash Next、Gemma 4、GPT OSS、Nemotron-H、DeepSeek V4、DeepSeek V4.1、GLM 5.x、Muse-Glimmer)会在最终答案前产生结构化的思维链。思考内容与可见回复分离,便于客户端显示或隐藏。
- Qwen 3.5/3.6 / Nemotron-H ——
<think>…</think>标签。 - Qwen 3.8 Flash Next —— 同样是
<think>…</think>标签,但始终开启:生成提示会无条件打开该块,没有非思考模式可切。 - Gemma 4 ——
<|channel>thought …<channel|>标签。 - GPT OSS —— Harmony 格式:
<|channel|>analysis用于思考,<|channel|>final用于答案。 - DeepSeek V4 ——
<think>…</think>标签;不显式开启思考时聊天模板会立即闭合该块,因此推理是按需启用的。 - DeepSeek V4.1 —— 同样的标签,但带有训练过的收尾转换:达到
TS_THINKING_BUDGET时模型输出</think>,并在原有max_tokens之内写完答案。当输出额度不少于 512 token 时,预算默认取 75%。 - GLM 5.x —— 同样是
<think>…</think>标签,也是按需开启:加--think会补上Reasoning Effort: Max系统行并留下一个未闭合的块由模型自己收尾,不加时提示里写的是空的<think></think>。历史轮次的思考内容始终不会带进提示。GLM-5.3-Flash 则始终思考:它的Reasoning Effort: Max系统行是无条件的,生成提示总是打开<think>,历史轮次的思考内容也会保留。 - Muse-Glimmer —— 聊天模板输出的
assistant to=self推理通道。
通过 --think(CLI)、"think": true(Ollama API / Web UI)或浏览器中的思考开关启用。响应会单独暴露推理 —— 例如 Ollama 聊天响应中的 message.thinking。
工具调用 / 函数调用
受支持的模型家族可以调用用户自定义工具,并参与多轮工具调用对话。将工具定义为 JSON,通过 --tools(CLI)或 tools 参数(API)传入。每个受支持架构使用各自的线格式,其输出解析器会将调用提取为结构化 tool_calls:
- Nemotron-H ——
<tool_call>{"name": …, "arguments": {…}}</tool_call> - Qwen 3.5 / 3.6 —— 同样是
<tool_call>块,但内容为 XML:<function=NAME><parameter=key>value</parameter></function>(JSON 形式仍被接受)。 - Gemma 4 ——
<|tool_call>call:function_name{args}<tool_call|> - GPT OSS (Harmony) —— 工具以 TypeScript 命名空间声明;调用在 commentary 通道发出。
- DeepSeek V4.1 —— 带空格的 DSML(
<|DSML| calls>),与 V4 不带空格的格式不兼容。在/v1/chat/completions上,请求级语法在 token 层面强制约束声明的工具:tool_choice的 auto / required / none / 指定函数,以及parallel_tool_calls: false都会被遵守;不支持的 schema 断言在生成前以 HTTP 400 拒绝。 - DeepSeek V4 —— DSML 标记:系统提示词负责讲解语法并携带每个函数的 JSON schema,模型以
<|DSML|tool_calls><|DSML|invoke name="NAME"><|DSML|parameter name="key" string="true|false">value</|DSML|parameter>…作答。 - GLM 5.x —— 逐参数标签的 XML:
<tool_call>NAME<arg_key>k</arg_key><arg_value>v</arg_value>…</tool_call>。函数名以裸文本紧跟在开标签之后,每个参数自成一组键值对;模板里用tojson渲染过的值会被解析回数字、数组与对象。 - Muse-Glimmer —— 聊天模板声明的 ATEM XML 标记;解析器会把调用提取成同样的结构化
tool_calls。
Qwen 3.8 Flash Next(qwen4exp)不在此列表中:其输出解析器无法返回工具调用,因此通用客户端工具与内置技能 / 代码工具都会被隐藏;选中的 Agent Skill 指令会作为无工具回退直接内联。
完整的请求/响应示例与续接循环见 通过 HTTP 进行工具调用。