Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa esercitazione illustra l'integrazione del modello RAG usando i modelli Open AI e le funzionalità di ricerca vettoriale in un'app .NET. L'applicazione di esempio esegue ricerche vettoriali sui dati personalizzati archiviati in Azure Cosmos DB per MongoDB e affina ulteriormente le risposte usando modelli di intelligenza artificiale generativi, ad esempio GPT-35 e GPT-4. Nelle sezioni seguenti si configurerà un'applicazione di esempio ed si esamineranno esempi di codice chiave che illustrano questi concetti.
Prerequisiti
- .NET 8.0
- Un account di Azure
- Servizio Azure Cosmos DB per MongoDB vCore
- Un servizio Azure Open AI
- Distribuire il modello
text-embedding-ada-002per gli embedding - Distribuire il
gpt-35-turbomodello per i completamenti della chat
- Distribuire il modello
Panoramica app
L'app Guida alle ricette di Cosmos consente di eseguire ricerche basate su vettori e intelligenza artificiale su un set di dati delle ricette. È possibile cercare direttamente le ricette disponibili o richiedere all'app i nomi degli ingredienti per trovare ricette correlate. L'app e le sezioni precedenti illustrano il flusso di lavoro seguente per illustrare questo tipo di funzionalità:
Caricare dati di esempio in un database Azure Cosmos DB per MongoDB.
Creare incorporamenti e un indice vettoriale per i dati di esempio caricati usando il modello OpenAI
text-embedding-ada-002di Azure.Eseguire una ricerca di somiglianza vettoriale in base alle richieste dell'utente.
Usare il modello di completamenti OpenAI
gpt-35-turbodi Azure per comporre risposte più significative in base ai dati dei risultati della ricerca.
Get started
Clonare il repository GitHub seguente:
git clone https://github.com/microsoft/AzureDataRetrievalAugmentedGenerationSamples.gitNella cartella C#/CosmosDB-MongoDBvCore aprire il file CosmosRecipeGuide.sln .
Nel file appsettings.json sostituire i valori di configurazione seguenti con i valori di Azure OpenAI e Azure CosmosDB per 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>"Avviare l'app premendo il pulsante Start nella parte superiore di Visual Studio.
Esplorare l'app
Quando si esegue l'app per la prima volta, si connette ad Azure Cosmos DB e segnala che non sono ancora disponibili ricette. Seguire i passaggi visualizzati dall'app per avviare il flusso di lavoro principale.
Selezionare Carica ricette in Cosmos DB e premere INVIO. Questo comando legge i file JSON di esempio dal progetto locale e li carica nell'account Cosmos DB.
Il codice della classe Utility.cs analizza i file JSON locali.
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; }Il
UpsertVectorAsyncmetodo nel file VCoreMongoService.cs carica i documenti in Azure Cosmos DB per 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; } }Selezionare Vectorize the recipe(s) and store them in Cosmos DB (Vettorizza le ricette) e archiviarle in Cosmos DB.
Gli elementi JSON caricati in Cosmos DB non contengono incorporamenti e pertanto non sono ottimizzati per RAG tramite la ricerca vettoriale. Un incorporamento è una rappresentazione numerica e densa di informazioni del significato semantico di una parte di testo. Le ricerche vettoriali sono in grado di trovare elementi con incorporamenti contestualmente simili.
Il
GetEmbeddingsAsyncmetodo nel file OpenAIService.cs crea un incorporamento per ogni elemento nel database.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; } }L'oggetto
CreateVectorIndexIfNotExistsnel file VCoreMongoService.cs crea un indice vettoriale, che consente di eseguire ricerche di somiglianza vettoriale.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; } }Selezionare l'opzione Ask AI Assistant (cercare una ricetta per nome o descrizione o porre una domanda) nell'applicazione per eseguire una query utente.
La query utente viene convertita in un incorporamento usando il servizio Open AI e il modello di incorporamento. L'incorporamento viene quindi inviato ad Azure Cosmos DB per MongoDB e viene usato per eseguire una ricerca vettoriale. Il
VectorSearchAsyncmetodo nel file VCoreMongoService.cs esegue una ricerca vettoriale per trovare vettori vicini al vettore fornito e restituisce un elenco di documenti da Azure Cosmos DB per 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; } }Il
GetChatCompletionAsyncmetodo genera una risposta di completamento della chat migliorata in base alla richiesta dell'utente e ai risultati della ricerca vettoriale correlati.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'app utilizza anche la progettazione dei prompt per garantire che il servizio Open AI rispetti i limiti e formatti la risposta per le ricette fornite.
//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.";