의미 체계 커널을 사용하여 벡터 저장소로 데이터를 수집하는 방법(미리 보기)
Warning
의미 체계 커널 벡터 저장소 기능은 미리 보기 상태이며 릴리스 전에 제한된 상황에서도 호환성이 손상되는 변경이 필요한 개선 사항이 계속 발생할 수 있습니다.
이 문서에서는 에 애플리케이션을 만드는 방법을 보여 줍니다.
- Microsoft Word 문서의 각 단락에서 텍스트 만들기
- 각 단락에 대한 포함 생성
- 텍스트를 삽입하고, 포함하며, 원래 위치에 대한 참조를 Redis 인스턴스에 삽입합니다.
필수 조건
이 샘플의 경우 필요합니다.
- Azure 또는 원하는 다른 공급자에서 호스트되는 포함 생성 모델입니다.
- Redis를 로컬로 실행할 수 있도록 Redis 또는 Docker Desktop의 인스턴스입니다.
- 구문 분석하고 로드할 Word 문서입니다. 다음은 다운로드하여 사용할 수 있는 샘플 Word 문서가 포함된 zip입니다 . vector-store-data-ingestion-input.zip.
Redis 설정
Redis 인스턴스가 이미 있는 경우 이를 사용할 수 있습니다. 프로젝트를 로컬로 테스트하려는 경우 docker를 사용하여 Redis 컨테이너를 쉽게 시작할 수 있습니다.
docker run -d --name redis-stack -p 6379:6379 -p 8001:8001 redis/redis-stack:latest
성공적으로 실행 중인지 확인하려면 브라우저를 방문 http://localhost:8001/redis-stack/browser 하세요.
이러한 지침의 나머지 부분에는 위의 설정을 사용하여 이 컨테이너를 사용한다고 가정합니다.
프로젝트 만들기
새 프로젝트를 만들고 의미 체계 커널에서 Redis 커넥터에 대한 nuget 패키지 참조, 문서를 읽을 수 있는 오픈 xml 패키지, 포함을 생성하기 위한 의미 체계 커널의 OpenAI 커넥터를 추가합니다.
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
데이터 모델 추가
데이터를 업로드하려면 먼저 데이터베이스에 데이터가 있어야 하는 형식을 설명해야 합니다. 각 속성의 함수를 설명하는 특성을 사용하여 데이터 모델을 만들어 이 작업을 수행할 수 있습니다.
호출 TextParagraph.cs
된 프로젝트에 새 파일을 추가하고 다음 모델을 추가합니다.
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; }
}
값을 1536
.에 전달합니다 VectorStoreRecordVectorAttribute
. 이는 벡터의 차원 크기이며 선택한 포함 생성기가 생성하는 벡터의 크기와 일치해야 합니다.
팁
데이터 모델에 주석을 추가하는 방법 및 각 특성에 사용할 수 있는 추가 옵션에 대한 자세한 내용은 데이터 모델 정의를 참조하세요.
문서의 단락 읽기
문서 단어를 읽고 각 단락의 텍스트를 찾으려면 몇 가지 코드가 필요합니다.
호출 DocumentReader.cs
된 프로젝트에 새 파일을 추가하고 다음 클래스를 추가하여 문서에서 단락을 읽습니다.
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
};
}
}
}
}
포함 생성 및 데이터 업로드
포함을 생성하고 단락을 Redis에 업로드하려면 몇 가지 코드가 필요합니다. 별도의 클래스에서 이 작업을 수행해 보겠습니다.
호출 DataUploader.cs
된 새 파일을 추가하고 다음 클래스를 추가합니다.
#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();
}
}
}
모든 요소 결합
마지막으로, 우리는 다른 조각을 함께 넣어해야합니다.
이 예제에서는 의미 체계 커널 종속성 주입 컨테이너를 사용하지만 모든 기반 컨테이너를 사용할 IServiceCollection
수도 있습니다.
파일에 다음 코드를 Program.cs
추가하여 컨테이너를 만들고, Redis 벡터 저장소를 등록하고, 포함 서비스를 등록합니다.
텍스트 포함 생성 설정을 사용자 고유의 값으로 바꿔야 합니다.
#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>();
마지막 단계로 단어 문서에서 단락을 읽고 데이터 업로더를 호출하여 포함 항목을 생성하고 단락을 업로드하려고 합니다.
// 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);
Redis에서 데이터 보기
Redis 스택 브라우저(예: http://localhost:8001/redis-stack/browser 이제 업로드된 단락을 볼 수 있는 위치)로 이동합니다. 다음은 업로드된 단락 중 하나에 대해 표시되는 내용의 예입니다.
{
"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" : [...]
}
서비스 예정
추가 지침은 곧 제공될 예정입니다.
서비스 예정
추가 지침은 곧 제공될 예정입니다.