.NET程序员AI开发基座:Microsoft.Extensions.AI
大家好,我是Edison。
微软在2024年11月就发布了新的AI核心库Microsoft.Extensions.AI,虽然目前还是一个预览版,但其可以大大简化我们的AI集成和开发工作。
Microsoft.Extensions.AI介绍
Microsoft.Extensions.AI 是一组核心 .NET 库,是在与整个 .NET 生态系统(包括语义内核)的开发人员协作中创建的。 这些库提供统一的 C# 抽象层,用于与 AI 服务交互,例如小型和大型语言模型(SLA 和 LLM)、嵌入和中间件。

Microsoft.Extensions.AI 提供可由各种服务实现的抽象,所有这些概念都遵循相同的核心概念。 此库不旨在提供针对任何特定提供商服务定制的 API。
Microsoft.Extensions.AI 目标是在 .NET 生态系统中充当一个统一层,使开发人员能够选择他们的首选框架和库,同时确保整个生态系统之间的无缝集成和协作。
画外音>开发者可以节省时间下来专注自己的应用程序的业务逻辑实现,从而不必花过多时间去做AI服务的集成调试,点个大大的赞!
我能使用哪些服务实现?
Microsoft.Extensions.AI 通过 NuGet 包提供了以下服务的实现:
- OpenAI
- Azure OpenAI
- Azure AI Inference
- Ollama
将来,这些抽象的服务实现都将会是客户端库的一部分。
基本使用
安装NuGet包:
Microsoft.Extensions.AI (9.1.0-preview)
Microsoft.Extensions.AI.OpenAI (9.1.0-preivew)
这里我们使用SiliconCloud提供的 DeepSeek-R1-Distill-Llama-8B 模型,这是一个使用DeepSeek-R1开发的基于Llama-3.1-8B的蒸馏模型,免费好用。
注册SiliconCloud:https://cloud.siliconflow.cn/i/DomqCefW
简单对话:
var openAIClientOptions = new OpenAIClientOptions();
openAIClientOptions.Endpoint = new Uri("https://api.siliconflow.cn/v1"); var client = new OpenAIClient(new ApiKeyCredential("sk-xxxxxxxxxx"), openAIClientOptions);
var chatClient = client.AsChatClient("deepseek-ai/DeepSeek-R1-Distill-Llama-8B");
var response = await chatClient.CompleteAsync("Who are you?");
Console.WriteLine(response.Message);
封装的IChatClient对象可以十分方便地屏蔽差异,用起来十分方便。
函数调用
要想实现函数调用(Function Calling),则需要调整一下:
var openAIClientOptions = new OpenAIClientOptions();
openAIClientOptions.Endpoint = new Uri("https://api.siliconflow.cn/v1"); [Description("Get the current time")]
string GetCurrentTime() => DateTime.Now.ToLocalTime().ToString(); var client = new ChatClientBuilder()
.UseFunctionInvocation()
.Use(new OpenAIClient(new ApiKeyCredential("sk-xxxxxxxxx"), openAIClientOptions)
.AsChatClient("deepseek-ai/DeepSeek-R1-Distill-Llama-8B"));
var response = await client.CompleteAsync(
"What's the time now?",
new() { Tools = [AIFunctionFactory.Create(GetCurrentTime)] });
Console.Write(response);
可以看到,需要主动使用 UseFunctionInvocation 方法 及 提供 Tools 注册列表,就能使用我们封装的 Tools 了。
多模型使用
很多时候,我们希望Chat入口用一个模型,业务处理则用另一个模型,我们完全可以对其进行独立配置。
例如,这里参考mingupupu大佬的PaperAssistant,我也实现了一个。
在配置文件中,配置多AI模型:
{
// For Paper Smmary
"PaperSummaryModel": {
"ModelId": "deepseek-ai/DeepSeek-R1-Distill-Llama-8B",
"ApiKey": "sk-xxxxxxxxxx",
"EndPoint": "https://api.siliconflow.cn"
},
// For Main Chat
"MainChatModel": {
"ModelId": "Qwen/Qwen2.5-7B-Instruct",
"ApiKey": "sk-xxxxxxxxxx",
"EndPoint": "https://api.siliconflow.cn"
}
}
对于某个业务处理,将其封装为Plugin,并使用 DeepSeek-R1-Distill-Llama-8B 模型:
public sealed class PaperAssistantPlugins
{
public PaperAssistantPlugins(IConfiguration config)
{
var apiKeyCredential = new ApiKeyCredential(config["PaperSummaryModel:ApiKey"]);
var aiClientOptions = new OpenAIClientOptions();
aiClientOptions.Endpoint = new Uri(config["PaperSummaryModel:EndPoint"]);
var aiClient = new OpenAIClient(apiKeyCredential, aiClientOptions)
.AsChatClient(config["PaperSummaryModel:ModelId"]);
ChatClient = new ChatClientBuilder(aiClient)
.UseFunctionInvocation()
.Build();
} public IChatClient ChatClient { get; } [Description("Read the PDF content from the file path")]
[return: Description("PDF content")]
public string ExtractPdfContent(string filePath)
{
Console.WriteLine($"[Tool] Now executing {nameof(ExtractPdfContent)}, params: {filePath}");
var pdfContentBuilder = new StringBuilder();
using (var document = PdfDocument.Open(filePath))
{
foreach (var page in document.GetPages())
pdfContentBuilder.Append(page.Text);
}
return pdfContentBuilder.ToString();
} [Description("Create a markdown note file by file path")]
public void SaveMarkDownFile([Description("The file path to save")] string filePath, [Description("The content of markdown note")] string content)
{
Console.WriteLine($"[Tool] Now executing {nameof(SaveMarkDownFile)}, params: {filePath}, {content}");
try
{
if (!File.Exists(filePath))
File.WriteAllText(filePath, content);
else
File.WriteAllText(filePath, content);
}
catch (Exception ex)
{
Console.WriteLine($"[Error] An error occurred: {ex.Message}");
}
} [Description("Generate one summary of one paper and save the summary to a local file by file path")]
public async Task GeneratePaperSummary(string sourceFilePath, string destFilePath)
{
var pdfContent = this.ExtractPdfContent(sourceFilePath);
var prompt = """
You're one smart agent for reading the content of a PDF paper and summarizing it into a markdown note.
User will provide the path of the paper and the path to create the note.
Please make sure the file path is in the following format:
"D:\Documents\xxx.pdf"
"D:\Documents\xxx.md"
Please summarize the abstract, introduction, literature review, main points, research methods, results, and conclusion of the paper.
The tile should be 《[Title]》, Authour should be [Author] and published in [Year].
Please make sure the summary should include the following:
(1) Abstrat
(2) Introduction
(3) Literature Review
(4) Main Research Questions and Background
(5) Research Methods and Techniques Used
(6) Main Results and Findings
(7) Conclusion and Future Research Directions
""";
var history = new List<ChatMessage>
{
new ChatMessage(ChatRole.System, prompt),
new ChatMessage(ChatRole.User, pdfContent)
};
var result = await ChatClient.CompleteAsync(history);
this.SaveMarkDownFile(destFilePath, result.ToString());
}
}
对于对话主入口,则使用 Qwen2.5-7B-Instruct 模型即可:
Console.WriteLine("Now loading the configuration...");
var config = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json")
.Build();
Console.WriteLine("Now loading the chat client...");
var apiKeyCredential = new ApiKeyCredential(config["MainChatModel:ApiKey"]);
var aiClientOptions = new OpenAIClientOptions();
aiClientOptions.Endpoint = new Uri(config["MainChatModel:EndPoint"]);
var aiClient = new OpenAIClient(apiKeyCredential, aiClientOptions)
.AsChatClient(config["MainChatModel:ModelId"]);
var chatClient = new ChatClientBuilder(aiClient)
.UseFunctionInvocation()
.Build();
Console.WriteLine("Now loading the plugins...");
var plugins = new PaperAssistantPlugins(config);
var chatOptions = new ChatOptions()
{
Tools =
[
AIFunctionFactory.Create(plugins.ExtractPdfContent),
AIFunctionFactory.Create(plugins.SaveMarkDownFile),
AIFunctionFactory.Create(plugins.GeneratePaperSummary)
]
};
Console.WriteLine("Now starting chatting...");
var prompt = """
You're one smart agent for reading the content of a PDF paper and summarizing it into a markdown note.
User will provide the path of the paper and the path to create the note.
Please make sure the file path is in the following format:
"D:\Documents\xxx.pdf"
"D:\Documents\xxx.md"
Please summarize the abstract, introduction, literature review, main points, research methods, results, and conclusion of the paper.
The tile should be 《[Title]》, Authour should be [Author] and published in [Year].
Please make sure the summary should include the following:
(1) Abstrat
(2) Introduction
(3) Literature Review
(4) Main Research Questions and Background
(5) Research Methods and Techniques Used
(6) Main Results and Findings
(7) Conclusion and Future Research Directions
""";
var history = new List<ChatMessage>
{
new ChatMessage(ChatRole.System, prompt)
};
bool isComplete = false;
Console.WriteLine("AI> I'm Ready! What can I do for you?");
do
{
Console.Write("You> ");
string? input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input))
continue;
if (input.Trim().Equals("EXIT", StringComparison.OrdinalIgnoreCase))
{
isComplete = true;
break;
}
if (input.Trim().Equals("Clear", StringComparison.OrdinalIgnoreCase))
{
history.Clear();
Console.WriteLine("Cleared our chatting history successfully!");
continue;
}
history.Add(new ChatMessage(ChatRole.User, input));
Console.WriteLine();
var result = await chatClient.CompleteAsync(input, chatOptions);
Console.WriteLine(result.ToString());
history.Add(new ChatMessage(ChatRole.Assistant, result.ToString() ?? string.Empty));
} while (!isComplete);
这里测试一下,我让它帮我总结一个pdf并将总结内容生成到一个md文件中输出到我指定的目录下保存。

可以看出,它成功地调用了Plugin完成了PDF读取、内容提取总结 和 生成Markdown文件。
eShopSupport
ShopSupport 是一个开源的AI示例应用程序,客户可以使用它来与AI客户对话查询产品,实现网站系统的“智能客服”的场景。


这个开源项目就使用了 Microsoft.Extensions.AI 作为和AI服务集成的抽象层,值得我们参考学习。

值得一提的是,它并没有说全部统一.NET技术栈,而是保留了Python作为机器学习模型训练和推理的,展示了技术异构在这个场景下的融合。
此外,基于Aspire来生成可观察和可靠的云原生应用也是这个项目带来的一个亮点,可以学习下。
小结
本文介绍了Microsoft.Extensions.AI的基本概念 和 基本使用,如果你也是.NET程序员希望参与AI应用的开发,那就快快了解和使用起来吧。
示例源码
GitHub:https://github.com/Coder-EdisonZhou/EDT.Agent.Demos
参考内容
mingupupu的文章:https://www.cnblogs.com/mingupupu/p/18651932
更多
Microsoft Learn: https://learn.microsoft.com/zh-cn/dotnet/ai/ai-extensions
eShopSupport: https://github.com/dotnet/eShopSupport

.NET程序员AI开发基座:Microsoft.Extensions.AI的更多相关文章
- 一名Delphi程序员的开发习惯
一名Delphi程序员的开发习惯 有关开发习惯的一些想法,如鲠在喉,不吐不快.究其发贴动机,当然不排除有骗取参与分的可能,但另一方面,也希望能给同行(念Xing)者提供一些 建议,或者参考(希望不是误 ...
- 程序员网站开发时应该注意的SEO问题
一.链接的统一性 搜索引擎排名最主要的因素就是网站内容和链接,假如网站内部链接不一致,在很大程度上直接影响着网站在搜索引擎中的排名.例如彩票专营店导航栏中的“首页”链接,程序员在开发时可能会有以下几种 ...
- Unity游戏设计与实现 南梦宫一线程序员的开发实例
图灵程序设计丛书 Unity游戏设计与实现:南梦宫一线程序员的开发实例(修订版) 加藤政树 (作者) 罗水东 (译者) c# 游戏 unity <内容提要>本书的作者是日本知 ...
- freecplus框架,Linux平台下C/C++程序员提高开发效率的利器
目录 一.freecplus框架简介 二.freecplus开源许可协议 三.freecplus框架内容 字符串操作 2.xml解析 3.日期时间 4.目录操作 5.文件操作 6.日志文件 7.参数文 ...
- .NET程序员项目开发必知必会—Dev环境中的集成测试用例执行时上下文环境检查(实战)
Microsoft.NET 解决方案,项目开发必知必会. 从这篇文章开始我将分享一系列我认为在实际工作中很有必要的一些.NET项目开发的核心技术点,所以我称为必知必会.尽管这一系列是使用.NET/C# ...
- JAVA程序员常用开发工具
1.JDK (Java Development Kit)Java开发工具集 SUN的Java不仅提了一个丰富的语言和运行环境,而且还提了一个免费的Java开发工具集(JDK).开发人员和最终用户可以利 ...
- 课程10:《黑马程序员_Hibernate开发资料》视频目录--没有细看
老师很厉害,讲得蛮详细的 \Hibernate视频教程\01_黑马程序员_Hibernate教程__Hibernate入门基础.avi; \Hibernate视频教程\02_黑马程序员_Hiberna ...
- 程序员便于开发的一些工具、网站、App。
http://www.kancloud.cn 关于文档,各种技术,框架的学习指南,API文档搜索方便. https://leetcode.com/ 程序员刷题面试网站,无聊的时候可以做一做.
- 程序员带你一步步分析AI如何玩Flappy Bird
以下内容来源于一次部门内部的分享,主要针对AI初学者,介绍包括CNN.Deep Q Network以及TensorFlow平台等内容.由于笔者并非深度学习算法研究者,因此以下更多从应用的角度对整个系统 ...
- Android Java 程序员必备开发工具
对于Java,有两种截然不同的观点:一种认为Java是最简单功能最强大的编程语言之一,另一种则表示这种编程语言既难用又复杂. 下面这些工具或许功能和作用不同,但是有着一个共同的主旨,那就是——它们都是 ...
随机推荐
- PythonDay4Advance
PythonDay4Advance 函数 引言:比如植物大战僵尸,这个游戏本身也是由代码编写,现在假设有一种豌豆射手,每发射一次 炮弹会执行100行逻辑代码 如果我在程序,每当需要发射炮弹的时候,都要 ...
- CentOS上配合nginx 使用 Certbot 生成SSL证书
您可以使用 Let's Encrypt 来申请免费的 SSL 证书.以下是在 CentOS 上安装 Certbot 并使用它来获取 Let's Encrypt SSL 证书的步骤: 安装 Certbo ...
- Element Plus组件el-select回显异常
前情 公司有经常需要做一些后台管理页面,我们选择了Element Plus,它是基于 Vue 3,面向设计师和开发者的组件库,是Vue框架生态中比较火的UI组件库,组件库丰富易用,组件链接:一个 Vu ...
- GPU 驱动漏洞:窥探驱动漏洞利用的技术奥秘
GPU 驱动漏洞:窥探驱动漏洞利用的技术奥秘 本文尝试以 GPU 漏洞为引介绍围绕 GPU 驱动这一攻击面,安全研究人员对内核漏洞利用技术做的一些探索. 背景介绍 目前移动 SOC 平台上由多个硬件模 ...
- 12C++循环结构-for循环(2)——教学
一.循环变量为字符型 (第32课 26个兄弟姐妹)参考视频1 试编一程序,按字典顺序输出26个字母. 流程图: 思考:先顺序输出26个小写英文字母,再逆序输出26个大写英文字母. 循环可以是递增型循环 ...
- 搭建SpringBoot中验证数据机制问题 Add a provider like Hibernate Validator (RI) to your classpath
搭建SpringBoot中的验证数据机制时出现的错误 报错代码 java.lang.IllegalStateException: Failed to load ApplicationContext a ...
- 前后端分离模式下Java Web开发中的技术栈概图
参考链接1:前后端的分离模式 参考链接2:浅谈前后端分离开发模式 参考链接3:前后端分离开发模式介绍
- 编译WorldWindJavav2.1.0中的ApplicationTemplate.java文件时有时报出“Exception in thread "main" java.lang.AbstractMethodError: javax.xml.parsers.DocumentBuilderFactory.setFeature(Ljava/lang/String;Z)V”错误的解决办法
1 问题 编译WorldWindJavav2.1.0中的ApplicationTemplate.java文件时有时报出如下错误: Exception in thread "main" ...
- [转]在WorldWind中加入*.x格式的三维模型
Nasa支持的WorldWind项目最近推出了1.4RC5版,可以加入三维模型,效果如下图所示: 点击查看大图 WW1.4对XML配置文件增加了许多新的元素,其中ModelFeature就是用来增加三 ...
- Web端IM系统:RainbowChat-Web v4.0发布
关于RainbowChat-Web ► RainbowChat-Web详细介绍:http://www.52im.net/thread-2483-1-1.html► 历史版本更新记录:http://ww ...