【译】 数据摄取构建模块简介(预览版)(一)

原文 | Luis, Adam

翻译 | 郑子铭

在构建人工智能应用程序时,上下文至关重要。

人工智能模型的知识水平有限,默认情况下无法访问您的个人或公司数据。为了生成高质量的答案,人工智能应用需要满足两个条件:

  • 获取高质量数据
  • 在恰当的时机呈现恰当信息的能力

两者都是通过上下文工程实现的,上下文工程是指设计系统和最佳实践,为人工智能模型提供相关的上下文信息。虽然上下文工程是一个更广泛的主题,但本文将重点讨论如何通过数据摄取管道实现对高质量数据的访问。

如今,.NET 开发人员面临着日益严峻的挑战:如何高效地摄取、转换和检索数据,以实现智能的、具有上下文感知能力的体验。

因此,我们很高兴地宣布推出.NET 数据摄取构建模块的预览版。

在这篇文章中,我们将分享这些构建模块如何赋能 .NET 生态系统,使其能够为其 AI 应用程序构建可组合的数据摄取管道。

什么是数据摄取?

数据摄取是指从文件、数据库、API 或云服务等不同来源收集、读取和准备数据,以便下游应用程序可以使用这些数据的过程。在实践中,这就是我们熟悉的提取、转换、加载 (ETL) 工作流程:

  • 从原始数据源提取数据,无论是 PDF、Word 文档、音频文件还是 Web API。
  • 通过清洗、分块、丰富或转换格式来转换数据。
  • 将数据加载到数据库、向量存储或人工智能模型等目标位置,以便进行检索和分析。

对于人工智能和机器学习场景,尤其是检索增强生成(RAG)而言,数据摄取不仅仅是数据传输,更重要的是使数据能够被智能应用所利用。这意味着要以保留文档结构和含义的方式对其进行表示,将其分割成易于管理的数据块,添加元数据或嵌入信息,并存储起来以便能够快速准确地检索。

.NET 开发人员面临的挑战不仅在于执行 ETL 操作,更在于如何以可靠、可扩展且易于维护的方式,在现代 AI 场景下实现 ETL。随着应用程序对上下文和智能的需求日益增长,当前数据采集方法的局限性也愈发凸显。

.NET 中的数据摄取构建模块简介

为了解决工作流程碎片化、人工操作和可扩展性有限的挑战,我们宣布推出适用于 .NET 的新数据摄取构建模块的预览版。

这些抽象是 .NET 数据处理的基础库。它们使开发人员能够读取、处理和准备文档,以用于人工智能和机器学习工作流程,特别是检索增强生成 (RAG) 场景。

借助这些构建模块,开发人员可以创建强大、灵活且智能的数据管道,以满足其应用程序的需求。此版本包含以下内容:

  • 统一文档表示:以一致的格式表示任何文件类型(PDF、图像、Microsoft Word 等),该格式与大型语言模型配合良好。
  • 灵活的数据摄取:使用多个内置读取器从云服务和本地来源读取文档,可以轻松地从任何位置导入数据。
  • 内置 AI 增强功能:自动丰富内容,包括摘要、情感分析、关键词提取和分类,为智能工作流程做好准备。
  • 可自定义的分块策略:使用基于词元、基于节或语义感知的方法将文档拆分成块,以便您可以针对检索和分析需求进行优化。
  • 生产就绪存储:将处理后的数据块持久化到流行的矢量数据库和文档存储中,并支持嵌入生成,使您的管道能够应对真实世界的场景。
  • 端到端管道组合:通过 API 将读取器、处理器、分块器和写入器链接在一起IngestionPipeline,减少样板代码,使构建、自定义和扩展完整工作流程变得容易。
  • 性能和可扩展性:这些组件专为可扩展的数据处理而设计,能够高效地处理大量数据,因此适用于企业级应用程序。

所有这些组件的设计都充分考虑了开放性和可扩展性。您可以添加自定义逻辑、新的连接器,并扩展系统以支持新兴的人工智能应用场景。通过标准化文档的表示、处理和存储方式,.NET 开发人员可以构建可靠、可扩展且易于维护的数据管道,而无需为每个项目重复造轮子。

建立在稳固的基础之上

这些新的数据摄取组件构建于 .NET 生态系统中经过验证且可扩展的组件之上,确保了可靠性、互操作性以及与现有 AI 工作流程的无缝集成。

  • Microsoft.ML.Tokenizers:分词器为基于词元对文档进行分块提供了基础。这使得内容能够被精确分割,这对于为大型语言模型准备数据和优化检索策略至关重要。
  • Microsoft.Extensions.AI:这套库利用大型语言模型实现丰富的转换功能。它支持摘要、情感分析、关键词提取和嵌入生成等功能,让您能够轻松地利用智能洞察增强数据。
  • Microsoft.Extensions.VectorData:这套库提供了一个一致的接口,用于将处理后的数据块存储在各种向量存储系统中,包括QdrantSQL ServerCosmosDBMongoDBElasticSearch等等。这确保您的数据管道能够随时使用,并可扩展到您首选的存储后端。

除了熟悉的模式和工具之外,这些构建模块还基于已有的可扩展组件。插件功能和互操作性至关重要,因此随着 .NET AI 生态系统其他部分的扩展,数据采集组件的功能也会随之增强。这种方法使开发人员能够轻松集成新的连接器、增强功能和存储选项,从而确保其管道能够面向未来,并适应不断发展的 AI 应用场景。

构建你的第一个数据摄取管道

在以下示例中,您将使用MarkdownReader解析 markdown 文档,应用一组文档和块处理技术,使用语义相似性块处理器进行块处理,并将块存储在 SQLite 向量存储中。

最简单的入门方法是在 GitHub Codespaces 中打开示例应用程序。

或者,下面的代码片段展示了示例的构建方式。完整的代码请参见DataIngestion 示例仓库

构建您的应用程序

创建一个新的基于文件的应用程序

复制代码
# Powershell
ni DataIngestion.cs

# Bash
touch DataIngestion.cs

安装Microsoft.Extensions.DataIngestion和其他相关的 NuGet 包。

复制代码
// Data Ingestion Building Blocks
#:package Microsoft.Extensions.DataIngestion@10.0.1-preview.1.25571.5
#:package Microsoft.Extensions.DataIngestion.Markdig@10.0.1-preview.1.25571.5

// OpenAI ChatClient
#:package Microsoft.Extensions.AI.OpenAI@10.0.1-preview.1.25571.5

// Logging
#:package Microsoft.Extensions.Logging.Console@10.0.0

// Tokenizer
#:package Microsoft.ML.Tokenizers.Data.Cl100kBase@2.0.0

// SQLite Vector Store
#:package Microsoft.SemanticKernel.Connectors.SqliteVec@1.67.1-preview

添加 using 语句

复制代码
using System.ClientModel;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DataIngestion;
using Microsoft.Extensions.DataIngestion.Chunkers;
using Microsoft.Extensions.Logging;
using Microsoft.ML.Tokenizers;
using Microsoft.SemanticKernel.Connectors.SqliteVec;
using OpenAI;

设置您的阅读器

读取文档是数据导入流程的第一步。readFile是对文件路径和/或字符串IngestionDocumentReader读取的抽象。在本例中,我们将使用它来读取 Markdown 文件,因为它是最简单的读取器,没有任何外部依赖项(例如云服务或 MCP 服务器)。IngestionDocumentStreamMarkDownReader

复制代码
IngestionDocumentReader reader = new MarkdownReader();

设置您的文档处理器

第二步是处理文档IngestionDocument。文档处理器在文档级别运行,可以丰富内容或执行其他转换。具体使用哪些处理器取决于您的使用场景。

此示例使用内置功能,通过 AI 服务为元素ImageAlternativeTextEnricher添加IngestionDocumentImage替代文本,因此为文本块生成的嵌入可以包含图像内容信息:

复制代码
using ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddSimpleConsole());

OpenAIClient openAIClient = new(
    new ApiKeyCredential(Environment.GetEnvironmentVariable("GITHUB_TOKEN")!),
    new OpenAIClientOptions { Endpoint = new Uri("https://models.github.ai/inference") });

IChatClient chatClient =
    openAIClient.GetChatClient("gpt-4.1").AsIChatClient();

EnricherOptions enricherOptions = new(chatClient)
{
    // Enricher failures should not fail the whole ingestion pipeline, as they are best-effort enhancements.
    // This logger factory can be used to create loggers to log such failures.
    LoggerFactory = loggerFactory
}

IngestionDocumentProcessor imageAlternativeTextEnricher = new ImageAlternativeTextEnricher(enricherOptions);

笔记

数据增强器故障不应导致整个数据摄取管道失效,因为它们只是尽力而为的改进。请使用相关工具LoggerFactory创建日志记录器来记录此类故障。

将数据拆分成多个块

每个数据都IngestionDocument需要被分割成若干IngestionChunk 个小块。目前,数据摄取库提供了三种分块策略:

  • 基于头部的分割,根据头部进行拆分。
  • 按章节进行分段,以章节(即页面)为单位进行拆分。
  • 基于语义相似主题的语义感知分块。

它们都支持基于令牌的限制,以确保数据块适合模型上下文窗口。

复制代码
IEmbeddingGenerator<string, Embedding<float>> embeddingGenerator =
    openAIClient.GetEmbeddingClient("text-embedding-3-small").AsIEmbeddingGenerator();

IngestionChunkerOptions chunkerOptions = new(TiktokenTokenizer.CreateForModel("gpt-4"))
{
    MaxTokensPerChunk = 2000,
    OverlapTokens = 0
};

IngestionChunker<string> chunker = new SemanticSimilarityChunker(embeddingGenerator, chunkerOptions);

原文链接

Introducing Data Ingestion Building Blocks (Preview)

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

如有任何疑问,请与我联系 (MingsonZheng@outlook.com)