Jak ingestovat data do vektorového úložiště pomocí sémantického jádra (Preview)
Upozorňující
Funkce sémantického úložiště vektorů jádra je ve verzi Preview a vylepšení, která vyžadují zásadní změny, se můžou vyskytovat za omezených okolností před vydáním.
Tento článek vám ukáže, jak vytvořit aplikaci pro
- Pořízení textu z každého odstavce v dokumentu Aplikace Microsoft Word
- Vygenerování vkládání pro každý odstavec
- Vložte text, vložení a odkaz na původní umístění do instance Redis.
Požadavky
Pro tuto ukázku budete potřebovat
- Model generování vkládání hostovaný v Azure nebo jiném poskytovateli podle vašeho výběru
- Instance Redis nebo Docker Desktopu, abyste mohli Spustit Redis místně.
- Wordový dokument, který se má analyzovat a načíst Tady je zip obsahující ukázkový wordový dokument, který si můžete stáhnout a použít: vector-store-data-ingestion-input.zip.
Nastavení Redis
Pokud už máte instanci Redis, můžete ji použít. Pokud chcete projekt otestovat místně, můžete kontejner Redis snadno spustit pomocí Dockeru.
docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest
Pokud chcete ověřit, že běží úspěšně, přejděte http://localhost:8001/redis-stack/browser do prohlížeče.
Ve zbývajících těchto pokynech se předpokládá, že tento kontejner používáte pomocí výše uvedených nastavení.
Vytvoření projektu
Vytvořte nový projekt a přidejte odkazy na balíčky NuGet pro konektor Redis z sémantického jádra, otevřený balíček XML pro čtení wordového dokumentu s konektorem OpenAI z sémantického jádra pro generování vkládání.
dotnet new console --framework net8.0 --name SKVectorIngest
cd SKVectorIngest
dotnet add package Microsoft.SemanticKernel.Connectors.AzureOpenAI
dotnet add package Microsoft.SemanticKernel.Connectors.Redis --prerelease
dotnet add package DocumentFormat.OpenXml
Přidání datového modelu
Abychom mohli nahrát data, musíme nejprve popsat, jaký formát by data měla mít v databázi. Můžeme to udělat vytvořením datového modelu s atributy, které popisují funkci každé vlastnosti.
Přidejte do projektu nový TextParagraph.cs
soubor a přidejte do něj následující model.
using Microsoft.Extensions.VectorData;
namespace SKVectorIngest;
internal class TextParagraph
{
/// <summary>A unique key for the text paragraph.</summary>
[VectorStoreRecordKey]
public required string Key { get; init; }
/// <summary>A uri that points at the original location of the document containing the text.</summary>
[VectorStoreRecordData]
public required string DocumentUri { get; init; }
/// <summary>The id of the paragraph from the document containing the text.</summary>
[VectorStoreRecordData]
public required string ParagraphId { get; init; }
/// <summary>The text of the paragraph.</summary>
[VectorStoreRecordData]
public required string Text { get; init; }
/// <summary>The embedding generated from the Text.</summary>
[VectorStoreRecordVector(1536)]
public ReadOnlyMemory<float> TextEmbedding { get; set; }
}
Všimněte si, že předáváme hodnotu 1536
do VectorStoreRecordVectorAttribute
. Toto je velikost rozměru vektoru a musí odpovídat velikosti vektoru, kterou vytváří vámi zvolený generátor vkládání.
Tip
Další informace o tom, jak datový model komentovat a jaké další možnosti jsou k dispozici pro jednotlivé atributy, najdete v tématu o definici datového modelu.
Čtení odstavců v dokumentu
Potřebujeme kód ke čtení wordového dokumentu a vyhledání textu každého odstavce v něm.
Přidejte do projektu volaný DocumentReader.cs
nový soubor a přidejte následující třídu pro čtení odstavců z dokumentu.
using System.Text;
using System.Xml;
using DocumentFormat.OpenXml.Packaging;
namespace SKVectorIngest;
internal class DocumentReader
{
public static IEnumerable<TextParagraph> ReadParagraphs(Stream documentContents, string documentUri)
{
// Open the document.
using WordprocessingDocument wordDoc = WordprocessingDocument.Open(documentContents, false);
if (wordDoc.MainDocumentPart == null)
{
yield break;
}
// Create an XmlDocument to hold the document contents and load the document contents into the XmlDocument.
XmlDocument xmlDoc = new XmlDocument();
XmlNamespaceManager nsManager = new XmlNamespaceManager(xmlDoc.NameTable);
nsManager.AddNamespace("w", "http://schemas.openxmlformats.org/wordprocessingml/2006/main");
nsManager.AddNamespace("w14", "http://schemas.microsoft.com/office/word/2010/wordml");
xmlDoc.Load(wordDoc.MainDocumentPart.GetStream());
// Select all paragraphs in the document and break if none found.
XmlNodeList? paragraphs = xmlDoc.SelectNodes("//w:p", nsManager);
if (paragraphs == null)
{
yield break;
}
// Iterate over each paragraph.
foreach (XmlNode paragraph in paragraphs)
{
// Select all text nodes in the paragraph and continue if none found.
XmlNodeList? texts = paragraph.SelectNodes(".//w:t", nsManager);
if (texts == null)
{
continue;
}
// Combine all non-empty text nodes into a single string.
var textBuilder = new StringBuilder();
foreach (XmlNode text in texts)
{
if (!string.IsNullOrWhiteSpace(text.InnerText))
{
textBuilder.Append(text.InnerText);
}
}
// Yield a new TextParagraph if the combined text is not empty.
var combinedText = textBuilder.ToString();
if (!string.IsNullOrWhiteSpace(combinedText))
{
Console.WriteLine("Found paragraph:");
Console.WriteLine(combinedText);
Console.WriteLine();
yield return new TextParagraph
{
Key = Guid.NewGuid().ToString(),
DocumentUri = documentUri,
ParagraphId = paragraph.Attributes?["w14:paraId"]?.Value ?? string.Empty,
Text = combinedText
};
}
}
}
}
Generování vkládání a nahrání dat
Budeme potřebovat kód pro vygenerování vkládání a nahrání odstavců do Redisu. Pojďme to udělat v samostatné třídě.
Přidejte do něj nový soubor s názvem DataUploader.cs
a přidejte do ní následující třídu.
#pragma warning disable SKEXP0001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Embeddings;
namespace SKVectorIngest;
internal class DataUploader(IVectorStore vectorStore, ITextEmbeddingGenerationService textEmbeddingGenerationService)
{
/// <summary>
/// Generate an embedding for each text paragraph and upload it to the specified collection.
/// </summary>
/// <param name="collectionName">The name of the collection to upload the text paragraphs to.</param>
/// <param name="textParagraphs">The text paragraphs to upload.</param>
/// <returns>An async task.</returns>
public async Task GenerateEmbeddingsAndUpload(string collectionName, IEnumerable<TextParagraph> textParagraphs)
{
var collection = vectorStore.GetCollection<string, TextParagraph>(collectionName);
await collection.CreateCollectionIfNotExistsAsync();
foreach (var paragraph in textParagraphs)
{
// Generate the text embedding.
Console.WriteLine($"Generating embedding for paragraph: {paragraph.ParagraphId}");
paragraph.TextEmbedding = await textEmbeddingGenerationService.GenerateEmbeddingAsync(paragraph.Text);
// Upload the text paragraph.
Console.WriteLine($"Upserting paragraph: {paragraph.ParagraphId}");
await collection.UpsertAsync(paragraph);
Console.WriteLine();
}
}
}
Spojení všech součástí dohromady
Nakonec musíme dát dohromady různé části.
V tomto příkladu použijeme kontejner injektáž závislostí se sémantickým jádrem, ale je také možné použít jakýkoliv IServiceCollection
založený kontejner.
Do souboru přidejte následující kód Program.cs
pro vytvoření kontejneru, zaregistrujte úložiště vektorů Redis a zaregistrujte službu vkládání.
Nezapomeňte nahradit nastavení generování vkládání textu vlastními hodnotami.
#pragma warning disable SKEXP0010 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
#pragma warning disable SKEXP0020 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using SKVectorIngest;
// Replace with your values.
var deploymentName = "text-embedding-ada-002";
var endpoint = "https://sksample.openai.azure.com/";
var apiKey = "your-api-key";
// Register Azure Open AI text embedding generation service and Redis vector store.
var builder = Kernel.CreateBuilder()
.AddAzureOpenAITextEmbeddingGeneration(deploymentName, endpoint, apiKey)
.AddRedisVectorStore("localhost:6379");
// Register the data uploader.
builder.Services.AddSingleton<DataUploader>();
// Build the kernel and get the data uploader.
var kernel = builder.Build();
var dataUploader = kernel.Services.GetRequiredService<DataUploader>();
V posledním kroku chceme přečíst odstavce z našeho wordového dokumentu a volat nahrání dat, aby vygeneroval vložené položky a nahrál odstavce.
// Load the data.
var textParagraphs = DocumentReader.ReadParagraphs(
new FileStream(
"vector-store-data-ingestion-input.docx",
FileMode.Open),
"file:///c:/vector-store-data-ingestion-input.docx");
await dataUploader.GenerateEmbeddingsAndUpload(
"sk-documentation",
textParagraphs);
Zobrazení dat v Redisu
Přejděte do prohlížeče zásobníku Redis, například http://localhost:8001/redis-stack/browser kam byste teď měli vidět nahrané odstavce. Tady je příklad toho, co byste měli vidět u jednoho z nahraných odstavců.
{
"DocumentUri" : "file:///c:/vector-store-data-ingestion-input.docx",
"ParagraphId" : "14CA7304",
"Text" : "Version 1.0+ support across C#, Python, and Java means it’s reliable, committed to non breaking changes. Any existing chat-based APIs are easily expanded to support additional modalities like voice and video.",
"TextEmbedding" : [...]
}
Již brzy
Další pokyny připravujeme
Již brzy
Další pokyny připravujeme