Aracılığıyla paylaş


.NET uygulamasında RAG ile Azure OpenAI'yi vektör araması kullanarak uygulayın.

Bu öğreticide, .NET uygulamasında açık yapay zeka modellerini ve vektör arama özelliklerini kullanarak RAG deseninin tümleştirilmesi inceleniyor. Örnek uygulama, MongoDB için Azure Cosmos DB'de depolanan özel verilerde vektör aramaları gerçekleştirir ve GPT-35 ve GPT-4 gibi üretken yapay zeka modellerini kullanarak yanıtları daha da iyileştirmektedir. İzleyen bölümlerde örnek bir uygulama ayarlayıp bu kavramları gösteren önemli kod örneklerini keşfedeceksiniz.

Önkoşullar

Uygulamaya genel bakış

Cosmos Yemek Tarifi Kılavuzu uygulaması, bir dizi tarif verisine karşı vektör ve yapay zeka temelli aramalar yapmanıza olanak tanır. Doğrudan kullanılabilir tarifler için arama yapabilir veya ilgili tarifleri bulmak için uygulamadan içerik adlarını isteyebilirsiniz. Uygulama ve sonraki bölümler, bu tür işlevleri göstermek için aşağıdaki iş akışında size yol gösterir:

  1. Örnek verileri MongoDB için Azure Cosmos DB veritabanına yükleyin.

  2. Azure OpenAI text-embedding-ada-002 modelini kullanarak karşıya yüklenen örnek veriler için eklemeler ve vektör dizini oluşturun.

  3. Kullanıcı istemlerine göre vektör benzerliği araması yapın.

  4. Arama sonuçları verilerine göre daha anlamlı yanıtlar oluşturmak için Azure OpenAI gpt-35-turbo tamamlama modelini kullanın.

    Çalışan örnek uygulamayı gösteren ekran görüntüsü.

Get started

  1. Aşağıdaki GitHub deposunu kopyalayın:

    git clone https://github.com/microsoft/AzureDataRetrievalAugmentedGenerationSamples.git
    
  2. C#/CosmosDB-MongoDBvCore klasöründe CosmosRecipeGuide.sln dosyasını açın.

  3. appsettings.json dosyasında aşağıdaki yapılandırma değerlerini MongoDb için Azure OpenAI ve Azure CosmosDB değerlerinizle değiştirin:

    "OpenAIEndpoint": "https://<your-service-name>.openai.azure.com/",
    "OpenAIKey": "<your-API-key>",
    "OpenAIEmbeddingDeployment": "<your-ADA-deployment-name>",
    "OpenAIcompletionsDeployment": "<your-GPT-deployment-name>",
    "MongoVcoreConnection": "<your-Mongo-connection-string>"
    
  4. Visual Studio'nun üst kısmındaki Başlat düğmesine basarak uygulamayı başlatın.

Uygulamayı keşfetme

Uygulamayı ilk kez çalıştırdığınızda, Azure Cosmos DB'ye bağlanır ve henüz kullanılabilir tarif olmadığını bildirir. Çekirdek iş akışını başlatmak için uygulama tarafından görüntülenen adımları izleyin.

  1. Tarifleri Cosmos DB'ye yükle'yi seçin ve Enter tuşuna basın. Bu komut, yerel projeden örnek JSON dosyalarını okur ve Cosmos DB hesabına yükler.

    Utility.cs sınıfındaki kod, yerel JSON dosyalarını ayrıştırıyor.

    public static List<Recipe> ParseDocuments(string Folderpath)
    {
        List<Recipe> recipes = new List<Recipe>();
    
        Directory.GetFiles(Folderpath)
            .ToList()
            .ForEach(f =>
            {
                var jsonString= System.IO.File.ReadAllText(f);
                Recipe recipe = JsonConvert.DeserializeObject<Recipe>(jsonString);
                recipe.id = recipe.name.ToLower().Replace(" ", "");
                recipes.Add(recipe);
            }
        );
    
        return recipes;
    }
    

    UpsertVectorAsync VCoreMongoService.cs dosyasındaki yöntemi, belgeleri MongoDB için Azure Cosmos DB'ye yükler.

    public async Task UpsertVectorAsync(Recipe recipe)
        {
            BsonDocument document = recipe.ToBsonDocument();
    
            if (!document.Contains("_id"))
            {
                Console.WriteLine("UpsertVectorAsync: Document does not contain _id.");
                throw new ArgumentException("UpsertVectorAsync: Document does not contain _id.");
            }
    
            string? _idValue = document["_id"].ToString();
    
            try
            {
                var filter = Builders<BsonDocument>.Filter.Eq("_id", _idValue);
                var options = new ReplaceOptions { IsUpsert = true };
                await _recipeCollection.ReplaceOneAsync(filter, document, options);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception: UpsertVectorAsync(): {ex.Message}");
                throw;
            }
        }
    
  2. Tarifleri vektörleştir'i seçin ve Cosmos DB'de depolayın.

    Cosmos DB'ye yüklenen JSON öğeleri ekleme içermez ve bu nedenle vektör araması yoluyla RAG için iyileştirilmemiştir. Ekleme, bir metin parçasının anlamsal anlamının bilgi yoğunluklu, sayısal bir gösterimidir. Vektör aramaları bağlamsal olarak benzer eklemelere sahip öğeleri bulabilir.

    GetEmbeddingsAsync OpenAIService.cs dosyasındaki yöntemi, veritabanındaki her öğe için bir ekleme oluşturur.

    public async Task<float[]?> GetEmbeddingsAsync(dynamic data)
    {
        try
        {
            EmbeddingsOptions options = new EmbeddingsOptions(data)
            {
                Input = data
            };
    
            var response = await _openAIClient.GetEmbeddingsAsync(openAIEmbeddingDeployment, options);
    
            Embeddings embeddings = response.Value;
            float[] embedding = embeddings.Data[0].Embedding.ToArray();
    
            return embedding;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"GetEmbeddingsAsync Exception: {ex.Message}");
            return null;
        }
    }
    

    CreateVectorIndexIfNotExists VCoreMongoService.cs dosyasında vektör benzerliği aramaları gerçekleştirmenizi sağlayan bir vektör dizini oluşturulur.

    public void CreateVectorIndexIfNotExists(string vectorIndexName)
    {
        try
        {
            //Find if vector index exists in vectors collection
            using (IAsyncCursor<BsonDocument> indexCursor = _recipeCollection.Indexes.List())
            {
                bool vectorIndexExists = indexCursor.ToList().Any(x => x["name"] == vectorIndexName);
                if (!vectorIndexExists)
                {
                    BsonDocumentCommand<BsonDocument> command = new BsonDocumentCommand<BsonDocument>(
                        BsonDocument.Parse(@"
                            { createIndexes: 'Recipe',
                                indexes: [{
                                name: 'vectorSearchIndex',
                                key: { embedding: 'cosmosSearch' },
                                cosmosSearchOptions: {
                                    kind: 'vector-ivf',
                                    numLists: 5,
                                    similarity: 'COS',
                                    dimensions: 1536 }
                                }]
                            }"));
    
                    BsonDocument result = _database.RunCommand(command);
                    if (result["ok"] != 1)
                    {
                        Console.WriteLine("CreateIndex failed with response: " + result.ToJson());
                    }
                }
            }
        }
        catch (MongoException ex)
        {
            Console.WriteLine("MongoDbService InitializeVectorIndex: " + ex.Message);
            throw;
        }
    }
    
  3. Kullanıcı sorgusu çalıştırmak için uygulamadaki AI Yardımcısı'na sorun (ada veya açıklamaya göre tarif arayın veya soru sorun) seçeneğini belirleyin.

    Kullanıcı sorgusu, Open AI hizmeti ve ekleme modeli kullanılarak bir eklemeye dönüştürülür. Ekleme daha sonra MongoDB için Azure Cosmos DB'ye gönderilir ve vektör araması yapmak için kullanılır. VectorSearchAsync VCoreMongoService.cs dosyasındaki yöntemi, sağlanan vektöre yakın vektörleri bulmak için bir vektör araması gerçekleştirir ve MongoDB sanal çekirdeği için Azure Cosmos DB'den belgelerin listesini döndürür.

    public async Task<List<Recipe>> VectorSearchAsync(float[] queryVector)
        {
            List<string> retDocs = new List<string>();
            string resultDocuments = string.Empty;
    
            try
            {
                //Search Azure Cosmos DB for MongoDB vCore collection for similar embeddings
                //Project the fields that are needed
                BsonDocument[] pipeline = new BsonDocument[]
                {
                    BsonDocument.Parse(
                        @$"{{$search: {{
                                cosmosSearch:
                                    {{ vector: [{string.Join(',', queryVector)}],
                                       path: 'embedding',
                                       k: {_maxVectorSearchResults}}},
                                       returnStoredSource:true
                                    }}
                                }}"),
                    BsonDocument.Parse($"{{$project: {{embedding: 0}}}}"),
                };
    
                var bsonDocuments = await _recipeCollection
                    .Aggregate<BsonDocument>(pipeline).ToListAsync();
    
                var recipes = bsonDocuments
                    .ToList()
                    .ConvertAll(bsonDocument =>
                        BsonSerializer.Deserialize<Recipe>(bsonDocument));
                return recipes;
            }
            catch (MongoException ex)
            {
                Console.WriteLine($"Exception: VectorSearchAsync(): {ex.Message}");
                throw;
            }
        }
    

    yöntemi, GetChatCompletionAsync kullanıcı istemine ve ilgili vektör arama sonuçlarına göre geliştirilmiş bir sohbet tamamlama yanıtı oluşturur.

    public async Task<(string response, int promptTokens, int responseTokens)> GetChatCompletionAsync(string userPrompt, string documents)
    {
        try
        {
            ChatMessage systemMessage = new ChatMessage(
                ChatRole.System, _systemPromptRecipeAssistant + documents);
            ChatMessage userMessage = new ChatMessage(
                ChatRole.User, userPrompt);
    
            ChatCompletionsOptions options = new()
            {
                Messages =
                {
                    systemMessage,
                    userMessage
                },
                MaxTokens = openAIMaxTokens,
                Temperature = 0.5f, //0.3f,
                NucleusSamplingFactor = 0.95f,
                FrequencyPenalty = 0,
                PresencePenalty = 0
            };
    
            Azure.Response<ChatCompletions> completionsResponse =
                await openAIClient.GetChatCompletionsAsync(openAICompletionDeployment, options);
            ChatCompletions completions = completionsResponse.Value;
    
            return (
                response: completions.Choices[0].Message.Content,
                promptTokens: completions.Usage.PromptTokens,
                responseTokens: completions.Usage.CompletionTokens
            );
    
        }
        catch (Exception ex)
        {
            string message = $"OpenAIService.GetChatCompletionAsync(): {ex.Message}";
            Console.WriteLine(message);
            throw;
        }
    }
    

    Uygulama ayrıca Açık yapay zeka hizmeti sınırlarının ve sağlanan tarifler için yanıtın biçimlendirilmesini sağlamak için istem mühendisliğini kullanır.

    //System prompts to send with user prompts to instruct the model for chat session
    private readonly string _systemPromptRecipeAssistant = @"
        You are an intelligent assistant for Contoso Recipes.
        You are designed to provide helpful answers to user questions about
        recipes, cooking instructions provided in JSON format below.
    
        Instructions:
        - Only answer questions related to the recipe provided below.
        - Don't reference any recipe not provided below.
        - If you're unsure of an answer, say ""I don't know"" and recommend users search themselves.
        - Your response  should be complete.
        - List the Name of the Recipe at the start of your response followed by step by step cooking instructions.
        - Assume the user is not an expert in cooking.
        - Format the content so that it can be printed to the Command Line console.
        - In case there is more than one recipe you find, let the user pick the most appropriate recipe.";