ExpandOpenAI 1.0.4

dotnet add package ExpandOpenAI --version 1.0.4
                    
NuGet\Install-Package ExpandOpenAI -Version 1.0.4
                    
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="ExpandOpenAI" Version="1.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ExpandOpenAI" Version="1.0.4" />
                    
Directory.Packages.props
<PackageReference Include="ExpandOpenAI" />
                    
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 ExpandOpenAI --version 1.0.4
                    
#r "nuget: ExpandOpenAI, 1.0.4"
                    
#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 ExpandOpenAI@1.0.4
                    
#: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=ExpandOpenAI&version=1.0.4
                    
Install as a Cake Addin
#tool nuget:?package=ExpandOpenAI&version=1.0.4
                    
Install as a Cake Tool

ExpandOpenAI

ExpandOpenAI 是一个面向 OpenAI Compatible 接口的轻量级 IChatClientIEmbeddingGenerator<string, Embedding<float>> 实现,基于 Microsoft.Extensions.AI 构建,适合接入 OpenAI、阿里云 DashScope 兼容模式,以及其他遵循 /chat/completions/embeddings 协议的模型服务。

它的目标不是重新发明一套 SDK,而是把“兼容 OpenAI 的 HTTP 接口”包装成标准的 IChatClientIEmbeddingGenerator,方便你继续使用 ChatMessageChatOptions、流式输出、工具调用、多模态内容和向量生成。

特性

  • 实现 Microsoft.Extensions.AI.IChatClient
  • 实现 Microsoft.Extensions.AI.IEmbeddingGenerator<string, Embedding<float>>
  • 支持普通响应和流式响应
  • 支持 OpenAI Compatible embeddings 请求
  • 支持 ChatOptions 常见参数映射
  • 支持工具声明、工具调用和工具结果消息
  • 支持 reasoning / reasoning_content 解析为 TextReasoningContent
  • 支持文本、图片、音频内容的 OpenAI Compatible 序列化
  • 支持通过 OpenAIRequestContent 扩展自定义内容片段
  • 支持环境变量初始化和代码配置初始化
  • 支持自定义请求头、认证头、请求体扩展字段和请求钩子

项目结构

  • ExpandOpenAI/:核心类库
  • ExpandOpenAI.TestConsole/:控制台示例项目

运行要求

  • .NET 10
  • NuGet 依赖:
    • Microsoft.Extensions.AI

快速开始

先克隆仓库并构建:

dotnet build

如果你要在自己的项目中直接引用源码项目:

dotnet add <YourProject>.csproj reference .\ExpandOpenAI\ExpandOpenAI.csproj

NuGet 打包

仓库内提供了打包脚本。Windows 下推荐直接用 cmd 包装器:

.\scripts\pack-nuget.cmd -Version 1.0.0

如果你希望直接执行 PowerShell 脚本:

powershell -ExecutionPolicy Bypass -File .\scripts\pack-nuget.ps1 -Version 1.0.0

默认输出目录为 .\artifacts\nuget,同时会生成:

  • .nupkg
  • .snupkg

常用参数示例:

.\scripts\pack-nuget.cmd -Version 1.0.0-preview.1
.\scripts\pack-nuget.cmd -Version 1.0.0 -OutputDir .\artifacts\release
.\scripts\pack-nuget.cmd -Version 1.0.0 -NoSymbols

基础调用

using ExpandOpenAI;
using Microsoft.Extensions.AI;

var client = new OpenAICompatibleChatClient(new OpenAICompatibleChatClientOptions
{
    Endpoint = new Uri("https://api.openai.com/v1"),
    ApiKey = "<your-api-key>",
    ModelId = "gpt-4o-mini",
});

var response = await client.GetResponseAsync(
[
    new ChatMessage(ChatRole.User, "用一句话介绍 ExpandOpenAI。")
]);

Console.WriteLine(response.Text);

流式输出

using ExpandOpenAI;
using Microsoft.Extensions.AI;

var client = new OpenAICompatibleChatClient(new OpenAICompatibleChatClientOptions
{
    Endpoint = new Uri("https://api.openai.com/v1"),
    ApiKey = "<your-api-key>",
    ModelId = "gpt-4o-mini",
});

await foreach (var update in client.GetStreamingResponseAsync(
[
    new ChatMessage(ChatRole.User, "请流式输出一段简短说明。")
]))
{
    foreach (var content in update.Contents)
    {
        if (content is TextReasoningContent reasoning)
        {
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            Console.Write(reasoning.Text);
            Console.ResetColor();
        }
        else if (content is TextContent text)
        {
            Console.Write(text.Text);
        }
    }
}

环境变量方式

OpenAICompatibleChatClient 支持直接从环境变量读取配置:

  • OPENAI_ENDPOINT
  • OPENAI_MODEL
  • OPENAI_API_KEY
  • OPENAI_REQUEST_PATH:可选,默认值为 chat/completions

示例:

$env:OPENAI_ENDPOINT="https://api.openai.com/v1"
$env:OPENAI_MODEL="gpt-4o-mini"
$env:OPENAI_API_KEY="<your-api-key>"
using ExpandOpenAI;

var client = new OpenAICompatibleChatClient();

向量模型

OpenAICompatibleEmbeddingGenerator 实现了 IEmbeddingGenerator<string, Embedding<float>>,可以直接用于 Microsoft.Extensions.VectorData、Qdrant、Semantic Kernel Vector Store 等依赖 Microsoft.Extensions.AI embedding 抽象的场景。

using ExpandOpenAI;
using Microsoft.Extensions.AI;

IEmbeddingGenerator<string, Embedding<float>> generator =
    new OpenAICompatibleEmbeddingGenerator(new OpenAICompatibleEmbeddingGeneratorOptions
    {
        Endpoint = new Uri("https://dashscope.aliyuncs.com/compatible-mode/v1"),
        ApiKey = "<your-api-key>",
        ModelId = "text-embedding-v4",
    });

var embedding = await generator.GenerateAsync("需要向量化的文本");
Console.WriteLine(embedding.Vector.Length);

批量生成:

var embeddings = await generator.GenerateAsync(
[
    "第一段文本",
    "第二段文本",
]);

foreach (var item in embeddings)
{
    Console.WriteLine(item.Vector.Length);
}

如果你的向量模型支持自定义维度,可以通过 EmbeddingGenerationOptions.Dimensions 传入:

var embedding = await generator.GenerateAsync(
    "需要向量化的文本",
    new EmbeddingGenerationOptions
    {
        Dimensions = 1024,
    });

也可以在生成器配置里设置默认维度;单次调用传入的 EmbeddingGenerationOptions.Dimensions 会覆盖默认值:

var generator = new OpenAICompatibleEmbeddingGenerator(new OpenAICompatibleEmbeddingGeneratorOptions
{
    Endpoint = new Uri("https://dashscope.aliyuncs.com/compatible-mode/v1"),
    ApiKey = "<your-api-key>",
    ModelId = "text-embedding-v4",
    DefaultModelDimensions = 1024,
});

使用便捷构造函数时也可以传入默认维度:

var generator = new OpenAICompatibleEmbeddingGenerator(
    "text-embedding-v4",
    "<your-api-key>",
    new Uri("https://dashscope.aliyuncs.com/compatible-mode/v1"),
    defaultModelDimensions: 1024);

向量模型也支持环境变量初始化:

  • OPENAI_ENDPOINT
  • OPENAI_EMBEDDING_MODEL
  • OPENAI_API_KEY
  • OPENAI_EMBEDDING_REQUEST_PATH:可选,默认值为 embeddings
var generator = new OpenAICompatibleEmbeddingGenerator();

配置项说明

OpenAICompatibleChatClientOptions 主要提供以下能力:

配置项 说明
Endpoint 服务根地址,例如 https://api.openai.com/v1
RequestPath 请求路径,默认 chat/completions,也可传绝对地址
ModelId 默认模型 ID
ApiKey API Key
ApiKeyHeaderName 认证头名称,默认 Authorization
ApiKeyScheme 认证方案,默认 Bearer,可设为 null 或空字符串
DefaultModelDimensions 向量生成默认维度;单次调用的 EmbeddingGenerationOptions.Dimensions 优先
Headers 额外请求头
RequestBody 额外请求体字段
SerializerOptions 自定义 JSON 序列化配置
ConfigureRequest 请求发送前自定义 HttpRequestMessage
ConfigureRequestBody 请求发送前自定义 JSON Body

例如某些兼容服务要求使用自定义认证头:

var client = new OpenAICompatibleChatClient(new OpenAICompatibleChatClientOptions
{
    Endpoint = new Uri("https://example.com/v1"),
    ModelId = "my-model",
    ApiKey = "<your-api-key>",
    ApiKeyHeaderName = "api-key",
    ApiKeyScheme = null,
});

多模态支持

默认请求构造器支持以下内容类型:

  • TextContent
  • DataContent 图片输入
  • UriContent 图片输入
  • DataContent 音频输入
  • UriContent 音频输入
  • 继承自 OpenAIRequestContent 的自定义内容

其中:

  • 图片会被序列化为 image_url
  • 音频会被序列化为 input_audio
  • 不支持的内容类型会抛出 NotSupportedException

DashScope 音频示例

仓库中已经提供了 DashScopeAudioContent,用于构造 DashScope 兼容接口所需的音频输入片段。

using ExpandOpenAI;
using ExpandOpenAI.Providers.DashScope;
using Microsoft.Extensions.AI;

var client = new OpenAICompatibleChatClient(new OpenAICompatibleChatClientOptions
{
    Endpoint = new Uri("https://dashscope.aliyuncs.com/compatible-mode/v1"),
    ApiKey = "<your-api-key>",
    ModelId = "qwen3-asr-flash",
});

var message = new ChatMessage(ChatRole.User)
{
    Contents =
    [
        new DashScopeAudioContent(
            new DataContent(File.ReadAllBytes("sample.mp3"), "audio/mpeg"))
    ]
};

await foreach (var update in client.GetStreamingResponseAsync([message]))
{
    foreach (var content in update.Contents.OfType<TextContent>())
    {
        Console.Write(content.Text);
    }
}

工具调用支持

请求构造器会自动处理:

  • ChatOptions.Tools
  • ChatOptions.ToolMode
  • ChatOptions.AllowMultipleToolCalls
  • FunctionCallContent
  • FunctionResultContent

响应解析器会把兼容接口返回的 tool_calls 解析回 FunctionCallContent,包括流式场景下分段返回的参数拼接。

扩展自定义内容

如果某个服务的内容结构不是标准的 OpenAI Compatible 格式,可以继承 OpenAIRequestContent 自己定义序列化逻辑:

using System.Text.Json;
using System.Text.Json.Nodes;
using ExpandOpenAI;

public sealed class CustomContent : OpenAIRequestContent
{
    public override JsonObject SerializeToOpenAIRequestContentPart(JsonSerializerOptions serializerOptions)
    {
        return new JsonObject
        {
            ["type"] = "custom_part",
            ["value"] = "hello"
        };
    }
}

示例项目

控制台示例位于 ExpandOpenAI.TestConsole/Program.cs,当前包含:

  • DashScope 音频输入示例
  • 图片理解示例
  • 流式响应输出示例

你可以直接修改其中的 EndpointApiKeyModelId 和本地文件路径进行测试。

License

本项目使用 MIT License

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.4 95 6/8/2026
1.0.3 97 6/5/2026
1.0.2 96 6/3/2026
1.0.1 98 5/21/2026
1.0.0 103 5/12/2026