从 C# 使用 TensorSharp
TensorSharp 是一个真正的 .NET 库,而不只是可执行文件。从源码 checkout 引用其项目,即可在不经过 HTTP 的情况下从自己的代码驱动推理。
项目与包边界
仓库按可发布包边界拆分。源码树的发布集合是下表的全部 13 个包,由 eng/verify-packages.ps1 校验,并作为发布流水线的门禁。
核验于 2026-09-08:NuGet.org 上目前只有其中 8 个,版本 3.1.2(2026 年 7 月):Tensors、Runtime、Models、三个后端、Server 与 Cli。它们落后于当前源码树与服务器版本——已发布的 TensorSharp.Server 早于日志层与聊天层拆分。其余 5 个(TensorSharp.Runtime.Logging、TensorSharp.AgentHost、TensorSharp.Chat、TensorSharp.Server.Host、TensorSharp.Distributed)已可打包并通过校验,但尚未推送。
| 项目 / 包 | 命名空间 | 职责 |
|---|---|---|
TensorSharp.Core / TensorSharp.Tensors | TensorSharp | 张量原语、运算、分配器、存储、设备抽象;NuGet ID 与项目名不同。 |
TensorSharp.Runtime.Logging | TensorSharp.Runtime.Logging | 各宿主共用的日志抽象与输出目标,不再压在引擎各层上。尚未发布到 NuGet.org。 |
TensorSharp.Runtime | TensorSharp.Runtime | GGUF 解析、分词器、提示词渲染、采样、分页 KV 缓存、连续批处理调度器。 |
TensorSharp.Models | TensorSharp.Models | ModelBase、架构实现、多模态编码器、批量/分页前向。 |
TensorSharp.Backends.GGML | TensorSharp.GGML | GGML 支撑的执行与原生互操作。 |
TensorSharp.Backends.Cuda | TensorSharp.Cuda | 直接 CUDA 分配器、存储、cuBLAS GEMM、PTX 内核、量化 CUDA 运算。 |
TensorSharp.Backends.MLX | TensorSharp.MLX | Apple Silicon MLX 后端(mlx-c / Metal)。 |
TensorSharp.Chat | TensorSharp.Chat | 与宿主无关的聊天流水线——ModelService、会话、生成、技能循环、Web UI 请求/流式契约。不依赖 ASP.NET Core;由服务器、CLI 与 iOS 应用共用。尚未发布到 NuGet.org。 |
TensorSharp.Server | TensorSharp.Server | ASP.NET Core 库:OpenAI/Ollama 适配器、基于 TensorSharp.Chat 的 HTTP 传输、Web UI 资源。它是库——单独构建不产生可执行文件。 |
TensorSharp.Server.Host | TensorSharp.Server.Host | 基于该库的可运行 Web 应用:Program.cs、宿主装配、wwwroot/ 与命令行。实际运行的是它。尚未发布到 NuGet.org。 |
TensorSharp.Cli | TensorSharp.Cli | 控制台宿主与调试 / 批处理工具。 |
TensorSharp.AgentHost | TensorSharp.AgentHost.* | 技能、有界智能体循环、五个代码工具、沙箱、工作区与产物。尚未发布到 NuGet.org。 |
TensorSharp.Distributed | TensorSharp.Distributed | 点对点 TCP 分布式张量并行。尚未发布到 NuGet.org。 |
典型嵌入场景只需引用 TensorSharp.Models.csproj;它已引用 Core、Runtime 与各后端项目。若你的应用与 TensorSharp checkout 同级:
dotnet add reference ../TensorSharp/TensorSharp.Models/TensorSharp.Models.csproj
NuGet 3.1.2 是较早的快照;需要当前实现时请使用项目引用。Runtime.Logging、AgentHost、Chat、Server.Host 与 Distributed 还没有已发布的包,必须从源码引用。源码构建默认编译原生 GGML/MLX;开发托管 CPU 路径时传入 -p:TensorSharpSkipGgmlNative=true -p:TensorSharpSkipMlxNative=true,或按后端页面构建原生库。
最小示例 —— 加载、生成、解码
每个模型都以相同方式加载:ModelBase.Create() 读取 GGUF 元数据并实例化正确的架构。从这里开始你做分词、运行前向、采样并解码。
using System;
using System.Collections.Generic;
using System.Linq;
using TensorSharp.Models;
using TensorSharp.Runtime;
// 1. 加载任意受支持的 GGUF —— 架构从元数据自动识别。
// 按你的构建选择 BackendType:GgmlCuda、GgmlMetal、GgmlVulkan 或 GgmlCpu。
using var model = ModelBase.Create("gemma-4-E4B-it-Q8_0.gguf", BackendType.GgmlCuda);
// 2. 配置采样(默认值与 Ollama 一致:temp 0.8、top_k 40、top_p 0.9)。
var sampling = new SamplingConfig { Temperature = 0.7f, TopP = 0.9f, TopK = 40 };
// 3. 对提示词分词。
var tokens = model.Tokenizer
.Encode("Explain mixture-of-experts in one sentence.", addSpecial: true)
.ToList();
var generated = new List<int>();
// 4. 完整提示词只 prefill 一次。
float[] logits = model.Forward(tokens.ToArray());
// 5. 每次只 decode 一个新 token。Forward() 自己维护 KV-cache 位置,
// prefill 后只传刚采样出的 token,不要重复传完整历史。
for (int step = 0; step < 200; step++)
{
int next = model.Sample(logits, sampling, generated); // 应用惩罚 + 采样
if (model.Tokenizer.IsEos(next)) break;
generated.Add(next);
logits = model.Forward(new[] { next });
}
// 6. 反分词得到结果。
Console.WriteLine(model.Tokenizer.Decode(generated));
要做贪心/确定性解码,请调用 model.SampleGreedy(logits) 而非 Sample。
冒烟测试变体
一次性健全性检查:加载模型、运行一次前向,并打印 top token:
using var model = ModelBase.Create(modelPath, backend);
var tokenIds = model.Tokenizer.Encode("Hello", addSpecial: true);
float[] logits = model.Forward(tokenIds.ToArray());
int topToken = model.SampleGreedy(logits);
Console.WriteLine($"vocab={model.Config.VocabSize}, tokens={tokenIds.Count}, topToken={topToken}");
DiffusionGemma — 文本扩散
DiffusionGemma 是块文本扩散模型,而非自回归模型。ModelBase.Create() 仍可加载它(GGUF 架构为 diffusion-gemma / diffusion_gemma)并返回 DiffusionGemmaModel,但其 Forward(int[]) 会故意抛出异常——生成需通过 DiffusionGemmaSampler,它在 [prompt | canvas] 序列上对定长的 canvas 块迭代去噪。架构详见 DiffusionGemma 模型卡。
using TensorSharp.Models;
using TensorSharp.Models.DiffusionGemma;
using TensorSharp.Runtime;
// 加载 diffusion-gemma GGUF——架构会自动检测。
using var model = (DiffusionGemmaModel)ModelBase.Create("diffusion-gemma.gguf", BackendType.GgmlCuda);
// 用模型的聊天模板渲染 prompt,然后分词。
var messages = new List<ChatMessage> { new() { Role = "user", Content = "Write a haiku about winter." } };
string rendered = PromptRenderer.Render(model.Config.ChatTemplate, messages,
addGenerationPrompt: true, architecture: model.Config.Architecture);
int[] promptTokens = model.Tokenizer.Encode(rendered, addSpecial: true).ToArray();
// 配置 EntropyBound 去噪采样器。
var p = new DiffusionEbParams
{
MaxDenoisingSteps = 48, // 每个 canvas 块的精化步数
Seed = 0, // 确定性
MaxBlocks = 1, // 块自回归的 canvas 块数
};
var sampler = new DiffusionGemmaSampler(model);
// 生成。可选回调在每个去噪步后触发,参数为
// (blockIndex, step, totalSteps, previewTokens)——适合做实时 UI。
List<int> generated = sampler.Generate(promptTokens, p,
(block, step, total, preview) => Console.Write($"\rblock {block + 1} step {step + 1}/{total} "));
Console.WriteLine();
Console.WriteLine(model.Tokenizer.Decode(generated));
DiffusionEbParams 的关键参数:MaxDenoisingSteps(48)、TMin/TMax 温度调度(0.4 / 0.8)、EntropyBound(0.1)、StabilityThreshold / ConfidenceThreshold 早停、Seed 与 MaxBlocks。model.CanvasLength 给出每块的 canvas 大小。
在 GPU 后端上,prompt 的 K/V 每块缓存一次并在各去噪步间复用;GGML 后端默认使用融合的整模型解码加融合 lm-head 尾。调优开关(DIFFUSION_STEPS、DIFFUSION_NO_SC 等)见高级页。
Qwen-Image-Edit — 图像编辑
Qwen-Image-Edit 接收提示词 + 一张输入图像并返回编辑后的图像。所加载的 qwen_image GGUF 仅是 MMDiT 扩散 Transformer;模型还会拉入两个伴随 GGUF(在 DiT 文件同目录解析,或通过 TS_QWEN_IMAGE_VAE / TS_QWEN_IMAGE_TE / TS_QWEN_IMAGE_MMPROJ 环境变量指定):Qwen-Image VAE 与 Qwen2.5-VL-7B 文本编码器。与 DiffusionGemma 一样,它不是自回归文本模型——自回归入口会抛异常,编辑通过 EditImage() 驱动。
using TensorSharp.Models;
using TensorSharp.Models.QwenImage;
using TensorSharp.Runtime;
// 加载 MMDiT GGUF(架构 = qwen_image)。VAE + Qwen2.5-VL
// 伴随文件从同一目录解析(或用 TS_QWEN_IMAGE_* 环境变量)。
using var model = (QwenImageModel)ModelBase.Create("qwen-image-edit-DiT-Q4_K_M.gguf", BackendType.GgmlCuda);
// 加载输入图像(PNG/JPEG 解码为 RgbImage)。
RgbImage input = ImageIO.Load("input.png");
var p = new QwenImageParams
{
Steps = 30, // FlowMatch-Euler 去噪步数
CfgScale = 4.0f, // true-CFG 引导;<= 1 关闭负向分支
NegativePrompt = " ", // 仅当 CfgScale > 1 时使用
Seed = 0,
TargetArea = 1024 * 1024, // ~1 MP;纵横比随输入(尺寸对齐到 /16)
// Width = 0, Height = 0, // 指定显式输出尺寸可绕过 VRAM 钳制
};
RgbImage output = model.EditImage("Make the sky a dramatic sunset.", input, p);
ImageIO.SavePng("edited.png", output);
Console.WriteLine($"Saved {output.Width}x{output.Height} edited image.");
若要做实时 UI,设置 p.OnStep = (step, total, preview) => { … } 与 p.PreviewCount,即可在节流的步上收到部分去噪潜变量解码出的 RGB 预览。RgbImage 暴露 Width、Height 与平面/交错的 Pixels 缓冲;ImageIO 提供 Load、Decode(byte[])、EncodePng、SavePng 及缩放辅助。
图像编辑计算量大:每个去噪步都要跑完整的 60 块 MMDiT(开启 CFG 时跑两遍)。请使用 CUDA 或 Metal 的 GGML 后端做实用的全质量编辑;除非你固定 Width/Height,否则流水线会按设备 VRAM 预算自动钳制目标面积。伴随 GGUF 布局见模型卡。
SamplingConfig
采样旋钮与 CLI 参数及 API 选项一一对应。默认值与 Ollama 一致。
| 属性 | 类型 | 默认 | 含义 |
|---|---|---|---|
Temperature | float | 0.8 | 随机性;0 = 贪心/确定性。 |
TopK | int | 40 | 限制为概率最高的 K 个 token;0 = 禁用。 |
TopP | float | 0.9 | 核采样;1.0 = 禁用。 |
MinP | float | 0 | 相对最大值的最小概率阈值。 |
RepetitionPenalty | float | 1.1 | 乘性惩罚;>1 抑制重复。 |
PresencePenalty | float | 0 | 对已出现 token 的加性惩罚。 |
FrequencyPenalty | float | 0 | 与 token 频率成比例的加性惩罚。 |
Seed | int | -1 | 可复现采样;-1 = 基于时间。 |
StopSequences | List<string> | null | 产生其中任一字符串时停止。 |
MaxTokens | int | 0 | 最大生成 token 数;0 = 使用调用方默认。 |
Agent Skills —— SkillsChatClient
Agent Skill(智能体技能)是一个面向模型的说明文件夹——一份 SKILL.md,外加它引用的脚本、参考文档与素材——模型只在任务需要时才加载它。SkillsChatClient(命名空间 TensorSharp.AgentHost.Skills,位于 TensorSharp.AgentHost 项目)就是 .NET 应用取用技能的入口。它通过 HTTP 调用兼容 OpenAI 的聊天端点,而不是在进程内加载 GGUF,因此与本页其余内容不同:它既不需要后端,也不需要引用 TensorSharp.Models。
在 TensorSharp 支持工具的聊天格式上,已选择和发现到的技能最初都只披露元数据;模型按需读取说明与随附文件。若模型没有可用的工具解析器,TensorSharp 会改为内联已选择技能的正文并隐藏内置技能/代码工具,使请求仍然有用,而不会假装工具往返能工作。
它覆盖实际会遇到的两种情形,由 SkillsChatClientOptions.Delivery 选择。
面向 TensorSharp.Server —— SkillDelivery.Server
只需点名技能,其余全部由服务端在模型旁边完成,渐进式披露的循环也在那里跑。每次请求不上传任何东西,技能文件也从不离开服务端。
using System;
using System.Threading.Tasks;
using TensorSharp.AgentHost.Skills;
using var client = new SkillsChatClient(new SkillsChatClientOptions
{
Endpoint = "http://localhost:5000", // 带不带结尾的 /v1 都可以
DefaultModel = "gemma-4-E4B-it-Q8_0.gguf",
Delivery = SkillDelivery.Server,
});
// 单轮场景的便捷写法:提示词 + 要使用的技能。
SkillsChatResponse reply = await client.CompleteAsync(
SkillsChatRequest.User("Extract the tables from report.pdf", "pdf"));
Console.WriteLine(reply.Content);
Console.WriteLine($"{reply.Rounds} 轮,prompt {reply.PromptTokens} + completion {reply.CompletionTokens} token");
服务端交付模式下,渐进式披露的循环跑在服务端内部,因此 reply.SkillInvocations 返回为空,reply.Rounds 为 1 —— 本客户端恰好只发出了一次请求。
面向任意其他兼容 OpenAI 的端点 —— SkillDelivery.Local
把客户端指向一个本地 SkillRegistry,它就会在本进程内构造提示词块、声明技能工具并运行整个循环,于是一个从没听说过技能的端点表现得就像原生支持一样。代价是模型每读一个文件多一次网络往返。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using TensorSharp.Runtime; // ChatMessage
using TensorSharp.AgentHost.Skills;
var registry = new SkillRegistry(new SkillRegistryOptions
{
Roots = new[] { "/srv/skills" }, // 最深扫描 MaxDepth(3)层
});
using var client = new SkillsChatClient(new SkillsChatClientOptions
{
Endpoint = "https://api.example.com/v1",
ApiKey = Environment.GetEnvironmentVariable("EXAMPLE_API_KEY"),
DefaultModel = "some-hosted-model",
Delivery = SkillDelivery.Local,
Registry = registry,
Discovery = true, // 同时展示本次请求没有点名的技能
});
SkillsChatResponse reply = await client.CompleteAsync(new SkillsChatRequest
{
Messages = { new ChatMessage { Role = "user", Content = "Fill in this AcroForm and tell me what you set." } },
Skills = { "pdf" },
MaxTokens = 800,
});
Console.WriteLine(reply.Content);
// 模型读过的每一个技能文件,按顺序排列。
foreach (SkillToolInvocation call in reply.SkillInvocations)
Console.WriteLine($"round {call.Round}: {call.Tool} {call.SkillId}/{call.ResourcePath} ok={call.Ok}");
默认值 SkillDelivery.Auto 会探测一次 /v1/skills,并把结果缓存到该客户端的整个生命周期:端点有响应就走服务端交付,没有响应且本客户端带了注册表就走本地交付。await client.ResolveDeliveryAsync() 会告诉你最终选了哪一种;await client.ListServerSkillsAsync() 则向端点询问它有哪些技能,端点没有实现技能 API 时返回空列表而不是抛异常。
SkillsChatResponse.ToolCalls 装的是对调用方自己的工具(即传入 SkillsChatRequest.Tools 的那些)的调用,客户端从不执行它们——只有调用方知道这些工具做什么。列表非空就意味着你需要自己执行它们,并在后续请求中把结果送回;技能工具此时已经应答完毕,reply.Messages 就是可以直接续写的完整对话记录。请求失败会抛出 SkillsChatException。
SkillsChatClientOptions
| 属性 | 类型 | 默认 | 含义 |
|---|---|---|---|
Endpoint | string | 必填 | API 根地址,带不带结尾的 /v1 都可以。 |
ApiKey | string? | null | 端点需要时使用的 Bearer token。TensorSharp.Server 不需要。 |
DefaultModel | string? | null | 未按请求单独指定时,随每次请求发送的模型名。 |
Delivery | SkillDelivery | Auto | 由谁解析技能:Auto、Server 或 Local。 |
Registry | SkillRegistry? | null | 本地交付时使用的技能集合。服务端交付时忽略——那时技能归端点所有。 |
PromptOptions | SkillPromptOptions | .Default | 本地交付的提示词预算。 |
LoopOptions | SkillAgentLoopOptions | .Default | 本地交付的循环上限 —— MaxRounds 8、MaxCallsPerRound 8,以及每次工具调用执行后触发的 OnInvocation 回调。 |
Discovery | bool | true | 把本次请求未点名的技能也展示给模型,好让它自己发现。SkillsChatRequest.Discovery 可按请求覆盖。 |
Timeout | TimeSpan | 10 分钟 | 单次请求超时。仅在客户端自行创建 HttpClient 时生效——若从 IHttpClientFactory 取一个传进构造函数,则不会改动它。 |
SkillsChatRequest 与 SkillsChatResponse
| 成员 | 类型 | 含义 |
|---|---|---|
SkillsChatRequest.Messages | List<ChatMessage> | 对话内容。首条 system 消息会与技能文本块合并,而不是被顶掉。 |
SkillsChatRequest.Skills | List<string> | 要使用的技能名,取自注册表中的名称。 |
SkillsChatRequest.Tools | List<ToolFunction>? | 调用方自己的工具。客户端从不执行,会原样回传给调用方处理。 |
SkillsChatRequest.Model · MaxTokens · Temperature · TopP · Think · Discovery | string? · int? · double? · double? · bool · bool? | 按请求覆盖的设置;为 null 时交由端点决定(Discovery 则回落到客户端自身的选项)。 |
SkillsChatRequest.User(prompt, params skills) | 静态方法 | 单轮常见场景的便捷写法。 |
SkillsChatResponse.Content · Thinking | string · string? | 助手的回答,以及模型给出推理内容时的推理文本。 |
SkillsChatResponse.ToolCalls | IReadOnlyList<ToolCall> | 对调用方自己的工具的调用,客户端从不执行。 |
SkillsChatResponse.Messages | List<ChatMessage> | 完整对话记录,含披露循环追加的全部内容。 |
SkillsChatResponse.SkillInvocations | IReadOnlyList<SkillToolInvocation> | 模型读过的每一个技能文件,按顺序排列 —— Round、Tool、SkillId、ResourcePath、Ok、ResultBytes。服务端交付时为空。 |
SkillsChatResponse.FinishReason · PromptTokens · CompletionTokens · Rounds | string? · int · int · int | 生成停止的原因、逐轮累加的 token 数,以及实际跑了几次生成。Rounds 为 1 表示模型没读任何东西就作答了。 |
SkillRegistry 与 SkillRegistryOptions
注册表负责发现(在配置的目录中查找 SKILL.md)、安装与查找;它是唯一接触技能存储的组件,因此边界约束规则集中在一处。CLI 与服务端也正是用 --skills-dir 构造出它。
| 成员 | 类型 / 默认 | 含义 |
|---|---|---|
SkillRegistryOptions.Roots | IReadOnlyList<string>,空 | 要扫描的目录,按优先级顺序排列。一个根目录可以是单个技能(直接含 SKILL.md),也可以是装着若干技能的目录。 |
SkillRegistryOptions.InstallDirectory | string?,null | 运行时安装的技能写入的位置;同样会被扫描,并且优先级永远排在最前。为 null 时注册表只读。 |
SkillRegistryOptions.MaxDepth | int,3 | 在一个根目录下查找 SKILL.md 的最大深度。 |
SkillRegistryOptions.MaxSkills · MaxManifestBytes · MaxSkillBytes · MaxSkillFiles | 512 · 4 MB · 256 MB · 4096 | 各项上限,好让指错目录的根目录显式失败,而不是耗尽内存。 |
Skills · Errors · Roots | IReadOnlyList<Skill> · IReadOnlyList<SkillLoadError> · IReadOnlyList<string> | 成功加载的技能、加载失败的项(含 Path 与 Message),以及实际扫描过的根目录。 |
CanInstall · InstallDirectory | bool · string? | 是否配置了运行时安装,以及安装到哪里。 |
TryGet(id, out Skill) · Resolve(ids, out unknown) | bool · IReadOnlyList<Skill> | 按名称查找单个技能,或解析一组选择并得知哪些名称没找到。 |
Refresh() | SkillScanResult | 重新扫描全部根目录 —— POST /api/skills/rescan 调用的就是它。 |
InstallFromDirectory(path, overwrite) · InstallFromZip(stream, overwrite, limits) · Remove(id) | Skill · Skill · bool | 从文件夹或上传的压缩包安装技能,或删除一个已安装的技能。压缩包的每个条目都要经过与模型读取相同的那道路径关卡;被拒绝的压缩包会抛出 SkillInstallException。 |
完整参考(frontmatter 字段、提示词预算与安全模型)见 docs/agent_skills.md。可直接取用的开源技能:github.com/anthropics/skills。
AgentHost 运行时层
TensorSharp.AgentHost 是构建在 TensorSharp.Runtime 之上的可选智能体层;Runtime 不反向依赖它。CodeExecOptions、ShellRunner 与 CodeRunnerAdapter 实现宿主拥有的五个工具:read_file、edit_file、write_file、shell、apply_patch。只有宿主提供持久工作区时才声明文件工具;没有工作区的直接调用方只获得 shell。
SkillAgentLoop 运行有界的单助手循环,只执行 TensorSharp 自有的技能/代码调用,并把应用自身工具的调用放入 SkillLoopResult.PendingClientToolCalls 返回。宿主默认最多生成 8 轮;提供代码工具时提升为 24,除非运维方显式设定。SessionWorkspaceManager 为每个服务器会话提供私有工作区;仅请求调用方则在一次请求内共享。工作文件、允许导出的环境状态与已安装包会在该作用域内保留,而 PATH 每次 shell 调用都会重建。
代码工具默认关闭,沙箱模式默认 required。macOS Seatbelt 无法保证清理刻意脱离的子进程;Linux 需要 bubblewrap 0.12+;Windows 作业对象无法约束文件或套接字,因此执行必须显式选择无隔离模式。这些是启动权限,不是逐命令审批,循环也不会生成子智能体。结构化输出请求会内联已选择技能并隐藏内置工具。完整边界见智能体工作。
关键类型与接口
| 类型 | 角色 |
|---|---|
ModelBase | 每个架构的抽象基类。Create(path, backend)、Forward(int[])、Sample(...)、SampleGreedy(...),外加 Config 与 Tokenizer。 |
BackendType | 枚举:Cpu、GgmlCpu、GgmlMetal、GgmlCuda、GgmlVulkan、Cuda、Mlx。 |
SamplingConfig | 采样配置(见上表)。 |
ITokenizer | Encode(text, addSpecial)、Decode(ids)、IsEos(id)、EosTokenIds(BPE 与 SentencePiece 实现)。 |
ModelConfig | 架构元数据:VocabSize、上下文长度等。 |
IBatchedPagedModel | 可选的批量/分页前向(ForwardBatch),多数架构为连续批处理而实现。 |
DiffusionGemmaModel + DiffusionGemmaSampler | 文本扩散模型及其 EntropyBound 去噪采样器(Generate(promptTokens, DiffusionEbParams, …))。Forward() 不受支持。 |
QwenImageModel + QwenImageParams | Qwen-Image-Edit 图像编辑器。EditImage(prompt, RgbImage, QwenImageParams) 返回修改后的 RgbImage;ImageIO 负责 PNG 加载/保存。 |
SkillsChatClient + SkillsChatClientOptions | 面向兼容 OpenAI 的端点使用 Agent Skills。CompleteAsync(SkillsChatRequest) 返回 SkillsChatResponse;SkillDelivery 决定披露循环由服务端还是本进程运行(位于 TensorSharp.AgentHost.Skills)。 |
SkillRegistry + SkillRegistryOptions | 宿主已知的技能集合:在配置的根目录中扫描 SKILL.md、从文件夹或 .zip 安装,以及查找。它是唯一接触技能存储的组件,因此边界约束集中在一处生效。 |
InferenceEngine | 支撑服务器连续批处理的 worker 线程调度器 + 分页块池(在 TensorSharp.Runtime.Scheduling 中)。 |
其他值得了解的运行时契约:IModelArchitecture、IPromptRenderer、IOutputProtocolParser、IMultimodalInjector、IKvBlockCodec(带内置 TurboQuantKvCodec)以及 IKVCachePolicy。
对多数应用而言,最简单的集成是运行 TensorSharp.Server 并通过兼容 OpenAI 的 API 调用它 —— 你的应用进程保持干净,并免费获得连续批处理。当你需要进程内控制或自定义解码时,再使用库 API。