服务器与 Web UI
TensorSharp.Server 是一个 ASP.NET Core 应用,托管单个 GGUF 模型,并在同一端口上暴露浏览器聊天 UI 以及兼容 Ollama 和 OpenAI 的 REST API。连续批处理引擎负责并发。
启动服务器
约 30 秒快速开始(Gemma 4 E4B)
按平台安装 .NET 10 SDK、Git、CMake 与 curl,然后在终端粘贴下面的命令。复制并运行这些命令约需 30 秒;7.48 GiB 的模型下载与首次还原/构建耗时更长,取决于网络速度与机器性能。它会通过原生 GGML 桥接托管仓库基准已验证的 Gemma 4 E4B Q8_0,使用推荐的公开 ggml-org 文件。下面的代码块面向 Linux + NVIDIA(CUDA 构建还需要 CUDA Toolkit):
git clone https://github.com/zhongkaifu/TensorSharp.git
cd TensorSharp
TENSORSHARP_GGML_NATIVE_ENABLE_CUDA=ON dotnet build TensorSharp.slnx -c Release -p:TensorSharpSkipMlxNative=true
curl --create-dirs --fail -L "https://huggingface.co/ggml-org/gemma-4-E4B-it-GGUF/resolve/main/gemma-4-E4B-it-Q8_0.gguf?download=true" -o models/gemma-4-E4B-it-Q8_0.gguf
dotnet run --project TensorSharp.Server -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;没有受支持的 GPU 时可省略该环境变量并使用 ggml_cpu。占用内存更低的 gemma-4-E4B-it-Q4_K_M.gguf 位于同一仓库。纯文本不需要投影器;图像、视频或音频还需匹配的 mmproj-gemma-4-E4B-it-Q8_0.gguf,并通过 --mmproj 传入。Windows PowerShell 与完整平台语法见快速开始。
在第二个终端中验证 OpenAI 兼容端点:
curl -s http://localhost:5000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"gemma-4-E4B-it-Q8_0.gguf","messages":[{"role":"user","content":"Reply with one short hello."}],"max_tokens":32}'
API 基址是 http://localhost:5000。内置聊天 UI 位于 http://localhost:5000/index.html;GET / 是存活检查接口,返回 "TensorSharp.Server is running"。
推理必须在启动时传入 --model。服务器只托管启动时指定的 GGUF,以及可选且必须显式传入的 --mmproj;它不会扫描模型目录或自动探测投影器。/api/models/load 只能用其他受支持后端重新加载同一启动组合。无模型进程不能在运行时选择 GGUF。监听地址固定为 http://0.0.0.0:5000,没有端口参数。
服务端没有内置 API Key 身份验证或 TLS,并监听所有网络接口。本机使用时请依靠主机防火墙;需要远程访问时应置于带身份验证的 HTTPS 反向代理之后,不要把 5000 端口直接暴露给不可信网络。
已构建的源码目录
构建完成后,从仓库根目录运行这些命令。它们会调用 TensorSharp.Server/bin/TensorSharp.Server.dll;该输出目录也包含复制好的原生库与 wwwroot/。当前 v3.0.5.0 GitHub Release 没有附带二进制压缩包。
# Apple Silicon / Metal
dotnet TensorSharp.Server/bin/TensorSharp.Server.dll --model ./models/model.gguf --backend ggml_metal
# NVIDIA / GGML CUDA
dotnet TensorSharp.Server/bin/TensorSharp.Server.dll --model ./models/model.gguf --backend ggml_cuda
# AMD、Intel 或 NVIDIA / Vulkan;先查看设备索引
dotnet TensorSharp.Server/bin/TensorSharp.Server.dll --list-gpus
dotnet TensorSharp.Server/bin/TensorSharp.Server.dll --model ./models/model.gguf --backend ggml_vulkan --gpu-device 1
# 多模态:投影器始终显式指定
dotnet TensorSharp.Server/bin/TensorSharp.Server.dll --model ./models/model.gguf --mmproj ./models/mmproj.gguf --backend ggml_cuda
服务器级默认采样
默认值会填补请求未提供的任何字段;逐请求的值始终优先。
dotnet TensorSharp.Server/bin/TensorSharp.Server.dll --model ./models/model.gguf --backend ggml_metal \
--temperature 0.7 --top-p 0.9 --top-k 40 --repeat-penalty 1.1 \
--presence-penalty 0.0 --frequency-penalty 0.0 --seed 42 \
--stop "</s>" --stop "<|endoftext|>"
Web UI 功能
打开 http://localhost:5000/index.html。浏览器界面支持:
- 多轮对话,带流式 token 生成(SSE)。
- 每标签页独立的聊天会话 —— 每个标签页拥有自己的跟踪对话历史;请求 KV 块与前缀复用由推理引擎管理。
- 用于多模态推理的图像、视频、音频、PDF 与文本 / 代码上传(最大 500 MB)。
- PDF 文档:原生数字 PDF 会完整抽取文本层并内联到提示词;扫描 PDF 在视觉模型上回退为逐页图像(
TS_PDF_MAX_PAGES限制读取页数)。最终渲染的提示词会根据模型的实际上下文窗口进行检查。 - 思考 / 推理模式开关,以及带函数定义的工具调用。
- 消息编辑与删除,并可从对话中任意位置重新生成。
- 当托管
diffusion-gemmaGGUF 时,提供 DiffusionGemma 去噪预览(每步替换整条助手消息,最后定稿)。 - 托管
qwen_imageDiT 时提供 Qwen-Image-Edit:上传图像并输入编辑指令后,最多 8 帧实时去噪预览会原位刷新,最终 PNG 提供下载链接。 - 自由滚动 —— 在新 token 流式输出时阅读较早的回复;自动滚动会在回到底部时恢复。
配置文件(--config)
可以用 --config 传入一个 JSON 文件,取代冗长的命令行;CLI 读取相同格式。命令行参数始终优先——先应用文件中的值,命令行上再次给出的参数会覆盖它们,因此可以在多台主机上复用同一个文件,只覆盖需要变化的部分。--config 可重复以叠加多个文件(后者优先)。允许注释与尾随逗号。
# 从文件读取全部参数;本次仅覆盖后端
dotnet TensorSharp.Server/bin/TensorSharp.Server.dll --config config/server-basic.json
dotnet TensorSharp.Server/bin/TensorSharp.Server.dll --config config/server-basic.json --backend ggml_cpu
键名与下方长选项名相同(可带或不带前缀 --)。字符串/数字展开为 --key value,true 展开为裸开关 --key,数组展开为重复的标志(如 "stop": ["</s>", "<|eot|>"])。
变量。 在 "variables" 中定义一次共享值,用 ${name} 在任意字符串值中引用(未定义的名称回退到同名环境变量)。可以定义任意多个根路径——位于不同目录的模型各用一个。
自动下载。 任何文件参数都可以写成带本地 path 与一个或多个 urls 的对象。若 path 不存在,则从第一个可用 URL 下载(镜像按顺序尝试),保存到该路径,之后复用;进度打印到 stderr,可选的 sha256 用于校验。
{
"variables": { "modelRoot": "C:/models", "repo": "https://huggingface.co/unsloth/gemma-4-E4B-it-GGUF/resolve/main" },
"backend": "ggml_cuda",
"max-tokens": 4096,
"continuous-batching": true,
"stop": ["</s>", "<|eot|>"],
"model": { "path": "${modelRoot}/gemma-4-E4B-it-Q8_0.gguf", "urls": [ "${repo}/gemma-4-E4B-it-Q8_0.gguf" ] },
"mmproj": { "path": "${modelRoot}/gemma-4-E4B-mmproj-F16.gguf", "urls": [ "${repo}/mmproj-F16.gguf" ] }
}
开箱即用的示例见仓库 config/ 目录(cli-basic.json、server-basic.json、variables.json、auto-download.json、qwen-image-edit.json)——每个都使用真实、公开、无需授权的 URL,因此在全新机器上也能直接运行。完整说明见 config/README.md。
服务器选项
| 选项 | 说明 |
|---|---|
--model <path> | 要托管的 GGUF 文件(推理必需)。 |
--mmproj <path> | 显式多模态投影器 GGUF;只写文件名时相对于模型目录解析(传 none 可禁用)。需要 --model;不会自动扫描投影器。 |
--backend <type> | 默认后端:cpu、cuda、mlx、ggml_cpu、ggml_metal、ggml_cuda、ggml_vulkan。 |
--tp <N> | 张量并行度 —— 把托管的模型切分到本机 N 张 GPU 上(默认:1;环境变量 TENSORSHARP_TP_DEGREE)。需要 --backend cuda、ggml_cuda 或 ggml_vulkan。→ 多 GPU 与多节点 |
--tp-node-id <N> / --tp-peers <list> | 加入多节点 TP 集群:本节点的 0 起始编号,以及所有节点共享且顺序一致的 host:port 列表。服务端只能是节点 0(负责采样并对外提供 HTTP 的 driver);其余节点运行 TensorSharp.Cli worker。 |
--gpu-device <N> | ggml_vulkan 后端在多 GPU 主机上使用的 Vulkan 设备索引(默认:0;环境变量 TS_GGML_VULKAN_DEVICE)。 |
--list-gpus | 列出 ggml-vulkan 可见的 Vulkan 设备(索引 + 显卡名称)后退出。 |
--help | 打印完整参数说明后退出;不带任何参数时也会显示。推理始终需要启动参数 --model。 |
--config <path> | 从 JSON 配置文件读取参数(命令行参数会覆盖它)。支持 ${变量} 与通过 { "path": ..., "urls": [...] } 自动下载模型。可重复。 |
--max-tokens <N> | Web UI 请求未指定时的默认生成上限(默认:20000);Ollama/OpenAI 兼容端点省略请求级上限时使用 200。 |
--temperature / --top-k / --top-p / --min-p | 请求未提供时的默认采样值(默认 0.8 / 40 / 0.9 / 0)。 |
--repeat-penalty / --presence-penalty / --frequency-penalty / --seed | 默认惩罚与随机种子(默认 1.1 / 0 / 0 / -1)。 |
--stop <string> | 默认停止序列(可重复)。逐请求的 stop 会替换该列表。 |
--continuous-batching / --no-continuous-batching | 启用(默认)或禁用迭代级分页批处理。别名:--paged-batching。 |
--mtp-spec / --no-mtp-spec | 启用 / 禁用 NextN / MTP 推测解码(默认关闭);只在模型确实带有 MTP/NextN 草稿头时生效。→ MTP |
--mtp-draft <N> | 每个推测步草拟的最大 token 数(默认 8)。 |
--mtp-pmin <f> | 保留某 token 所需的草稿头最低置信度(默认 0.75)。 |
--mtp-draft-model <path> | 独立的 MTP 草稿 GGUF(Gemma 4 的 gemma4-assistant)。Qwen 3.6 的 NextN 位于主 GGUF 中,不需要此参数;显式草稿无法激活时启动会失败。 |
--prefill-chunk-size <N> | 每个调度步的最大 prefill token 数(设置 TS_SCHED_PREFILL_CHUNK)。 |
--kv-cache-dtype <type> | KV 缓存精度:f32、f16、q8_0 或 q4_0(默认自动,由后端 / 模型选择;环境变量 KV_CACHE_DTYPE)。 |
--paged-kv / --no-paged-kv | 独立 PagedKvCacheManager 的旧兼容开关,不在当前服务请求路径上;活跃请求 KV 由引擎管理。 |
--paged-kv-block-size / --paged-kv-ram-mb / --paged-kv-ssd-dir / --paged-kv-ssd-mb | 旧的独立 paged-KV 调参。当前服务请求请使用下方 TS_SCHED_* 引擎设置。 |
--paged-kv-quant-bits <b> | 旧的独立 TurboQuant 设置;服务端参数接受 0、4 或 8(运行时环境变量与 CLI 还接受 2)。 |
--qwen-image-vae / --qwen-image-vl / --qwen-image-mmproj <path> | 覆盖解析到的 Qwen-Image-Edit 伴随 GGUF(VAE / Qwen2.5-VL 文本编码器 / mmproj)。 |
--qwen-image-lora <path> | Qwen-Image-Edit Lightning 蒸馏 LoRA(.safetensors),合并进 DiT;自动推导去噪步数,并将 CFG 切换为 1.0。 |
逐请求字段(temperature、top_p、seed、stop ……)始终覆盖这些服务器级默认值;默认值只填补客户端省略的部分。
环境变量
| 变量 | 说明 |
|---|---|
BACKEND | 未传 --backend 时的默认后端(默认:macOS 上为 ggml_metal,其他平台为 ggml_cpu)。 |
MAX_TOKENS | 默认最大生成长度(默认:20000)。 |
TS_PDF_MAX_PAGES | 上传 PDF 时读取的页数上限,文本提取与页面图像渲染均遵循(默认:0 = 全部页面;CLI --pdf 同样遵循)。 |
VIDEO_SAMPLE_FPS / VIDEO_MAX_FRAMES | 每秒视频采样的帧数 / 可选的抽帧上限。 |
TS_FUSED_QKNORM_ROPE | Direct cuda 后端上 Qwen 3.5/3.6 文本 prefill 的融合 QK-Norm + RoPE CUDA 内核(默认开启;0 关闭)。 |
TENSORSHARP_TEMPERATURE、…_TOP_K、…_TOP_P、…_MIN_P | 当参数与请求体都未设置时的默认采样值。 |
TENSORSHARP_REPEAT_PENALTY、…_PRESENCE_PENALTY、…_FREQUENCY_PENALTY、…_SEED | 默认惩罚与随机种子。 |
TENSORSHARP_LOG_LEVEL / …_LOG_DIR / …_LOG_FILE | 日志级别、目录与文件开关(CLI 同样遵循)。 |
DIFFUSION_STEPS / DIFFUSION_MAX_BATCH | DiffusionGemma 每块去噪步数 / 批处理的最大并发扩散请求数。 |
TENSORSHARP_TP_DEGREE | 把托管模型切分到本机多少张 GPU 上(默认:1);服务端也支持 --tp N 参数。需要 --backend cuda、ggml_cuda 或 ggml_vulkan。→ 多 GPU 与多节点 |
TENSORSHARP_TP_DEVICES | 各 TP rank 使用的 GPU 序号,例如 0,2(默认 0..tp-1)。用于 GGML 后端。 |
TENSORSHARP_TP_NODE_ID / TENSORSHARP_TP_PEERS | 把张量并行扩展到多台机器:本节点的 0 起始编号,以及所有节点共用的逗号分隔 host:port 列表。两者必须同时设置。 |
TS_KV_CACHE_REDIS_URL / TS_KV_CACHE_REDIS_TTL_MINUTES | 把分页 KV 块持久化到 Redis,实现跨会话(乃至跨进程)复用,以及条目 TTL(分钟,默认 1440;0 = 不过期)。CLI:--redis-url / --paged-kv-redis-url / --paged-kv-redis-ttl。 |
TS_RESPONSES_STORE_REDIS_URL | 用 Redis 而非进程内存承载 OpenAI Responses API 存储。CLI:--redis-url。 |
当前二进制固定监听 http://0.0.0.0:5000;Docker Space 镜像在构建时把该常量改为 7860。
连续批处理调参
调度器 / 引擎的旋钮在进程启动时读取。通过环境变量(或会被翻译成它们的 --continuous-batching 系列参数)设置。
| 变量 | 说明 |
|---|---|
TS_SCHED_DISABLE_BATCHED | 1 强制逐序列 KV 交换,即使模型支持批处理(= --no-continuous-batching)。 |
TS_SCHED_MAX_BATCHED_TOKENS | 每步 token 预算(默认 4096)。 |
TS_SCHED_MAX_RUNNING_SEQS | 最大在飞序列数(默认 16)。 |
TS_SCHED_PREFILL_CHUNK | 每步最大 prefill token 数(默认 1024)。 |
TS_SCHED_SOLO_PREFILL_CHUNK | 系统中最多一个序列时的 prefill 分块大小,会限制所有独占 prefill 分块(默认 8192)。 |
TS_SCHED_DECODE_QUANTUM | 切换序列前的 decode token 数(默认 256 = 块大小)。 |
TS_SCHED_NUM_BLOCKS / TS_SCHED_BLOCK_SIZE | 引擎池中的物理块数(默认 256) / 每块 token 数(默认 256)。 |
TS_SCHED_PREFIX_CACHE | 0 禁用跨请求的块哈希前缀共享。 |
TS_<FAMILY>_BATCHED=0 | 逐模型的逃生口(如 TS_GEMMA4_BATCHED=0),回退到逐序列 KV 交换。 |