PaperAssistant:使用Microsoft.Extensions.AI实现

前言

上篇文章介绍了使用Semantic Kernel Chat Completion Agent实现的版本。

使用C#构建一个论文总结AI Agent

今天来介绍一下使用Microsoft.Extensions.AI的版本。

Microsoft.Extensions.AI介绍

Microsoft.Extensions.AI 是微软为 .NET 生态系统推出的一组核心库,旨在为开发者提供统一的 C# 抽象层,简化与 AI 服务的集成。它通过与 .NET 生态系统的深度协作(包括与 Semantic Kernel 团队的合作),为开发者提供了一种标准化的方式来与各种 AI 服务(如大型语言模型、嵌入生成、工具调用等)进行交互。

GitHub地址:https://github.com/dotnet/extensions/tree/main/src/Libraries/Microsoft.Extensions.AI

实践

新建一个C#控制台项目。

安装包:

创建插件:

csharp 复制代码
internal sealed class PaperAssistantPlugin
{
    public PaperAssistantPlugin()
    {
        var envVars = DotEnv.Read();
        ApiKeyCredential apiKeyCredential = new ApiKeyCredential(envVars["PaperSummaryApiKey"]);

        OpenAIClientOptions openAIClientOptions = new OpenAIClientOptions();
        openAIClientOptions.Endpoint = new Uri($"{envVars["PaperSummaryEndpoint"]}");

        IChatClient openaiClient =
        new OpenAIClient(apiKeyCredential, openAIClientOptions)
            .AsChatClient(envVars["PaperSummaryModelId"]);

        Client = new ChatClientBuilder(openaiClient)
                     .UseFunctionInvocation()
                     .Build();
    }

    internal IChatClient Client { get; set; }

    [Description("读取指定路径的PDF文档内容")]
    [return: Description("PDF文档内容")]
    public string ExtractPDFContent(string filePath)
    {
        Console.WriteLine($"执行函数ExtractPDFContent,参数{filePath}");

        StringBuilder text = new StringBuilder();
        // 读取PDF内容
        using (PdfDocument document = PdfDocument.Open(filePath))
        {
            foreach (var page in document.GetPages())
            {
                text.Append(page.Text);
            }
        }
        return text.ToString();
    }

    [Description("根据文件路径与笔记内容创建一个md格式的文件")]
    public void SaveMDNotes([Description("保存笔记的路径")] string filePath, [Description("笔记的md格式内容")] string mdContent)
    {
        try
        {
            Console.WriteLine($"执行函数SaveMDNotes,参数1:{filePath},参数2:{mdContent}");

            // 检查文件是否存在,如果不存在则创建
            if (!File.Exists(filePath))
            {
                // 创建文件并写入内容
                File.WriteAllText(filePath, mdContent);
            }
            else
            {
                // 如果文件已存在,覆盖写入内容
                File.WriteAllText(filePath, mdContent);
            }
        }
        catch (Exception ex)
        {
            // 处理异常
            Console.WriteLine($"An error occurred: {ex.Message}");
        }
    }

    [Description("总结论文内容生成一个md格式的笔记,并将笔记保存到指定路径")]
    public async void GeneratePaperSummary(string filePath1, string filePath2)
    {
        Console.WriteLine($"执行函数GeneratePaperSummary,参数1:{filePath1},参数2:{filePath2}");

        StringBuilder text = new StringBuilder();
        // 读取PDF内容
        using (PdfDocument document = PdfDocument.Open(filePath1))
        {
            foreach (var page in document.GetPages())
            {
                text.Append(page.Text);
            }
        }

        // 生成md格式的笔记
        string skPrompt = """
                            请使用md格式总结论文的摘要、前言、文献综述、主要论点、研究方法、结果和结论。
                            论文标题为《[论文标题]》,作者为[作者姓名],发表于[发表年份]。请确保总结包含以下内容:
                            论文摘要
                            论文前言
                            论文文献综诉
                            主要研究问题和背景
                            使用的研究方法和技术
                            主要结果和发现
                            论文的结论和未来研究方向
                            """;
        List<ChatMessage> history = [];
        history.Add(new ChatMessage(ChatRole.System, skPrompt));
        history.Add(new ChatMessage(ChatRole.User, text.ToString()));

        var result = await Client.CompleteAsync(history);

        try
        {
            // 检查文件是否存在,如果不存在则创建
            if (!File.Exists(filePath2))
            {
                // 创建文件并写入内容
                File.WriteAllText(filePath2, result.ToString());
                Console.WriteLine($"生成笔记成功,笔记路径:{filePath2}");
            }
            else
            {
                // 如果文件已存在,覆盖写入内容
                File.WriteAllText(filePath2, result.ToString());
            }
        }
        catch (Exception ex)
        {
            // 处理异常
            Console.WriteLine($"An error occurred: {ex.Message}");
        }
    }
}

创建好了插件之后,我们需要创建一个IChatClient,由于国内大模型提供商大部分都已经兼容了OpenAI格式,所以安装Microsoft.Extensions.AI.OpenAI就可以用了。

在Microsoft.Extensions.AI.OpenAI中使用国内大语言模型的方式如下所示:

csharp 复制代码
 var envVars = DotEnv.Read();

 ApiKeyCredential apiKeyCredential = new ApiKeyCredential(envVars["ToolUseApiKey"]);

 OpenAIClientOptions openAIClientOptions = new OpenAIClientOptions();
 openAIClientOptions.Endpoint = new Uri($"{envVars["ToolUseEndpoint"]}");

 IChatClient openaiClient =
 new OpenAIClient(apiKeyCredential, openAIClientOptions)
 .AsChatClient(envVars["ToolUseModelId"]);

 IChatClient client = new ChatClientBuilder(openaiClient)
 .UseFunctionInvocation()
 .Build();

在ChatOptions中导入工具:

csharp 复制代码
 ChatOptions chatOptions = new()
 {
     Tools = [AIFunctionFactory.Create(paperAssistantPlugin.ExtractPDFContent),
              AIFunctionFactory.Create(paperAssistantPlugin.SaveMDNotes),
              AIFunctionFactory.Create(paperAssistantPlugin.GeneratePaperSummary)]
 };

总结论文并将笔记保存至指定路径:

提问论文相关问题:

将笔记保存至指定路径:

总结

只是一个非常简单的示例,希望对大家使用Microsoft.Extensions.AI实现自己的应用有所帮助。代码已上传至GitHub,地址:https://github.com/Ming-jiayou/PaperAssistant。

相关推荐
测试开发技术5 分钟前
AI 测试提效 | 告别手工写脚本,分享我的 Playwright + Skill 批量生成 UI 自动化脚本方案
自动化测试·人工智能·ui·自动化·agent·skill·ai测试
乐思智能科技有限公司18 分钟前
PLECS软件学习使用(二)直流电机基本系统模型
人工智能·算法·机器学习·面试·职场和发展
极连AI19 分钟前
极连AI平台解读、Codex5.6仅需0.01倍率,无需Token焦虑,极速响应
人工智能·gpt·chatgpt·aigc·ai编程·ai写作·gpu算力
MartinYeung525 分钟前
[论文学习]PACT:溯源感知能力合约——面向智能体安全的参数级溯源
人工智能·学习·安全
带娃的IT创业者28 分钟前
Inkling:当开源模型开始思考“如何思考”
人工智能·开源·大语言模型·多模态·moe·开源模型·inkling
远航计算机1 小时前
职业技能培训机构如何利用QClaw+Skills做豆包GEO:知识库搭建×内容创作×效果监测的完整实操手册
大数据·人工智能·自动化·aigc·火山引擎
旋生万物1 小时前
电磁力 = 螺旋联络的 90° 旋转?麦克斯韦方程组的几何重构
人工智能·python·算法·机器学习·copilot·世界模型·物理ai
Vince的修炼之路1 小时前
防 Prompt 注入安全技术深度分析
人工智能·安全
Vince的修炼之路1 小时前
RAG 文档处理技术深度分析:PDF 解析、表格提取、OCR 识别全链路
人工智能·架构
Vuji1 小时前
MCP: 一条 tool 调用链路的旅程
前端·人工智能