Microsoft.Extensions.AI 入门指南

引言

在 AI 技术日新月异的今天,.NET 开发者终于迎来了属于自己的 AI 开发标准——Microsoft.Extensions.AI (MEAI)。作为微软官方推出的 AI 抽象层,MEAI 旨在为 .NET 生态系统提供统一、简洁的 AI 服务集成方式,让开发者能够轻松地在不同 AI 模型和服务之间切换,而无需重写代码。

本文将带你快速了解 MEAI 的核心概念、使用方法,以及它为何能成为 .NET AI 开发的基石。

为什么需要 MEAI?

传统痛点

在 MEAI 出现之前,.NET 开发者接入 AI 服务面临诸多挑战:

  • 🔴 API 不统一:每个 AI 提供商都有自己的 SDK,学习成本高
  • 🔴 切换成本高:从 OpenAI 切换到 Azure OpenAI 需要大量代码改动
  • 🔴 难以测试:缺乏统一的抽象接口,Mock 和单元测试困难
  • 🔴 功能分散:日志、缓存、遥测等横切关注点需要重复实现

MEAI 的解决方案

MEAI 通过提供统一的抽象接口,完美解决了这些问题:

graph TB
    A[你的应用] --> B[Microsoft.Extensions.AI]
    B --> C1[OpenAI]
    B --> C2[Azure OpenAI]
    B --> C3[DeepSeek]
    B --> C4[Ollama]
    B --> C5[其他模型]
    
    style B fill:#4CAF50,stroke:#2E7D32,stroke-width:3px

核心接口详解

1. IChatClient:对话型 AI 的统一抽象

IChatClient 是 MEAI 的核心接口之一,定义了与聊天型 AI 服务交互的标准方式。

核心方法:

// 完整响应
Task<ChatResponse> GetResponseAsync(
    IEnumerable<ChatMessage> messages, 
    ChatOptions? options = null, 
    CancellationToken ct = default
)

// 流式响应
IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseAsync(
    IEnumerable<ChatMessage> messages, 
    ChatOptions? options = null, 
    CancellationToken ct = default
)

示例:快速上手

// 安装必要的包
// #r "nuget: Microsoft.Extensions.AI"
// #r "nuget: Microsoft.Extensions.AI.OpenAI"

using Microsoft.Extensions.AI;
using Azure.AI.OpenAI;

// 1. 创建客户端(以 OpenAI 兼容服务为例)
OpenAIClientOptions clientOptions = new OpenAIClientOptions();
clientOptions.Endpoint = new Uri("https://api.deepseek.com");

OpenAIClient aiClient = new(
    new ApiKeyCredential("your-api-key"), 
    clientOptions
);

IChatClient chatClient = aiClient.AsChatClient("deepseek-chat");

// 2. 构建消息
var messages = new List<ChatMessage>
{
    new ChatMessage(ChatRole.System, "你是一个专业的.NET开发助手"),
    new ChatMessage(ChatRole.User, "什么是依赖注入?")
};

// 3. 发送请求并获取响应
var response = await chatClient.GetResponseAsync(messages);
Console.WriteLine(response.Text);

2. IEmbeddingGenerator:向量嵌入生成器

IEmbeddingGenerator<TInput, TEmbedding> 提供了生成向量嵌入的统一接口,支持多种输入类型:

// 为文本生成向量嵌入
IEmbeddingGenerator<string, Embedding<float>> embeddingGenerator = ...;
var embeddings = await embeddingGenerator.GenerateAsync(
    new[] { "Hello, world!", "AI is amazing!" }
);

foreach (var embedding in embeddings)
{
    Console.WriteLine($"向量维度: {embedding.Vector.Length}");
}

MEAI 的五大核心优势

1. 服务无关性:一次编码,多处运行

通过统一的 IChatClient 接口,你可以轻松切换 AI 服务提供商:

// 切换服务只需改变客户端创建方式
IChatClient chatClient;

// 使用 OpenAI
chatClient = new OpenAIClient(...).AsChatClient("gpt-4");

// 切换到 Azure OpenAI
chatClient = new AzureOpenAIClient(...).AsChatClient("gpt-4");

// 切换到 Ollama
chatClient = new OllamaApiClient(...);

// 后续代码完全不变!
var response = await chatClient.GetResponseAsync(messages);

2. 依赖注入友好:原生支持 .NET DI

MEAI 完全拥抱 .NET 的依赖注入(DI)模式:

// 在 Startup 或 Program.cs 中注册
services.AddSingleton<IChatClient>(serviceProvider => 
{
    var openAIClient = new OpenAIClient(...);
    return openAIClient.AsChatClient("gpt-4");
});

// 在服务中注入使用
public class MyService
{
    private readonly IChatClient _chatClient;
    
    public MyService(IChatClient chatClient)
    {
        _chatClient = chatClient;
    }
    
    public async Task<string> AnalyzeCodeAsync(string code)
    {
        var messages = new[] 
        { 
            new ChatMessage(ChatRole.User, $"分析这段代码:{code}") 
        };
        var response = await _chatClient.GetResponseAsync(messages);
        return response.Text;
    }
}

3. 中间件模式:横切关注点一站式解决

MEAI 引入了中间件(Middleware)模式,让你能够轻松添加日志、缓存、遥测等功能:

IChatClient chatClient = new OpenAIClient(...)
    .AsChatClient("gpt-4")
    .UseLogging()           // 添加日志记录
    .UseOpenTelemetry()     // 添加遥测
    .UseDistributedCache(cache)  // 添加缓存
    .UseFunctionInvocation(); // 添加自动函数调用

4. 多模态支持:不止于文本

IChatClient 原生支持多模态内容:

var messages = new List<ChatMessage>
{
    new ChatMessage(ChatRole.User, 
    [
        new TextContent("图片中是什么?"),
        new ImageContent(imageBytes, "image/jpeg")
    ])
};

var response = await chatClient.GetResponseAsync(messages);

5. 流式响应:实时反馈优化用户体验

对于长文本生成场景,流式响应能显著提升用户体验:

var messages = new[] 
{ 
    new ChatMessage(ChatRole.User, "写一篇关于.NET的文章") 
};

await foreach (var update in chatClient.GetStreamingResponseAsync(messages))
{
    Console.Write(update.Text);  // 逐字输出
}

ChatOptions:精细控制生成行为

ChatOptions 类提供了丰富的配置选项来控制 AI 的行为:

var options = new ChatOptions
{
    ModelId = "gpt-4o",              // 指定模型
    Temperature = 0.7f,              // 控制创造性(0-2)
    TopP = 0.9f,                     // 核采样
    MaxOutputTokens = 2000,          // 最大输出长度
    StopSequences = new[] { "\n\n" },// 停止序列
    ResponseFormat = ChatResponseFormat.Json,  // 输出格式
    
    // 工具调用
    Tools = new[] { weatherTool },
    ToolMode = ChatToolMode.Auto,
    
    // 对话管理
    ConversationId = "user-123",
};

var response = await chatClient.GetResponseAsync(messages, options);

关键参数说明

参数

说明

推荐值

Temperature

控制随机性,值越高越创造性

0.7-1.0(创意任务)
0.0-0.3(精确任务)

TopP

核采样,与 Temperature 互补

0.9-1.0

MaxOutputTokens

限制输出长度

根据需求设置

ToolMode

工具调用模式

Auto(自动判断)
Required(强制调用)

ResponseFormat

输出格式

TextJsonJsonSchema

结构化输出:让 AI 返回可靠的数据

MEAI 支持强制 AI 按照预定义的 JSON Schema 返回数据:

// 定义数据模型
public record PersonInfo(string Name, int Age, string City);

// 直接获取强类型结果(推荐方式)
var response = await chatClient.GetResponseAsync<PersonInfo>(
    new[] { new ChatMessage(ChatRole.User, "张三今年25岁,住在北京") }
);

PersonInfo person = response.Result;
Console.WriteLine($"{person.Name}, {person.Age}岁, {person.City}");
// 输出: 张三, 25岁, 北京

与其他框架的集成

1. Semantic Kernel

using Microsoft.SemanticKernel;

// MEAI 客户端可以无缝集成到 SK
var kernel = Kernel.CreateBuilder()
    .AddChatCompletionService(chatClient)  // 使用 MEAI 客户端
    .Build();

2. Microsoft Agent Framework

using Microsoft.Extensions.AI.Agents;

// 创建 Agent(构建在 MEAI 之上)
var agent = new AIAgent(chatClient, new AIAgentOptions
{
    Name = "编程助手",
    Instructions = "你是一个专业的.NET开发专家"
});

最佳实践

1. 使用依赖注入管理客户端生命周期

// ❌ 避免:每次请求都创建新客户端
var client = new OpenAIClient(...).AsChatClient("gpt-4");

// ✅ 推荐:使用 DI 注册为单例
services.AddSingleton<IChatClient>(sp => 
    new OpenAIClient(...).AsChatClient("gpt-4")
);

2. 合理配置缓存减少成本

services.AddDistributedMemoryCache();

services.AddSingleton<IChatClient>(sp => 
{
    var cache = sp.GetRequiredService<IDistributedCache>();
    return new OpenAIClient(...)
        .AsChatClient("gpt-4")
        .UseDistributedCache(cache);  // 相同请求直接返回缓存
});

3. 使用日志监控 AI 调用

IChatClient chatClient = new OpenAIClient(...)
    .AsChatClient("gpt-4")
    .UseLogging(loggerFactory);  // 自动记录所有请求/响应

4. 设置合理的超时和重试

var options = new ChatOptions
{
    // 使用取消令牌设置超时
};

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
var response = await chatClient.GetResponseAsync(messages, options, cts.Token);

实战案例:构建一个智能代码审查助手

让我们整合所学知识,构建一个完整的应用:

using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

// 1. 配置依赖注入
var services = new ServiceCollection();

services.AddLogging(builder => builder.AddConsole());
services.AddDistributedMemoryCache();

services.AddSingleton<IChatClient>(sp => 
{
    var logger = sp.GetRequiredService<ILoggerFactory>();
    var cache = sp.GetRequiredService<IDistributedCache>();
    
    return new OpenAIClient(new ApiKeyCredential("your-key"))
        .AsChatClient("gpt-4")
        .UseLogging(logger)
        .UseDistributedCache(cache);
});

services.AddSingleton<CodeReviewService>();

var provider = services.BuildServiceProvider();

// 2. 定义服务
public class CodeReviewService
{
    private readonly IChatClient _chatClient;
    private readonly ILogger<CodeReviewService> _logger;
    
    public CodeReviewService(
        IChatClient chatClient, 
        ILogger<CodeReviewService> logger)
    {
        _chatClient = chatClient;
        _logger = logger;
    }
    
    public async Task<CodeReviewResult> ReviewCodeAsync(string code)
    {
        var messages = new List<ChatMessage>
        {
            new(ChatRole.System, @"你是一个专业的代码审查专家。
                请分析代码并返回以下内容:
                - 潜在的bug
                - 性能问题
                - 最佳实践建议"),
            new(ChatRole.User, $"请审查这段代码:\n```csharp\n{code}\n```")
        };
        
        var options = new ChatOptions
        {
            Temperature = 0.3f,  // 审查任务需要更确定的结果
            MaxOutputTokens = 1000
        };
        
        try
        {
            var response = await _chatClient.GetResponseAsync<CodeReviewResult>(
                messages, 
                options
            );
            
            _logger.LogInformation("代码审查完成,发现 {Count} 个问题", 
                response.Result.Issues.Count);
            
            return response.Result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "代码审查失败");
            throw;
        }
    }
}

public record CodeReviewResult(
    List<string> Bugs,
    List<string> PerformanceIssues,
    List<string> BestPractices
)
{
    public int TotalIssues => Bugs.Count + PerformanceIssues.Count + BestPractices.Count;
    public List<string> Issues => Bugs.Concat(PerformanceIssues).Concat(BestPractices).ToList();
}

// 3. 使用服务
var reviewService = provider.GetRequiredService<CodeReviewService>();
var result = await reviewService.ReviewCodeAsync(@"
    public void ProcessData(List<string> data)
    {
        for(int i=0; i<data.Count; i++)
        {
            Console.WriteLine(data[i]);
        }
    }
");

Console.WriteLine($"发现 {result.TotalIssues} 个问题");

总结

Microsoft.Extensions.AI 为 .NET 开发者带来了:

统一的抽象接口IChatClientIEmbeddingGenerator 简化 AI 集成
服务无关性:轻松切换不同 AI 提供商
中间件生态:日志、缓存、遥测开箱即用
依赖注入友好:完美融入 .NET 生态
生产级特性:结构化输出、流式响应、多模态支持

MEAI 不仅是一个库,更是 .NET AI 生态系统的基石。无论你是构建简单的聊天机器人,还是复杂的企业级 AI 应用,MEAI 都能提供坚实的支持。

资源链接