Bitzsoft.Integrations.AI 1.0.2

dotnet add package Bitzsoft.Integrations.AI --version 1.0.2
                    
NuGet\Install-Package Bitzsoft.Integrations.AI -Version 1.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Bitzsoft.Integrations.AI" Version="1.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Bitzsoft.Integrations.AI" Version="1.0.2" />
                    
Directory.Packages.props
<PackageReference Include="Bitzsoft.Integrations.AI" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Bitzsoft.Integrations.AI --version 1.0.2
                    
#r "nuget: Bitzsoft.Integrations.AI, 1.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Bitzsoft.Integrations.AI@1.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Bitzsoft.Integrations.AI&version=1.0.2
                    
Install as a Cake Addin
#tool nuget:?package=Bitzsoft.Integrations.AI&version=1.0.2
                    
Install as a Cake Tool

Bitzsoft.Integrations.AI

基于 Microsoft.Extensions.AI 的多供应商模型接入层。它统一提供 IChatClientIEmbeddingGenerator<string, Embedding<float>>,把模型协议、租户上下文、 凭据解析和统一审计放在一个稳定 Seam 中,不复制各厂商 SDK 的业务 API。

兼容性与安装

dotnet add package Bitzsoft.Integrations.AI
  • 目标框架:net8.0;net10.0
  • OpenAI、智谱、Kimi、通义和 DeepSeek 使用 OpenAI Chat Completions 兼容协议;
  • OpenAI 同时支持 Responses API;
  • OpenAI、智谱和通义提供已确认的 OpenAI-compatible 文本向量接入;
  • Claude 使用独立的 Bitzsoft.Integrations.AI.Anthropic 原生 Adapter;
  • API Key 不进入 Options、持久化模型、日志或调试输出。

.NET 5 宿主应把 AI 能力部署为独立的 .NET 8/10 服务,通过受控 HTTP 或 MCP 调用。

完整最小示例

下面同时注册聊天和向量生成,并演示开发环境的租户凭据。进程内凭据 Store 只用于本地 开发和测试:

using Bitzsoft.Integrations.AI;
using Bitzsoft.Integrations.Core;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();

// 仅开发/测试:生产环境替换为 Vault、KMS 或云密钥服务解析器。
services.AddInMemoryIntegrationCredentials();

// 默认聊天客户端;ProviderId 决定凭据键 AI:openai-dev。
services.AddBitzChatClient(options =>
{
    options.ProviderId = "openai-dev";
    options.ProfileId = "openai-responses";
    options.ModelId = "<已批准的聊天模型>";
    options.EnableTelemetry = true;
    options.EnableLogging = true;
    options.EnableRequestAudit = true;
});

// 命名 Embedding;维度必须与向量数据库 Collection Schema 一致。
services.AddBitzEmbeddingGenerator("knowledge", options =>
{
    options.ProviderId = "openai-dev";
    options.ProfileId = "openai-chat";
    options.ModelId = "text-embedding-3-small";
    options.Dimensions = 1536;
});

await using var provider = services.BuildServiceProvider(
    new ServiceProviderOptions { ValidateScopes = true });

// 写入 tenant-a 的开发凭据。真实密钥应来自 User Secrets,而不是源码。
var credentialStore = provider.GetRequiredService<
    InMemoryIntegrationCredentialStore>();
using (var credential = new IntegrationCredential(
[
    new(AICredentialFieldNames.ApiKey, "<开发环境 API Key>")
]))
{
    credentialStore.Set(
        new IntegrationCredentialKey(
            tenantId: "tenant-a",
            providerKey: "AI:openai-dev",
            environment: IntegrationEnvironments.Development),
        credential);
}

// 每个业务请求创建 Scope,并显式设置租户与环境上下文。
using var scope = provider.CreateScope();
var contextAccessor = scope.ServiceProvider.GetRequiredService<
    IIntegrationContextAccessor>();
using (contextAccessor.Push(new IntegrationContext(
    tenantId: "tenant-a",
    environment: IntegrationEnvironments.Development,
    correlationId: Guid.NewGuid().ToString("N"))))
{
    var chatClient = scope.ServiceProvider.GetRequiredService<IChatClient>();
    var embeddingGenerator = scope.ServiceProvider.GetRequiredKeyedService<
        IEmbeddingGenerator<string, Embedding<float>>>("knowledge");

    // 聊天与向量调用都会按当前 tenant-a 动态解析凭据。
    var answer = await chatClient.GetResponseAsync("用一句话介绍公司知识库。");
    var embeddings = await embeddingGenerator.GenerateAsync(
        ["需要建立索引的文档正文"]);

    Console.WriteLine(answer.Text);
    Console.WriteLine($"Vector dimensions: {embeddings[0].Vector.Length}");
}

生产环境不要调用 AddInMemoryIntegrationCredentials。应实现 IIntegrationCredentialResolver,并保证返回的凭据快照可轮换、可审计且不会进入普通 日志。

支持矩阵

ProfileId 默认端点 协议 保守声明的可移植能力
openai-responses https://api.openai.com/v1/ Responses Chat、Streaming、Tools、Structured Output、Vision、Reasoning、Hosted Tools、Remote MCP、Embeddings
openai-chat https://api.openai.com/v1/ Chat Completions Chat、Streaming、Tools、Structured Output、Vision、Embeddings
zhipu https://open.bigmodel.cn/api/paas/v4/ OpenAI-compatible Chat、Streaming、Tools、Embeddings
kimi https://api.moonshot.cn/v1/ OpenAI-compatible Chat、Streaming、Tools
qwen https://dashscope.aliyuncs.com/compatible-mode/v1/ OpenAI-compatible Chat、Streaming、Tools、Embeddings
deepseek https://api.deepseek.com/ OpenAI-compatible Chat、Streaming、Tools、Reasoning
anthropic https://api.anthropic.com/ Anthropic Messages 由 Anthropic Adapter 提供

能力是协议层的保守上限,不代表每个模型或账户都具备。区域端点、模型白名单、工具调用、 结构化输出和视觉能力必须用目标账户执行契约测试。供应商私有参数不会被假装成可移植能力。

OpenAI .NET SDK 当前仍给 Responses 客户端类型标注 OPENAI001。本包只在 Responses Adapter 的最小范围抑制该诊断并由测试保护;如果不能接受该 SDK 兼容风险,请使用 openai-chat Profile。

注册

先注册非敏感配置:

// 默认客户端适合应用的主要模型。
services.AddBitzChatClient(options =>
{
    options.ProviderId = "deepseek-prod";
    options.ProfileId = "deepseek";
    options.ModelId = "deepseek-chat";
    options.CredentialName = "default";
});

// 命名客户端用于不同权限、成本中心或模型能力。
services.AddBitzChatClient("reasoning", options =>
{
    options.ProviderId = "openai-prod";
    options.ProfileId = "openai-responses";
    options.ModelId = "approved-reasoning-model";
});

// 向量模型独立注册;聊天和向量可以使用不同 ProviderId。
services.AddBitzEmbeddingGenerator("knowledge", options =>
{
    options.ProviderId = "qwen-prod";
    options.ProfileId = "qwen";
    options.ModelId = "text-embedding-v4";
    options.Dimensions = 1024;
    options.CredentialName = "default";
});

命名客户端的 Key 就是注册名:

// 命名客户端的 Key 就是注册时的原始名称。
var client = serviceProvider
    .GetRequiredKeyedService<IChatClient>("reasoning");

var embeddingGenerator = serviceProvider.GetRequiredKeyedService<
    IEmbeddingGenerator<string, Embedding<float>>>("knowledge");

不存在旧式 BitzChatClient_ 前缀。

凭据

每次聊天或向量调用都会根据当前 IntegrationContext 解析:

tenant + region + environment + "AI:{ProviderId}" + CredentialName

凭据必须包含 AICredentialFieldNames.ApiKey。开发和测试可以显式启用进程内 Store:

// 仅开发/测试:生产环境不要使用进程内凭据 Store。
services.AddInMemoryIntegrationCredentials(); // 仅开发/测试

// 凭据对象持有敏感字符,使用后立即释放调用方快照。
using var credential = new IntegrationCredential(
[
    new(AICredentialFieldNames.ApiKey, secretFromUserSecrets)
]);

credentialStore.Set(
    new IntegrationCredentialKey(
        "tenant-a",
        "AI:deepseek-prod",
        environment: IntegrationEnvironments.Production),
    credential);

生产环境实现 IIntegrationCredentialResolver,接入 Vault、KMS 或云密钥服务。解析器返回 短生命周期凭据快照;Adapter 在创建客户端时读取密钥,不能长期缓存快照。

调用

必须在租户上下文中使用客户端:

// 当前上下文是所有凭据解析和租户隔离的强制输入。
using (contextAccessor.Push(new IntegrationContext(
    tenantId: "tenant-a",
    region: "cn",
    environment: IntegrationEnvironments.Production)))
{
    // 不要把原始 Prompt 或响应写入未经治理的普通日志。
    var response = await client.GetResponseAsync(
        [
            new(ChatRole.System, "只回答已授权业务范围内的问题。"),
            new(ChatRole.User, question)
        ],
        cancellationToken: cancellationToken);
}

客户端代理会在每次非流式、流式或向量调用时重新解析上下文与凭据。流式调用结束、取消或 失败后才释放厂商客户端,不能把枚举器带出创建它的业务 Scope。向量生成器在单次 GenerateAsync 完成后立即释放底层 SDK 客户端。

单次调用可通过 ChatOptions.ModelId 覆盖已注册模型。模型覆盖仍使用同一 Provider 凭据; 如果模型需要不同权限、限额或成本中心,应注册独立命名客户端。

向量生成示例:

// 向量维度将在 RAG 层和向量 Store 中再次校验。
using (contextAccessor.Push(new IntegrationContext(
    tenantId: "tenant-a",
    region: "cn",
    environment: IntegrationEnvironments.Production)))
{
    var vectors = await embeddingGenerator.GenerateAsync(
        ["需要建立索引的业务文本"],
        cancellationToken: cancellationToken);

    ReadOnlyMemory<float> vector = vectors[0].Vector;
}

Dimensions 留空时使用模型默认值;设置后必须与向量数据库 Collection Schema 完全一致。 切换模型或维度不能直接复用旧索引,必须建立新索引并完成迁移。批大小、单条 Token 上限和 允许的维度属于模型契约,需按目标供应商与模型做部署验证。

自定义 Provider

厂商使用既有 OpenAI-compatible 协议时,可注册自定义 Profile:

// 自定义 Profile 只声明已经通过契约测试的能力。
services.AddBitzAIProviderProfile(new AIProviderProfile(
    profileId: "private-openai",
    displayName: "Private OpenAI Gateway",
    protocol: AIProviderProtocol.OpenAIChatCompletions,
    defaultEndpoint: new Uri("https://ai.example.com/v1/"),
    capabilities:
        AIModelCapabilities.Chat |
        AIModelCapabilities.Streaming));

全新协议使用 AIProviderProtocol.Custom 并实现 IAIChatClientProviderAdapter。自定义向量协议实现 IAIEmbeddingGeneratorProviderAdapter。同一协议、同一用途只能有一个 Adapter;重复 Adapter 或重复 Profile 会快速失败,避免运行时随机选取。

端点必须是绝对 HTTPS URI;仅允许 loopback 使用 HTTP。不要把最终用户输入用于 Endpoint。

审计与可观测性

默认管道包括:

  • OpenTelemetry;
  • Microsoft.Extensions.AI 日志;
  • Bitzsoft.Integrations.RequestLogging 请求审计。

RequestLogging 默认完整记录请求和响应,不强制截断兆级正文。宿主可以使用 MaxInMemoryBodyBytes 把大 HTTP 正文转移到加密临时文件;该阈值不影响最终正文完整性。 AI SDK 流式正文和向量输入/输出会完整聚合后交给 Recorder。生产 Store 应使用大字段、 对象存储引用或其他明确的数据保留策略,并配置脱敏、加密、访问控制和删除期限。Embedding 向量本身也可能泄露语义或成员关系,不应视为匿名数据。

成功的抽象调用记为 200;异常或取消时状态为空。IChatClient 不公开厂商原始 HTTP 状态码和响应头。审计只保存异常类型,不持久化可能夹带凭据或正文的 SDK 异常消息; Recorder 失败也不会改变模型业务调用结果。审计开启时,消息枚举会先固化一次,避免 一次性输入被日志和模型重复枚举。

客户端通过 GetService 公开不含凭据的 ChatClientMetadata / EmbeddingGeneratorMetadata,供 Semantic Kernel、Agent Framework 和遥测读取 Provider、endpoint、模型与维度;元数据不会触发凭据解析。

OpenTelemetry 与普通日志是否包含敏感正文取决于上游库和宿主配置。生产环境不要启用 sensitive data 导出;提示词、RAG 上下文、工具参数和模型响应都应按敏感业务数据治理。

Claude 与 Codex

Claude 应安装并注册原生 Adapter:

dotnet add package Bitzsoft.Integrations.AI.Anthropic
services.AddBitzAnthropicAI();
services.AddBitzChatClient("claude", options =>
{
    options.ProviderId = "anthropic-prod";
    options.ProfileId = "anthropic";
    options.ModelId = "approved-claude-model";
});

OpenAI Responses 可以作为普通模型客户端调用支持的代码模型。完整 Codex coding agent 包含工作区、命令执行、审批和长任务状态,不等同于 IChatClient;应通过 Codex App Server/SDK sidecar 或 MCP 边界接入,不能把普通对话客户端命名为 Codex 后声称能力完整。

生产检查

  • 为每个租户、环境和地域准备独立凭据;
  • 对模型 ID、Endpoint 和 Profile 使用部署白名单;
  • 为超时、重试、并发、Token、成本和工具轮次设置宿主策略;
  • 只重试明确可重试且无副作用的调用,并尊重厂商退避响应;
  • 对输出进入 SQL、Shell、HTML、文件路径或业务写操作前执行验证和编码;
  • 用真实账户验证流式、取消、工具、结构化输出、限流和错误映射;
  • 用真实账户验证向量维度、批大小、Token 上限、吞吐和索引迁移;
  • RAG 文档、MCP 工具描述和模型输出都视为不可信输入。

相关包

用途
Bitzsoft.Integrations.AI.Abstractions Profile、模型能力、Factory 与 Adapter 契约
Bitzsoft.Integrations.AI.Anthropic Claude 原生 Messages Adapter
Bitzsoft.Integrations.AgentFramework Microsoft Agent Framework Agent
Bitzsoft.Integrations.RAG 检索增强生成与知识存储 Seam
Bitzsoft.Integrations.McpServer MCP Client/Server 与工具边界
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Bitzsoft.Integrations.AI:

Package Downloads
Bitzsoft.Integrations.All

Bitzsoft 第三方集成聚合包 — net5.0 包含传统连接器,net8.0+ 额外包含受上游 TFM 限制的 AI 模块

Bitzsoft.Integrations.AI.Anthropic

Anthropic Claude 原生 Messages 协议与 Microsoft.Extensions.AI 集成

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.2 133 8/29/2026
1.0.1 170 8/3/2026
1.0.0 165 8/2/2026
1.0.0-alpha.10 244 7/26/2026
1.0.0-alpha.9 83 7/12/2026
1.0.0-alpha.8 74 7/1/2026
1.0.0-alpha.7 85 6/16/2026
1.0.0-alpha.6 86 6/16/2026
1.0.0-alpha.5 74 6/14/2026
1.0.0-alpha.4 85 6/14/2026
1.0.0-alpha.3 80 6/7/2026
1.0.0-alpha.2 75 5/29/2026
1.0.0-alpha.1 67 5/28/2026