当前位置: 首页 > news >正文

[MAF预定义的AIContextProvider-07]FileAccessProvider——为Agent提供文件读写能力

作为LangChain Harness框架的Deep Agents利用BackendProtocol协议定义了一个文件系统,并利用FileSystemMiddleware注册的工具提供了操作文件系统的能力。MAF也提供了类似的能力,它利用抽象类AgentFileStore定义了一个抽象的文件系统,并利用FileAccessProvider这个AIContextProvider为Agent提供了文件读写能力。FileAccessProvider提供的文件系统不仅可以被Agent直接使用,它同时也是其他一些依赖持久化能力组件的基础构建,比如基于文件系统的记忆组件。

1. 以自然语言的方式操作文件系统

借助于FileAccessProvider提供的工具,使得Agent可以采用自然语言的方式实现文件的读写和执行一些基本的目录操作,如下的实例演示了这一点。如代码片段所示,我们在调用AsAIAgent方法时提供了一个ChatClientAgentOptions对象,在这个对象中我们注册了FileAccessProvider这个AIContextProvider。创建FileAccessProvider对象时需要传入一个AgentFileStore对象,我们使用的时一个InMemoryAgentFileStore对象,它在内存中模拟了一个文件系统。

usingdotenv.net;usingMicrosoft.Agents.AI;usingMicrosoft.Extensions.AI;usingOpenAI;usingSystem.ClientModel;DotEnv.Load();varmodel=Environment.GetEnvironmentVariable("MODEL")!;varapiKey=Environment.GetEnvironmentVariable("API_KEY")!;varendpoint=Environment.GetEnvironmentVariable("OPENAI_URL")!;varagent=newOpenAIClient(newApiKeyCredential(apiKey),newOpenAIClientOptions{Endpoint=newUri(endpoint)}).GetChatClient(model).AsIChatClient().AsAIAgent(options:newChatClientAgentOptions{AIContextProviders=[newFileAccessProvider(newInMemoryAgentFileStore())],});varsession=awaitagent.CreateSessionAsync();while(true){Console.Write("\n请输入命令:");varcommand=Console.ReadLine();if(string.IsNullOrEmpty(command))break;varresponse=awaitagent.RunAsync(command,session);Console.WriteLine(response);}

然后我们开启了一个循环,在每次循环中我们都从控制台读取用户输入的命令,并将这个命令发送给Agent来执行。如下所示的Agent针对我们输入命令的响应结果。

请输入命令:写入文本内容"Hello world!"到foo.txt 已成功将文本内容 “Hello world!” 写入到 `foo.txt`。 请输入命令:写入随机文本到bar.txt 已成功将随机文本写入到 `bar.txt`。 请输入命令:读取文件foo.txt的内容 `foo.txt` 的内容如下: ``` Hello world! ``` 请输入命令:读取文件bar.txt的内容 `bar.txt` 的内容如下: ``` Zx7qLm2pR9tVb4nK8wXc1dF6hJ0sY3uA Random sequence: 48291-ABXZ-77qpL Lorem ipsum fragment: velorix tanem sulvar quentis arvolex. Timestamp-like string: 2026-06-02T14:37:52Z ``` 请输入命令:列出当前目录下所有文件 当前目录下的文件如下: - `bar.txt` - `foo.txt` 请输入命令:删除文件bar.txt 已成功删除文件 `bar.txt`。 请输入命令:列出当前目录下所有文件 当前目录下的文件如下: - `foo.txt`

2. 由AgentFileStore定义的抽象文件系统

AgentFileStore通过提供7个操作文件和目录的方法定义了一个抽象的文件系统,这些方法包括:写文件、读文件、删除文件、列出目录下的文件、检查文件是否存在、搜索文件以及创建目录。通过实现AgentFileStore,开发者可以将不同的存储系统(如本地文件系统、云存储服务等)适配到FileAccessProvider中,从而为Agent提供持久化的文件读写能力。

publicabstractclassAgentFileStore{publicabstractTaskWriteFileAsync(stringpath,stringcontent,CancellationTokencancellationToken=default);publicabstractTask<string?>ReadFileAsync(stringpath,CancellationTokencancellationToken=default);publicabstractTask<bool>DeleteFileAsync(stringpath,CancellationTokencancellationToken=default);publicabstractTask<IReadOnlyList<string>>ListFilesAsync(stringdirectory,CancellationTokencancellationToken=default);publicabstractTask<bool>FileExistsAsync(stringpath,CancellationTokencancellationToken=default);publicabstractTask<IReadOnlyList<FileSearchResult>>SearchFilesAsync(stringdirectory,stringregexPattern,string?filePattern=null,CancellationTokencancellationToken=default);publicabstractTaskCreateDirectoryAsync(stringpath,CancellationTokencancellationToken=default);}

七个方法说明如下:

  • WriteFileAsync:将指定内容写入到指定路径的文件中。
  • ReadFileAsync:读取指定路径的文件内容。
  • DeleteFileAsync:删除指定路径的文件。
  • ListFilesAsync:列出指定目录下的所有文件。
  • FileExistsAsync:检查指定路径的文件是否存在。
  • SearchFilesAsync:在指定目录下根据正则表达式搜索文件。
  • CreateDirectoryAsync:创建指定路径的目录。

2.1 InMemoryAgentFileStore

上面演示实例使用的InMemoryAgentFileStoreAgentFileStore的一个内存实现版本,它使用一个字典(ConcurrentDictionary<string, string>)来模拟文件系统中的文件和目录结构。虽然它不提供持久化的存储能力,但它可以用于测试和演示目的。

publicsealedclassInMemoryAgentFileStore:AgentFileStore{publicoverrideTaskWriteFileAsync(stringpath,stringcontent,CancellationTokencancellationToken=default);publicoverrideTask<string?>ReadFileAsync(stringpath,CancellationTokencancellationToken=default);publicoverrideTask<bool>DeleteFileAsync(stringpath,CancellationTokencancellationToken=default);publicoverrideTask<IReadOnlyList<string>>ListFilesAsync(stringdirectory,CancellationTokencancellationToken=default);publicoverrideTask<bool>FileExistsAsync(stringpath,CancellationTokencancellationToken=default);publicoverrideTask<IReadOnlyList<FileSearchResult>>SearchFilesAsync(stringdirectory,stringregexPattern,string?filePattern=null,CancellationTokencancellationToken=default);publicoverrideTaskCreateDirectoryAsync(stringpath,CancellationTokencancellationToken=default);}

2.2 FileSystemAgentFileStore

FileSystemAgentFileStoreAgentFileStore的另一个实现版本,它使用本地文件系统来存储文件和目录。通过构造函数指定的根目录,FileSystemAgentFileStore将所有的文件操作限制在这个根目录及其子目录下,从而提供了一定程度的安全性。

publicsealedclassFileSystemAgentFileStore:AgentFileStore{publicFileSystemAgentFileStore(stringrootDirectory);publicoverrideTaskWriteFileAsync(stringpath,stringcontent,CancellationTokencancellationToken=default);publicoverrideTask<string?>ReadFileAsync(stringpath,CancellationTokencancellationToken=default);publicoverrideTask<bool>DeleteFileAsync(stringpath,CancellationTokencancellationToken=default);publicoverrideTask<IReadOnlyList<string>>ListFilesAsync(stringdirectory,CancellationTokencancellationToken=default);publicoverrideTask<bool>FileExistsAsync(stringpath,CancellationTokencancellationToken=default);publicoverrideTask<IReadOnlyList<FileSearchResult>>SearchFilesAsync(stringdirectory,stringregexPattern,string?filePattern=null,CancellationTokencancellationToken=default);publicoverrideTaskCreateDirectoryAsync(stringpath,CancellationTokencancellationToken=default);}

3. FileAccessProvider

FileAccessProvider的实现非常简单。我们构建该对象时会提供一个AgentFileStore对象和作为配置选项的FileAccessProviderOptions对象(可选)。在重写的ProvideAIContextAsync方法中,FileAccessProvider会创建用于操作AgentFileStore对象的一系列工具和系统指令,并注册到返回的AIContext对象中。

publicsealedclassFileAccessProvider:AIContextProvider{publicFileAccessProvider(AgentFileStorefileStore,FileAccessProviderOptions?options=null);protectedoverrideValueTask<AIContext>ProvideAIContextAsync(InvokingContextcontext,CancellationTokencancellationToken=default);}publicsealedclassFileAccessProviderOptions{publicstring?Instructions{get;set;}}

FileAccessProviderOptions只提供用来作为系统指令的Instructions属性。如果没有提供这个属性,FileAccessProvider会使用一个默认的系统指令,内容如下:

## File Access You have access to a shared file storage area via the `FileAccess_*` tools for reading, writing, and managing files. These files persist beyond the current session and may be shared across sessions or agents. Use these tools to read input data provided by the user, write output artifacts, and manage any files the user has asked you to work with. - Never delete or overwrite existing files unless the user has explicitly asked you to do so.

4. 查看注册的工具

我们可以通过一个自定义的AIContextProvider来查看FileAccessProvider注册到AIContext中的工具。如下所示的ToolTrackingProviderProvideAIContextAsync方法中会遍历当前上下文中的工具列表,并将其中的工具信息打印到控制台上。

classToolTrackingProvider:AIContextProvider{protectedoverrideValueTask<AIContext>ProvideAIContextAsync(InvokingContextcontext,CancellationTokencancellationToken=default){varindex=1;foreach(vartoolincontext.AIContext.Tools!){if(toolisAIFunctionfunction){Console.WriteLine($"""{newstring('-',50)}Tool{index++}{newstring('-',50)}Name:{tool.Name}Description:{tool.Description}JsonSchema:{JsonSerializer.Serialize(function.JsonSchema,newJsonSerializerOptions{WriteIndented=true})}""");}}returnbase.ProvideAIContextAsync(context,cancellationToken);}}

我们采用如下的形式将ToolTrackingProviderFileAccessProvider一起注册到Agent中,运行Agent之后我们就可以在控制台上看到FileAccessProvider注册的工具信息了。

usingdotenv.net;usingMicrosoft.Agents.AI;usingMicrosoft.Extensions.AI;usingOpenAI;usingSystem.ClientModel;usingSystem.Text.Json;DotEnv.Load();varmodel=Environment.GetEnvironmentVariable("MODEL")!;varapiKey=Environment.GetEnvironmentVariable("API_KEY")!;varendpoint=Environment.GetEnvironmentVariable("OPENAI_URL")!;varagent=newOpenAIClient(newApiKeyCredential(apiKey),newOpenAIClientOptions{Endpoint=newUri(endpoint)}).GetChatClient(model).AsIChatClient().AsAIAgent(options:newChatClientAgentOptions{AIContextProviders=[newFileAccessProvider(newInMemoryAgentFileStore()),newToolTrackingProvider()],});awaitagent.RunAsync();

输出:

-------------------------------------------------- Tool 1 -------------------------------------------------- Name: FileAccess_SaveFile Description: Save a file with the given name and content. By default, does not overwrite an existing file unless overwrite is set to true. JsonSchema: { "type": "object", "properties": { "fileName": { "type": "string" }, "content": { "type": "string" }, "overwrite": { "type": "boolean", "default": false } }, "required": [ "fileName", "content" ] } -------------------------------------------------- Tool 2 -------------------------------------------------- Name: FileAccess_ReadFile Description: Read the content of a file by name. Returns the file content or a message indicating the file was not found. JsonSchema: { "type": "object", "properties": { "fileName": { "type": "string" } }, "required": [ "fileName" ] } -------------------------------------------------- Tool 3 -------------------------------------------------- Name: FileAccess_DeleteFile Description: Delete a file by name. JsonSchema: { "type": "object", "properties": { "fileName": { "type": "string" } }, "required": [ "fileName" ] } -------------------------------------------------- Tool 4 -------------------------------------------------- Name: FileAccess_ListFiles Description: List all file names. JsonSchema: { "type": "object", "properties": {} } -------------------------------------------------- Tool 5 -------------------------------------------------- Name: FileAccess_SearchFiles Description: Search file contents using a regular expression pattern (case-insensitive). Optionally filter which files to search using a glob pattern (e.g., "*.md", "research*"). Returns matching file names, snippets, and matching lines with line numbers. JsonSchema: { "type": "object", "properties": { "regexPattern": { "type": "string" }, "filePattern": { "type": [ "string", "null" ], "default": null } }, "required": [ "regexPattern" ] }

从输出可以看出,FileAccessProvider为Agent注册了5个工具,它们分别是:

  • FileAccess_SaveFile:将指定内容保存到指定名称的文件中。默认情况下,如果文件已存在则不覆盖,除非overwrite参数设置为true。
  • FileAccess_ReadFile:通过文件名读取文件内容。返回文件内容或者指示文件未找到的消息。
  • FileAccess_DeleteFile:通过文件名删除文件。
  • FileAccess_ListFiles:列出所有文件名。
  • FileAccess_SearchFiles:使用正则表达式模式(不区分大小写)搜索文件内容。可选地使用glob模式(例如,“.md”,“research”)过滤要搜索的文件。返回匹配的文件名、片段以及带有行号的匹配行。

AgentFileStore定义的7个抽象方法相比,FileAccessProvider注册的工具覆盖了其中的5个方法,少了用于创建目录和检查文件是否存在的工具。

http://www.cnnetsun.cn/news/2746294.html

相关文章:

  • 手把手教你排查PHY自协商失败:从寄存器状态到硬件走线的完整调试流程
  • 简单3步集成!MOSS-TTS-Nano-100M-ONNX与MOSS-Audio-Tokenizer的无缝对接指南
  • Arxiv上传后想撤稿?先了解这3个‘流氓’规则,别毁了你的专利!
  • 30 分钟完成企业站开发,OpenClaw 自动化生成 HTML5 前端项目(含安装包)
  • 别再被MATLAB的PSNR/SSIM函数坑了!RGB和灰度图计算的差异详解与实战避坑
  • 终极Windows窗口管理指南:如何使用X-Mouse Controls实现鼠标悬停激活窗口
  • 116.彻底搞懂手机刷机底层逻辑|启动链+分区表+USB协议+故障修复全解析
  • Matlab版DTMF拨号音识别工具:支持录音分析与结果可视化
  • Dreamweaver CS6里的‘层’到底怎么用?手把手教你用AP Div搞定网页布局
  • Electron应用容器化部署实战:跨越环境鸿沟的技术解法
  • 3步搞定抖音无水印下载:douyin-downloader的极简实战指南
  • GD32E230 ADC注入通道实战:用定时器2触发,1ms精准采样电机相电流
  • Boss Show Time高效指南:5个技巧精准掌握招聘发布时间,提升求职成功率
  • 第十七篇:《Docker 日志管理:驱动配置与集中收集》
  • 滚动轴承多负载故障识别Python工具包:含12K数据集、预处理脚本与1D-CNN训练代码
  • 5分钟完成原神成就自动化管理:YaeAchievement终极免费工具全解析
  • 语义内核操作逻辑模型:AI认知的底层运行机制
  • 保姆级教程:在嵌入式Linux上实战I3C SDR模式的热加入与带内中断
  • Cookie 是什么?一篇讲给非技术朋友的“小纸条
  • 告别OPC!用Snap7和Visual Studio 2022轻松搞定西门子PLC通信(附完整C++代码)
  • 别再分开求实部虚部了!Wirtinger导数教你像处理实数一样优雅地处理复数求导
  • 告别Windows 7!手把手教你下载安装最新版DevEco Studio 2.0,10分钟搞定鸿蒙开发环境
  • Gemma 1.1深度解析:48层架构、8K上下文与4-bit量化的工业级落地实践
  • CTF解题新思路:当Session文件写入遇上路径穿越——以BUU‘Easy Notes’为例
  • 企业级AI智能关联整合方案(Gartner未公开评估模型首次披露)
  • Claude高效工作流三要素:角色锚定、上下文压缩、输出驯化
  • 【职场】你越相信公司使命,你就越容易成为被牺牲的那个人
  • 手机号定位神器:3秒查询归属地,地图精准导航
  • bonsai-image-ternary-4B-gemlite-2bit开发者指南:Python API与自定义集成
  • 3分钟极速上手:哔哩下载姬DownKyi全方位视频管理解决方案