尧图精选

Semantic Kernel 结构化数据连接器(Structured Data Connector)设计与实战指南

🕒 发布时间:2026/9/11 16:07:56 📁 来源:尧图网络
Semantic Kernel 结构化数据连接器Structured Data Connector设计与实战指南【免费下载链接】semantic-kernelIntegrate cutting-edge LLM technology quickly and easily into your apps项目地址: https://gitcode.com/GitHub_Trending/se/semantic-kernel本文以 Semantic Kernel 仓库中的架构决策记录 0068-structed-data-connector 为主体结合 Plugins.StructuredData.EntityFramework 的实际源码、StructuredDataPlugin 演示项目 与 单元测试系统讲解这一实验性数据库-AI 集成方案的架构设计、核心组件、CRUD 能力与实战接入方式。读完本文你将掌握如何把 Entity Framework 数据库操作封装为 Semantic Kernel 插件、如何让 LLM 通过函数调用Function Calling直接对数据库执行增删改查以及该方案背后的类型安全与 JSON 交互设计原理。一、背景与问题AI 应用为什么需要结构化数据连接器现代 AI 应用经常需要一边调用大语言模型LLM完成推理一边与数据库中的结构化数据打交道。而 Semantic Kernel 的核心定位是 AI 编排AI orchestration它本身并不关心数据如何存储。因此我们需要一种标准化方式把数据库操作与 AI 能力整合在一起。0068 号 ADR 提出的解决方案是构建一个实验性的StructuredDataConnector作为数据库与 AI 集成问题的初始方案重点覆盖基础的 CRUD 操作Create / Read / Update / Delete简单查询能力与 Semantic Kernel 插件Plugin架构对齐通过真实使用场景验证方案可行性。决策驱动因素该方案的设计遵循以下驱动因素驱动因素说明初始数据库集成模式需要为 SK 提供首个与数据库集成的标准模式可组合的 AI 与数据库操作数据库操作要能作为可组合的能力被 LLM 编排调用对齐插件架构方案必须融入 SK 现有的 Plugin 体系而非另起炉灶真实场景验证需要通过实际使用来验证方案是否成立强类型 Schema 校验依赖 SK 的KernelJsonSchema提供类型安全一致的 JSON 格式AI 交互需要统一、规范的 JSON 数据格式二、核心设计插件化、类型安全与 JSON 交互从源码结构看该方案由四个核心构件组成它们共同构成了数据库服务 → 扩展方法 → 插件工厂 → Kernel 插件的完整链路2.1 核心组件总览组件源码文件职责StructuredDataServiceTContextStructuredDataService.cs数据库操作的基础服务封装对DbContext的增删改查StructuredDataServiceExtensionsStructuredDataServiceExtensions.cs将服务方法包装为KernelFunction的扩展方法StructuredDataPluginFactoryStructuredDataPluginFactory.cs工厂类按操作集合批量生成 SK 插件StructuredDataOperationStructuredDataOperation.cs描述受支持数据库操作的只读结构体2.2 关键特性自动生成实体类型 Schema利用KernelJsonSchemaBuilder.Build(typeof(TEntity))从实体类型直接生成 JSON SchemaLLM 由此获知实体的字段结构、类型与含义规范的 JSON 响应格式查询、插入结果以规范格式的 JSON 返回便于 AI 理解与后续编排基于扩展方法的可维护架构每个 CRUD 操作对应一个独立的扩展方法CreateInsertFunction、CreateSelectFunction、CreateUpdateFunction、CreateDeleteFunction职责单一、易于测试与扩展对 Entity Framework 的支持服务直接约束TContext : DbContext可对接任意 EF 支持的数据库。2.3 操作集合StructuredDataOperationStructuredDataOperation.cs 定义了一个只读结构体用字符串标签标识四种操作并提供Default集合public static StructuredDataOperation Select { get; } new(Select); public static StructuredDataOperation Insert { get; } new(Insert); public static StructuredDataOperation Update { get; } new(Update); public static StructuredDataOperation Delete { get; } new(Delete); public static readonly HashSetStructuredDataOperation Default [ Select, Insert, Update, Delete ];值得注意的实现细节该结构体实现了IEquatableStructuredDataOperation其相等性比较基于标签且不区分大小写StringComparison.OrdinalIgnoreCase。这意味着你可以通过new StructuredDataOperation(insert)等方式自定义操作标签同时仍能与Insert正确匹配——这为后续按需裁剪操作集合提供了灵活性。三、StructuredDataService数据库操作的服务层StructuredDataServiceTContextStructuredDataService.cs是整个方案的底层服务泛型参数TContext约束为 Entity Framework 的DbContext。它提供两种构造方式// 方式一传入连接字符串服务内部通过反射创建 DbContext 实例 var service1 new StructuredDataServiceApplicationDbContext(connectionString); // 方式二传入已构建的 DbContext 实例推荐用于 DI 场景 var service2 new StructuredDataServiceApplicationDbContext(dbContext);若使用连接字符串构造服务内部会用Activator.CreateInstance(typeof(TContext), connectionString)创建上下文并记录_internalContext true在Dispose()时只释放自己创建的上下文而外部传入的 DbContext 则由调用方负责生命周期管理。3.1 查询SelectSelectTEntity(string? query null)返回IQueryableTEntity数据库查询延迟到结果被枚举时才真正执行源码注释明确说明 The search to the database is deferred until the query is enumerated。当提供query参数时会通过 OData 过滤器语法进行条件过滤var result this.Context.SetTEntity().AsQueryable(); if (!string.IsNullOrWhiteSpace(query)) { result result.OData().Filter(query); }OData 过滤支持两种底层实现在 .NETNET符号下使用OData2Linq包在 .NET Standard/.NET Framework 目标下使用Community.OData.Linq包见 csproj 的条件引用。3.2 写入InsertAsync / UpdateAsync / DeleteAsync方法签名返回InsertAsyncTaskTEntity InsertAsyncTEntity(TEntity entity, CancellationToken)插入后的实体含数据库生成的字段UpdateAsyncTaskint UpdateAsyncTEntity(TEntity entity, CancellationToken)受影响的行数DeleteAsyncTaskint DeleteAsyncTEntity(TEntity entity, CancellationToken)受影响的行数InsertAsync将实体Add到DbSet后调用SaveChangesAsync并返回实体本身因此调用方可以获得数据库生成的主键如DatabaseGeneratedOption.Identity的自增列。UpdateAsync对游离Detached实体的处理比较精细从源码StructuredDataService.cs可以看到其内部流程通过IObjectContextAdapter获取 ObjectContext并从实体集元数据中解析出主键成员名用主键值在DbSet中Find已存在的实体若存在则用CurrentValues.SetValues(entity)覆盖其值保留 EF 的变更跟踪若不存在则Attach实体并标记为EntityState.Modified最后SaveChangesAsync并返回受影响行数失败时抛出InvalidOperationException。DeleteAsync采用类似的游离实体处理策略先按主键查找现有实体找到则直接Remove找不到则Attach后Remove从而保证删除操作在任意实体状态下都能正确执行。四、从服务到 Kernel 函数扩展方法封装StructuredDataServiceExtensions.cs 提供四个静态扩展方法把服务方法包装成KernelFunction并自动生成函数名、描述、参数元数据与返回类型。四个函数遵循统一的命名约定扩展方法默认函数名描述示例参数返回值CreateInsertFunctionInsert{Entity}RecordInsert a Product record into the database.entity实体类型必填含 JSON SchemaTEntityCreateSelectFunctionSelect{Entity}RecordsGets Product records from the database.filter字符串可选IListTEntityCreateUpdateFunctionUpdate{Entity}RecordUpdate a Product record in the database.entity实体类型必填int受影响行数CreateDeleteFunctionDelete{Entity}RecordDelete a Product record from the database.entity实体类型必填int受影响行数4.1 类型安全的 Schema 生成插入函数通过KernelJsonSchemaBuilder.Build(typeof(TEntity))为参数生成 JSON Schema使 LLM 在调用函数前就能了解实体结构。实体属性上的[Description]特性来自System.ComponentModel会被纳入 Schema 描述——例如演示项目 Product.cs 中的[Description(The price of the product in USD.)]这直接提升了 LLM 生成参数值的准确性。4.2 面向 LLM 的 OData 过滤器说明CreateSelectFunction生成的函数描述中内置了对 LLM 的过滤语法指引StructuredDataServiceExtensions.cs支持运算符gt大于、lt小于、eq等于、contains包含、startswith开头匹配、endswith结尾匹配组合逻辑and、or字符串值必须用单引号包裹如Name eq Book。配合单元测试StructuredDataServiceTests.cs还可以进一步确认实际支持的能力边界完整比较运算符eq、ne、gt、lt、ge、le测试SelectWithNullableTypesHandlesAllOperators逐一验证可空类型的null比较NullableDate eq null、NullableInt eq null日期时间过滤支持yyyy-MM-ddTHH:mm:ssZ与yyyy-MM-ddTHH:mm:ss.000Z等多种格式字符串中的特殊字符单引号需双写转义Products Test双引号可用表示复杂组合条件NullableDate eq {date} and Name eq Test1、NullableDate eq null or Name eq Test3。五、插件工厂一键生成数据库插件StructuredDataPluginFactory.cs 提供CreateStructuredDataPluginTContext, TEntity静态方法将上述能力聚合为完整的KernelPluginpublic static KernelPlugin CreateStructuredDataPluginTContext, TEntity( StructuredDataServiceTContext service, IEnumerableStructuredDataOperation? operations null, string? description null) where TContext : DbContext where TEntity : class参数说明参数类型默认值说明serviceStructuredDataServiceTContext必填数据库服务实例operationsIEnumerableStructuredDataOperationStructuredDataOperation.Default全部四种操作需要暴露给插件的操作集合可按需裁剪descriptionstring?Allows CRUD operations against the {Entity} entity in the database插件描述会提供给 LLM 帮助其理解插件用途工厂内部通过反射实现操作的动态装配对每个operation构造Create{operation}Function方法名在StructuredDataServiceExtensions中查找对应静态方法再通过MakeGenericMethod(typeof(TContext), typeof(TEntity))泛型实例化并调用最终用KernelPluginFactory.CreateFromFunctions生成插件。插件默认命名为{Entity}DatabasePlugin例如ProductDatabasePlugin。若指定的操作没有对应的扩展方法工厂会抛出InvalidOperationExceptionOperation {operation} is not supported. Extension method {methodName} not found.从而保证操作集合必须能被实现支持这一约束。六、端到端实战让 LLM 直接操作数据库仓库中提供了完整的可运行演示项目 StructuredDataPlugin下面按其脉络还原完整接入流程。6.1 定义实体与 DbContext实体定义Product.cs——注意用[Description]描述每个字段它们会成为 JSON Schema 的一部分public sealed class Product { [Description(The unique identifier for the product.)] [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid? Id { get; set; } [Description(The name of the product.)] public string? Name { get; set; } [Description(The price of the product in USD.)] public decimal? Price { get; set; } [Description(The date the product was created)] [DatabaseGenerated(DatabaseGeneratedOption.Computed)] public DateTime? DateCreated { get; set; } }DbContext 定义ApplicationDbContext.cs——继承 Entity Framework 的DbContext支持从配置读取连接字符串internal sealed class ApplicationDbContext : DbContext { public ApplicationDbContext(IConfiguration config) : base(config[$ConnectionStrings:{nameof(ApplicationDbContext)}]!) { } public ApplicationDbContext(string connectionString) : base(connectionString) { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { Database.SetInitializerApplicationDbContext(null); // 禁用自动初始化 modelBuilder.EntityProduct().ToTable(Products); base.OnModelCreating(modelBuilder); } }6.2 注册服务、创建插件并接入 Kernel核心接入代码Program.cs分为四步// 1. 通过 DI 注册 DbContext 与 StructuredDataService var serviceCollection new ServiceCollection() .AddTransientApplicationDbContext() .AddTransientStructuredDataServiceApplicationDbContext(); var serviceProvider serviceCollection.BuildServiceProvider(); using var structuredDataService serviceProvider.GetRequiredServiceStructuredDataServiceApplicationDbContext(); // 2. 构建 Kernel 并接入 OpenAI 聊天模型 var kernelBuilder Kernel.CreateBuilder() .AddOpenAIChatCompletion(modelId: gpt-4o, apiKey: config[OpenAI:ApiKey]!); // 3. 用工厂创建数据库插件并加入 Kernel var databasePlugin StructuredDataPluginFactory .CreateStructuredDataPluginApplicationDbContext, Product(structuredDataService); kernelBuilder.Plugins.Add(databasePlugin); var kernel kernelBuilder.Build(); // 4. 开启自动函数调用 var settings new OpenAIPromptExecutionSettings { FunctionChoiceBehavior FunctionChoiceBehavior.Auto() };6.3 用自然语言驱动数据库操作启用FunctionChoiceBehavior.Auto()后LLM 会依据用户意图自动选择合适的数据库函数。演示项目展示了四类典型交互Program.cs// 插入LLM 自动调用 InsertProductRecord var insertResult await kernel.InvokePromptAsync( Insert a new product with name Book and price 29.99, new(settings)); // 查询LLM 自动调用 SelectProductRecords 并生成 OData 过滤器 var queryResult await kernel.InvokePromptAsync( Find all products under $50, new(settings)); // 更新LLM 自动调用 UpdateProductRecord var updateResult await kernel.InvokePromptAsync( Update the price of Book to 39.99 and keep its name, new(settings)); // 删除LLM 自动调用 DeleteProductRecord var deleteResult await kernel.InvokePromptAsync( Delete the product Book, new(settings));演示项目还包含一个交互式聊天循环用户输入Find all products under $50Insert a new product with name Table and price 19.99等自然语言指令由 Kernel 自动完成意图理解 → 函数选择 → 参数生成 → 数据库执行 → 结果返回的完整闭环。该演示项目在 csproj 中通过ProjectReference直接引用Plugins.StructuredData.EntityFramework与Connectors.OpenAI并显式设置了SKEXP0050警告抑制——这印证了该插件当前属于实验性Experimental功能正式使用前需了解其 API 可能变化的预期。七、实现约束与适用范围7.1 目标框架与依赖从 Plugins.StructuredData.EntityFramework.csproj 可以确认目标框架net10.0、net8.0、net462版本号为alpha后缀的实验性版本EF 版本Entity Framework6.5非 EF Corecsproj 注释明确说明 EntityFramework 6.5 is not compatible with .Net Standard 2.0因此支持的最低框架为 .NET Framework 4.6.2OData 依赖.NET 目标使用OData2LinqMicrosoft.AspNetCore.OData非 .NET 目标使用Community.OData.LinqSchema 工具编译时引入InternalUtilities/src/Schema与Diagnostics目录下的内部工具类KernelJsonSchemaBuilder的实现来源。7.2 与 0051 号 ADR 的关联EF 的角色边界需要特别说明的是Semantic Kernel 仓库中还有一份相关的架构决策 0051-entity-framework-as-connector其结论是不为 EF 增加 Vector Store 连接器原因是各 EF Provider 对集合管理、键管理与向量类型的支持不统一。而 0068 号 ADR 聚焦的是**结构化数据关系型 CRUD**场景两者并不矛盾EF 适合作为结构化数据访问层但不适合作为统一向量存储抽象。这也解释了为何本插件的定位是Structured Data而非Vector Store。7.3 适用前提与限制该方案是实验性的文档状态为proposed将根据社区反馈持续演进API 可能发生变化面向关系型数据库的 CRUD 与简单查询不覆盖复杂事务、批量操作、向量检索等场景Select依赖 OData 过滤器语法LLM 生成的过滤表达式质量直接影响查询结果更新与删除对游离实体的处理依赖主键解析实体必须包含有效主键值。八、验证与测试单元测试如何保证行为仓库在 StructuredDataServiceTests.cs 中为StructuredDataService提供了完整的单元测试覆盖可作为行为契约参考测试组验证内容构造函数连接字符串构造可创建上下文null DbContext 抛出ArgumentNullExceptionSelect 基础无查询返回全部实体带过滤器时正确过滤Insert调用Add一次并SaveChangesAsync一次返回同一实体实例Update / Delete返回受影响行数且SaveChangesAsync被调用OData 运算符eq/ne/gt/lt/ge/le六种比较在可空类型上的行为可空类型null比较、NullableInt/NullableDouble/NullableBool混合条件日期时间多种 ISO 8601 格式、null处理、日期与字符串组合条件字符串转义含空格、and/or关键字、单引号、双引号的字符串过滤测试中TestDbContext通过Database.SetInitializerTestDbContext(null)禁用数据库初始化以纯内存方式验证查询逻辑说明该服务层的过滤逻辑与具体数据库解耦可在 SQLite 等测试环境中独立验证。九、总结Structured Data Connector当前落地为Microsoft.SemanticKernel.Plugins.StructuredData.EntityFramework插件是 Semantic Kernel 在AI 数据库集成方向上的实验性探索。它以插件化架构为骨架、以KernelJsonSchema为类型安全底座、以 OData 过滤器为 LLM 友好的查询语言把 CRUD 能力封装成语义清晰的KernelFunction使 LLM 可以通过自然语言直接完成数据库操作。虽然目前处于实验阶段、以 Entity Framework 6.5 为第一实现载体但它确立了数据库服务层 → 函数封装 → 插件工厂 → Kernel 编排这一可复用的集成模式为后续支持更多数据库与更复杂操作奠定了架构基础。相关参考文件架构决策docs/decisions/0068-structured-data-connector.md、docs/decisions/0051-entity-framework-as-connector.md核心源码StructuredDataService.cs、StructuredDataServiceExtensions.cs、StructuredDataPluginFactory.cs、StructuredDataOperation.cs演示项目dotnet/samples/Demos/StructuredDataPlugin/单元测试dotnet/src/Plugins/Plugins.UnitTests/StructuredData/StructuredDataServiceTests.cs【免费下载链接】semantic-kernelIntegrate cutting-edge LLM technology quickly and easily into your apps项目地址: https://gitcode.com/GitHub_Trending/se/semantic-kernel创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →