深入解析 Tomur:用 .NET 10 构建本地 AI 运行时,贯通纯 C# 推理、多模态与兼容 API
本地 AI 的门槛,往往出现在模型之外。
下载一份模型权重,只是开始。要让它真正服务于日常开发,还需要处理推理后端、硬件选择、接口适配、对话历史、文件附件、运行诊断和程序更新。文本模型可以正常运行,也不意味着语音、视觉和图像生成已经具备同样完整的使用路径。
Tomur 希望把这些工作整合为一个本地程序。它基于 .NET 10 与 C#,定位是面向本地 AI 工作负载的运行时与开发者工作台,默认面向离线优先、隐私敏感、希望降低运维成本的个人与团队开发环境。
Tomur 值得关注的一个技术特点,是同时维护两条推理路线:以 llama.cpp 为核心的 native runtime,以及由 C# 实现模型加载和推理核心的托管 provider。两条路线共享模型管理、协议入口、诊断和 Web Chat,用户可以在同一个工作台中使用不同架构的本地模型。
本文从产品使用与源码设计两个角度展开,介绍 Tomur 当前具备的能力,也说明各项能力的验证范围。内容依据 2026 年 10 月 5 日的仓库源码及已有验证记录,参考基线为 5cd90dd;文中的历史验证结果均可通过文末链接查阅。
一、Tomur 解决什么问题
Tomur 将几个通常分散的环节纳入同一个产品边界:
- 使用模型:在 Web Chat 中对话,也可以通过 HTTP API 调用。
- 准备模型:查看 Catalog、选择推荐包、下载权重并校验必要资产。
- 管理运行时:准备 native bundle,查看模型 session、硬件与资源状态。
- 保留本地状态:持久化会话、附件、工具摘要和生成结果。
- 定位问题:区分模型未下载、资产损坏、后端不可用、上下文超限与资源不足。
- 融入开发环境:提供 OpenAI、Ollama 和 Anthropic Messages 风格入口,以及 CLI 和系统服务管理代码。
这种设计适合需要本地 API 的应用开发者、希望在本机处理文本和多模态任务的用户,以及研究 .NET 推理实现的工程师。它的重点是本机模型体验,产品范围保持克制,不引入默认的多租户治理、SSO 或复杂后台管理体系。
离线优先也有明确前提:模型权重和所需运行时需要提前准备。下载阶段仍可能访问模型源;完成资产准备后,受支持的推理链路在本地执行。
二、整体架构:一个产品宿主,清晰的推理边界
Tomur 的主程序位于 app/Tomur.csproj。它同时承担 CLI、本地 ASP.NET Core HTTP 服务、系统服务 host、模型资产管理、会话管理、运行诊断和 Web 静态资源托管。
仓库的主要组成如下:
| 目录 | 职责 |
|---|---|
app/ |
产品宿主、API、CLI、会话、模型管理、诊断与运行时调度 |
providers/Abstractions/ |
托管模型描述、推理、session 等稳定契约 |
providers/Glm/ |
纯 C# GLM / MoE 模型 provider |
providers/Olmoe/ |
纯 C# OLMoE 模型 provider |
native/ |
上游 native 源码、Tomur 适配工程与 bundle 清单 |
web/ |
React、TypeScript、Vite 与 Ant Design X 工作台 |
tests/ |
分阶段契约、回归和专项验证项目 |
docs/ |
协议设计、发布记录和真实模型验证证据 |
从请求路径看,浏览器、CLI 和兼容客户端进入同一宿主,再由模型目录与 manifest 确定实际使用的 provider 或 native runtime。对上层应用而言,模型实现发生变化时,不需要随之更换服务地址和会话管理方式。
托管 provider 是构建期纳入主程序的类库,不提供独立服务,也不从外部目录任意加载程序集。Program.cs 负责进程入口、顶层命令分发和帮助,具体 CLI 实现按类别放在 app/Cli/,避免入口文件承担全部业务逻辑。
这里的“单体”指统一的产品宿主与本地服务。现有图像生成路径会使用内部 worker 子进程隔离 native assert 或崩溃,降低故障对主服务的影响。托管文本推理则在 Tomur 同一进程内执行。
三、两条推理路线:native 实用路径与纯 C# 探索
1. native runtime:GGUF 文本与 embeddings 的默认路径
llama.cpp 是 Tomur 当前文本与 embeddings 兼容 API 的默认推理路线。Tomur 在其外侧提供模型 session、backend 选择、GPU offload、CPU fallback、动态库加载与故障诊断。
native 能力还覆盖 Whisper、OCR 适配、stable-diffusion.cpp、GGUF TTS,以及 HyperLPR3/MNN 车牌识别桥接。各条链路有自己的模型资产和运行依赖,不能因为某个 backend 可见,就认为所有多模态任务都已经可用。
native 文件由 bundle manifest 管理,准备到 Tomur 数据目录下的 runtime 缓存。模型权重独立下载,不随程序更新反复打包。对 ggml 相关动态库的版本与依赖管理也属于这一层,避免不同 native 能力之间发生难以定位的加载冲突。
2. managed provider:推理核心由 C# 实现
providers/Glm 与 providers/Olmoe 的意义,在于 Tomur 已经进入模型执行核心,而不只是用 C# 包装一个外部推理服务。
托管路线实现了 safetensors 读取、tokenizer、张量操作、量化 kernel、KV cache、attention、MoE routing、expert cache 和生成流程。它使用 C# 的内存与向量化能力,围绕资源预算、模型元数据和取消响应建立执行边界,不依赖第三方推理动态库。
GLM / MoE 路线包含 MLA 与压缩 KV、packed int4/int8、专家权重按需读取、专家缓存和 SIMD kernel 等实现;OLMoE 路线包含标准 causal attention、full KV cache、q/k RMSNorm、RoPE、top-k router,以及 BF16 和 signed-int8 experts 等实现。OLMoE 同时复用部分托管 tensor、kernel 与存储基础。
不过,safetensors 是权重容器,不能代替模型架构契约。当前托管路线支持显式声明的架构、格式和转换布局,不意味着任意 safetensors 模型都可以直接加载。Tomur 通过 manifest 和元数据匹配 provider,避免把不兼容的模型交给错误的执行路径。
3. 已经取得什么实证
仓库记录了 GLM-4.7 Flash REAP 23B A3B 与 OLMoE 1B-7B Instruct 的真实模型加载、非流式推理和 Web Chat 对话证据。两者均由 Tomur 的纯 C# provider 执行。


这些证据回答了“完整模型能否沿托管路径产生真实结果”,但还没有覆盖所有协议、持续吞吐、重复取消、资源释放和跨平台条件。纯 C# 路线目前适合工程研究与定向验证,不能据此宣称已经达到成熟 native backend 的整体性能。
例如,GLM 记录中有一次 MLA 优化对照:在相同 prompt="a"、max_tokens=1 的 greedy 请求下,耗时由约 186.60 秒降至 26.60 秒,两次返回相同 token,端到端改善约 7.02 倍。这个数字只描述该单 token 对照,不能推导为完整聊天速度或持续 token 吞吐。
四、兼容 API:让本地模型进入现有开发工具链
Tomur 提供的是一组明确的兼容入口。调用方式尽量沿用现有协议习惯,实际执行仍由本地模型与 runtime 完成。
| 协议或用途 | 主要入口 |
|---|---|
| 健康与版本 | GET /health、GET /api/version |
| OpenAI 风格文本 | GET /v1/models、POST /v1/chat/completions、POST /v1/completions |
| OpenAI 风格 embeddings | POST /v1/embeddings |
| Ollama 风格 | GET /api/tags、POST /api/show、POST /api/generate、POST /api/chat |
| Anthropic Messages 风格 | POST /v1/messages、POST /v1/messages/count_tokens |
| 音频 | POST /v1/audio/transcriptions、POST /v1/audio/speech |
| 图像生成 | POST /v1/images/generations |
| Tomur 视觉与 OCR | POST /api/vision/analyze、POST /api/ocr/analyze |
| 模型资产 | GET /api/models/catalog、GET /api/models/installed |
| 本地 Agent | POST /api/agents/chat |
API 层不仅负责 JSON 字段转换,也需要处理流式响应、结束帧、usage、模型未安装、上下文超限和运行时错误。某项协议入口已经存在,不代表每个 provider 都通过了该协议的完整真实模型矩阵,选择模型时仍需看其实际能力。
Anthropic Messages 入口面向 Claude Code 等客户端所需的访问形态。GET /v1/models?limit=1000 会为本地文本模型提供 claude-tomur-* 发现别名。别名对应 Tomur 本地模型,不代表接入了云端 Claude 模型;实际可用 ID 以当前机器的模型列表为准。
使用 Python OpenAI SDK 时,可以将地址指向本地服务。以下是调用方式示例,模型需提前安装:
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:5137/v1",
api_key="local-client-placeholder",
)
result = client.chat.completions.create(
model="qwen35-9b-q4km",
messages=[
{"role": "user", "content": "用三句话介绍本地 AI 的应用场景。"}
],
stream=False,
)
print(result.choices[0].message.content)
示例中的 api_key 是 SDK 初始化占位参数,不能作为服务已启用鉴权的证明。Tomur 的默认使用环境是本地,公网服务所需的认证与网络边界需要单独设计。
五、模型资产管理:下载成功与模型可用之间还有一层校验
本地模型经常由多个文件组成。文本权重之外,视觉模型可能需要 projector,TTS 需要配套 tokenizer,图像生成需要 VAE 和文本编码器。只拿到一个主权重文件,并不构成完整的运行包。
Tomur 使用 Catalog 与安装清单管理这些关系。下载流程包含断点续传、checksum 校验、代理配置、许可提示与硬件档位推荐,模型安装清单保存到 <data>/models/models.manifest.json。
常用命令如下:
tomur list --catalog
tomur pull recommended
tomur list
tomur ps
Catalog 表示可以准备的模型资产;list 与兼容模型列表反映本地可见模型;ps 用于查看运行中的模型 session。资产校验失败、必需 sidecar 缺失或 provider 不匹配时,不能把模型当作可运行资产。
推荐包根据硬件档位选择,不是对任何机器的运行速度或显存占用作统一保证。开发者应结合实际内存、上下文长度和并发负载评估模型,而不是仅依据参数规模作决定。
六、多模态:语音、视觉和图像生成已经形成哪些链路
Tomur 的多模态能力有一份可查阅的历史真实模型 smoke 报告。2026 年 7 月 2 日,以下公开接口在当时环境中获得了实际结果:
| 能力 | 已记录的真实链路 | 结果范围 |
|---|---|---|
| 语音转写 | Whisper large-v3-turbo | 对真实音频样本返回转写文本 |
| 语音合成 | OuteTTS + WavTokenizer | 返回带 RIFF/WAVE 标识的音频文件 |
| 视觉理解 | SmolVLM + projector | 图片聊天与视觉 API 识别测试图中文字 |
| OCR | 当次通过 SmolVLM 视觉路线 | 返回测试图中的 OK42 文本 |
| 图像生成 | FLUX.2 klein + 配套资产 | 返回有效 PNG 文件 |
这份证据覆盖当时的 adapter、公开 API 和诊断面。尤其需要区分:OCR 接口的该次成功使用了视觉模型路线,不能直接扩大为所有 OCR native backend 和任意文档场景均已验证。
在 Web Chat 中,语音和图片能力继续被组织成用户可以理解的操作:录制语音回合、选择音频仅转写、发送附件、确认本地图片生成,以及预览、下载和打开生成结果。基础推理证据与新增交互的验收记录分别维护。
车牌识别采用另一条专门路径:Tomur 通过稳定 C ABI 调用 HyperLPR3/MNN,并将 plate.recognize 接入受控模式下的只读工具,返回车牌文本、色码、VehicleId、置信度与候选框。该桥接已有专项自动化测试及 Linux ARM64 native 构建、ABI 和依赖闭包记录,真实图片与目标机 smoke 仍待执行。路线图中的纯 C# 车牌 provider 是后续方向。
七、Tool Calling 与 Agent:能力和执行权限分别处理
工具调用有两个不同的场景,Tomur 为它们保留了清晰边界。
客户端工具:模型提出调用,由客户端执行
OpenAI 与 Ollama 兼容聊天入口支持标准工具声明、模型返回 tool calls,以及客户端执行工具后回灌结果。
完整流程是:客户端发送 tools,模型生成调用建议,客户端执行对应函数,再将原 assistant 消息与工具结果追加到后续请求。OpenAI 风格使用 tool_call_id 关联调用和结果。
这种兼容入口不会在服务端执行客户端声明的任意函数。目前 OpenAI strict=true 明确返回 400;现有工具调用 streaming 在完整推理与协议解析后发送可聚合帧,还不是逐 token 的参数增量。
Tomur 本地 Agent:受限循环内选择本地工具
POST /api/agents/chat 可以在受限服务端循环中,让模型自主选择 Tomur 本地工具。默认工具轮次为 2,最大为 4;即使同轮返回多个调用,执行仍按顺序进行。
只读工具可以自动执行。涉及副作用的工具,需要请求显式允许,并取得与完整 JSON 参数绑定的一次性确认。模型选择了某个动作,不会因此获得额外权限。
这一点直接影响本地 AI 的可靠性:模型建议、用户授权和真实执行结果是不同的信息,不能混在一条“智能体已完成任务”的描述中。调用 ID、参数指纹、确认状态和本地事件记录为排查问题提供了依据。
Tomur 使用 Microsoft.Extensions.AI 和 Microsoft Agent Framework 组织相关能力。既有 Tool Calling 基础代码有专项测试与 Windows x64 Native AOT 历史证据,但完整真实模型自主工具循环仍未闭环;当前 Agent Framework 1.19.0 升级后的构建与 smoke 也需要后续复核。
八、本地文件检索与会话:让结果留在工作台里
Tomur 使用 SQLite 保存会话消息、附件、工具摘要、诊断和生成产物记录。用户可以查看历史会话、追加消息、软删除会话,并读取对应产物。
文件检索则采用文本分块与 SQLite FTS5 / BM25,FTS5 不可用时提供 LIKE fallback。检索结果可以返回相对路径、行号范围和上下文,便于模型回答后追溯来源。
这是一条具体的本地全文检索链路。它限定在 Tomur 管理的文件目录内,并对文件数量、单文件大小、分块长度和返回结果数量设置上限。当前不能将其描述为已经完成向量数据库、混合检索和 reranker 的完整 RAG 平台,也不能把 Catalog 中存在 reranker 模型等同于重排推理已经接通。
这种边界有利于本地应用保持可解释性:读者可以知道检索基于什么文件、为什么返回这些内容,以及哪些文档格式仍需要后续处理能力。
九、Web 工作台:从对话开始,按需查看状态
Tomur Web 使用 React、TypeScript 和 Vite,AI 对话组件直接采用官方 Ant Design X 技术栈,包括 antd、@ant-design/x、@ant-design/x-markdown 和 @ant-design/x-sdk。
工作台采用 Chat-first 信息架构。用户先进入对话,再按需处理模型选择、附件、录音、图片生成和运行诊断。Models、Downloads、Runtime 和 Files 收敛在 Settings 分组或上下文入口中,避免使用前先面对一套管理后台。
现有代码支持流式显示、停止、重新生成、复制、历史懒加载和产物操作。重新生成会替换持久化消息尾部,已经生成的本地产物文件继续保留,避免将一次界面重试误当作文件清理指令。
前端由 Tomur 本地 HTTP 服务托管,无需另起一个前端产品。可视化下载队列、Settings 写入及更完整的模型导入体验仍属于后续工作,当前界面入口与最终交互验收需要分别看待。
十、诊断、硬件选择与本地数据
本地推理最常见的问题,通常是“为什么这台机器不能运行这个模型”。Tomur 将诊断作为核心能力提供,而不是只返回一段底层异常。
tomur doctor
tomur native prepare
doctor 用于检查操作系统、架构、CPU、内存、磁盘、代理、端口、SQLite、模型和 native runtime 等状态。Runtime API 和 Web 诊断入口也会显示实际 provider、session 与可用性信息。
硬件层处理 backend 枚举、设备选择、GPU offload 和 CPU fallback。Intel GPU/NPU 的可见性、选择、opt-in 和错误诊断已经接入,但 SYCL/OpenVINO/NPU 的真实推理矩阵仍需要实机证据。动态库存在、设备可枚举、模型成功加载和真实推理通过,是四个不同状态。
Tomur 的默认数据目录如下:
| 平台 | 数据目录 |
|---|---|
| Windows | %LOCALAPPDATA%\Tomur |
| Linux | ~/.local/share/tomur |
| macOS | ~/Library/Application Support/Tomur |
目录内保存 config/tomur.json、tomur.db、models/、runtime/ 和 logs/ 等本地状态,也可以通过 --data-dir 或 TOMUR_DATA_DIR 指定位置。
模型权重、数据库、日志和用户文件独立于程序二进制,便于升级、备份和排查问题。Agent 事件和 telemetry 默认在本地维护,OpenTelemetry exporter 为 opt-in;外部采集并非默认运行前提。
十一、Native AOT 与服务形态:部署体验如何收敛
Tomur 保留两种发布路线:Native AOT,以及非 AOT 的自包含单文件发布。目的都是降低本地使用的前置条件,让发行产物承担运行时准备工作。
仓库已有 Windows x64 Native AOT 发布通过、0 warnings 和 0 errors 的历史记录。API DTO、配置、模型目录与其他持久化类型通过 source-generated JSON 管理,托管 provider 由静态项目引用纳入,避免依赖任意程序集动态加载。
单文件发布也不会将所有东西塞进可执行文件:模型、SQLite、日志和生成结果仍保存在数据目录;native bundle 根据目标 RID 管理随包资产与版本化缓存。
系统服务代码覆盖 Windows Service、Linux systemd 和 macOS launchd,使用同一套 host 逻辑。服务标识分别为 Tomur、tomur.service 和 dev.tomur.service,管理入口为 tomur service。
跨平台 AOT、native bundle 完整性、系统服务和托盘的实机发布矩阵仍在收敛。已有一项平台记录,不代表全部平台与最新依赖组合都完成了发行验收。
十二、如何开始使用
使用发布产物时,可以从帮助、运行时准备和推荐模型开始:
tomur --help
tomur native prepare
tomur pull recommended
tomur open
也可以直接启动本地服务并打开工作台:
tomur serve --open
默认地址是 http://127.0.0.1:5137。在 PowerShell 7 中检查 HTTP 入口:
Invoke-RestMethod http://127.0.0.1:5137/health
Invoke-RestMethod http://127.0.0.1:5137/api/version
Invoke-RestMethod http://127.0.0.1:5137/v1/models
从源码运行需要 .NET 10 SDK 与 Node.js/npm。进入仓库后,主程序开发入口是:
dotnet run --project app -- --help
dotnet run --project app -- serve --open
前端资产由主项目按需构建和托管。上述命令是读者使用示例,本文撰写过程没有重新运行 Tomur 构建或模型 smoke。
十三、当前进度与值得关注的后续方向
理解一个持续迭代的 AI 项目,最有用的方式是把“代码接通”“真实模型跑通”和“发布质量达标”分开。
| 能力面 | 当前口径 |
|---|---|
| native 文本、embeddings 和基础多模态 | 已有对应阶段的实现与历史真实模型记录,证据按模型和环境限定 |
| 纯 C# GLM / OLMoE | 已有真实非流式推理与 Web Chat,完整协议、性能和资源矩阵继续推进 |
| Tool Calling / 本地 Agent | 协议和受控执行代码已接入,完整自主真实模型闭环仍待验证 |
| Native AOT 与服务发布 | Windows x64 有历史证据,跨平台与完整发行矩阵继续收敛 |
| Intel GPU / NPU | 选择与诊断代码已接入,实机推理验收待补齐 |
| Realtime v1 | 原生会话管线代码进行中,设备、延迟、质量与发布验收待验证 |
| 下载队列与 Settings 写入 | 路线图计划中 |
| ONNX 视觉矩阵与 Sezika provider | 路线图方向,尚不能作为可用产品能力介绍 |
Realtime v1 正在将语音能力推进到连续会话:本地 WebSocket、一次性 ticket、Silero VAD、Whisper、文本模型、TTS、滚动转写、短句音频、取消和历史回写已有相关代码,Web 端提供 AudioWorklet 采集播放、设备选择和有界重连。
首版协议为 tomur.realtime.v1,默认半双工;双向模式要求设备 AEC,并作为实验选项。该路径采用 ASR → 文本模型 → TTS 的级联设计,真实设备 smoke 仍为 pending,也尚未完成 OpenAI Realtime 适配,不能把原生网关接通写成全双工低延迟语音已经发布。
ONNX 视觉 provider 计划形成统一视觉能力矩阵,逐步覆盖分类、检测、分割、OCR、姿态、人脸、深度和图像增强等方向。目前是能力规划,尚未形成新增视觉模型的接入与验证闭环。
Sezika 决策引擎接入 则面向类型化问题:对本地文本或 JSON state 输出 Choice、Score、Boolean 等预测。Tomur 已建立 decision 契约以及请求、资产校验基础,但尚未纳入可运行 Sezika provider、真实决策模型和可用决策 API。预测和工具执行授权仍保持独立。
这些方向延续了同一个工程原则:先明确模型、资产、协议和资源边界,再用可复核的真实证据判断能力是否可用。
十四、开源地址与延伸阅读
Tomur 的自有代码以 Apache License 2.0 发布,由 IoTSharp contributors 维护。第三方库、native runtime 和模型权重继续遵守各自许可;主项目开源不意味着所有可选模型都可以无条件商用。
如果你关注本地 AI 应用、.NET 模型执行或兼容协议工程,可以从以下入口阅读源码与验证记录:
- Tomur 项目地址与 README
- 长期路线图与已完成历史
- GLM-4.7 纯 C# 推理验证
- OLMoE int8 转换与真实推理记录
- 多模态真实模型 smoke 报告
- Native AOT 发布记录
- Realtime v1 协议与边界
Tomur 为本地 AI 提供了一条值得研究的 .NET 实现路径:在统一工作台与协议入口之下,保留 native 的实用能力,也让 C# 直接参与模型运行核心。读者既可以把它作为本地应用接入对象,也可以沿源码深入理解模型资产、session 生命周期、量化推理和运行诊断如何协同工作。
关注我们,扫码进群沟通
欢迎关注我们,扫码加入微信或 QQ 交流群,一起交流技术实践,分享使用经验和问题反馈。
微信交流二维码

QQ 交流群:IoTSharp,群号 63631741

请扫码并关注我们,进群沟通。若二维码暂时无法使用,可通过 QQ 群号 63631741 搜索加入。

浙公网安备 33010602011771号