資料擷取是指從不同來源(如檔案、資料庫、API 或雲端服務)收集、讀取及準備資料的過程,以便用於下游應用程式。 實務上,此流程遵循擷取-轉換-載入(ETL)工作流程。
- 從原始來源擷取資料,無論是 PDF、Word 文件、音訊檔或網頁 API。
- 透過清理、分塊、豐富或轉換格式來轉換資料。
- 將資料載入 資料庫、向量儲存庫或 AI 模型等目的地,以便檢索和分析。
對於人工智慧與機器學習情境,尤其是檢索增強生成(RAG),資料擷取不僅僅是將資料從一種格式轉換到另一種格式。 而是讓資料可用於智慧應用。 這意味著要以保留文件結構與意義的方式來呈現文件,將它們拆分成可管理的區塊,並以元資料或嵌入豐富內容,並儲存以便快速且準確地檢索。
為什麼資料擷取對 AI 應用很重要
想像你正在打造一個由 RAG 驅動的聊天機器人,幫助員工在公司龐大的文件庫中尋找資訊。 這些文件可能包括 PDF、Word 檔案、PowerPoint 簡報,以及分散在不同系統上的網頁。
你的聊天機器人需要理解並搜尋數千份文件,才能提供準確且具上下文的答案。 但原始文件並不適合 AI 系統。 你需要將它們轉換成一種既保留意義又能搜尋和檢索的格式。
這時資料擷取變得至關重要。 你需要從不同檔案格式中擷取文字,將大型文件拆分成符合 AI 模型限制的小區塊,豐富內容以加入元資料,產生語意搜尋的嵌入,並以能快速檢索的方式儲存所有內容。 每一步都需要謹慎考慮如何保留原始意義與脈絡。
資料導入的建構單元
Microsoft.Extensions.DataIngestion 函式庫圍繞多個關鍵元件共同運作,建立完整的資料處理流程。 本節將探討每個組成部分及其如何相互配合。
文件與文件閱讀器
函式庫的基礎是由IngestionDocument型別組成,提供一種統一的方式來表示任何檔案格式,且不會遺失重要資訊。
IngestionDocument 以 Markdown 為中心,因為大型語言模型最適合搭配 Markdown 格式。
抽象化 IngestionDocumentReader 處理從各種來源載入文件,無論是本地檔案還是串流。 有幾個讀取器可用:
未來還會新增更多讀取器(包括 LlamaParse 和 Azure 文件智慧)。
這種設計意味著你可以使用相同一致的 API 處理來自不同來源的文件,使程式碼更易維護且更具彈性。
文件處理
文件處理者在文件層級進行轉換以增強與準備內容。 函式庫提供此 ImageAlternativeTextEnricher 類別作為內建處理器,利用大型語言模型生成文件中圖片的描述性替代文字。
區塊和分塊策略
文件載入後,通常需要拆解成稱為區塊的小塊。 區塊代表文件的子區塊,AI系統能有效處理、儲存與檢索。 這種分塊過程對於需要快速找到最相關資訊的檢索增強生成場景至關重要。
函式庫提供多種分區策略以適應不同的使用情境:
- 基於標頭的分塊以在標頭處進行拆分。
- 基於區段的拆分,可以根據區段(例如頁面)進行拆分。
- 以語意感知區塊來保存完整的思緒。
這些分塊策略建立在 Microsoft.ML.Tokenizers 函式庫之上,能智慧地將文字拆分成適合大型語言模型的適當大小片段。 正確的分塊策略取決於你的文件類型以及你計畫如何擷取資訊。
Tokenizer tokenizer = TiktokenTokenizer.CreateForModel("gpt-5");
IngestionChunkerOptions options = new(tokenizer)
{
MaxTokensPerChunk = 2000,
OverlapTokens = 0
};
IngestionChunker<string> chunker = new HeaderChunker(options);
塊狀處理與濃縮
文件拆分成多個區塊後,你可以使用處理器來強化和豐富內容。 區塊處理器處理單一零件,能執行:
-
內容豐富, 包括自動摘要(
SummaryEnricher)、情感分析(SentimentEnricher)、以及關鍵字萃取(KeywordEnricher)。 - 基於預先定義類別
ClassificationEnricher()的自動內容分類()。
這些處理器使用 Microsoft.Extensions.AI.Abstractions ,利用大型語言模型進行智慧內容轉換,使區塊對後續 AI 應用更具用處。
文件編寫與儲存
IngestionChunkWriter<T> 將處理過的區塊儲存到資料儲存庫,以便日後檢索。 該庫使用 Microsoft.Extensions.AI 和 Microsoft.Extensions.VectorData,並提供這個 VectorStoreWriter<T> 類別。 本編寫者支援將區塊儲存在任何支援的Microsoft.Extensions.VectorData中。
向量儲存包括熱門選項如 Qdrant、SQL Server、Azure Cosmos DB、MongoDB、Chroma 和 Elasticsearch。 欲了解更多供應商的資訊,請參閱「 開箱即用的 Vector Store 供應商」。 (儘管部分套件名稱中包含「SemanticKernel」,這些提供者與 語意核心 無關,且可在 .NET 中任何地方使用,包括 Agent Framework。)
作者也能自動生成你的區塊 Microsoft.Extensions.AI嵌入,為語意搜尋和檢索場景做好準備。
OpenAIClient openAIClient = new(
new ApiKeyCredential(Environment.GetEnvironmentVariable("OPENAI_API_KEY")!));
IEmbeddingGenerator<string, Embedding<float>> embeddingGenerator =
openAIClient.GetEmbeddingClient("text-embedding-3-small").AsIEmbeddingGenerator();
using SqliteVectorStore vectorStore = new(
"Data Source=vectors.db;Pooling=false",
new()
{
EmbeddingGenerator = embeddingGenerator
});
// The writer requires the embedding dimension count to be specified.
// For OpenAI's `text-embedding-3-small`, the dimension count is 1536.
using VectorStoreWriter<string> writer = new(vectorStore, dimensionCount: 1536);
文件處理流程
API IngestionPipeline<T> 允許你將各種資料擷取元件串接成完整的工作流程。 你可以結合:
- 讀取器可從各種來源載入文件。
- 處理器用來轉換並豐富文件內容。
- 分塊器 將文件拆解成易於處理的部分。
- 作者 會將最終結果儲存在你選擇的資料庫中。
這種管線方法減少了模板程式碼,並使建立、測試及維護複雜的資料擷取工作流程變得容易。
using IngestionPipeline<string> pipeline = new(reader, chunker, writer, loggerFactory: loggerFactory)
{
DocumentProcessors = { imageAlternativeTextEnricher },
ChunkProcessors = { summaryEnricher }
};
await foreach (var result in pipeline.ProcessAsync(new DirectoryInfo("."), searchPattern: "*.md"))
{
Console.WriteLine($"Completed processing '{result.DocumentId}'. Succeeded: '{result.Succeeded}'.");
}
單一文件擷取失敗不應該讓整個流程都失敗。 這就是為什麼 IngestionPipeline<T>.ProcessAsync 透過返回 IAsyncEnumerable<IngestionResult>來實現部分成功。 呼叫者負責處理任何失敗(例如重試失敗文件或在首次錯誤時停止)。