So wird's ausgeführt: Aufnehmen von Daten in einen Vektorspeicher mithilfe des semantischen Kernels (Vorschau)
Warnung
Die Funktionalität des semantischen Kernelvektorspeichers befindet sich in der Vorschau, und Verbesserungen, die fehlerhafte Änderungen erfordern, können unter begrenzten Umständen noch vor der Veröffentlichung auftreten.
In diesem Artikel wird veranschaulicht, wie Sie eine Anwendung erstellen, für die
- Text aus jedem Absatz in einem Microsoft Word-Dokument übernehmen
- Generieren einer Einbettung für jeden Absatz
- Upsert den Text, das Einbetten und einen Verweis auf die ursprüngliche Position in eine Redis-Instanz.
Voraussetzungen
Für dieses Beispiel benötigen Sie
- Ein in Azure oder einem anderen Anbieter Ihrer Wahl gehostetes Einbettungsmodell.
- Eine Instanz von Redis oder Docker Desktop, sodass Sie Redis lokal ausführen können.
- Ein Word-Dokument zum Analysieren und Laden. Hier ist eine Zip-Datei mit einem Word-Beispieldokument, das Sie herunterladen und verwenden können: vector-store-data-ingestion-input.zip.
Einrichten von Redis
Wenn Sie bereits über eine Redis-Instanz verfügen, können Sie dies verwenden. Wenn Sie Ihr Projekt lieber lokal testen möchten, können Sie problemlos einen Redis-Container mit Docker starten.
docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest
Um zu überprüfen, ob sie erfolgreich ausgeführt wird, besuchen Sie http://localhost:8001/redis-stack/browser in Ihrem Browser.
Bei den restlichen Anweisungen wird davon ausgegangen, dass Sie diesen Container mit den oben genannten Einstellungen verwenden.
Erstellen Ihres Projekts
Erstellen Sie ein neues Projekt, und fügen Sie Nuget-Paketverweise für den Redis-Connector aus dem semantischen Kernel, das Open XML-Paket zum Lesen des Wortdokuments und den OpenAI-Connector aus dem semantischen Kernel zum Generieren von Einbettungen hinzu.
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
Hinzufügen eines Datenmodells
Um Daten hochzuladen, müssen wir zunächst beschreiben, welches Format die Daten in der Datenbank aufweisen sollen. Dazu können wir ein Datenmodell mit Attributen erstellen, die die Funktion jeder Eigenschaft beschreiben.
Fügen Sie dem aufgerufenen TextParagraph.cs
Projekt eine neue Datei hinzu, und fügen Sie ihr das folgende Modell hinzu.
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; }
}
Beachten Sie, dass wir den Wert 1536
an die VectorStoreRecordVectorAttribute
. Dies ist die Dimension des Vektors und muss mit der Größe des Vektors übereinstimmen, den der ausgewählte Einbettungsgenerator erzeugt.
Tipp
Weitere Informationen dazu, wie Sie Ihr Datenmodell kommentieren und welche zusätzlichen Optionen für jedes Attribut verfügbar sind, finden Sie unter Definieren des Datenmodells.
Lesen der Absätze im Dokument
Wir benötigen Code, um das Wortdokument zu lesen und den Text der einzelnen Absätze darin zu finden.
Fügen Sie dem aufgerufenen DocumentReader.cs
Projekt eine neue Datei hinzu, und fügen Sie die folgende Klasse hinzu, um die Absätze aus einem Dokument zu lesen.
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
};
}
}
}
}
Generieren von Einbettungen und Hochladen der Daten
Wir benötigen Code, um Einbettungen zu generieren und die Absätze in Redis hochzuladen. Lassen Sie uns dies in einer separaten Klasse tun.
Fügen Sie eine neue Datei namens hinzu DataUploader.cs
, und fügen Sie die folgende Klasse hinzu.
#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();
}
}
}
Korrektes Zusammenfügen
Schließlich müssen wir die verschiedenen Teile zusammenbringen.
In diesem Beispiel wird der Container für semantische Kernelabhängigkeitseinfügung verwendet, aber es ist auch möglich, jeden IServiceCollection
basierten Container zu verwenden.
Fügen Sie Ihrer Program.cs
Datei den folgenden Code hinzu, um den Container zu erstellen, den Redis-Vektorspeicher zu registrieren und den Einbettungsdienst zu registrieren.
Stellen Sie sicher, dass Sie die Einstellungen für die Texteinbettung durch Ihre eigenen Werte ersetzen.
#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>();
Im letzten Schritt möchten wir die Absätze aus unserem Word-Dokument lesen und den Datenuploader aufrufen, um die Einbettungen zu generieren und die Absätze hochzuladen.
// 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);
Anzeigen Ihrer Daten in Redis
Navigieren Sie zum Redis-Stapelbrowser, z. B. http://localhost:8001/redis-stack/browser wo Sie jetzt Ihre hochgeladenen Absätze sehen können sollten. Hier sehen Sie ein Beispiel dafür, was Sie für einen der hochgeladenen Absätze sehen sollten.
{
"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" : [...]
}
In Kürze verfügbar
Weitere Anweisungen in Kürze verfügbar
In Kürze verfügbar
Weitere Anweisungen in Kürze verfügbar