Freigeben über


Schnellstart: Generative Suche (RAG) mit Verwendung von Erdungsdaten aus Azure KI-Suche

In diesem Schnellstart erfahren Sie, wie Sie über Ihre indizierten Inhalte in Azure KI-Suche Abfragen an ein Chatvervollständigungsmodell senden, um eine Sucherfahrung im Unterhaltungsstil zu erhalten. Nachdem Sie Azure OpenAI- und Azure AI Search-Ressourcen im Azure-Portal eingerichtet haben, führen Sie Code aus, um die APIs aufzurufen.

Voraussetzungen

Konfigurieren des Zugriffs

Anforderungen an den Suchendpunkt müssen authentifiziert und autorisiert werden. Sie können für diese Aufgabe API-Schlüssel oder Rollen verwenden. Schlüssel sind für ein Einstieg einfacher, Rollen sind jedoch sicherer. In diesem Schnellstart werden Rollen vorausgesetzt.

Sie richten zwei Clients ein, daher benötigen Sie Berechtigungen für beide Ressourcen.

Azure KI-Suche empfängt die Abfrageanforderung von Ihrem lokalen System. Weisen Sie sich selbst die Rolle Suchindexdatenleser zu, wenn der Beispielindex für Hotels bereits vorhanden ist. Wenn sie nicht vorhanden ist, weisen Sie sich die Rollen Mitwirkender von Suchdienst und Mitwirkender an Suchindexdaten zu, damit Sie den Index erstellen und abfragen können.

Azure OpenAI empfängt die Abfrage und die Suchergebnisse aus Ihrem lokalen System. Weisen Sie sich in Azure OpenAI die Rolle Cognitive Services OpenAI-Benutzer zu.

  1. Melden Sie sich beim Azure-Portal an.

  2. Konfigurieren von Azure KI-Suche für rollenbasierten Zugriff:

    1. Suchen Sie im Azure-Portal nach Ihrem Azure KI-Suchdienst.

    2. Wählen Sie im linken Menü Einstellungen>Schlüsselaus, und wählen Sie dann entweder die Option Rollenbasierte Zugriffssteuerung oder Beides aus.

  3. Zuweisen von Rollen:

    1. Wählen Sie im linken Menü Zugriffssteuerung (IAM) aus.

    2. Wählen Sie in Azure KI-Suche diese Rollen aus, um einen Suchindex zu erstellen, zu laden und abzufragen, und weisen Sie sie dann Ihrer Microsoft Entra ID-Benutzeridentität zu:

      • Mitwirkender an Suchindexdaten
      • Mitwirkender von Suchdienst
    3. Wählen Sie in Azure OpenAI Zugriffssteuerung (IAM) aus, um sich diese Rolle in Azure OpenAI selbst zuzuweisen:

      • Cognitive Services OpenAI-Benutzer

Es kann einige Minuten dauern, bis die Berechtigungen in Kraft treten.

Erstellen eines Index

Ein Suchindex stellt Groundingdaten für das Chatmodell bereit. Wir empfehlen den Index hotels-sample-index, der in Minuten erstellt und auf jeder Suchdienstebene ausgeführt werden kann. Dieser Index wird mit integrierten Beispieldaten erstellt.

  1. Suchen Sie im Azure-Portal nach Ihrem Suchdienst.

  2. Wählen Sie auf der Startseite Übersicht die Option Daten importieren aus, um den Assistenten zu starten.

  3. Wählen Sie auf der Seite Mit Ihren Daten verbinden die Option Beispiele aus der Dropdownliste aus.

  4. Wählen Sie das Beispiel hotels-sample aus.

  5. Wählen Sie auf den restlichen Seiten jeweils Weiter aus, und akzeptieren Sie die Standardwerte.

  6. Nachdem der Index erstellt wurde, wählen Sie im linken Menü Suchverwaltung>Indizes aus, um den Index zu öffnen.

  7. Wählen Sie JSON bearbeiten aus.

  8. Scrollen Sie zum Ende des Indexes, wo Sie Platzhalter für Konstrukte finden, die zu einem Index hinzugefügt werden können.

    "analyzers": [],
    "tokenizers": [],
    "tokenFilters": [],
    "charFilters": [],
    "normalizers": [],
    
  9. Fügen Sie in einer neuen Zeile nach „normalizers“ die folgende semantische Konfiguration ein. In diesem Beispiel wird "defaultConfiguration" angegeben, was für die Ausführung dieses Schnellstarts wichtig ist.

    "semantic":{
       "defaultConfiguration":"semantic-config",
       "configurations":[
          {
             "name":"semantic-config",
             "prioritizedFields":{
                "titleField":{
                   "fieldName":"HotelName"
                },
                "prioritizedContentFields":[
                   {
                      "fieldName":"Description"
                   }
                ],
                "prioritizedKeywordsFields":[
                   {
                      "fieldName":"Category"
                   },
                   {
                      "fieldName":"Tags"
                   }
                ]
             }
          }
       ]
    },
    
  10. Speichern Sie die Änderungen.

  11. Führen Sie die folgende Abfrage im Such-Explorer aus, um den Index zu testen: complimentary breakfast.

    Die Ausgabe sollte etwa folgendem Beispiel entsprechen. Die Ergebnisse, die direkt von der Suchmaschine zurückgegeben werden, bestehen aus Feldern und deren wörtlichen Werten, zusammen mit Metadaten wie einem Suchergebnis und einem Ergebnis für das semantische Ranking sowie einer Beschriftung, wenn Sie den semantischen Sortierer verwenden. Wir haben eine Auswahlanweisung verwendet, um nur die Felder „HotelName“, „Beschreibung“ und „Tags“ zurückzugeben.

    {
    "@odata.count": 18,
    "@search.answers": [],
    "value": [
       {
          "@search.score": 2.2896252,
          "@search.rerankerScore": 2.506816864013672,
          "@search.captions": [
          {
             "text": "Head Wind Resort. Suite. coffee in lobby\r\nfree wifi\r\nview. The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a **complimentary continental breakfast** in the lobby, and free Wi-Fi throughout the hotel..",
             "highlights": ""
          }
          ],
          "HotelName": "Head Wind Resort",
          "Description": "The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a complimentary continental breakfast in the lobby, and free Wi-Fi throughout the hotel.",
          "Tags": [
          "coffee in lobby",
          "free wifi",
          "view"
          ]
       },
       {
          "@search.score": 2.2158256,
          "@search.rerankerScore": 2.288334846496582,
          "@search.captions": [
          {
             "text": "Swan Bird Lake Inn. Budget. continental breakfast\r\nfree wifi\r\n24-hour front desk service. We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins..",
             "highlights": ""
          }
          ],
          "HotelName": "Swan Bird Lake Inn",
          "Description": "We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins.",
          "Tags": [
          "continental breakfast",
          "free wifi",
          "24-hour front desk service"
          ]
       },
       {
          "@search.score": 0.92481667,
          "@search.rerankerScore": 2.221315860748291,
          "@search.captions": [
          {
             "text": "White Mountain Lodge & Suites. Resort and Spa. continental breakfast\r\npool\r\nrestaurant. Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings..",
             "highlights": ""
          }
          ],
          "HotelName": "White Mountain Lodge & Suites",
          "Description": "Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings.",
          "Tags": [
          "continental breakfast",
          "pool",
          "restaurant"
          ]
       },
       . . .
    ]}
    

Abrufen von Dienstendpunkten

In den verbleibenden Abschnitten richten Sie API-Aufrufe für Azure OpenAI und die Azure KI-Suche ein. Rufen Sie die Dienstendpunkte ab, damit Sie sie als Variablen im Code bereitstellen können.

  1. Melden Sie sich beim Azure-Portal an.

  2. Suchen Sie Ihren Suchdienst.

  3. Sie finden die URL auf der Startseite Übersicht. Ein Beispiel für einen Endpunkt ist https://example.search.windows.net.

  4. Suchen Sie Ihren Azure OpenAI-Dienst.

  5. Wählen Sie auf der Startseite Übersicht den Link aus, um die Endpunkte anzuzeigen. Kopieren Sie die URL. Ein Beispiel für einen Endpunkt ist https://example.openai.azure.com/.

Anmelden bei Azure

Sie verwenden Microsoft Entra ID und Rollenzuweisungen für die Verbindung. Stellen Sie sicher, dass Sie bei demselben Mandanten und Abonnement wie Azure KI-Suche und Azure OpenAI angemeldet sind. Sie können die Azure CLI in der Befehlszeile verwenden, um aktuelle Eigenschaften anzuzeigen, sie zu ändern und um sich anzumelden. Weitere Informationen finden Sie unter Herstellen einer Verbindung ohne Schlüssel.

Führen Sie die folgenden Befehle nacheinander aus.

az account show

az account set --subscription <PUT YOUR SUBSCRIPTION ID HERE>

az login --tenant <PUT YOUR TENANT ID HERE>

Sie sollten jetzt von Ihrem lokalen Gerät aus bei Azure angemeldet sein.

Einrichten der .NET-App

Um die folgenden Schritte auszuführen, können Sie entweder die fertige Beispiel-App von GitHub klonen oder die App selbst erstellen.

Klonen der Beispiel-App

So greifen Sie auf die fertige Beispiel-App für diesen Artikel zu:

  1. Klonen Sie das Azure-search-dotnet-samples-Repository von GitHub.

    git clone https://github.com/Azure-Samples/azure-search-dotnet-samples
    
  2. Navigieren Sie in den quickstart-rag Ordner.

  3. Öffnen Sie den quickstart-rag Ordner in Visual Studio Code, oder öffnen Sie die Projektmappendatei mit Visual Studio.

Erstellen der Beispiel-App

Schließen Sie die folgenden Schritte ab, um eine App für eine .NET-Konsole zu erstellen, die sich mit einem KI-Modell verbindet.

  1. Verwenden Sie in einem leeren Verzeichnis auf Ihrem Computer den Befehl dotnet new, um eine neue Konsolen-App zu erstellen:

    dotnet new console -o AISearchRag
    
  2. Wechseln Sie das Verzeichnis in den App-Ordner:

    cd AISearchRag
    
  3. Installieren Sie die erforderlichen Pakete:

    dotnet add package Azure.AI.OpenAI
    dotnet add package Azure.Identity
    dotnet add package Azure.Search.Documents
    
  4. Öffnen Sie die App in Visual Studio Code (oder Ihrem ausgewählten Editor).

    code .
    

Einrichten des Abfrage- und Chatthreads

Im folgenden Beispiel wird veranschaulicht, wie Sie ein minimales RAG-Szenario mit Azure AI Search einrichten, um ein OpenAI-Modell mit kontextbezogenen Ressourcen bereitzustellen, um die generierten Antworten zu verbessern.

  1. Öffnen Sie im minimal-query Projekt des Beispiel-Repositorys die Program.cs Datei, um das erste Beispiel anzuzeigen. Wenn Sie das Projekt selbst erstellt haben, fügen Sie den folgenden Code hinzu, um eine Verbindung mit den Azure AI Search- und Azure OpenAI-Diensten herzustellen und abzufragen.

    Hinweis

    Ersetzen Sie die Platzhalter für den Azure OpenAI-Endpunkt und den Modellnamen sowie den Azure AI Search-Endpunkt und den Indexnamen.

    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Azure.Identity;
    using Azure.Search.Documents;
    using Azure.Search.Documents.Models;
    using Azure.AI.OpenAI;
    using OpenAI.Chat;
    using System.Text.Json;
    using Microsoft.Extensions.Logging;
    
    // Azure resource endpoints and deployment info
    string azureSearchServiceEndpoint = "azure-ai-search-endpoint";
    string azureOpenAIEndpoint = "azure-ai-openai-endpoint";
    string azureDeploymentModel = "azure-ai-deployment-name";
    string indexName = "hotels-sample-index";
    
    // Set up Azure credentials and clients
    var credential = new DefaultAzureCredential();
    var searchClient = new SearchClient(new Uri(azureSearchServiceEndpoint), indexName, credential);
    var openAIClient = new AzureOpenAIClient(new Uri(azureOpenAIEndpoint), credential);
    
    // Prompt template for grounding the LLM response in search results
    string GROUNDED_PROMPT = @"You are a friendly assistant that recommends hotels based on activities and amenities.
        Answer the query using only the sources provided below in a friendly and concise bulleted manner
        Answer ONLY with the facts listed in the list of sources below.
        If there isn't enough information below, say you don't know.
        Do not generate answers that don't use the sources below.
        Query: {0}
        Sources: {1}";
    
    // The user's query
    string query = "Can you recommend a few hotels with complimentary breakfast?";
    
    // Configure search options: top 5 results, select relevant fields
    var options = new SearchOptions { Size = 5 };
    options.Select.Add("Description");
    options.Select.Add("HotelName");
    options.Select.Add("Tags");
    
    // Execute the search
    var searchResults = await searchClient.SearchAsync<SearchDocument>(query, options);
    var sources = new List<string>();
    
    await foreach (var result in searchResults.Value.GetResultsAsync())
    {
        var doc = result.Document;
        // Format each result as: HotelName:Description:Tags
        sources.Add($"{doc["HotelName"]}:{doc["Description"]}:{doc["Tags"]}");
    }
    string sourcesFormatted = string.Join("\n", sources);
    
    // Format the prompt with the query and sources
    string formattedPrompt = string.Format(GROUNDED_PROMPT, query, sourcesFormatted);
    
    // Create a chat client for the specified deployment/model
    ChatClient chatClient = openAIClient.GetChatClient(azureDeploymentModel);
    
    // Send the prompt to the LLM and stream the response
    var chatUpdates = chatClient.CompleteChatStreamingAsync(
        [ new UserChatMessage(formattedPrompt) ]
    );
    
    // Print the streaming response to the console
    await foreach (var chatUpdate in chatUpdates)
    {
        if (chatUpdate.Role.HasValue)
        {
            Console.Write($"{chatUpdate.Role} : ");
        }
        foreach (var contentPart in chatUpdate.ContentUpdate)
        {
            Console.Write(contentPart.Text);
        }
    }
    

    Der vorangehende Code führt Folgendes aus:

    • Durchsucht einen Azure Search-Index nach Hotels, die einer Benutzerabfrage zum kostenlosen Frühstück entsprechen, und ruft Hotelname, Beschreibung und Tags ab.
    • Formatiert die Suchergebnisse in eine strukturierte Liste, die als kontextbezogene Quellen für das generative KI-Modell dienen soll.
    • Erstellt eine Eingabeaufforderung, in der das Azure OpenAI-Modell angewiesen wird, nur die bereitgestellten Quellen zu verwenden.
    • Sendet die Aufforderung an das KI-Modell und streamt die generierte Antwort.
    • Gibt die Antwort der KI auf die Konsole aus, wobei sowohl die Rolle als auch der Inhalt beim Streamen angezeigt werden.
  2. Führen Sie das Projekt aus, um ein grundlegendes RAG-Szenario zu initiieren. Die Ausgabe von Azure OpenAI besteht aus Empfehlungen für mehrere Hotels, z. B. das folgende Beispiel:

    Sure! Here are a few hotels that offer complimentary breakfast:
    
    - **Head Wind Resort**
    - Complimentary continental breakfast in the lobby
    - Free Wi-Fi throughout the hotel
    
    - **Double Sanctuary Resort**
    - Continental breakfast included
    
    - **White Mountain Lodge & Suites**
    - Continental breakfast available
    
    - **Swan Bird Lake Inn**
    - Continental-style breakfast each morning with a variety of food and drinks 
       such as caramel cinnamon rolls, coffee, orange juice, milk, cereal, 
       instant oatmeal, bagels, and muffins
    

Um weiter zu experimentieren, ändern Sie die Abfrage, und führen Sie den letzten Schritt erneut aus, um besser zu verstehen, wie das Modell mit den Groundingdaten funktioniert. Sie können auch den Prompt ändern, um den Ton oder die Struktur der Ausgabe zu ändern.

Problembehandlung

Möglicherweise erhalten Sie beim Testen eine der folgenden Fehler:

  • Verboten: Überprüfen Sie die Azure AI Search-Konfiguration, um sicherzustellen, dass der rollenbasierte Zugriff aktiviert ist.
  • Autorisierungsfehler: Warten Sie einige Minuten, und versuchen Sie es erneut. Es kann mehrere Minuten dauern, bis Rollenzuweisungen betriebsbereit sind.
  • Ressource nicht gefunden: Überprüfen Sie die Ressourcen-URIs, und stellen Sie sicher, dass die API-Version des Chatmodells gültig ist.

Senden einer komplexen RAG-Abfrage

Azure KI-Suche unterstützt komplexe Typen für geschachtelte JSON-Strukturen. Im Hotelbeispielindex ist Address ein Beispiel für einen komplexen Typ, bestehend aus Address.StreetAddress, Address.City, Address.StateProvince, Address.PostalCode und Address.Country. Der Index verfügt auch über eine komplexe Sammlung von Rooms für jedes Hotel. Wenn Ihr Index komplexe Typen aufweist, kann Ihre Abfrage diese Felder bereitstellen, wenn Sie die Ausgabe der Suchergebnisse zuerst in JSON konvertieren und dann das JSON an das Chatmodell übergeben.

  1. Öffnen Sie die complex-query Datei im Program.cs Projekt des Beispiel-Repositorys. Wenn Sie das Projekt selbst erstellt haben, ersetzen Sie den Code durch Folgendes:

    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using Azure.Identity;
    using Azure.Search.Documents;
    using Azure.Search.Documents.Models;
    using Azure.AI.OpenAI;
    using OpenAI.Chat;
    using System.Text.Json;
    using Microsoft.Extensions.Logging;
    
    // Azure resource endpoints and deployment info
    string azureSearchServiceEndpoint = "azure-ai-search-endpoint";
    string azureOpenAIEndpoint = "azure-ai-openai-endpoint";
    string azureDeploymentModel = "azure-ai-deployment-name";
    string indexName = "hotels-sample-index";
    
    // Set up Azure credentials and clients
    var credential = new DefaultAzureCredential();
    var searchClient = new SearchClient(new Uri(azureSearchServiceEndpoint), indexName, credential);
    var openAIClient = new AzureOpenAIClient(new Uri(azureOpenAIEndpoint), credential);
    
    // Prompt template for the OpenAI model
    string groundedPrompt =
        @"You are a friendly assistant that recommends hotels based on activities and amenities.
        Answer the query using only the sources provided below in a friendly and concise bulleted manner.
        Answer ONLY with the facts listed in the list of sources below.
        If there isn't enough information below, say you don't know.
        Do not generate answers that don't use the sources below.
        Query: {0}
        Sources: {1}";
    
    // The user query and fields to select from search
    var query = "Can you recommend a few hotels that offer complimentary breakfast? Tell me their description, address, tags, and the rate for one room that sleeps 4 people.";
    var selectedFields = new[] { "HotelName", "Description", "Address", "Rooms", "Tags" };
    
    // Configure search options
    var options = new SearchOptions { Size = 5 };
    foreach (var field in selectedFields)
    {
        options.Select.Add(field);
    }
    
    // Run Azure Cognitive Search
    var searchResults = await searchClient.SearchAsync<SearchDocument>(query, options);
    
    // Filter and format search results
    var sourcesFiltered = new List<Dictionary<string, object>>();
    await foreach (var result in searchResults.Value.GetResultsAsync())
    {
        sourcesFiltered.Add(
            selectedFields
                .Where(f => result.Document.TryGetValue(f, out _))
                .ToDictionary(f => f, f => result.Document[f])
        );
    }
    var sourcesFormatted = string.Join("\n", sourcesFiltered.ConvertAll(source => JsonSerializer.Serialize(source)));
    
    // Format the prompt for OpenAI
    string formattedPrompt = string.Format(groundedPrompt, query, sourcesFormatted);
    
    // Get a chat client for the OpenAI deployment
    ChatClient chatClient = openAIClient.GetChatClient(azureDeploymentModel);
    
    // Send the prompt to Azure OpenAI and stream the response
    var chatUpdates = chatClient.CompleteChatStreamingAsync(
        new[] { new UserChatMessage(formattedPrompt) }
    );
    
    // Output the streamed chat response
    await foreach (var chatUpdate in chatUpdates)
    {
        if (chatUpdate.Role.HasValue)
        {
            Console.Write($"{chatUpdate.Role} : ");
        }
        foreach (var contentPart in chatUpdate.ContentUpdate)
        {
            Console.Write(contentPart.Text);
        }
    }
    
  2. Führen Sie das Projekt aus, um ein grundlegendes RAG-Szenario zu initiieren. Die Ausgabe von Azure OpenAI besteht aus Empfehlungen für mehrere Hotels, z. B. das folgende Beispiel:

    1. **Double Sanctuary Resort**
       - **Description**: 5-star luxury hotel with the biggest rooms in the city. Recognized as the #1 hotel in the area by Traveler magazine. Features include free WiFi, flexible check-in/out, a fitness center, and in-room espresso.
       - **Address**: 2211 Elliott Ave, Seattle, WA, 98121, USA
       - **Tags**: view, pool, restaurant, bar, continental breakfast
       - **Room Rate for 4 People**: 
         - Suite, 2 Queen Beds: $254.99 per night
    
    2. **Starlight Suites**
       - **Description**: Spacious all-suite hotel with complimentary airport shuttle and WiFi. Facilities include an indoor/outdoor pool, fitness center, and Florida Green certification. Complimentary coffee and HDTV are also available.
       - **Address**: 19575 Biscayne Blvd, Aventura, FL, 33180, USA
       - **Tags**: pool, coffee in lobby, free wifi
       - **Room Rate for 4 People**:
         - Suite, 2 Queen Beds (Cityside): $231.99 per night
         - Deluxe Room, 2 Queen Beds (Waterfront View): $148.99 per night
    
    3. **Good Business Hotel**
       - **Description**: Located one mile from the airport with free WiFi, an outdoor pool, and a complimentary airport shuttle. Close proximity to Lake Lanier and downtown. The business center includes printers, a copy machine, fax, and a work area.
       - **Address**: 4400 Ashford Dunwoody Rd NE, Atlanta, GA, 30346, USA
       - **Tags**: pool, continental breakfast, free parking
       - **Room Rate for 4 People**:
         - Budget Room, 2 Queen Beds (Amenities): $60.99 per night
         - Deluxe Room, 2 Queen Beds (Amenities): $139.99 per night
    

Problembehandlung

Wenn beim Debuggen Ausgabemeldungen im Zusammenhang mit ManagedIdentityCredential und Tokenerwerbsfehlern angezeigt werden, kann es sein, dass Sie über mehrere Mandanten verfügen und Ihre Azure-Anmeldung einen Mandanten verwendet, der nicht über Ihren Suchdienst verfügt. Um Ihre Mandanten-ID zu erhalten, suchen Sie im Azure-Portal nach „Mandanteneigenschaften“, oder führen Sie az login tenant list aus.

Wenn Sie über eine Mandanten-ID verfügen, führen Sie an einer Eingabeaufforderung az login --tenant <YOUR-TENANT-ID> aus, und führen Sie dann das Skript erneut aus.

Sie können auch Fehler in Ihrem Code protokollieren, indem Sie eine Instanz von ILogger:

using var loggerFactory = LoggerFactory.Create(builder =>
{
   builder.AddConsole();
});
ILogger logger = loggerFactory.CreateLogger<Program>();

Bereinigung

Wenn Sie in Ihrem eigenen Abonnement arbeiten, sollten Sie sich am Ende eines Projekts überlegen, ob Sie die erstellten Ressourcen noch benötigen. Ressourcen, die weiterhin ausgeführt werden, können Geld kosten. Sie können entweder einzelne Ressourcen oder aber die Ressourcengruppe löschen, um den gesamten Ressourcensatz zu entfernen.

Ressourcen können im Azure-Portal über den Link Alle Ressourcen oder Ressourcengruppen im linken Navigationsbereich gesucht und verwaltet werden.

Voraussetzungen

Konfigurieren des Zugriffs

Anforderungen an den Suchendpunkt müssen authentifiziert und autorisiert werden. Sie können für diese Aufgabe API-Schlüssel oder Rollen verwenden. Schlüssel sind für ein Einstieg einfacher, Rollen sind jedoch sicherer. In diesem Schnellstart werden Rollen vorausgesetzt.

Sie richten zwei Clients ein, daher benötigen Sie Berechtigungen für beide Ressourcen.

Azure KI-Suche empfängt die Abfrageanforderung von Ihrem lokalen System. Weisen Sie sich selbst die Rolle Suchindexdatenleser zu, wenn der Beispielindex für Hotels bereits vorhanden ist. Wenn sie nicht vorhanden ist, weisen Sie sich die Rollen Mitwirkender von Suchdienst und Mitwirkender an Suchindexdaten zu, damit Sie den Index erstellen und abfragen können.

Azure OpenAI empfängt die Abfrage und die Suchergebnisse von Ihrem lokalen System. Weisen Sie sich in Azure OpenAI die Rolle Cognitive Services OpenAI-Benutzer zu.

  1. Melden Sie sich beim Azure-Portal an.

  2. Konfigurieren von Azure KI-Suche für rollenbasierten Zugriff:

    1. Suchen Sie im Azure-Portal nach Ihrem Azure KI-Suchdienst.

    2. Wählen Sie im linken Menü Einstellungen>Schlüssel aus, und wählen Sie dann entweder die Option Rollenbasierte Zugriffssteuerung oder Beides aus.

  3. Zuweisen von Rollen:

    1. Wählen Sie im linken Menü Zugriffssteuerung (IAM) aus.

    2. Wählen Sie in Azure KI-Suche diese Rollen aus, um einen Suchindex zu erstellen, zu laden und abzufragen, und weisen Sie sie dann Ihrer Microsoft Entra ID-Benutzeridentität zu:

      • Mitwirkender an Suchindexdaten
      • Mitwirkender von Suchdienst
    3. Wählen Sie in Azure OpenAI Zugriffssteuerung (IAM) aus, um sich diese Rolle in Azure OpenAI selbst zuzuweisen:

      • Cognitive Services OpenAI-Benutzer

Es kann einige Minuten dauern, bis die Berechtigungen in Kraft treten.

Erstellen eines Index

Ein Suchindex stellt Groundingdaten für das Chatmodell bereit. Wir empfehlen den Index hotels-sample-index, den Sie in wenigen Minuten erstellen, und der auf jeder Suchdienstebene ausgeführt werden kann. Dieser Index verwendet integrierte Beispieldaten.

  1. Suchen Sie im Azure-Portal nach Ihrem Suchdienst.

  2. Wählen Sie auf der Startseite Übersicht die Option Daten importieren aus, um den Assistenten zu starten.

  3. Wählen Sie auf der Seite Mit Ihren Daten verbinden die Option Beispiele aus der Dropdownliste aus.

  4. Wählen Sie das Beispiel hotels-sample aus.

  5. Wählen Sie auf den restlichen Seiten jeweils Weiter aus, und akzeptieren Sie die Standardwerte.

  6. Nachdem der Index erstellt wurde, wählen Sie im linken Menü Suchverwaltung>Indizes aus, um den Index zu öffnen.

  7. Wählen Sie JSON bearbeiten aus.

  8. Scrollen Sie zum Ende des Indexes, wo Sie Platzhalter für Konstrukte finden, die Sie zu einem Index hinzufügen können.

    "analyzers": [],
    "tokenizers": [],
    "tokenFilters": [],
    "charFilters": [],
    "normalizers": [],
    
  9. Fügen Sie in einer neuen Zeile nach „normalizers“ die folgende semantische Konfiguration ein. In diesem Beispiel wird "defaultConfiguration" angegeben, was für die Ausführung dieses Schnellstarts wichtig ist.

    "semantic":{
       "defaultConfiguration":"semantic-config",
       "configurations":[
          {
             "name":"semantic-config",
             "prioritizedFields":{
                "titleField":{
                   "fieldName":"HotelName"
                },
                "prioritizedContentFields":[
                   {
                      "fieldName":"Description"
                   }
                ],
                "prioritizedKeywordsFields":[
                   {
                      "fieldName":"Category"
                   },
                   {
                      "fieldName":"Tags"
                   }
                ]
             }
          }
       ]
    },
    
  10. Speichern Sie die Änderungen.

  11. Führen Sie die folgende Abfrage im Such-Explorer aus, um den Index zu testen: complimentary breakfast.

    Die Ausgabe sollte in etwa wie im folgenden Beispiel aussehen. Die Ergebnisse, die direkt von der Suchmaschine zurückgegeben werden, bestehen aus Feldern und deren wörtlichen Werten, zusammen mit Metadaten wie einem Suchergebnis und einem Ergebnis für das semantische Ranking sowie einer Beschriftung, wenn Sie den semantischen Sortierer verwenden. Wir haben eine Auswahlanweisung verwendet, um nur die Felder „HotelName“, „Beschreibung“ und „Tags“ zurückzugeben.

    {
    "@odata.count": 18,
    "@search.answers": [],
    "value": [
       {
          "@search.score": 2.2896252,
          "@search.rerankerScore": 2.506816864013672,
          "@search.captions": [
          {
             "text": "Head Wind Resort. Suite. coffee in lobby\r\nfree wifi\r\nview. The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a **complimentary continental breakfast** in the lobby, and free Wi-Fi throughout the hotel..",
             "highlights": ""
          }
          ],
          "HotelName": "Head Wind Resort",
          "Description": "The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a complimentary continental breakfast in the lobby, and free Wi-Fi throughout the hotel.",
          "Tags": [
          "coffee in lobby",
          "free wifi",
          "view"
          ]
       },
       {
          "@search.score": 2.2158256,
          "@search.rerankerScore": 2.288334846496582,
          "@search.captions": [
          {
             "text": "Swan Bird Lake Inn. Budget. continental breakfast\r\nfree wifi\r\n24-hour front desk service. We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins..",
             "highlights": ""
          }
          ],
          "HotelName": "Swan Bird Lake Inn",
          "Description": "We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins.",
          "Tags": [
          "continental breakfast",
          "free wifi",
          "24-hour front desk service"
          ]
       },
       {
          "@search.score": 0.92481667,
          "@search.rerankerScore": 2.221315860748291,
          "@search.captions": [
          {
             "text": "White Mountain Lodge & Suites. Resort and Spa. continental breakfast\r\npool\r\nrestaurant. Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings..",
             "highlights": ""
          }
          ],
          "HotelName": "White Mountain Lodge & Suites",
          "Description": "Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings.",
          "Tags": [
          "continental breakfast",
          "pool",
          "restaurant"
          ]
       },
       . . .
    ]}
    

Abrufen von Dienstendpunkten

In den folgenden Abschnitten richten Sie API-Aufrufe für Azure OpenAI und die Azure KI-Suche ein. Rufen Sie die Dienstendpunkte ab, damit Sie sie als Variablen im Code bereitstellen können.

  1. Melden Sie sich beim Azure-Portal an.

  2. Suchen Sie Ihren Suchdienst.

  3. Sie finden die URL auf der Startseite Übersicht. Ein Beispiel für einen Endpunkt ist https://example.search.windows.net.

  4. Suchen Sie Ihren Azure OpenAI-Dienst.

  5. Wählen Sie auf der Startseite Übersicht den Link aus, um die Endpunkte anzuzeigen. Kopieren Sie die URL. Ein Beispiel für einen Endpunkt ist https://example.openai.azure.com/.

Einrichten von Umgebungsvariablen für die lokale Entwicklung

Definieren Sie Umgebungsvariablen mithilfe der folgenden Befehle. Ersetzen Sie die Platzhalter durch Ihre tatsächlichen Werte.

export AZURE_SEARCH_ENDPOINT=<YOUR AZURE AI SEARCH ENDPOINT>
export AZURE_SEARCH_INDEX_NAME=hotels-sample-index
export AZURE_OPENAI_ENDPOINT=<YOUR AZURE OPENAI ENDPOINT>
export AZURE_DEPLOYMENT_MODEL=<YOUR DEPLOYMENT NAME>

Anmelden bei Azure

Sie verwenden Microsoft Entra ID und Rollenzuweisungen für die Verbindung. Stellen Sie sicher, dass Sie bei demselben Mandanten und Abonnement wie Azure KI-Suche und Azure OpenAI angemeldet sind. Sie können die Azure CLI in der Befehlszeile verwenden, um aktuelle Eigenschaften anzuzeigen, sie zu ändern und um sich anzumelden. Weitere Informationen finden Sie unter Herstellen einer Verbindung ohne Schlüssel.

Führen Sie die folgenden Befehle nacheinander aus.

az account show

az account set --subscription <PUT YOUR SUBSCRIPTION ID HERE>

az login --tenant <PUT YOUR TENANT ID HERE>

Sie sind jetzt über Ihr lokales Gerät bei Azure angemeldet.

Einrichten des Java-Projekts

Richten Sie ein Maven-Projekt mit den erforderlichen Abhängigkeiten ein.

  1. Erstellen Sie ein neues Verzeichnis, und navigieren Sie dorthin:

    mkdir rag-quickstart && cd rag-quickstart
    
  2. Erstellen Sie eine Maven-Projektstruktur:

    mkdir -p src/main/java/com/example/rag
    
  3. Erstellen Sie die Datei pom.xml mit folgendem Inhalt:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
             http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.example.rag</groupId>
        <artifactId>rag-quickstart</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <maven.compiler.source>21</maven.compiler.source>
            <maven.compiler.target>21</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>com.azure</groupId>
                <artifactId>azure-search-documents</artifactId>
                <version>11.7.8</version>
            </dependency>
            <dependency>
                <groupId>com.azure</groupId>
                <artifactId>azure-identity</artifactId>
                <version>1.16.3</version>
            </dependency>
            <dependency>
                <groupId>com.azure</groupId>
                <artifactId>azure-ai-openai</artifactId>
                <version>1.0.0-beta.16</version>
            </dependency>
        </dependencies>
    </project>
    

Einrichten von Abfrage- und Chatthreads

Erstellen Sie ein Abfrageskript, das den Azure AI Search-Index und das Chatmodell verwendet, um Antworten basierend auf Erdungsdaten zu generieren. Die folgenden Schritte führen Sie durch das Einrichten des Abfrageskripts.

  1. Erstellen Sie mithilfe des folgenden Codes eine Query.java-Datei im Verzeichnis src/main/java/com/example/rag:

    package com.example.rag;
    
    import com.azure.ai.openai.OpenAIClient;
    import com.azure.ai.openai.OpenAIClientBuilder;
    import com.azure.ai.openai.models.ChatCompletions;
    import com.azure.ai.openai.models.ChatCompletionsOptions;
    import com.azure.ai.openai.models.ChatRequestSystemMessage;
    import com.azure.ai.openai.models.ChatRequestUserMessage;
    import com.azure.identity.DefaultAzureCredentialBuilder;
    import com.azure.search.documents.SearchClient;
    import com.azure.search.documents.SearchClientBuilder;
    import com.azure.search.documents.models.SearchOptions;
    import com.azure.search.documents.models.SearchResult;
    
    import java.util.List;
    
    public class Query {
        private static SearchClient getSearchClient() {
            String searchEndpoint = System.getenv("AZURE_SEARCH_ENDPOINT");
            String searchIndex = System.getenv("AZURE_SEARCH_INDEX_NAME");
    
            return new SearchClientBuilder()
                    .endpoint(searchEndpoint)
                    .indexName(searchIndex)
                    .credential(new DefaultAzureCredentialBuilder().build())
                    .buildClient();
        }
    
        private static OpenAIClient getOpenAIClient() {
            String openaiEndpoint = System.getenv("AZURE_OPENAI_ENDPOINT");
    
            return new OpenAIClientBuilder()
                    .endpoint(openaiEndpoint)
                    .credential(new DefaultAzureCredentialBuilder().build())
                    .buildClient();
        }
    
        private static List<SearchResult> searchDocuments(
            SearchClient searchClient, String query) {
            var searchOptions = new SearchOptions()
                    .setTop(5)
                    .setQueryType(com.azure.search.documents.models.QueryType.SEMANTIC)
                    .setSemanticSearchOptions(new com.azure.search.documents.models.SemanticSearchOptions()
                            .setSemanticConfigurationName("semantic-config"))
                    .setSelect("HotelName", "Description", "Tags");
    
            return searchClient.search(query, searchOptions, null)
                    .stream()
                    .limit(5)
                    .toList();
        }
    
        private static String queryOpenAI(OpenAIClient openAIClient,
            String userQuery, List<SearchResult> sources) {
            String deploymentModel = System.getenv("AZURE_DEPLOYMENT_MODEL");
    
            String sourcesText = sources.stream()
                    .map(source -> source.getDocument(Object.class).toString())
                    .collect(java.util.stream.Collectors.joining("\n"));
    
            var messages = List.of(
                    new ChatRequestSystemMessage("""
                        You are an assistant that recommends hotels based on 
                        search results."""),
                    new ChatRequestUserMessage("""
                        Can you recommend a few hotels that offer %s?
                        Here are the search results:
                        %s""".formatted(userQuery, sourcesText))
            );
    
            var chatOptions = new ChatCompletionsOptions(messages);
            ChatCompletions response = openAIClient.getChatCompletions(deploymentModel, chatOptions);
    
            return response.getChoices().get(0).getMessage().getContent();
        }
    
        public static void main(String[] args) {
            SearchClient searchClient = getSearchClient();
            OpenAIClient openAIClient = getOpenAIClient();
    
            String userQuery = "complimentary breakfast";
            List<SearchResult> sources = searchDocuments(searchClient, userQuery);
            String response = queryOpenAI(openAIClient, userQuery, sources);
    
            System.out.println(response);
            System.exit(0);
        }
    }
    

    Der vorangehende Code führt die folgenden Schritte aus:

    • Er lädt mithilfe von System.getenv. Umgebungsvariablen.
    • Er konfiguriert Azure KI-Suche- und Azure OpenAI-Clients mithilfe rollenbasierter Authentifizierung.
    • Er fragt Azure KI-Suche mithilfe der semantischen Suche nach Hotels mit kostenlosem Frühstück ab.
    • Er sendet die Suchergebnisse als Kontext für einen Chatvervollständigung an Azure OpenAI.
    • Er druckt die Antwort des Modells.
  2. Führen Sie den folgenden Befehl in einem Terminal aus, um das Abfrageskript auszuführen:

    mvn compile exec:java -Dexec.mainClass="com.example.rag.Query"
    
  3. Sehen Sie sich die Ausgabe an, die aus Empfehlungen für mehrere Hotels besteht. Hier sehen Sie ein Beispiel für eine mögliche Ausgabe:

    Sure! Here are a few hotels that offer complimentary breakfast:
    
    - **Head Wind Resort**
    - Complimentary continental breakfast in the lobby
    - Free Wi-Fi throughout the hotel
    
    - **Double Sanctuary Resort**
    - Continental breakfast included
    
    - **White Mountain Lodge & Suites**
    - Continental breakfast available
    
    - **Swan Bird Lake Inn**
    - Continental-style breakfast each morning with a variety of food and drinks 
        such as caramel cinnamon rolls, coffee, orange juice, milk, cereal, 
        instant oatmeal, bagels, and muffins
    

Problembehandlung

Wenn Sie eine Verboten-Fehlermeldung erhalten, überprüfen Sie Ihre Azure KI-Suche-Konfiguration, um sicherzustellen, dass Sie den rollenbasierten Zugriff aktiviert haben.

Wenn Sie die Fehlermeldung Autorisierung fehlgeschlagen erhalten, warten Sie einige Minuten, und versuchen Sie es erneut. Es kann mehrere Minuten dauern, bis Rollenzuweisungen betriebsbereit sind.

Wenn sie die Fehlermeldung Ressource nicht gefunden erhalten, überprüfen Sie die Ressourcen-URIs, und stellen Sie sicher, dass die API-Version des Chatmodells gültig ist.

Ändern Sie andernfalls um weiter zu experimentieren die Abfrage, und führen Sie den letzten Schritt erneut aus, um besser zu verstehen, wie das Modell mit den Groundingdaten funktioniert.

Sie können auch den Prompt ändern, um den Ton oder die Struktur der Ausgabe zu ändern.

Sie können die Abfrage auch ohne semantische Rangfolge ausprobieren, indem Sie die Optionen für die semantische Suche im Schritt „Abfrageparameter“ entfernen. Die semantische Rangfolge kann die Relevanz von Abfrageergebnissen und die Fähigkeit des LLMs, nützliche Informationen zurückzugeben, spürbar verbessern. Durch Experimentieren können Sie herausfinden, ob es für Ihre Inhalte einen Unterschied macht.

Senden einer komplexen RAG-Abfrage

Azure KI-Suche unterstützt komplexe Typen für geschachtelte JSON-Strukturen. Im Hotelbeispielindex ist Address ein Beispiel für einen komplexen Typ, bestehend aus Address.StreetAddress, Address.City, Address.StateProvince, Address.PostalCode und Address.Country. Der Index verfügt auch über eine komplexe Sammlung von Rooms für jedes Hotel.

Wenn Ihr Index komplexe Typen aufweist, ändern Sie Die Aufforderung so, dass Formatierungsanweisungen eingeschlossen werden:

Can you recommend a few hotels that offer complimentary breakfast? 
Tell me their description, address, tags, and the rate for one room that sleeps 4 people.
  1. Erstellen Sie eine neue Datei QueryComplex.java im src/main/java/com/example/rag Verzeichnis.

  2. Kopieren Sie den folgenden Code in die Datei:

    package com.example.rag;
    
    import com.azure.ai.openai.OpenAIClient;
    import com.azure.ai.openai.OpenAIClientBuilder;
    import com.azure.ai.openai.models.ChatCompletions;
    import com.azure.ai.openai.models.ChatCompletionsOptions;
    import com.azure.ai.openai.models.ChatRequestSystemMessage;
    import com.azure.ai.openai.models.ChatRequestUserMessage;
    import com.azure.identity.DefaultAzureCredentialBuilder;
    import com.azure.search.documents.SearchClient;
    import com.azure.search.documents.SearchClientBuilder;
    import com.azure.search.documents.models.SearchOptions;
    import com.azure.search.documents.models.SearchResult;
    
    import java.util.List;
    
    public class QueryComplex {
        private static SearchClient getSearchClient() {
            String searchEndpoint = System.getenv("AZURE_SEARCH_ENDPOINT");
            String searchIndex = System.getenv("AZURE_SEARCH_INDEX_NAME");
    
            return new SearchClientBuilder()
                    .endpoint(searchEndpoint)
                    .indexName(searchIndex)
                    .credential(new DefaultAzureCredentialBuilder().build())
                    .buildClient();
        }
    
        private static OpenAIClient getOpenAIClient() {
            String openaiEndpoint = System.getenv("AZURE_OPENAI_ENDPOINT");
    
            return new OpenAIClientBuilder()
                    .endpoint(openaiEndpoint)
                    .credential(new DefaultAzureCredentialBuilder().build())
                    .buildClient();
        }
    
        private static List<SearchResult> searchDocuments(
            SearchClient searchClient, String query) {
            var searchOptions = new SearchOptions()
                    .setTop(5)
                    .setQueryType(com.azure.search.documents.models.QueryType.SEMANTIC)
                    .setSemanticSearchOptions(new com.azure.search.documents.models.SemanticSearchOptions()
                            .setSemanticConfigurationName("semantic-config"))
                    .setSelect("HotelName", "Description", "Address", "Rooms", "Tags");
    
            return searchClient.search(query, searchOptions, null)
                    .stream()
                    .limit(5)
                    .toList();
        }
    
        private static String queryOpenAI(OpenAIClient openAIClient,
            String userQuery, List<SearchResult> sources) {
            String deploymentModel = System.getenv("AZURE_DEPLOYMENT_MODEL");
    
            String sourcesText = sources.stream()
                    .map(source -> source.getDocument(Object.class).toString())
                    .collect(java.util.stream.Collectors.joining("\n"));
    
            var messages = List.of(
                    new ChatRequestSystemMessage("""
                        You are an assistant that recommends hotels based on 
                        search results."""),
                    new ChatRequestUserMessage("""
                        Can you recommend a few hotels that offer %s?
                        Tell me their description, address, tags,
                        and the rate for one room that sleeps 4 people.
                        Here are the search results:
                        %s""".formatted(userQuery, sourcesText))
            );
    
            var chatOptions = new ChatCompletionsOptions(messages);
            ChatCompletions response = openAIClient.getChatCompletions(
                deploymentModel, chatOptions);
    
            return response.getChoices().get(0).getMessage().getContent();
        }
    
        public static void main(String[] args) {
            SearchClient searchClient = getSearchClient();
            OpenAIClient openAIClient = getOpenAIClient();
    
            String userQuery = "complimentary breakfast";
            List<SearchResult> sources = searchDocuments(searchClient, userQuery);
            String response = queryOpenAI(openAIClient, userQuery, sources);
    
            System.out.println(response);
            System.exit(0);
        }
    }
    
  3. Führen Sie den folgenden Befehl in einem Terminal aus, um das Abfrageskript auszuführen:

    mvn compile exec:java -Dexec.mainClass="com.example.rag.QueryComplex"
    
  4. Zeigen Sie die Ausgabe von Azure OpenAI an, und sie fügt Inhalte aus komplexen Typen hinzu.

    Here are a few hotels that offer complimentary breakfast and have rooms that sleep 4 people:
    
    1. **Head Wind Resort**
       - **Description:** The best of old town hospitality combined with views of the river and 
       cool breezes off the prairie. Enjoy a complimentary continental breakfast in the lobby, 
       and free Wi-Fi throughout the hotel.
       - **Address:** 7633 E 63rd Pl, Tulsa, OK 74133, USA
       - **Tags:** Coffee in lobby, free Wi-Fi, view
       - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99
    
    2. **Double Sanctuary Resort**
       - **Description:** 5-star Luxury Hotel - Biggest Rooms in the city. #1 Hotel in the area 
       listed by Traveler magazine. Free WiFi, Flexible check in/out, Fitness Center & espresso 
       in room. Offers continental breakfast.
       - **Address:** 2211 Elliott Ave, Seattle, WA 98121, USA
       - **Tags:** View, pool, restaurant, bar, continental breakfast
       - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99
    
    3. **Swan Bird Lake Inn**
       - **Description:** Continental-style breakfast featuring a variety of food and drinks. 
       Locally made caramel cinnamon rolls are a favorite.
       - **Address:** 1 Memorial Dr, Cambridge, MA 02142, USA
       - **Tags:** Continental breakfast, free Wi-Fi, 24-hour front desk service
       - **Room for 4:** Budget Room, 2 Queen Beds (City View) - $85.99
    
    4. **Gastronomic Landscape Hotel**
       - **Description:** Known for its culinary excellence under the management of William Dough, 
       offers continental breakfast.
       - **Address:** 3393 Peachtree Rd, Atlanta, GA 30326, USA
       - **Tags:** Restaurant, bar, continental breakfast
       - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $66.99
    ...
       - **Tags:** Pool, continental breakfast, free parking
       - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $60.99
    
    Enjoy your stay! Let me know if you need any more information.
    

Problembehandlung

Um Azure SDK-Fehler zu debuggen, aktivieren Sie die Protokollierung, indem Sie die folgende Abhängigkeit zu pom.xml hinzufügen:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>2.0.7</version>
</dependency>

Legen Sie dann beim Ausführen der Anwendung die folgenden Systemeigenschaften fest:

mvn compile exec:java -Dexec.mainClass="com.example.rag.Query" \
    -Dorg.slf4j.simpleLogger.defaultLogLevel=debug

Diese Konfiguration ermöglicht eine detaillierte Protokollierung für das Azure SDK, wodurch Sie Probleme mit der Authentifizierung, der Netzwerkkonnektivität sowie andere Probleme identifizieren können.

Führen Sie das Abfrageskript erneut aus. Sie sollten nun Informationsanweisungen der SDKs in der Ausgabe sehen, die weitere Details zu möglichen Problemen bereitstellen.

Wenn Sie Ausgabemeldungen im Zusammenhang mit ManagedIdentityCredential und dem fehlgeschlagenen Token-Erwerb sehen, könnte es sein, dass Sie mehrere Mandanten haben und Ihre Azure-Anmeldung einen Mandanten verwendet, der nicht über Ihren Suchdienst verfügt. Um Ihre Mandanten-ID zu erhalten, suchen Sie im Azure-Portal nach „Mandanteneigenschaften“, oder führen Sie az login tenant list aus.

Nachdem Sie die Mandanten-ID erhalten haben, führen Sie an einer Eingabeaufforderung az login --tenant <YOUR-TENANT-ID> aus. Führen Sie dann das Skript erneut aus.

Bereinigung

Wenn Sie in Ihrem eigenen Abonnement arbeiten, sollten Sie am Ende eines Projekts überprüfen, ob Sie die erstellten Ressourcen noch benötigen. Ressourcen, die weiterhin ausgeführt werden, können Geld kosten. Sie können entweder einzelne Ressourcen oder aber die Ressourcengruppe löschen, um den gesamten Ressourcensatz zu entfernen.

Ressourcen können im Azure-Portal über den Link Alle Ressourcen oder Ressourcengruppen im linken Navigationsbereich gesucht und verwaltet werden.

Voraussetzungen

Konfigurieren des Zugriffs

Anforderungen an den Suchendpunkt müssen authentifiziert und autorisiert werden. Sie können für diese Aufgabe API-Schlüssel oder Rollen verwenden. Schlüssel sind für ein Einstieg einfacher, Rollen sind jedoch sicherer. In diesem Schnellstart werden Rollen vorausgesetzt.

Sie richten zwei Clients ein, daher benötigen Sie Berechtigungen für beide Ressourcen.

Azure KI-Suche empfängt die Abfrageanforderung von Ihrem lokalen System. Weisen Sie sich selbst die Rolle Suchindexdatenleser zu, wenn der Beispielindex für Hotels bereits vorhanden ist. Wenn sie nicht vorhanden ist, weisen Sie sich die Rollen Mitwirkender von Suchdienst und Mitwirkender an Suchindexdaten zu, damit Sie den Index erstellen und abfragen können.

Azure OpenAI empfängt die Abfrage und die Suchergebnisse aus Ihrem lokalen System. Weisen Sie sich in Azure OpenAI die Rolle Cognitive Services OpenAI-Benutzer zu.

  1. Melden Sie sich beim Azure-Portal an.

  2. Konfigurieren von Azure KI-Suche für rollenbasierten Zugriff:

    1. Suchen Sie im Azure-Portal nach Ihrem Azure KI-Suchdienst.

    2. Wählen Sie im linken Menü Einstellungen>Schlüsselaus, und wählen Sie dann entweder die Option Rollenbasierte Zugriffssteuerung oder Beides aus.

  3. Zuweisen von Rollen:

    1. Wählen Sie im linken Menü Zugriffssteuerung (IAM) aus.

    2. Wählen Sie in Azure KI-Suche diese Rollen aus, um einen Suchindex zu erstellen, zu laden und abzufragen, und weisen Sie sie dann Ihrer Microsoft Entra ID-Benutzeridentität zu:

      • Mitwirkender an Suchindexdaten
      • Mitwirkender von Suchdienst
    3. Wählen Sie in Azure OpenAI Zugriffssteuerung (IAM) aus, um sich diese Rolle in Azure OpenAI selbst zuzuweisen:

      • Cognitive Services OpenAI-Benutzer

Es kann einige Minuten dauern, bis die Berechtigungen in Kraft treten.

Erstellen eines Index

Ein Suchindex stellt Groundingdaten für das Chatmodell bereit. Wir empfehlen den Index hotels-sample-index, der in Minuten erstellt und auf jeder Suchdienstebene ausgeführt werden kann. Dieser Index wird mit integrierten Beispieldaten erstellt.

  1. Suchen Sie im Azure-Portal nach Ihrem Suchdienst.

  2. Wählen Sie auf der Startseite Übersicht die Option Daten importieren aus, um den Assistenten zu starten.

  3. Wählen Sie auf der Seite Mit Ihren Daten verbinden die Option Beispiele aus der Dropdownliste aus.

  4. Wählen Sie das Beispiel hotels-sample aus.

  5. Wählen Sie auf den restlichen Seiten jeweils Weiter aus, und akzeptieren Sie die Standardwerte.

  6. Nachdem der Index erstellt wurde, wählen Sie im linken Menü Suchverwaltung>Indizes aus, um den Index zu öffnen.

  7. Wählen Sie JSON bearbeiten aus.

  8. Scrollen Sie zum Ende des Indexes, wo Sie Platzhalter für Konstrukte finden, die zu einem Index hinzugefügt werden können.

    "analyzers": [],
    "tokenizers": [],
    "tokenFilters": [],
    "charFilters": [],
    "normalizers": [],
    
  9. Fügen Sie in einer neuen Zeile nach „normalizers“ die folgende semantische Konfiguration ein. In diesem Beispiel wird "defaultConfiguration" angegeben, was für die Ausführung dieses Schnellstarts wichtig ist.

    "semantic":{
       "defaultConfiguration":"semantic-config",
       "configurations":[
          {
             "name":"semantic-config",
             "prioritizedFields":{
                "titleField":{
                   "fieldName":"HotelName"
                },
                "prioritizedContentFields":[
                   {
                      "fieldName":"Description"
                   }
                ],
                "prioritizedKeywordsFields":[
                   {
                      "fieldName":"Category"
                   },
                   {
                      "fieldName":"Tags"
                   }
                ]
             }
          }
       ]
    },
    
  10. Speichern Sie die Änderungen.

  11. Führen Sie die folgende Abfrage im Such-Explorer aus, um den Index zu testen: complimentary breakfast.

    Die Ausgabe sollte etwa folgendem Beispiel entsprechen. Die Ergebnisse, die direkt von der Suchmaschine zurückgegeben werden, bestehen aus Feldern und deren wörtlichen Werten, zusammen mit Metadaten wie einem Suchergebnis und einem Ergebnis für das semantische Ranking sowie einer Beschriftung, wenn Sie den semantischen Sortierer verwenden. Wir haben eine Auswahlanweisung verwendet, um nur die Felder „HotelName“, „Beschreibung“ und „Tags“ zurückzugeben.

    {
    "@odata.count": 18,
    "@search.answers": [],
    "value": [
       {
          "@search.score": 2.2896252,
          "@search.rerankerScore": 2.506816864013672,
          "@search.captions": [
          {
             "text": "Head Wind Resort. Suite. coffee in lobby\r\nfree wifi\r\nview. The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a **complimentary continental breakfast** in the lobby, and free Wi-Fi throughout the hotel..",
             "highlights": ""
          }
          ],
          "HotelName": "Head Wind Resort",
          "Description": "The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a complimentary continental breakfast in the lobby, and free Wi-Fi throughout the hotel.",
          "Tags": [
          "coffee in lobby",
          "free wifi",
          "view"
          ]
       },
       {
          "@search.score": 2.2158256,
          "@search.rerankerScore": 2.288334846496582,
          "@search.captions": [
          {
             "text": "Swan Bird Lake Inn. Budget. continental breakfast\r\nfree wifi\r\n24-hour front desk service. We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins..",
             "highlights": ""
          }
          ],
          "HotelName": "Swan Bird Lake Inn",
          "Description": "We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins.",
          "Tags": [
          "continental breakfast",
          "free wifi",
          "24-hour front desk service"
          ]
       },
       {
          "@search.score": 0.92481667,
          "@search.rerankerScore": 2.221315860748291,
          "@search.captions": [
          {
             "text": "White Mountain Lodge & Suites. Resort and Spa. continental breakfast\r\npool\r\nrestaurant. Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings..",
             "highlights": ""
          }
          ],
          "HotelName": "White Mountain Lodge & Suites",
          "Description": "Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings.",
          "Tags": [
          "continental breakfast",
          "pool",
          "restaurant"
          ]
       },
       . . .
    ]}
    

Abrufen von Dienstendpunkten

In den verbleibenden Abschnitten richten Sie API-Aufrufe für Azure OpenAI und die Azure KI-Suche ein. Rufen Sie die Dienstendpunkte ab, damit Sie sie als Variablen im Code bereitstellen können.

  1. Melden Sie sich beim Azure-Portal an.

  2. Suchen Sie Ihren Suchdienst.

  3. Sie finden die URL auf der Startseite Übersicht. Ein Beispiel für einen Endpunkt ist https://example.search.windows.net.

  4. Suchen Sie Ihren Azure OpenAI-Dienst.

  5. Wählen Sie auf der Startseite Übersicht den Link aus, um die Endpunkte anzuzeigen. Kopieren Sie die URL. Ein Beispiel für einen Endpunkt ist https://example.openai.azure.com/.

Einrichten von Umgebungsvariablen für die lokale Entwicklung

  1. Erstellen Sie die Datei .env.

  2. Fügen Sie der .env Datei die folgenden Umgebungsvariablen hinzu, und ersetzen Sie die Werte durch Ihre eigenen Dienstendpunkte und Schlüssel.

    AZURE_SEARCH_ENDPOINT=<YOUR AZURE AI SEARCH ENDPOINT>
    AZURE_SEARCH_INDEX_NAME=hotels-sample-index
    
    AZURE_OPENAI_ENDPOINT=<YOUR AZURE OPENAI ENDPOINT>
    AZURE_OPENAI_VERSION=<YOUR AZURE OPENAI API VERSION>
    AZURE_DEPLOYMENT_MODEL=<YOUR DEPLOYMENT NAME>
    

Einrichten des Node.JS Projekts

Einrichten des Projekts mit Visual Studio Code und TypeScript.

  1. Starten Sie Visual Studio Code in einem neuen Verzeichnis.

    mkdir rag-quickstart && cd rag-quickstart
    code .
    
  2. Erstellen Sie ein neues Paket für ESM-Module in Ihrem Projektverzeichnis.

    npm init -y
    npm pkg set type=module
    

    Dadurch wird eine package.json Datei mit Standardwerten erstellt.

  3. Installieren Sie die folgenden npm-Pakete.

    npm install @azure/identity @azure/search-documents openai dotenv 
    
  4. Erstellen Sie ein src Verzeichnis in Ihrem Projektverzeichnis.

    mkdir src
    

Anmelden bei Azure

Sie verwenden Microsoft Entra ID und Rollenzuweisungen für die Verbindung. Stellen Sie sicher, dass Sie bei demselben Mandanten und Abonnement wie Azure KI-Suche und Azure OpenAI angemeldet sind. Sie können die Azure CLI in der Befehlszeile verwenden, um aktuelle Eigenschaften anzuzeigen, sie zu ändern und um sich anzumelden. Weitere Informationen finden Sie unter Herstellen einer Verbindung ohne Schlüssel.

Führen Sie die folgenden Befehle nacheinander aus.

az account show

az account set --subscription <PUT YOUR SUBSCRIPTION ID HERE>

az login --tenant <PUT YOUR TENANT ID HERE>

Sie sollten jetzt von Ihrem lokalen Gerät aus bei Azure angemeldet sein.

Einrichten von Abfrage- und Chatthreads

Erstellen Sie ein Abfrageskript, das den Azure AI Search-Index und das Chatmodell verwendet, um Antworten basierend auf Erdungsdaten zu generieren. Die folgenden Schritte führen Sie durch das Einrichten des Abfrageskripts.

  1. Erstellen Sie eine query.js Datei im src Verzeichnis mit dem folgenden Code.

    // This is a RAG (Retrieval Augmented Generation) implementation that:
    // 1. Takes a user query about hotels
    // 2. Searches a hotel database using Azure AI Search
    // 3. Formats the search results for the LLM
    // 4. Sends the query and formatted results to Azure OpenAI
    // 5. Returns a grounded response based only on the retrieved information
    
    import { SearchClient } from "@azure/search-documents";
    import { AzureOpenAI } from "openai";
    import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
    
    function getClients() {
    
        const credential = new DefaultAzureCredential();
    
        // Search
        const azureSearchEndpoint = process.env.AZURE_SEARCH_ENDPOINT;
        const azureSearchIndexName = process.env.AZURE_SEARCH_INDEX_NAME;
    
        const searchClient = new SearchClient(
            azureSearchEndpoint,
            azureSearchIndexName,
            credential
        );
    
    
        // OpenAI
        const azureOpenAiEndpoint = process.env.AZURE_OPENAI_ENDPOINT;
        const azureOpenAiApiVersion = process.env.AZURE_OPENAI_VERSION;
        const azureOpenAiDeploymentName = process.env.AZURE_DEPLOYMENT_MODEL;
    
        const scope = "https://cognitiveservices.azure.com/.default";
        const azureADTokenProvider = getBearerTokenProvider(credential, scope);
        const options = { azureADTokenProvider, deployment: azureOpenAiDeploymentName, apiVersion: azureOpenAiApiVersion, endpoint: azureOpenAiEndpoint }
        const openaiClient = new AzureOpenAI(options);
    
        return { openaiClient, searchClient, modelName: azureOpenAiDeploymentName };
    }
    
    async function queryAISearchForSources(searchClient, query) {
        console.log(`Searching for: "${query}"\n`);
        const searchResults = await searchClient.search(query, {
            top: 5,
            select: ["Description", "HotelName", "Tags"]
        });
    
        const sources = [];
        for await (const result of searchResults.results) {
            const doc = result.document;
            sources.push(
                `Hotel: ${doc.HotelName}\n` +
                `Description: ${doc.Description}\n` +
                `Tags: ${Array.isArray(doc.Tags) ? doc.Tags.join(', ') : doc.Tags}\n`
            );
        }
        const sourcesFormatted = sources.join("\n---\n");
        return sourcesFormatted;
    }
    async function queryOpenAIForResponse(openaiClient, query, sourcesFormatted, modelName) {
    
        const GROUNDED_PROMPT = `
     You are a friendly assistant that recommends hotels based on activities and amenities.
     Answer the query using only the sources provided below in a friendly and concise bulleted manner.
     Answer ONLY with the facts listed in the list of sources below.
     If there isn't enough information below, say you don't know.
     Do not generate answers that don't use the sources below.
    
    Query: {query}
    Sources: {sources}
    `;
    
        return openaiClient.chat.completions.create({
            model: modelName,
            messages: [
                {
                    role: "user",
                    content: GROUNDED_PROMPT.replace("{query}", query).replace("{sources}", sourcesFormatted),
                }
            ],
            temperature: 0.7,
            max_tokens: 800,
        });
    }
    
    async function main() {
    
        const { openaiClient, searchClient, modelName } = getClients();
    
        const query = "Can you recommend a few hotels with complimentary breakfast?";
    
        const sources = await queryAISearchForSources(searchClient, query);
        const response = await queryOpenAIForResponse(openaiClient, query, sources, modelName);
    
        // Print the response from the chat model
        const content = response.choices[0].message.content;
        if (content) {
            console.log(content);
        } else {
            console.log("No content available in the response.");
        }
    }
    
    main().catch((error) => {
        console.error("An error occurred:", error);
        process.exit(1);
    });
    

    Der vorangehende Code führt folgende Aktionen aus:

    • Importiert die erforderlichen Bibliotheken für Azure AI Search und Azure OpenAI.
    • Verwendet Umgebungsvariablen zum Konfigurieren der Azure AI Search- und Azure OpenAI-Clients.
    • Definiert eine Funktion zum Abrufen der Clients für Azure AI Search und Azure OpenAI unter Verwendung von Umgebungsvariablen für die Konfiguration.
    • Definiert eine Funktion zum Abfragen von Azure AI Search nach Quellen basierend auf der Benutzerabfrage.
    • Definiert eine Funktion zum Abfragen von Azure OpenAI für eine Antwort basierend auf der Benutzerabfrage und den aus Azure AI Search abgerufenen Quellen.
    • Die main Funktion koordiniert den Fluss durch Aufrufen der Such- und OpenAI-Funktionen und druckt dann die Antwort.
  2. Führen Sie den folgenden Befehl in einem Terminal aus, um das Abfrageskript auszuführen:

    node -r dotenv/config query.js
    

    .env wird mithilfe von -r dotenv/config in die Runtime übergeben.

  3. Sehen Sie sich die Ausgabe an, die aus Empfehlungen für mehrere Hotels besteht. Hier sehen Sie ein Beispiel für eine mögliche Ausgabe:

    Sure! Here are a few hotels that offer complimentary breakfast:
    
    - **Head Wind Resort**
    - Complimentary continental breakfast in the lobby
    - Free Wi-Fi throughout the hotel
    
    - **Double Sanctuary Resort**
    - Continental breakfast included
    
    - **White Mountain Lodge & Suites**
    - Continental breakfast available
    
    - **Swan Bird Lake Inn**
    - Continental-style breakfast each morning with a variety of food and drinks 
        such as caramel cinnamon rolls, coffee, orange juice, milk, cereal, 
        instant oatmeal, bagels, and muffins
    

Problembehandlung

Wenn Sie die Fehlermeldung Verboten erhalten, überprüfen Sie die Konfiguration für Azure KI-Suche, um sicherzustellen, dass der rollenbasierte Zugriff aktiviert ist.

Wenn Sie die Fehlermeldung Autorisierung fehlgeschlagen erhalten, warten Sie einige Minuten, und versuchen Sie es erneut. Es kann mehrere Minuten dauern, bis Rollenzuweisungen betriebsbereit sind.

Wenn sie die Fehlermeldung Ressource nicht gefunden erhalten, überprüfen Sie die Ressourcen-URIs, und stellen Sie sicher, dass die API-Version des Chatmodells gültig ist.

Ändern Sie andernfalls um weiter zu experimentieren die Abfrage, und führen Sie den letzten Schritt erneut aus, um besser zu verstehen, wie das Modell mit den Groundingdaten funktioniert.

Sie können auch den Prompt ändern, um den Ton oder die Struktur der Ausgabe zu ändern.

Sie können die Abfrage auch ohne semantische Rangfolge ausprobieren, indem Sie use_semantic_reranker=False im Abfrageparameterschritt festlegen. Die semantische Rangfolge kann die Relevanz von Abfrageergebnissen und die Fähigkeit des LLM, nützliche Informationen zurückzugeben, deutlich verbessern. Durch Experimentieren können Sie herausfinden, ob es für Ihre Inhalte einen Unterschied macht.

Senden einer komplexen RAG-Abfrage

Azure KI-Suche unterstützt komplexe Typen für geschachtelte JSON-Strukturen. Im Hotelbeispielindex ist Address ein Beispiel für einen komplexen Typ, bestehend aus Address.StreetAddress, Address.City, Address.StateProvince, Address.PostalCode und Address.Country. Der Index verfügt auch über eine komplexe Sammlung von Rooms für jedes Hotel.

Wenn Ihr Index komplexe Typen aufweist, ändern Sie Die Aufforderung so, dass Formatierungsanweisungen eingeschlossen werden:

Can you recommend a few hotels that offer complimentary breakfast? 
Tell me their description, address, tags, and the rate for one room that sleeps 4 people.
  1. Erstellen Sie eine neue Datei queryComplex.js.

  2. Kopieren Sie den folgenden Code in die Datei:

    // This is a RAG (Retrieval Augmented Generation) implementation that:
    // 1. Takes a user query about hotels
    // 2. Searches a hotel database using Azure AI Search
    // 3. Formats the search results for the LLM
    // 4. Sends the query and formatted results to Azure OpenAI
    // 5. Returns a grounded response based only on the retrieved information
    
    import { SearchClient } from "@azure/search-documents";
    import { AzureOpenAI } from "openai";
    import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
    
    function getClients() {
    
        const credential = new DefaultAzureCredential();
    
        // Search
        const azureSearchEndpoint = process.env.AZURE_SEARCH_ENDPOINT;
        const azureSearchIndexName = process.env.AZURE_SEARCH_INDEX_NAME;
    
        const searchClient = new SearchClient(
            azureSearchEndpoint,
            azureSearchIndexName,
            credential
        );
    
    
        // OpenAI
        const azureOpenAiEndpoint = process.env.AZURE_OPENAI_ENDPOINT;
        const azureOpenAiApiVersion = process.env.AZURE_OPENAI_VERSION;
        const azureOpenAiDeploymentName = process.env.AZURE_DEPLOYMENT_MODEL;
    
        const scope = "https://cognitiveservices.azure.com/.default";
        const azureADTokenProvider = getBearerTokenProvider(credential, scope);
        const options = { azureADTokenProvider, deployment: azureOpenAiDeploymentName, apiVersion: azureOpenAiApiVersion, endpoint: azureOpenAiEndpoint }
        const openaiClient = new AzureOpenAI(options);
    
        return { openaiClient, searchClient, modelName: azureOpenAiDeploymentName };
    }
    
    async function queryAISearchForSources(
        searchClient,
        query
    ) {
        console.log(`Searching for: "${query}"\n`);
    
        const selectedFields = ["HotelName", "Description", "Address", "Rooms", "Tags"];
        const searchResults = await searchClient.search(query, {
            top: 5,
            select: selectedFields,
            queryType: "semantic",
            semanticSearchOptions: {},
        });
    
        return searchResults;
    }
    async function queryOpenAIForResponse(
        openaiClient, 
        query, 
        sourcesFormatted, 
        modelName
    ){
    
        const GROUNDED_PROMPT = `
     You are a friendly assistant that recommends hotels based on activities and amenities.
     Answer the query using only the sources provided below in a friendly and concise bulleted manner.
     Answer ONLY with the facts listed in the list of sources below.
     If there isn't enough information below, say you don't know.
     Do not generate answers that don't use the sources below.
    
    Query: {query}
    Sources: {sources}
    `;
    
        return openaiClient.chat.completions.create({
            model: modelName,
            messages: [
                {
                    role: "user",
                    content: GROUNDED_PROMPT.replace("{query}", query).replace("{sources}", sourcesFormatted),
                }
            ],
            temperature: 0.7,
            max_tokens: 800,
        });
    }
    
    async function main() {
    
        const { openaiClient, searchClient, modelName } = getClients();
    
        const query = `
        Can you recommend a few hotels that offer complimentary breakfast? 
        Tell me their description, address, tags, and the rate for one room that sleeps 4 people.
        `;
    
        const sourcesResult = await queryAISearchForSources(searchClient, query);
        let sourcesFormatted = "";
    
        for await (const result of sourcesResult.results) {
            // Explicitly typing result to ensure compatibility
            sourcesFormatted += JSON.stringify(result.document) + "\n";
        }
    
        const response = await queryOpenAIForResponse(openaiClient, query, sourcesFormatted.trim(), modelName);
    
        // Print the response from the chat model
        const content = response.choices[0].message.content;
        if (content) {
            console.log(content);
        } else {
            console.log("No content available in the response.");
        }
    }
    
    main().catch((error) => {
        console.error("An error occurred:", error);
        process.exit(1);
    });
    
  3. Führen Sie den folgenden Befehl in einem Terminal aus, um das Abfrageskript auszuführen:

    node -r dotenv/config queryComplex.js
    

    .env wird mithilfe von -r dotenv/config in die Runtime übergeben.

  4. Zeigen Sie die Ausgabe von Azure OpenAI an, und sie fügt Inhalte aus komplexen Typen hinzu.

    Here are a few hotels that offer complimentary breakfast and have rooms that sleep 4 people:
    
    1. **Head Wind Resort**
       - **Description:** The best of old town hospitality combined with views of the river and 
       cool breezes off the prairie. Enjoy a complimentary continental breakfast in the lobby, 
       and free Wi-Fi throughout the hotel.
       - **Address:** 7633 E 63rd Pl, Tulsa, OK 74133, USA
       - **Tags:** Coffee in lobby, free Wi-Fi, view
       - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99
    
    2. **Double Sanctuary Resort**
       - **Description:** 5-star Luxury Hotel - Biggest Rooms in the city. #1 Hotel in the area 
       listed by Traveler magazine. Free WiFi, Flexible check in/out, Fitness Center & espresso 
       in room. Offers continental breakfast.
       - **Address:** 2211 Elliott Ave, Seattle, WA 98121, USA
       - **Tags:** View, pool, restaurant, bar, continental breakfast
       - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99
    
    3. **Swan Bird Lake Inn**
       - **Description:** Continental-style breakfast featuring a variety of food and drinks. 
       Locally made caramel cinnamon rolls are a favorite.
       - **Address:** 1 Memorial Dr, Cambridge, MA 02142, USA
       - **Tags:** Continental breakfast, free Wi-Fi, 24-hour front desk service
       - **Room for 4:** Budget Room, 2 Queen Beds (City View) - $85.99
    
    4. **Gastronomic Landscape Hotel**
       - **Description:** Known for its culinary excellence under the management of William Dough, 
       offers continental breakfast.
       - **Address:** 3393 Peachtree Rd, Atlanta, GA 30326, USA
       - **Tags:** Restaurant, bar, continental breakfast
       - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $66.99
    ...
       - **Tags:** Pool, continental breakfast, free parking
       - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $60.99
    
    Enjoy your stay! Let me know if you need any more information.
    

Problembehandlung

Um Azure SDK-Fehler zu debuggen, legen Sie die Umgebungsvariable AZURE_LOG_LEVEL auf eine der folgenden Werte fest: verbose, , info, . warningerror Dadurch wird die detaillierte Protokollierung für das Azure SDK ermöglicht, wodurch Probleme mit Authentifizierung, Netzwerkkonnektivität oder anderen Problemen identifiziert werden können.

Führen Sie das Abfrageskript erneut aus. Sie sollten jetzt informative Anweisungen von den SDKs in der Ausgabe abrufen, die weitere Details zu Problemen bereitstellen.

Wenn Sie Ausgabemeldungen im Zusammenhang mit ManagedIdentityCredential und dem fehlgeschlagenen Token-Erwerb sehen, könnte es sein, dass Sie mehrere Mandanten haben und Ihre Azure-Anmeldung über einen Mandanten erfolgt, der nicht über Ihren Suchdienst verfügt. Um Ihre Mandanten-ID zu erhalten, suchen Sie im Azure-Portal nach „Mandanteneigenschaften“, oder führen Sie az login tenant list aus.

Wenn Sie über eine Mandanten-ID verfügen, führen Sie an einer Eingabeaufforderung az login --tenant <YOUR-TENANT-ID> aus, und führen Sie dann das Skript erneut aus.

Bereinigung

Wenn Sie in Ihrem eigenen Abonnement arbeiten, sollten Sie sich am Ende eines Projekts überlegen, ob Sie die erstellten Ressourcen noch benötigen. Ressourcen, die weiterhin ausgeführt werden, können Geld kosten. Sie können entweder einzelne Ressourcen oder aber die Ressourcengruppe löschen, um den gesamten Ressourcensatz zu entfernen.

Ressourcen können im Azure-Portal über den Link Alle Ressourcen oder Ressourcengruppen im linken Navigationsbereich gesucht und verwaltet werden.

Voraussetzungen

Herunterladen der Datei

Laden Sie ein Jupyter-Notebook von GitHub herunter, um die Anforderungen in diesem Schnellstart zu senden. Weitere Informationen finden Sie unter Herunterladen von Dateien von GitHub.

Sie können auch eine neue Datei auf Ihrem lokalen System anlegen und die Abfragen manuell anhand der Anleitung in diesem Artikel erstellen.

Konfigurieren des Zugriffs

Anforderungen an den Suchendpunkt müssen authentifiziert und autorisiert werden. Sie können für diese Aufgabe API-Schlüssel oder Rollen verwenden. Schlüssel sind für ein Einstieg einfacher, Rollen sind jedoch sicherer. In diesem Schnellstart werden Rollen vorausgesetzt.

Sie richten zwei Clients ein, daher benötigen Sie Berechtigungen für beide Ressourcen.

Azure KI-Suche empfängt die Abfrageanforderung von Ihrem lokalen System. Weisen Sie sich selbst die Rolle Suchindexdatenleser zu, wenn der Beispielindex für Hotels bereits vorhanden ist. Wenn sie nicht vorhanden ist, weisen Sie sich die Rollen Mitwirkender von Suchdienst und Mitwirkender an Suchindexdaten zu, damit Sie den Index erstellen und abfragen können.

Azure OpenAI empfängt die Abfrage und die Suchergebnisse aus Ihrem lokalen System. Weisen Sie sich in Azure OpenAI die Rolle Cognitive Services OpenAI-Benutzer zu.

  1. Melden Sie sich beim Azure-Portal an.

  2. Konfigurieren von Azure KI-Suche für rollenbasierten Zugriff:

    1. Suchen Sie im Azure-Portal nach Ihrem Azure KI-Suchdienst.

    2. Wählen Sie im linken Menü Einstellungen>Schlüsselaus, und wählen Sie dann entweder die Option Rollenbasierte Zugriffssteuerung oder Beides aus.

  3. Zuweisen von Rollen:

    1. Wählen Sie im linken Menü Zugriffssteuerung (IAM) aus.

    2. Wählen Sie in Azure KI-Suche diese Rollen aus, um einen Suchindex zu erstellen, zu laden und abzufragen, und weisen Sie sie dann Ihrer Microsoft Entra ID-Benutzeridentität zu:

      • Mitwirkender an Suchindexdaten
      • Mitwirkender von Suchdienst
    3. Wählen Sie in Azure OpenAI Zugriffssteuerung (IAM) aus, um sich diese Rolle in Azure OpenAI selbst zuzuweisen:

      • Cognitive Services OpenAI-Benutzer

Es kann einige Minuten dauern, bis die Berechtigungen in Kraft treten.

Aktualisieren des Hotels-Beispielindex

Ein Suchindex stellt Groundingdaten für das Chatmodell bereit. Wir empfehlen den Index hotels-sample-index, der in Minuten erstellt und auf jeder Suchdienstebene ausgeführt werden kann. Dieser Index wird mit integrierten Beispieldaten erstellt.

  1. Suchen Sie im Azure-Portal nach Ihrem Suchdienst.

  2. Wählen Sie auf der Startseite Übersicht die Option Daten importieren aus, um den Assistenten zu starten.

  3. Wählen Sie auf der Seite Mit Ihren Daten verbinden die Option Beispiele aus der Dropdownliste aus.

  4. Wählen Sie das Beispiel hotels-sample aus.

  5. Wählen Sie auf den restlichen Seiten jeweils Weiter aus, und akzeptieren Sie die Standardwerte.

  6. Nachdem der Index erstellt wurde, wählen Sie im linken Menü Suchverwaltung>Indizes aus, um den Index zu öffnen.

  7. Wählen Sie JSON bearbeiten aus.

  8. Scrollen Sie zum Ende des Indexes, wo Sie Platzhalter für Konstrukte finden, die zu einem Index hinzugefügt werden können.

    "analyzers": [],
    "tokenizers": [],
    "tokenFilters": [],
    "charFilters": [],
    "normalizers": [],
    
  9. Fügen Sie in einer neuen Zeile nach „normalizers“ die folgende semantische Konfiguration ein. In diesem Beispiel wird "defaultConfiguration" angegeben, was für die Ausführung dieses Schnellstarts wichtig ist.

    "semantic":{
       "defaultConfiguration":"semantic-config",
       "configurations":[
          {
             "name":"semantic-config",
             "prioritizedFields":{
                "titleField":{
                   "fieldName":"HotelName"
                },
                "prioritizedContentFields":[
                   {
                      "fieldName":"Description"
                   }
                ],
                "prioritizedKeywordsFields":[
                   {
                      "fieldName":"Category"
                   },
                   {
                      "fieldName":"Tags"
                   }
                ]
             }
          }
       ]
    },
    
  10. Speichern Sie die Änderungen.

  11. Führen Sie die folgende Abfrage im Such-Explorer aus, um den Index zu testen: complimentary breakfast.

    Die Ausgabe sollte etwa folgendem Beispiel entsprechen. Die Ergebnisse, die direkt von der Suchmaschine zurückgegeben werden, bestehen aus Feldern und deren wörtlichen Werten, zusammen mit Metadaten wie einem Suchergebnis und einem Ergebnis für das semantische Ranking sowie einer Beschriftung, wenn Sie den semantischen Sortierer verwenden. Wir haben eine Auswahlanweisung verwendet, um nur die Felder „HotelName“, „Beschreibung“ und „Tags“ zurückzugeben.

    {
    "@odata.count": 18,
    "@search.answers": [],
    "value": [
       {
          "@search.score": 2.2896252,
          "@search.rerankerScore": 2.506816864013672,
          "@search.captions": [
          {
             "text": "Head Wind Resort. Suite. coffee in lobby\r\nfree wifi\r\nview. The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a **complimentary continental breakfast** in the lobby, and free Wi-Fi throughout the hotel..",
             "highlights": ""
          }
          ],
          "HotelName": "Head Wind Resort",
          "Description": "The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a complimentary continental breakfast in the lobby, and free Wi-Fi throughout the hotel.",
          "Tags": [
          "coffee in lobby",
          "free wifi",
          "view"
          ]
       },
       {
          "@search.score": 2.2158256,
          "@search.rerankerScore": 2.288334846496582,
          "@search.captions": [
          {
             "text": "Swan Bird Lake Inn. Budget. continental breakfast\r\nfree wifi\r\n24-hour front desk service. We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins..",
             "highlights": ""
          }
          ],
          "HotelName": "Swan Bird Lake Inn",
          "Description": "We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins.",
          "Tags": [
          "continental breakfast",
          "free wifi",
          "24-hour front desk service"
          ]
       },
       {
          "@search.score": 0.92481667,
          "@search.rerankerScore": 2.221315860748291,
          "@search.captions": [
          {
             "text": "White Mountain Lodge & Suites. Resort and Spa. continental breakfast\r\npool\r\nrestaurant. Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings..",
             "highlights": ""
          }
          ],
          "HotelName": "White Mountain Lodge & Suites",
          "Description": "Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings.",
          "Tags": [
          "continental breakfast",
          "pool",
          "restaurant"
          ]
       },
       . . .
    ]}
    

Abrufen von Dienstendpunkten

In den verbleibenden Abschnitten richten Sie API-Aufrufe für Azure OpenAI und die Azure KI-Suche ein. Rufen Sie die Dienstendpunkte ab, damit Sie sie als Variablen im Code bereitstellen können.

  1. Melden Sie sich beim Azure-Portal an.

  2. Suchen Sie Ihren Suchdienst.

  3. Sie finden die URL auf der Startseite Übersicht. Ein Beispiel für einen Endpunkt ist https://example.search.windows.net.

  4. Suchen Sie Ihren Azure OpenAI-Dienst.

  5. Wählen Sie auf der Startseite Übersicht den Link aus, um die Endpunkte anzuzeigen. Kopieren Sie die URL. Ein Beispiel für einen Endpunkt ist https://example.openai.azure.com/.

Erstellen einer virtuellen Umgebung

Wechseln Sie für diesen Schritt zu Ihrem lokalen System und zu Visual Studio Code zurück. Es wird empfohlen, eine virtuelle Umgebung zu erstellen, damit Sie die Abhängigkeiten isoliert installieren können.

  1. Öffnen Sie in Visual Studio Code den Ordner, der die zu aktualisierende Datei „Quickstart-RAG.ipynb“ enthält.

  2. Drücken Sie STRG-UMSCHALT-P, um die Befehlspalette zu öffnen. Suchen Sie nach „Python: Umgebung erstellen“, und wählen Sie dann Venv aus, um eine virtuelle Umgebung im aktuellen Arbeitsbereich zu erstellen.

  3. Wählen Sie für die Abhängigkeiten „Quickstart-RAG\requirements.txt“ aus.

Die Erstellung der Umgebung dauert einige Minuten. Fahren Sie mit dem nächsten Schritt fort, sobald die Umgebung bereit ist.

Anmelden bei Azure

Sie verwenden Microsoft Entra ID und Rollenzuweisungen für die Verbindung. Stellen Sie sicher, dass Sie bei demselben Mandanten und Abonnement wie Azure KI-Suche und Azure OpenAI angemeldet sind. Sie können die Azure CLI in der Befehlszeile verwenden, um aktuelle Eigenschaften anzuzeigen, sie zu ändern und um sich anzumelden. Weitere Informationen finden Sie unter Herstellen einer Verbindung ohne Schlüssel.

Führen Sie die folgenden Befehle nacheinander aus.

az account show

az account set --subscription <PUT YOUR SUBSCRIPTION ID HERE>

az login --tenant <PUT YOUR TENANT ID HERE>

Sie sollten jetzt von Ihrem lokalen Gerät aus bei Azure angemeldet sein.

Einrichten des Abfrage- und Chatthreads

In diesem Abschnitt werden Visual Studio Code und Python verwendet, um die Chatvervollständigungs-APIs in Azure OpenAI aufzurufen.

  1. Starten Sie Visual Studio Code, und öffnen Sie die IPYNB-Datei oder erstellen Sie eine neue Python-Datei.

  2. Installieren Sie die folgenden Python-Pakete.

    ! pip install azure-search-documents==11.6.0b5 --quiet
    ! pip install azure-identity==1.16.1 --quiet
    ! pip install openai --quiet
    ! pip install aiohttp --quiet
    ! pip install ipykernel --quiet
    
  3. Legen Sie die folgenden Variablen fest, und ersetzen Sie dabei die Platzhalter durch die Endpunkte, die Sie im vorigen Schritt gesammelt haben.

     AZURE_SEARCH_SERVICE: str = "PUT YOUR SEARCH SERVICE ENDPOINT HERE"
     AZURE_OPENAI_ACCOUNT: str = "PUT YOUR AZURE OPENAI ENDPOINT HERE"
     AZURE_DEPLOYMENT_MODEL: str = "gpt-4o"
    
  4. Richten Sie Clients, Prompt, Abfrage und Antwort ein.

    Ändern Sie für die Azure Government-Cloud den API-Endpunkt des Tokenanbieters in "https://cognitiveservices.azure.us/.default".

    # Set up the query for generating responses
     from azure.identity import DefaultAzureCredential
     from azure.identity import get_bearer_token_provider
     from azure.search.documents import SearchClient
     from openai import AzureOpenAI
    
     credential = DefaultAzureCredential()
     token_provider = get_bearer_token_provider(credential, "https://cognitiveservices.azure.com/.default")
     openai_client = AzureOpenAI(
         api_version="2024-06-01",
         azure_endpoint=AZURE_OPENAI_ACCOUNT,
         azure_ad_token_provider=token_provider
     )
    
     search_client = SearchClient(
         endpoint=AZURE_SEARCH_SERVICE,
         index_name="hotels-sample-index",
         credential=credential
     )
    
     # This prompt provides instructions to the model
     GROUNDED_PROMPT="""
     You are a friendly assistant that recommends hotels based on activities and amenities.
     Answer the query using only the sources provided below in a friendly and concise bulleted manner.
     Answer ONLY with the facts listed in the list of sources below.
     If there isn't enough information below, say you don't know.
     Do not generate answers that don't use the sources below.
     Query: {query}
     Sources:\n{sources}
     """
    
     # Query is the question being asked. It's sent to the search engine and the chat model
     query="Can you recommend a few hotels with complimentary breakfast?"
    
     # Search results are created by the search client
     # Search results are composed of the top 5 results and the fields selected from the search index
     # Search results include the top 5 matches to your query
     search_results = search_client.search(
         search_text=query,
         top=5,
         select="Description,HotelName,Tags"
     )
     sources_formatted = "\n".join([f'{document["HotelName"]}:{document["Description"]}:{document["Tags"]}' for document in search_results])
    
     # Send the search results and the query to the LLM to generate a response based on the prompt.
     response = openai_client.chat.completions.create(
         messages=[
             {
                 "role": "user",
                 "content": GROUNDED_PROMPT.format(query=query, sources=sources_formatted)
             }
         ],
         model=AZURE_DEPLOYMENT_MODEL
     )
    
     # Here is the response from the chat model.
     print(response.choices[0].message.content)
    

    Die Ausgabe stammt aus Azure OpenAI und besteht aus Empfehlungen für mehrere Hotels. Hier sehen Sie ein Beispiel für eine mögliche Ausgabe:

    Sure! Here are a few hotels that offer complimentary breakfast:
    
    - **Head Wind Resort**
    - Complimentary continental breakfast in the lobby
    - Free Wi-Fi throughout the hotel
    
    - **Double Sanctuary Resort**
    - Continental breakfast included
    
    - **White Mountain Lodge & Suites**
    - Continental breakfast available
    
    - **Swan Bird Lake Inn**
    - Continental-style breakfast each morning with a variety of food and drinks 
     such as caramel cinnamon rolls, coffee, orange juice, milk, cereal, 
     instant oatmeal, bagels, and muffins
    

    Wenn Sie die Fehlermeldung Verboten erhalten, überprüfen Sie die Konfiguration für Azure KI-Suche, um sicherzustellen, dass der rollenbasierte Zugriff aktiviert ist.

    Wenn Sie die Fehlermeldung Autorisierung fehlgeschlagen erhalten, warten Sie einige Minuten, und versuchen Sie es erneut. Es kann mehrere Minuten dauern, bis Rollenzuweisungen betriebsbereit sind.

    Wenn sie die Fehlermeldung Ressource nicht gefunden erhalten, überprüfen Sie die Ressourcen-URIs, und stellen Sie sicher, dass die API-Version des Chatmodells gültig ist.

    Ändern Sie andernfalls um weiter zu experimentieren die Abfrage, und führen Sie den letzten Schritt erneut aus, um besser zu verstehen, wie das Modell mit den Groundingdaten funktioniert.

    Sie können auch den Prompt ändern, um den Ton oder die Struktur der Ausgabe zu ändern.

    Sie können die Abfrage auch ohne semantische Rangfolge ausprobieren, indem Sie use_semantic_reranker=False im Abfrageparameterschritt festlegen. Die semantische Rangfolge kann die Relevanz von Abfrageergebnissen und die Fähigkeit des LLM, nützliche Informationen zurückzugeben, deutlich verbessern. Durch Experimentieren können Sie herausfinden, ob es für Ihre Inhalte einen Unterschied macht.

Senden einer komplexen RAG-Abfrage

Azure KI-Suche unterstützt komplexe Typen für geschachtelte JSON-Strukturen. Im Hotelbeispielindex ist Address ein Beispiel für einen komplexen Typ, bestehend aus Address.StreetAddress, Address.City, Address.StateProvince, Address.PostalCode und Address.Country. Der Index verfügt auch über eine komplexe Sammlung von Rooms für jedes Hotel.

Wenn Ihr Index komplexe Typen aufweist, kann Ihre Abfrage diese Felder bereitstellen, wenn Sie die Ausgabe der Suchergebnisse zuerst in JSON konvertieren und dann das JSON an das Chatmodell übergeben. Im folgenden Beispiel werden der Anforderung komplexe Typen hinzugefügt. Die Formatierungsanweisungen enthalten eine JSON-Spezifikation.

import json

# Query is the question being asked. It's sent to the search engine and the LLM.
query="Can you recommend a few hotels that offer complimentary breakfast? 
Tell me their description, address, tags, and the rate for one room that sleeps 4 people."

# Set up the search results and the chat thread.
# Retrieve the selected fields from the search index related to the question.
selected_fields = ["HotelName","Description","Address","Rooms","Tags"]
search_results = search_client.search(
    search_text=query,
    top=5,
    select=selected_fields,
    query_type="semantic"
)
sources_filtered = [{field: result[field] for field in selected_fields} for result in search_results]
sources_formatted = "\n".join([json.dumps(source) for source in sources_filtered])

response = openai_client.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": GROUNDED_PROMPT.format(query=query, sources=sources_formatted)
        }
    ],
    model=AZURE_DEPLOYMENT_MODEL
)

print(response.choices[0].message.content)

Die Ausgabe stammt aus Azure OpenAI und fügt Inhalte aus komplexen Typen hinzu.

Here are a few hotels that offer complimentary breakfast and have rooms that sleep 4 people:

1. **Head Wind Resort**
   - **Description:** The best of old town hospitality combined with views of the river and 
   cool breezes off the prairie. Enjoy a complimentary continental breakfast in the lobby, 
   and free Wi-Fi throughout the hotel.
   - **Address:** 7633 E 63rd Pl, Tulsa, OK 74133, USA
   - **Tags:** Coffee in lobby, free Wi-Fi, view
   - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99

2. **Double Sanctuary Resort**
   - **Description:** 5-star Luxury Hotel - Biggest Rooms in the city. #1 Hotel in the area 
   listed by Traveler magazine. Free WiFi, Flexible check in/out, Fitness Center & espresso 
   in room. Offers continental breakfast.
   - **Address:** 2211 Elliott Ave, Seattle, WA 98121, USA
   - **Tags:** View, pool, restaurant, bar, continental breakfast
   - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99

3. **Swan Bird Lake Inn**
   - **Description:** Continental-style breakfast featuring a variety of food and drinks. 
   Locally made caramel cinnamon rolls are a favorite.
   - **Address:** 1 Memorial Dr, Cambridge, MA 02142, USA
   - **Tags:** Continental breakfast, free Wi-Fi, 24-hour front desk service
   - **Room for 4:** Budget Room, 2 Queen Beds (City View) - $85.99

4. **Gastronomic Landscape Hotel**
   - **Description:** Known for its culinary excellence under the management of William Dough, 
   offers continental breakfast.
   - **Address:** 3393 Peachtree Rd, Atlanta, GA 30326, USA
   - **Tags:** Restaurant, bar, continental breakfast
   - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $66.99
...
   - **Tags:** Pool, continental breakfast, free parking
   - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $60.99

Enjoy your stay! Let me know if you need any more information.

Problembehandlung

Um Authentifizierungsfehler zu beheben, fügen Sie den folgenden Code vor dem Schritt ein, der die Suchmaschine und das LLM aufruft.

import sys
import logging # Set the logging level for all azure-storage-* libraries
logger = logging.getLogger('azure.identity') 
logger.setLevel(logging.DEBUG)

handler = logging.StreamHandler(stream=sys.stdout)
formatter = logging.Formatter('[%(levelname)s %(name)s] %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

Führen Sie das Abfrageskript erneut aus. Sie sollten nun INFO- und DEBUG- Meldungen in der Ausgabe erhalten, die mehr Details über das Problem liefern.

Wenn Sie Ausgabemeldungen im Zusammenhang mit ManagedIdentityCredential und dem fehlgeschlagenen Token-Erwerb sehen, könnte es sein, dass Sie mehrere Mandanten haben und Ihre Azure-Anmeldung über einen Mandanten erfolgt, der nicht über Ihren Suchdienst verfügt. Um Ihre Mandanten-ID zu erhalten, suchen Sie im Azure-Portal nach „Mandanteneigenschaften“, oder führen Sie az login tenant list aus.

Wenn Sie über eine Mandanten-ID verfügen, führen Sie an einer Eingabeaufforderung az login --tenant <YOUR-TENANT-ID> aus, und führen Sie dann das Skript erneut aus.

Bereinigung

Wenn Sie in Ihrem eigenen Abonnement arbeiten, sollten Sie sich am Ende eines Projekts überlegen, ob Sie die erstellten Ressourcen noch benötigen. Ressourcen, die weiterhin ausgeführt werden, können Geld kosten. Sie können entweder einzelne Ressourcen oder aber die Ressourcengruppe löschen, um den gesamten Ressourcensatz zu entfernen.

Ressourcen können im Azure-Portal über den Link Alle Ressourcen oder Ressourcengruppen im linken Navigationsbereich gesucht und verwaltet werden.

Voraussetzungen

Herunterladen der Datei

Laden Sie eine REST-Datei von GitHub herunter, um die Anforderungen in dieser Schnellstartanleitung zu senden. Weitere Informationen finden Sie unter Herunterladen von Dateien von GitHub.

Sie können auch eine neue Datei auf Ihrem lokalen System anlegen und die Abfragen manuell anhand der Anleitung in diesem Artikel erstellen.

Konfigurieren des Zugriffs

Anforderungen an den Suchendpunkt müssen authentifiziert und autorisiert werden. Sie können API-Schlüssel oder Rollen für diese Aufgabe verwenden. Schlüssel sind für ein Einstieg einfacher, Rollen sind jedoch sicherer. In diesem Schnellstart werden Rollen vorausgesetzt.

Sie richten zwei Clients ein, daher benötigen Sie Berechtigungen für beide Ressourcen.

Azure KI-Suche empfängt die Abfrageanforderung von Ihrem lokalen System. Weisen Sie sich selbst die Rolle Suchindexdatenleser zu, wenn der Beispielindex für Hotels bereits vorhanden ist. Wenn sie nicht vorhanden ist, weisen Sie sich die Rollen Mitwirkender von Suchdienst und Mitwirkender an Suchindexdaten zu, damit Sie den Index erstellen und abfragen können.

Azure OpenAI empfängt die Abfrage und die Suchergebnisse aus Ihrem lokalen System. Weisen Sie sich in Azure OpenAI die Rolle Cognitive Services OpenAI-Benutzer zu.

  1. Melden Sie sich beim Azure-Portal an.

  2. Konfigurieren von Azure KI-Suche für rollenbasierten Zugriff:

    1. Suchen Sie im Azure-Portal nach Ihrem Azure KI-Suchdienst.

    2. Wählen Sie im linken Menü Einstellungen>Schlüsselaus, und wählen Sie dann entweder die Option Rollenbasierte Zugriffssteuerung oder Beides aus.

  3. Zuweisen von Rollen:

    1. Wählen Sie im linken Menü Zugriffssteuerung (IAM) aus.

    2. Wählen Sie in Azure KI-Suche diese Rollen aus, um einen Suchindex zu erstellen, zu laden und abzufragen, und weisen Sie sie dann Ihrer Microsoft Entra ID-Benutzeridentität zu:

      • Mitwirkender an Suchindexdaten
      • Mitwirkender von Suchdienst
    3. Wählen Sie in Azure OpenAI Zugriffssteuerung (IAM) aus, um sich diese Rolle in Azure OpenAI selbst zuzuweisen:

      • Cognitive Services OpenAI-Benutzer

Es kann einige Minuten dauern, bis die Berechtigungen in Kraft treten.

Abrufen von Service-Endpunkten und Token

In den verbleibenden Abschnitten richten Sie API-Aufrufe für Azure OpenAI und die Azure KI-Suche ein. Rufen Sie die Dienstendpunkte und -token ab, damit Sie sie als Variablen in Ihrem Code bereitstellen können.

  1. Melden Sie sich beim Azure-Portal an.

  2. Suchen Sie Ihren Suchdienst.

  3. Sie finden die URL auf der Startseite Übersicht. Ein Beispiel für einen Endpunkt ist https://example.search.windows.net.

  4. Suchen Sie Ihren Azure OpenAI-Dienst.

  5. Wählen Sie auf der Startseite Übersicht den Link aus, um die Endpunkte anzuzeigen. Kopieren Sie die URL. Ein Beispiel für einen Endpunkt ist https://example.openai.azure.com/.

  6. Rufen Sie persönliche Zugriffstoken über das Azure CLI in einem Terminal ab. Hier sind die Befehle für jede Ressource:

    • az account get-access-token --resource https://search.azure.com --query "accessToken" -o tsv
    • az account get-access-token --resource https://cognitiveservices.azure.com --query "accessToken" -o tsv

Einrichten des Clients

In dieser Schnellstartanleitung verwenden Sie einen REST-Client und die Azure AI Search-REST-APIs, um das RAG-Muster zu implementieren.

Wir empfehlen Visual Studio Code mit einer REST-Clienterweiterung für diese Schnellstartanleitung.

Tipp

Sie können den Quellcode herunterladen, um mit einem fertigen Projekt zu beginnen, oder diese Schritte ausführen, um ein eigenes zu erstellen.

  1. Starten Sie Visual Studio Code, und öffnen Sie die Datei "quickstart-rag.rest ", oder erstellen Sie eine neue Datei.

  2. Legen Sie oben Umgebungsvariablen für Ihren Suchdienst, die Autorisierung und den Indexnamen fest.

    • Fügen Sie für @searchUrl den Suchendpunkt ein.
    • Fügen Sie für @aoaiUrl den Azure OpenAI-Endpunkt ein.
    • Fügen Sie für @searchAccessToken das Zugriffstoken ein, das zu https://search.azure.com gehört.
    • Fügen Sie für @aoaiAccessToken das Zugriffstoken ein, das zu https://cognitiveservices.azure.com gehört.
  3. Um die Verbindung zu testen, senden Sie Ihre erste Anforderung.

    ### List existing indexes by name (verify the connection)
     GET  {{searchUrl}}/indexes?api-version=2025-08-01-preview&$select=name  HTTP/1.1
     Authorization: Bearer {{personalAccessToken}}
    
  4. Wählen Sie "Gesendete Anforderung" aus.

    Screenshot des Links zum Senden einer Anfrage im REST-Client.

  5. Die Ausgabe für diese GET-Anforderung sollte eine Liste von Indizes sein. Sie sollten den hotels-sample-index darunter sehen.

Einrichten des Abfrage- und Chatthreads

In diesem Abschnitt wird Visual Studio Code und REST verwendet, um die Chatabschluss-APIs in Azure OpenAI aufzurufen.

  1. Richten Sie eine Abfrageanforderung für den Ausdruck "Können Sie ein paar Hotels mit kostenlosem Frühstück empfehlen?" ein. Diese Abfrage verwendet die semantische Rangfolge, um relevante Übereinstimmungen zurückzugeben, auch wenn der Text nicht exakt übereinstimmt. Ergebnisse werden in der SearchRequest-Variablen für die Wiederverwendung in der nächsten Anforderung gespeichert.

    # @name searchRequest
     POST {{searchUrl}}/indexes/{{index-name}}/docs/search?api-version={{api-version}} HTTP/1.1
     Content-Type: application/json
     Authorization: Bearer {{searchAccessToken}}
    
     {
       "search": "Can you recommend a few hotels with complimentary breakfast?",
       "queryType": "semantic",
       "semanticConfiguration": "semantic-config",
       "select": "Description,HotelName,Tags",
       "top": 5
     }
    
     ### 3 - Use search results in Azure OpenAI call to a chat completion model
     POST {{aoaiUrl}}/openai/deployments/{{aoaiGptDeployment}}/chat/completions?api-version=2024-08-01-preview HTTP/1.1
     Content-Type: application/json
     Authorization: Bearer {{aoaiAccessToken}}
    
     {
       "messages": [
         {
           "role": "system", 
           "content": "You recommend hotels based on activities and amenities. Answer the query using only the search result. Answer in a friendly and concise manner. Answer ONLY with the facts provided. If there isn't enough information below, say you don't know."
         },
         {
           "role": "user",
           "content": "Based on the hotel search results, can you recommend hotels with breakfast? Here are all the hotels I found:\n\nHotel 1: {{searchRequest.response.body.value[0].HotelName}}\nDescription: {{searchRequest.response.body.value[0].Description}}\n\nHotel 2: {{searchRequest.response.body.value[1].HotelName}}\nDescription: {{searchRequest.response.body.value[1].Description}}\n\nHotel 3: {{searchRequest.response.body.value[2].HotelName}}\nDescription: {{searchRequest.response.body.value[2].Description}}\n\nHotel 4: {{searchRequest.response.body.value[3].HotelName}}\nDescription: {{searchRequest.response.body.value[3].Description}}\n\nHotel 5: {{searchRequest.response.body.value[4].HotelName}}\nDescription: {{searchRequest.response.body.value[4].Description}}\n\nPlease recommend which hotels offer breakfast based on their descriptions."
         }
       ],
       "max_tokens": 1000,
       "temperature": 0.7
     }`
    
  2. Senden Sie die Anforderung.

  3. Die Ausgabe sollte etwa folgendem Beispiel entsprechen:

       "value": [
         {
           "@search.score": 3.9269178,
           "@search.rerankerScore": 2.380699872970581,
           "HotelName": "Head Wind Resort",
           "Description": "The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a complimentary continental breakfast in the lobby, and free Wi-Fi throughout the hotel.",
           "Tags": [
             "coffee in lobby",
             "free wifi",
             "view"
           ]
         },
         {
           "@search.score": 1.5450059,
           "@search.rerankerScore": 2.1258809566497803,
           "HotelName": "Thunderbird Motel",
           "Description": "Book Now & Save. Clean, Comfortable rooms at the lowest price. Enjoy complimentary coffee and tea in common areas.",
           "Tags": [
             "coffee in lobby",
             "free parking",
             "free wifi"
           ]
         },
         {
           "@search.score": 2.2158256,
           "@search.rerankerScore": 2.121671438217163,
           "HotelName": "Swan Bird Lake Inn",
           "Description": "We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins.",
           "Tags": [
             "continental breakfast",
             "free wifi",
             "24-hour front desk service"
           ]
         },
         {
           "@search.score": 0.6395861,
           "@search.rerankerScore": 2.116753339767456,
           "HotelName": "Waterfront Scottish Inn",
           "Description": "Newly Redesigned Rooms & airport shuttle. Minutes from the airport, enjoy lakeside amenities, a resort-style pool & stylish new guestrooms with Internet TVs.",
           "Tags": [
             "24-hour front desk service",
             "continental breakfast",
             "free wifi"
           ]
         },
         {
           "@search.score": 4.885111,
           "@search.rerankerScore": 2.0008862018585205,
           "HotelName": "Double Sanctuary Resort",
           "Description": "5 star Luxury Hotel - Biggest Rooms in the city. #1 Hotel in the area listed by Traveler magazine. Free WiFi, Flexible check in/out, Fitness Center & espresso in room.",
           "Tags": [
             "view",
             "pool",
             "restaurant",
             "bar",
             "continental breakfast"
           ]
         }
       ]
    
  4. Richten Sie eine Gesprächssequenz mit einem Chat-Vervollständigungsmodell ein. Diese Anforderung enthält eine Eingabeaufforderung, die Anweisungen für die Antwort bereitstellt. Der max_tokens Wert ist groß genug, um die Suchergebnisse aus der vorherigen Abfrage aufzunehmen.

     POST {{aoaiUrl}}/openai/deployments/{{aoaiGptDeployment}}/chat/completions?api-version=2024-08-01-preview HTTP/1.1
     Content-Type: application/json
     Authorization: Bearer {{aoaiAccessToken}}
    
     {
     "messages": [
     {
       "role": "system", 
       "content": "You  are a friendly assistant that recommends hotels based on activities and amenities. Answer the query using only the search result. Answer in a friendly and concise manner. Answer ONLY with the facts provided. If there isn't enough information below, say you don't know."
         },
     {
       "role": "user",
       "content": "Based on the hotel search results, can you recommend hotels with breakfast? Here are all the hotels I found:\n\nHotel 1: {{searchRequest.response.body.value[0].HotelName}}\nDescription: {{searchRequest.response.body.value[0].Description}}\n\nHotel 2: {{searchRequest.response.body.value[1].HotelName}}\nDescription: {{searchRequest.response.body.value[1].Description}}\n\nHotel 3: {{searchRequest.response.body.value[2].HotelName}}\nDescription: {{searchRequest.response.body.value[2].Description}}\n\nHotel 4: {{searchRequest.response.body.value[3].HotelName}}\nDescription: {{searchRequest.response.body.value[3].Description}}\n\nHotel 5: {{searchRequest.response.body.value[4].HotelName}}\nDescription: {{searchRequest.response.body.value[4].Description}}\n\nPlease recommend which hotels offer breakfast based on their descriptions."
     }
     ],
     "max_tokens": 1000,
     "temperature": 0.7
     }
    
  5. Senden Sie die Anforderung.

  6. Die Ausgabe sollte eine HTTP 200-Erfolgsstatusmeldung sein. In der Ausgabe enthalten sind Inhalte, die die Frage beantworten:

     "message": {
       "annotations": [],
       "content": "I recommend the following hotels that offer breakfast:\n\n1. **Head Wind Resort** - Offers a complimentary continental breakfast in the lobby.\n2. **Swan Bird Lake Inn** - Serves a continental-style breakfast each morning, including a variety of food and drinks. \n\nEnjoy your stay!",
       "refusal": null,
       "role": "assistant"
     }
    

Beachten Sie, dass in der Ausgabe mehrere Hotels fehlen, in denen das Frühstück im Feld "Tags" erwähnt wird. Das Feld "Tags" ist ein Array, und die Einbeziehung dieses Felds beschädigt die JSON-Struktur in den Ergebnissen. Da im REST-Client keine Zeichenfolgenkonvertierungsfunktionen vorhanden sind, ist zusätzlicher Code zum manuellen Konvertieren des JSON-Codes in eine Zeichenfolge erforderlich, wenn Arrays einbezogen werden sollen. Dieser Schritt wird für diese Schnellstartanleitung weggelassen.

Bereinigung

Wenn Sie in Ihrem eigenen Abonnement arbeiten, sollten Sie sich am Ende eines Projekts überlegen, ob Sie die erstellten Ressourcen noch benötigen. Ressourcen, die weiterhin ausgeführt werden, können Geld kosten. Sie können entweder einzelne Ressourcen oder aber die Ressourcengruppe löschen, um den gesamten Ressourcensatz zu entfernen.

Ressourcen können im Azure-Portal über den Link Alle Ressourcen oder Ressourcengruppen im linken Navigationsbereich gesucht und verwaltet werden.

Voraussetzungen

Konfigurieren des Zugriffs

Anforderungen an den Suchendpunkt müssen authentifiziert und autorisiert werden. Sie können für diese Aufgabe API-Schlüssel oder Rollen verwenden. Schlüssel sind für ein Einstieg einfacher, Rollen sind jedoch sicherer. In diesem Schnellstart werden Rollen vorausgesetzt.

Sie richten zwei Clients ein, daher benötigen Sie Berechtigungen für beide Ressourcen.

Azure KI-Suche empfängt die Abfrageanforderung von Ihrem lokalen System. Weisen Sie sich selbst die Rolle Suchindexdatenleser zu, wenn der Beispielindex für Hotels bereits vorhanden ist. Wenn sie nicht vorhanden ist, weisen Sie sich die Rollen Mitwirkender von Suchdienst und Mitwirkender an Suchindexdaten zu, damit Sie den Index erstellen und abfragen können.

Azure OpenAI empfängt die Abfrage und die Suchergebnisse aus Ihrem lokalen System. Weisen Sie sich in Azure OpenAI die Rolle Cognitive Services OpenAI-Benutzer zu.

  1. Melden Sie sich beim Azure-Portal an.

  2. Konfigurieren von Azure KI-Suche für rollenbasierten Zugriff:

    1. Suchen Sie im Azure-Portal nach Ihrem Azure KI-Suchdienst.

    2. Wählen Sie im linken Menü Einstellungen>Schlüsselaus, und wählen Sie dann entweder die Option Rollenbasierte Zugriffssteuerung oder Beides aus.

  3. Zuweisen von Rollen:

    1. Wählen Sie im linken Menü Zugriffssteuerung (IAM) aus.

    2. Wählen Sie in Azure KI-Suche diese Rollen aus, um einen Suchindex zu erstellen, zu laden und abzufragen, und weisen Sie sie dann Ihrer Microsoft Entra ID-Benutzeridentität zu:

      • Mitwirkender an Suchindexdaten
      • Mitwirkender von Suchdienst
    3. Wählen Sie in Azure OpenAI Zugriffssteuerung (IAM) aus, um sich diese Rolle in Azure OpenAI selbst zuzuweisen:

      • Cognitive Services OpenAI-Benutzer

Es kann einige Minuten dauern, bis die Berechtigungen in Kraft treten.

Erstellen eines Index

Ein Suchindex stellt Groundingdaten für das Chatmodell bereit. Wir empfehlen den Index hotels-sample-index, der in Minuten erstellt und auf jeder Suchdienstebene ausgeführt werden kann. Dieser Index wird mit integrierten Beispieldaten erstellt.

  1. Suchen Sie im Azure-Portal nach Ihrem Suchdienst.

  2. Wählen Sie auf der Startseite Übersicht die Option Daten importieren aus, um den Assistenten zu starten.

  3. Wählen Sie auf der Seite Mit Ihren Daten verbinden die Option Beispiele aus der Dropdownliste aus.

  4. Wählen Sie das Beispiel hotels-sample aus.

  5. Wählen Sie auf den restlichen Seiten jeweils Weiter aus, und akzeptieren Sie die Standardwerte.

  6. Nachdem der Index erstellt wurde, wählen Sie im linken Menü Suchverwaltung>Indizes aus, um den Index zu öffnen.

  7. Wählen Sie JSON bearbeiten aus.

  8. Scrollen Sie zum Ende des Indexes, wo Sie Platzhalter für Konstrukte finden, die zu einem Index hinzugefügt werden können.

    "analyzers": [],
    "tokenizers": [],
    "tokenFilters": [],
    "charFilters": [],
    "normalizers": [],
    
  9. Fügen Sie in einer neuen Zeile nach „normalizers“ die folgende semantische Konfiguration ein. In diesem Beispiel wird "defaultConfiguration" angegeben, was für die Ausführung dieses Schnellstarts wichtig ist.

    "semantic":{
       "defaultConfiguration":"semantic-config",
       "configurations":[
          {
             "name":"semantic-config",
             "prioritizedFields":{
                "titleField":{
                   "fieldName":"HotelName"
                },
                "prioritizedContentFields":[
                   {
                      "fieldName":"Description"
                   }
                ],
                "prioritizedKeywordsFields":[
                   {
                      "fieldName":"Category"
                   },
                   {
                      "fieldName":"Tags"
                   }
                ]
             }
          }
       ]
    },
    
  10. Speichern Sie die Änderungen.

  11. Führen Sie die folgende Abfrage im Such-Explorer aus, um den Index zu testen: complimentary breakfast.

    Die Ausgabe sollte etwa folgendem Beispiel entsprechen. Die Ergebnisse, die direkt von der Suchmaschine zurückgegeben werden, bestehen aus Feldern und deren wörtlichen Werten, zusammen mit Metadaten wie einem Suchergebnis und einem Ergebnis für das semantische Ranking sowie einer Beschriftung, wenn Sie den semantischen Sortierer verwenden. Wir haben eine Auswahlanweisung verwendet, um nur die Felder „HotelName“, „Beschreibung“ und „Tags“ zurückzugeben.

    {
    "@odata.count": 18,
    "@search.answers": [],
    "value": [
       {
          "@search.score": 2.2896252,
          "@search.rerankerScore": 2.506816864013672,
          "@search.captions": [
          {
             "text": "Head Wind Resort. Suite. coffee in lobby\r\nfree wifi\r\nview. The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a **complimentary continental breakfast** in the lobby, and free Wi-Fi throughout the hotel..",
             "highlights": ""
          }
          ],
          "HotelName": "Head Wind Resort",
          "Description": "The best of old town hospitality combined with views of the river and cool breezes off the prairie. Our penthouse suites offer views for miles and the rooftop plaza is open to all guests from sunset to 10 p.m. Enjoy a complimentary continental breakfast in the lobby, and free Wi-Fi throughout the hotel.",
          "Tags": [
          "coffee in lobby",
          "free wifi",
          "view"
          ]
       },
       {
          "@search.score": 2.2158256,
          "@search.rerankerScore": 2.288334846496582,
          "@search.captions": [
          {
             "text": "Swan Bird Lake Inn. Budget. continental breakfast\r\nfree wifi\r\n24-hour front desk service. We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins..",
             "highlights": ""
          }
          ],
          "HotelName": "Swan Bird Lake Inn",
          "Description": "We serve a continental-style breakfast each morning, featuring a variety of food and drinks. Our locally made, oh-so-soft, caramel cinnamon rolls are a favorite with our guests. Other breakfast items include coffee, orange juice, milk, cereal, instant oatmeal, bagels, and muffins.",
          "Tags": [
          "continental breakfast",
          "free wifi",
          "24-hour front desk service"
          ]
       },
       {
          "@search.score": 0.92481667,
          "@search.rerankerScore": 2.221315860748291,
          "@search.captions": [
          {
             "text": "White Mountain Lodge & Suites. Resort and Spa. continental breakfast\r\npool\r\nrestaurant. Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings..",
             "highlights": ""
          }
          ],
          "HotelName": "White Mountain Lodge & Suites",
          "Description": "Live amongst the trees in the heart of the forest. Hike along our extensive trail system. Visit the Natural Hot Springs, or enjoy our signature hot stone massage in the Cathedral of Firs. Relax in the meditation gardens, or join new friends around the communal firepit. Weekend evening entertainment on the patio features special guest musicians or poetry readings.",
          "Tags": [
          "continental breakfast",
          "pool",
          "restaurant"
          ]
       },
       . . .
    ]}
    

Abrufen von Dienstendpunkten

In den verbleibenden Abschnitten richten Sie API-Aufrufe für Azure OpenAI und die Azure KI-Suche ein. Rufen Sie die Dienstendpunkte ab, damit Sie sie als Variablen im Code bereitstellen können.

  1. Melden Sie sich beim Azure-Portal an.

  2. Suchen Sie Ihren Suchdienst.

  3. Sie finden die URL auf der Startseite Übersicht. Ein Beispiel für einen Endpunkt ist https://example.search.windows.net.

  4. Suchen Sie Ihren Azure OpenAI-Dienst.

  5. Wählen Sie auf der Startseite Übersicht den Link aus, um die Endpunkte anzuzeigen. Kopieren Sie die URL. Ein Beispiel für einen Endpunkt ist https://example.openai.azure.com/.

Einrichten von Umgebungsvariablen für die lokale Entwicklung

  1. Erstellen Sie die Datei .env.

  2. Fügen Sie der .env Datei die folgenden Umgebungsvariablen hinzu, und ersetzen Sie die Werte durch Ihre eigenen Dienstendpunkte und Schlüssel.

    AZURE_SEARCH_ENDPOINT=<YOUR AZURE AI SEARCH ENDPOINT>
    AZURE_SEARCH_INDEX_NAME=hotels-sample-index
    
    AZURE_OPENAI_ENDPOINT=<YOUR AZURE OPENAI ENDPOINT>
    AZURE_OPENAI_VERSION=<YOUR AZURE OPENAI API VERSION>
    AZURE_DEPLOYMENT_MODEL=<YOUR DEPLOYMENT NAME>
    

Einrichten des Node.JS Projekts

Einrichten des Projekts mit Visual Studio Code und TypeScript.

  1. Starten Sie Visual Studio Code in einem neuen Verzeichnis.

    mkdir rag-quickstart && cd rag-quickstart
    code .
    
  2. Erstellen Sie ein neues Paket für ESM-Module in Ihrem Projektverzeichnis.

    npm init -y
    npm pkg set type=module
    

    Dadurch wird eine package.json Datei mit Standardwerten erstellt.

  3. Installieren Sie die folgenden npm-Pakete.

    npm install @azure/identity @azure/search-documents openai dotenv @types/node
    
  4. Erstellen Sie ein src Verzeichnis in Ihrem Projektverzeichnis.

    mkdir src
    
  5. Erstellen Sie eine tsconfig.json Datei im Projektverzeichnis für ESM mit dem folgenden Inhalt.

    {
      "compilerOptions": {
        "target": "esnext",
        "module": "NodeNext",
        "moduleResolution": "nodenext",
        "rootDir": "./src",
        "outDir": "./dist/",
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true,
        "declaration": true,
        "sourceMap": true,
        "resolveJsonModule": true,
        "moduleDetection": "force", // Add this for ESM
        "allowSyntheticDefaultImports": true // Helpful for ESM interop
      },
      "include": [
        "src/**/*.ts"
      ]
    }
    

Anmelden bei Azure

Sie verwenden Microsoft Entra ID und Rollenzuweisungen für die Verbindung. Stellen Sie sicher, dass Sie bei demselben Mandanten und Abonnement wie Azure KI-Suche und Azure OpenAI angemeldet sind. Sie können die Azure CLI in der Befehlszeile verwenden, um aktuelle Eigenschaften anzuzeigen, sie zu ändern und um sich anzumelden. Weitere Informationen finden Sie unter Herstellen einer Verbindung ohne Schlüssel.

Führen Sie die folgenden Befehle nacheinander aus.

az account show

az account set --subscription <PUT YOUR SUBSCRIPTION ID HERE>

az login --tenant <PUT YOUR TENANT ID HERE>

Sie sollten jetzt von Ihrem lokalen Gerät aus bei Azure angemeldet sein.

Einrichten von Abfrage- und Chatthreads

Erstellen Sie ein Abfrageskript, das den Azure AI Search-Index und das Chatmodell verwendet, um Antworten basierend auf Erdungsdaten zu generieren. Die folgenden Schritte führen Sie durch das Einrichten des Abfrageskripts.

  1. Erstellen Sie eine query.ts Datei im src Verzeichnis mit dem folgenden Code.

    // This is a RAG (Retrieval Augmented Generation) implementation that:
    // 1. Takes a user query about hotels
    // 2. Searches a hotel database using Azure AI Search
    // 3. Formats the search results for the LLM
    // 4. Sends the query and formatted results to Azure OpenAI
    // 5. Returns a grounded response based only on the retrieved information
    
    import { SearchClient, AzureKeyCredential, SearchDocumentsResult } from "@azure/search-documents";
    import { AzureOpenAI } from "openai";
    import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
    
    function getClients(): { openaiClient: AzureOpenAI, searchClient: SearchClient<{ HotelName: string; Description: string; Tags: string[] | string }>, modelName: string }  {
    
        const credential = new DefaultAzureCredential();
    
        // Search
        const azureSearchEndpoint = process.env.AZURE_SEARCH_ENDPOINT!;
        const azureSearchIndexName = process.env.AZURE_SEARCH_INDEX_NAME!;
    
        const searchClient = new SearchClient<{ HotelName: string; Description: string; Tags: string[] | string }>(
            azureSearchEndpoint,
            azureSearchIndexName,
            credential
        );
    
    
        // OpenAI
        const azureOpenAiEndpoint = process.env.AZURE_OPENAI_ENDPOINT!;
        const azureOpenAiApiVersion = process.env.AZURE_OPENAI_VERSION!;
        const azureOpenAiDeploymentName = process.env.AZURE_DEPLOYMENT_MODEL!;
    
        const scope = "https://cognitiveservices.azure.com/.default";
        const azureADTokenProvider = getBearerTokenProvider(credential, scope);
        const options = { azureADTokenProvider, deployment: azureOpenAiDeploymentName, apiVersion: azureOpenAiApiVersion, endpoint: azureOpenAiEndpoint }
        const openaiClient = new AzureOpenAI(options);
    
        return { openaiClient, searchClient, modelName: azureOpenAiDeploymentName };
    }
    
    async function queryAISearchForSources(searchClient: SearchClient<{ HotelName: string; Description: string; Tags: string[] | string }>, query: string): Promise<string> {
        console.log(`Searching for: "${query}"\n`);
        const searchResults: SearchDocumentsResult<{ HotelName: string; Description: string; Tags: string[] | string }> = await searchClient.search(query, {
            top: 5,
            select: ["Description", "HotelName", "Tags"]
        });
    
        const sources: string[] = [];
        for await (const result of searchResults.results) {
            const doc = result.document;
            sources.push(
                `Hotel: ${doc.HotelName}\n` +
                `Description: ${doc.Description}\n` +
                `Tags: ${Array.isArray(doc.Tags) ? doc.Tags.join(', ') : doc.Tags}\n`
            );
        }
        const sourcesFormatted = sources.join("\n---\n");
        return sourcesFormatted;
    }
    async function queryOpenAIForResponse(
        openaiClient: AzureOpenAI, 
        query: string, 
        sourcesFormatted: string, 
        modelName: string
    ): Promise<{ choices: { message: { content: string | null } }[] }> {
    
        const GROUNDED_PROMPT = `
     You are a friendly assistant that recommends hotels based on activities and amenities.
     Answer the query using only the sources provided below in a friendly and concise bulleted manner.
     Answer ONLY with the facts listed in the list of sources below.
     If there isn't enough information below, say you don't know.
     Do not generate answers that don't use the sources below.
    
    Query: {query}
    Sources: {sources}
    `;
    
        return openaiClient.chat.completions.create({
            model: modelName,
            messages: [
                {
                    role: "user",
                    content: GROUNDED_PROMPT.replace("{query}", query).replace("{sources}", sourcesFormatted),
                }
            ],
            temperature: 0.7,
            max_tokens: 800,
        });
    }
    
    async function main():Promise<void> {
    
        const { openaiClient, searchClient, modelName } = getClients();
    
        const query = "Can you recommend a few hotels with complimentary breakfast?";
    
        const sources = await queryAISearchForSources(searchClient, query);
        const response = await queryOpenAIForResponse(openaiClient, query, sources, modelName);
    
        // Print the response from the chat model
        const content = response.choices[0].message.content;
        if (content) {
            console.log(content);
        } else {
            console.log("No content available in the response.");
        }
    }
    
    main().catch((error) => {
        console.error("An error occurred:", error);
        process.exit(1);
    });
    

    Der vorangehende Code führt folgende Aktionen aus:

    • Importiert die erforderlichen Bibliotheken für Azure AI Search und Azure OpenAI.
    • Verwendet Umgebungsvariablen zum Konfigurieren der Azure AI Search- und Azure OpenAI-Clients.
    • Definiert eine Funktion zum Abrufen der Clients für Azure AI Search und Azure OpenAI unter Verwendung von Umgebungsvariablen für die Konfiguration.
    • Definiert eine Funktion zum Abfragen von Azure AI Search nach Quellen basierend auf der Benutzerabfrage.
    • Definiert eine Funktion zum Abfragen von Azure OpenAI für eine Antwort basierend auf der Benutzerabfrage und den aus Azure AI Search abgerufenen Quellen.
    • Die main Funktion koordiniert den Fluss durch Aufrufen der Such- und OpenAI-Funktionen und druckt dann die Antwort.
  2. Erstellen Sie den TypeScript-Code in JavaScript.

    tsc
    

    Dieser Befehl kompiliert den TypeScript-Code im src Verzeichnis und gibt die JavaScript-Dateien im dist Verzeichnis aus.

  3. Führen Sie den folgenden Befehl in einem Terminal aus, um das Abfrageskript auszuführen:

    node -r dotenv/config dist/query.js
    

    .env wird mithilfe von -r dotenv/config in die Runtime übergeben.

  4. Sehen Sie sich die Ausgabe an, die aus mehreren Hotelempfehlungen besteht. Hier sehen Sie ein Beispiel für eine mögliche Ausgabe:

    Sure! Here are a few hotels that offer complimentary breakfast:
    
    - **Head Wind Resort**
    - Complimentary continental breakfast in the lobby
    - Free Wi-Fi throughout the hotel
    
    - **Double Sanctuary Resort**
    - Continental breakfast included
    
    - **White Mountain Lodge & Suites**
    - Continental breakfast available
    
    - **Swan Bird Lake Inn**
    - Continental-style breakfast each morning with a variety of food and drinks 
        such as caramel cinnamon rolls, coffee, orange juice, milk, cereal, 
        instant oatmeal, bagels, and muffins
    

Problembehandlung

Wenn Sie die Fehlermeldung Verboten erhalten, überprüfen Sie die Konfiguration für Azure KI-Suche, um sicherzustellen, dass der rollenbasierte Zugriff aktiviert ist.

Wenn Sie die Fehlermeldung Autorisierung fehlgeschlagen erhalten, warten Sie einige Minuten, und versuchen Sie es erneut. Es kann mehrere Minuten dauern, bis Rollenzuweisungen betriebsbereit sind.

Wenn sie die Fehlermeldung Ressource nicht gefunden erhalten, überprüfen Sie die Ressourcen-URIs, und stellen Sie sicher, dass die API-Version des Chatmodells gültig ist.

Ändern Sie andernfalls um weiter zu experimentieren die Abfrage, und führen Sie den letzten Schritt erneut aus, um besser zu verstehen, wie das Modell mit den Groundingdaten funktioniert.

Sie können auch den Prompt ändern, um den Ton oder die Struktur der Ausgabe zu ändern.

Sie können die Abfrage auch ohne semantische Rangfolge ausprobieren, indem Sie use_semantic_reranker=False im Abfrageparameterschritt festlegen. Die semantische Rangfolge kann die Relevanz von Abfrageergebnissen und die Fähigkeit des LLM, nützliche Informationen zurückzugeben, deutlich verbessern. Durch Experimentieren können Sie herausfinden, ob es für Ihre Inhalte einen Unterschied macht.

Senden einer komplexen RAG-Abfrage

Azure KI-Suche unterstützt komplexe Typen für geschachtelte JSON-Strukturen. Im Hotelbeispielindex ist Address ein Beispiel für einen komplexen Typ, bestehend aus Address.StreetAddress, Address.City, Address.StateProvince, Address.PostalCode und Address.Country. Der Index verfügt auch über eine komplexe Sammlung von Rooms für jedes Hotel.

Wenn Ihr Index komplexe Typen aufweist, ändern Sie Die Aufforderung so, dass Formatierungsanweisungen eingeschlossen werden:

Can you recommend a few hotels that offer complimentary breakfast? 
Tell me their description, address, tags, and the rate for one room that sleeps 4 people.
  1. Erstellen Sie eine neue Datei queryComplex.ts im src Verzeichnis.

  2. Kopieren Sie den folgenden Code in die Datei:

    // This is a RAG (Retrieval Augmented Generation) implementation that:
    // 1. Takes a user query about hotels
    // 2. Searches a hotel database using Azure AI Search
    // 3. Formats the search results for the LLM
    // 4. Sends the query and formatted results to Azure OpenAI
    // 5. Returns a grounded response based only on the retrieved information
    
    import { SearchClient, SearchDocumentsResult } from "@azure/search-documents";
    import { AzureOpenAI } from "openai";
    import { DefaultAzureCredential, getBearerTokenProvider } from "@azure/identity";
    
    function getClients(): { openaiClient: AzureOpenAI; searchClient: SearchClient<{ HotelName: string; Description: string; Tags: string[] | string; Address: string; Rooms: string }>; modelName: string }  {
    
        const credential = new DefaultAzureCredential();
    
        // Search
        const azureSearchEndpoint = process.env.AZURE_SEARCH_ENDPOINT!;
        const azureSearchIndexName = process.env.AZURE_SEARCH_INDEX_NAME!;
        const searchClient = new SearchClient<{ HotelName: string; Description: string; Tags: string[] | string; Address: string; Rooms: string }>(
            azureSearchEndpoint,
            azureSearchIndexName,
            credential
        );
    
        // OpenAI
        const azureOpenAiEndpoint = process.env.AZURE_OPENAI_ENDPOINT!;
        const azureOpenAiApiVersion = process.env.AZURE_OPENAI_VERSION!;
        const azureOpenAiDeploymentName = process.env.AZURE_DEPLOYMENT_MODEL!;
    
        const scope = "https://cognitiveservices.azure.com/.default";
        const azureADTokenProvider = getBearerTokenProvider(credential, scope);
        const options = { azureADTokenProvider, deployment: azureOpenAiDeploymentName, apiVersion: azureOpenAiApiVersion, endpoint: azureOpenAiEndpoint }
        const openaiClient = new AzureOpenAI(options);
    
        return { openaiClient, searchClient, modelName: azureOpenAiDeploymentName };
    }
    
    
    async function queryAISearchForSources(
        searchClient: SearchClient<{ HotelName: string; Description: string; Tags: string[] | string; Address: string; Rooms: string }>,
        query: string
    ): Promise<SearchDocumentsResult<{ HotelName: string; Description: string; Tags: string[] | string; Address: string; Rooms: string }>> {
        console.log(`Searching for: "${query}"\n`);
    
        const selectedFields: readonly ["HotelName", "Description", "Address", "Rooms", "Tags"] = ["HotelName", "Description", "Address", "Rooms", "Tags"];
        const searchResults = await searchClient.search(query, {
            top: 5,
            select: selectedFields,
            queryType: "semantic",
            semanticSearchOptions: {},
        });
    
        return searchResults;
    }
    async function queryOpenAIForResponse(
        openaiClient: AzureOpenAI, 
        query: string, 
        sourcesFormatted: string, 
        modelName: string
    ): Promise<{ choices: { message: { content: string | null } }[] }> {
    
        const GROUNDED_PROMPT = `
     You are a friendly assistant that recommends hotels based on activities and amenities.
     Answer the query using only the sources provided below in a friendly and concise bulleted manner.
     Answer ONLY with the facts listed in the list of sources below.
     If there isn't enough information below, say you don't know.
     Do not generate answers that don't use the sources below.
    
    Query: {query}
    Sources: {sources}
    `;
    
        return openaiClient.chat.completions.create({
            model: modelName,
            messages: [
                {
                    role: "user",
                    content: GROUNDED_PROMPT.replace("{query}", query).replace("{sources}", sourcesFormatted),
                }
            ],
            temperature: 0.7,
            max_tokens: 800,
        });
    }
    
    async function main(): Promise<void> {
    
        const { openaiClient, searchClient, modelName } = getClients();
    
        const query = `
        Can you recommend a few hotels that offer complimentary breakfast? 
        Tell me their description, address, tags, and the rate for one room that sleeps 4 people.
        `;
    
        const sourcesResult = await queryAISearchForSources(searchClient, query);
        let sourcesFormatted = "";
    
        for await (const result of sourcesResult.results) {
            // Explicitly typing result to ensure compatibility
            sourcesFormatted += JSON.stringify(result.document) + "\n";
        }
    
        const response = await queryOpenAIForResponse(openaiClient, query, sourcesFormatted.trim(), modelName);
    
        // Print the response from the chat model
        const content = response.choices[0].message.content;
        if (content) {
            console.log(content);
        } else {
            console.log("No content available in the response.");
        }
    }
    
    main().catch((error) => {
        console.error("An error occurred:", error);
        process.exit(1);
    });
    
  3. Erstellen Sie den TypeScript-Code in JavaScript.

    tsc
    

    Dieser Befehl kompiliert den TypeScript-Code im src Verzeichnis und gibt die JavaScript-Dateien im dist Verzeichnis aus.

  4. Führen Sie den folgenden Befehl in einem Terminal aus, um das Abfrageskript auszuführen:

    node -r dotenv/config dist/queryComplex.js
    

    .env wird mithilfe von -r dotenv/config in die Runtime übergeben.

  5. Zeigen Sie die Ausgabe von Azure OpenAI an, und sie fügt Inhalte aus komplexen Typen hinzu.

Here are a few hotels that offer complimentary breakfast and have rooms that sleep 4 people:

1. **Head Wind Resort**
   - **Description:** The best of old town hospitality combined with views of the river and 
   cool breezes off the prairie. Enjoy a complimentary continental breakfast in the lobby, 
   and free Wi-Fi throughout the hotel.
   - **Address:** 7633 E 63rd Pl, Tulsa, OK 74133, USA
   - **Tags:** Coffee in lobby, free Wi-Fi, view
   - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99

2. **Double Sanctuary Resort**
   - **Description:** 5-star Luxury Hotel - Biggest Rooms in the city. #1 Hotel in the area 
   listed by Traveler magazine. Free WiFi, Flexible check in/out, Fitness Center & espresso 
   in room. Offers continental breakfast.
   - **Address:** 2211 Elliott Ave, Seattle, WA 98121, USA
   - **Tags:** View, pool, restaurant, bar, continental breakfast
   - **Room for 4:** Suite, 2 Queen Beds (Amenities) - $254.99

3. **Swan Bird Lake Inn**
   - **Description:** Continental-style breakfast featuring a variety of food and drinks. 
   Locally made caramel cinnamon rolls are a favorite.
   - **Address:** 1 Memorial Dr, Cambridge, MA 02142, USA
   - **Tags:** Continental breakfast, free Wi-Fi, 24-hour front desk service
   - **Room for 4:** Budget Room, 2 Queen Beds (City View) - $85.99

4. **Gastronomic Landscape Hotel**
   - **Description:** Known for its culinary excellence under the management of William Dough, 
   offers continental breakfast.
   - **Address:** 3393 Peachtree Rd, Atlanta, GA 30326, USA
   - **Tags:** Restaurant, bar, continental breakfast
   - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $66.99
...
   - **Tags:** Pool, continental breakfast, free parking
   - **Room for 4:** Budget Room, 2 Queen Beds (Amenities) - $60.99

Enjoy your stay! Let me know if you need any more information.

Problembehandlung

Um Azure SDK-Fehler zu debuggen, legen Sie die Umgebungsvariable AZURE_LOG_LEVEL auf eine der folgenden Werte fest: verbose, , info, . warningerror Dadurch wird die detaillierte Protokollierung für das Azure SDK ermöglicht, wodurch Probleme mit Authentifizierung, Netzwerkkonnektivität oder anderen Problemen identifiziert werden können.

Führen Sie das Abfrageskript erneut aus. Sie sollten jetzt informative Anweisungen von den SDKs in der Ausgabe abrufen, die weitere Details zu Problemen bereitstellen.

Wenn Sie Ausgabemeldungen im Zusammenhang mit ManagedIdentityCredential und dem fehlgeschlagenen Token-Erwerb sehen, könnte es sein, dass Sie mehrere Mandanten haben und Ihre Azure-Anmeldung über einen Mandanten erfolgt, der nicht über Ihren Suchdienst verfügt. Um Ihre Mandanten-ID zu erhalten, suchen Sie im Azure-Portal nach „Mandanteneigenschaften“, oder führen Sie az login tenant list aus.

Wenn Sie über eine Mandanten-ID verfügen, führen Sie an einer Eingabeaufforderung az login --tenant <YOUR-TENANT-ID> aus, und führen Sie dann das Skript erneut aus.

Bereinigung

Wenn Sie in Ihrem eigenen Abonnement arbeiten, sollten Sie sich am Ende eines Projekts überlegen, ob Sie die erstellten Ressourcen noch benötigen. Ressourcen, die weiterhin ausgeführt werden, können Geld kosten. Sie können entweder einzelne Ressourcen oder aber die Ressourcengruppe löschen, um den gesamten Ressourcensatz zu entfernen.

Ressourcen können im Azure-Portal über den Link Alle Ressourcen oder Ressourcengruppen im linken Navigationsbereich gesucht und verwaltet werden.