Remarque
L’accès à cette page requiert une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page requiert une autorisation. Vous pouvez essayer de modifier des répertoires.
Ce tutoriel explore l’intégration du modèle RAG à l’aide de modèles Open AI et de fonctionnalités de recherche vectorielle dans une application .NET. L’exemple d’application effectue des recherches vectorielles sur des données personnalisées stockées dans Azure Cosmos DB pour MongoDB et affine davantage les réponses à l’aide de modèles IA génératifs, tels que GPT-35 et GPT-4. Dans les sections qui suivent, vous allez configurer un exemple d’application et explorer des exemples de code clés qui illustrent ces concepts.
Prerequisites
- .NET 8.0
- Un compte Azure
- Un service Azure Cosmos DB pour MongoDB vCore
- Un service Azure Open AI
- Déployer le
text-embedding-ada-002modèle pour les incorporations - Déployer un
gpt-35-turbomodèle pour les achèvements de conversation
- Déployer le
Vue d’ensemble de l’application
L’application Cosmos Recipe Guide vous permet d’effectuer des recherches vectorielles et pilotées par l’IA sur un ensemble de données de recette. Vous pouvez rechercher directement des recettes disponibles ou inviter l’application avec des noms d’ingrédients pour trouver des recettes connexes. L’application et les sections à l’avance vous guident tout au long du flux de travail suivant pour illustrer ce type de fonctionnalité :
Chargez des exemples de données dans une base de données Azure Cosmos DB pour MongoDB.
Créez des incorporations et un index vectoriel pour les exemples de données chargés à l’aide du modèle Azure OpenAI
text-embedding-ada-002.Effectuez une recherche de similarité vectorielle en fonction des invites de l’utilisateur.
Utilisez le modèle d’achèvement Azure OpenAI
gpt-35-turbopour composer des réponses plus significatives en fonction des données des résultats de la recherche.
Get started
Clonez le référentiel GitHub suivant :
git clone https://github.com/microsoft/AzureDataRetrievalAugmentedGenerationSamples.gitDans le dossier C#/CosmosDB-MongoDBvCore , ouvrez le fichier CosmosRecipeGuide.sln .
Dans le fichier appsettings.json , remplacez les valeurs de configuration suivantes par vos valeurs Azure OpenAI et Azure CosmosDB pour MongoDb :
"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>"Lancez l’application en appuyant sur le bouton Démarrer en haut de Visual Studio.
Explorer l’application
Lorsque vous exécutez l’application pour la première fois, elle se connecte à Azure Cosmos DB et signale qu’aucune recette n’est encore disponible. Suivez les étapes affichées par l’application pour commencer le flux de travail principal.
Sélectionnez Charger des recettes dans Cosmos DB , puis appuyez sur Entrée. Cette commande lit des exemples de fichiers JSON à partir du projet local et les charge dans le compte Cosmos DB.
Le code de la classe Utility.cs analyse les fichiers JSON locaux.
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; }La
UpsertVectorAsyncméthode du fichier VCoreMongoService.cs charge les documents dans Azure Cosmos DB pour MongoDB.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; } }Sélectionnez Vectoriser les recettes et les stocker dans Cosmos DB.
Les éléments JSON chargés dans Cosmos DB ne contiennent pas d’incorporations et ne sont donc pas optimisés pour RAG via la recherche vectorielle. Une incorporation est une représentation numérique dense d’informations de la signification sémantique d’un morceau de texte. Les recherches vectorielles sont en mesure de rechercher des éléments avec des incorporations contextuellement similaires.
La
GetEmbeddingsAsyncméthode dans le fichier OpenAIService.cs crée une incorporation pour chaque élément de la base de données.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; } }Le
CreateVectorIndexIfNotExistsfichier VCoreMongoService.cs crée un index vectoriel, qui vous permet d’effectuer des recherches de similarité vectorielle.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; } }Sélectionnez l’option Assistant IA (recherchez une recette par nom ou description, ou posez une question) dans l’application pour exécuter une requête utilisateur.
La requête utilisateur est convertie en incorporation à l’aide du service Open AI et du modèle d’incorporation. L’incorporation est ensuite envoyée à Azure Cosmos DB pour MongoDB et est utilisée pour effectuer une recherche vectorielle. La
VectorSearchAsyncméthode du fichier VCoreMongoService.cs effectue une recherche vectorielle pour rechercher des vecteurs proches du vecteur fourni et retourne une liste de documents d’Azure Cosmos DB pour MongoDB vCore.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; } }La méthode
GetChatCompletionAsyncgénère une réponse de complétion de chat améliorée en fonction de la sollicitation de l'utilisateur et des résultats de recherche vectorielle associés.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; } }L’application utilise également l’ingénierie rapide pour garantir que les limites du service Open AI et met en forme la réponse pour les recettes fournies.
//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.";