Пример семантического ядра Azure с внедрениями и сосновой шишкой
Microsoft недавно выпустила семантическое ядро в Azure. Это механизм на базе Azure OpenAI API, аналогичный LangChain, но как на C#, так и на Python. Там есть куча примеров, и я пытаюсь запустить Пример38 в своем проекте. В частности, этот код:
public static async Task RunAsync()
{
using (Log.VerboseCall())
{
string apiKey = "...xxxxxxxxxxxxxxxxxxx..."; // I got this from Pinecone
string pineconeEnvironment = "us-west1-gcp-free"; // I got this from Pinecone
string openAiKey = "...xxxxxxxxxxxxxxxxxxxxx..."; // I got this from OpenAI
PineconeMemoryStore memoryStore = new(pineconeEnvironment, apiKey);
IKernel kernel = Kernel.Builder
.WithOpenAITextCompletionService("text-davinci-003", openAiKey)
.WithOpenAITextEmbeddingGenerationService("text-embedding-ada-002", openAiKey)
.WithMemoryStorage(memoryStore)
.Build();
Console.WriteLine("== Printing Collections in DB ==");
IAsyncEnumerable<string> collections = memoryStore.GetCollectionsAsync();
await foreach (string collection in collections)
{
Console.WriteLine(collection);
}
Console.WriteLine("== Adding Memories ==");
Dictionary<string, object> metadata = new()
{
{ "type", "text" },
{ "tags", new List<string>() { "memory", "cats" } }
};
string additionalMetadata = System.Text.Json.JsonSerializer.Serialize(metadata);
try
{
// !!! This line throws exception - see below. !!!
string key1 = await kernel.Memory.SaveInformationAsync(MemoryCollectionName, "british short hair", "cat1", null, additionalMetadata);
string key2 = await kernel.Memory.SaveInformationAsync(MemoryCollectionName, "orange tabby", "cat2", null, additionalMetadata);
string key3 = await kernel.Memory.SaveInformationAsync(MemoryCollectionName, "norwegian forest cat", "cat3", null, additionalMetadata);
Console.WriteLine("== Retrieving Memories Through the Kernel ==");
MemoryQueryResult? lookup = await kernel.Memory.GetAsync(MemoryCollectionName, "cat1");
Console.WriteLine(lookup != null ? lookup.Metadata.Text : "ERROR: memory not found");
Console.WriteLine("== Retrieving Memories Directly From the Store ==");
var memory1 = await memoryStore.GetAsync(MemoryCollectionName, key1);
var memory2 = await memoryStore.GetAsync(MemoryCollectionName, key2);
var memory3 = await memoryStore.GetAsync(MemoryCollectionName, key3);
Console.WriteLine(memory1 != null ? memory1.Metadata.Text : "ERROR: memory not found");
Console.WriteLine(memory2 != null ? memory2.Metadata.Text : "ERROR: memory not found");
Console.WriteLine(memory3 != null ? memory3.Metadata.Text : "ERROR: memory not found");
Console.WriteLine("== Similarity Searching Memories: My favorite color is orange ==");
IAsyncEnumerable<MemoryQueryResult> searchResults = kernel.Memory.SearchAsync(MemoryCollectionName, "My favorite color is orange", 1, 0.8);
await foreach (MemoryQueryResult item in searchResults)
{
Console.WriteLine(item.Metadata.Text + " : " + item.Relevance);
}
}
catch (Exception ex)
{
Log.Verbose(ex);
}
}
}
Я получаю следующее исключение в указанной строке:
Создание индекса не поддерживается в хранилище памяти. Его следует создать вручную или с помощью CreateIndexAsync. Убедитесь, что индекс находится в состоянии «Готов».
2 ответа
В текущей конструкции памяти SK предполагается, что создание векторного индекса является быстрой операцией, занимающей от миллисекунд до нескольких секунд (аналогично Azure Search и Qdrant). Однако после интеграции Pinecone выяснилось, что создание индекса занимает значительно больше времени, иногда на это уходит несколько минут. Это требует опроса API, чтобы проверить, готов ли индекс, что приводит к неожиданным тайм-аутам в приложениях, предназначенных для создания индексов «на лету» (например, пример 38).
В качестве обходного пути интеграция Pinecone в SK в настоящее время требует от разработчиков приложений создавать индексы вручную либо через портал, либо с помощьюMicrosoft.SemanticKernel.Connectors.Memory.Pinecone.PineconeClient.CreateIndexAsync()
. Это позволяет избежать необходимости ставить операцию в очередь и ждать в течение длительного периода времени при опросе службы.
Потенциальным улучшением может быть добавление комментария в примере 38, поясняющего это поведение, или предоставление возможности переопределить поведение по умолчанию и разрешить ожидание. Это было бы ценным усовершенствованием для тех, кто заинтересован в его реализации.
Я также провожу тесты по интеграции Pinecone с SK. На линии:
string key1 = await kernel.Memory.SaveInformationAsync(MemoryCollectionName, "british short hair", "cat1", null, additionalMetadata);
Я попытался поместить имя индекса в первый параметр, и у меня это сработало.
Когда вы ссылаетесь на пример 38, где эти примеры?