Not
Åtkomst till denna sida kräver auktorisation. Du kan prova att logga in eller byta katalog.
Åtkomst till denna sida kräver auktorisation. Du kan prova att byta katalog.
Den här självstudien utforskar integreringen av RAG-mönstret med hjälp av OpenAI-modeller och vektorsökningsfunktioner i en .NET-app. Exempelprogrammet utför vektorsökningar på anpassade data som lagras i Azure Cosmos DB för MongoDB och förfinar svaren ytterligare med generativa AI-modeller, till exempel GPT-35 och GPT-4. I de avsnitt som följer konfigurerar du ett exempelprogram och utforskar viktiga kodexempel som visar dessa begrepp.
Förutsättningar
- .NET 8.0
- Ett Azure-konto
- En Azure Cosmos DB for MongoDB vCore-tjänst
- En Azure Open AI-tjänst
- Distribuera
text-embedding-ada-002modell för inbäddningar - Distribuera
gpt-35-turbo-modellen för chattkompletteringar
- Distribuera
Appöversikt
Med Cosmos Receptguide-appen kan du utföra vektor- och AI-drivna sökningar mot en uppsättning receptdata. Du kan söka direkt efter tillgängliga recept eller uppmana appen med ingrediensnamn att hitta relaterade recept. Appen och avsnitten i förväg vägleder dig genom följande arbetsflöde för att demonstrera den här typen av funktioner:
Ladda upp exempeldata till en Azure Cosmos DB for MongoDB-databas.
Skapa inbäddningar och ett vektorindex för uppladdade exempeldata med hjälp av Azure OpenAI-modellen
text-embedding-ada-002.Utför vektorlikhetssökning baserat på användarens uppmaningar.
Använd modellen för Azure OpenAI-slutförande
gpt-35-turboför att skapa mer meningsfulla svar baserat på sökresultatdata.
Get started
Klona följande GitHub-lagringsplats:
git clone https://github.com/microsoft/AzureDataRetrievalAugmentedGenerationSamples.gitÖppna CosmosRecipeGuide.sln-filen i mappen C#/CosmosDB-MongoDBvCore.
I filenappsettings.json ersätter du följande konfigurationsvärden med dina Azure OpenAI- och Azure CosmosDB-värden för 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>"Starta appen genom att trycka på startknappen överst i Visual Studio.
Utforska appen
När du kör appen för första gången ansluter den till Azure Cosmos DB och rapporterar att det inte finns några tillgängliga recept ännu. Följ stegen som visas av appen för att påbörja kärnarbetsflödet.
Välj Ladda upp recept till Cosmos DB och tryck på Retur. Det här kommandot läser JSON-exempelfiler från det lokala projektet och laddar upp dem till Cosmos DB-kontot.
Koden från klassen Utility.cs parsar de lokala JSON-filerna.
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; }Metoden
UpsertVectorAsynci VCoreMongoService.cs-filen laddar upp dokumenten till Azure Cosmos DB för 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; } }Välj Vektorisera recepten och lagra dem i Cosmos DB.
JSON-objekten som laddas upp till Cosmos DB innehåller inte inbäddningar och är därför inte optimerade för RAG via vektorsökning. En inbäddning är en informationstät, numerisk representation av den semantiska innebörden av ett stycke text. Vektorsökningar kan hitta objekt med kontextuellt liknande inbäddningar.
Metoden
GetEmbeddingsAsynci OpenAIService.cs-filen skapar en inbäddning för varje objekt i databasen.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; } }I
CreateVectorIndexIfNotExistsfilen i VCoreMongoService.cs skapas ett vektorindex som gör att du kan utföra vektorlikhetssökningar.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; } }Välj alternativet Fråga AI Assistant (sök efter ett recept efter namn eller beskrivning eller ställ en fråga) i programmet för att köra en användarfråga.
Användarfrågan konverteras till en inbäddning med hjälp av Open AI-tjänsten och inbäddningsmodellen. Inbäddningen skickas sedan till Azure Cosmos DB för MongoDB och används för att utföra en vektorsökning. Metoden
VectorSearchAsynci VCoreMongoService.cs-filen utför en vektorsökning för att hitta vektorer som ligger nära den angivna vektorn och returnerar en lista med dokument från Azure Cosmos DB för 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; } }Metoden
GetChatCompletionAsyncgenererar ett förbättrat svar för chattens slutförande baserat på användarprompten och de relaterade vektorsökresultaten.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; } }Appen använder också prompt engineering för att säkerställa open AI-tjänstens gränser och formaterar svaret för angivna recept.
//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.";