|
| 1 | +--- |
| 2 | +manager: nitinme |
| 3 | +author: heidisteen |
| 4 | +ms.author: haileytapia |
| 5 | +ms.service: azure-ai-search |
| 6 | +ms.topic: include |
| 7 | +ms.date: 07/08/2025 |
| 8 | +--- |
| 9 | + |
| 10 | +## Prerequisites |
| 11 | + |
| 12 | +- An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/?WT.mc_id=A261C142F). |
| 13 | + |
| 14 | +- An [Azure OpenAI resource](/azure/ai-services/openai/how-to/create-resource). |
| 15 | + - [Choose a region](/azure/ai-services/openai/concepts/models?tabs=global-standard%2Cstandard-chat-completions#global-standard-model-availability) that supports the chat completion model you want to use (gpt-4o, gpt-4o-mini, or an equivalent model). |
| 16 | + - [Deploy the chat completion model](/azure/ai-foundry/how-to/deploy-models-openai) in Azure AI Foundry or [use another approach](/azure/ai-services/openai/how-to/working-with-models). |
| 17 | +- An [Azure AI Search resource](../../search-create-service-portal.md). |
| 18 | + - We recommend using the Basic tier or higher. |
| 19 | + - [Enable semantic ranking](../../semantic-how-to-enable-disable.md). |
| 20 | + |
| 21 | +- A [new or existing index](../../search-how-to-create-search-index.md) with descriptive or verbose text fields, attributed as retrievable in your index. This quickstart assumes the [hotels-sample-index](../../search-get-started-portal.md). |
| 22 | + |
| 23 | +- The [Azure CLI](/cli/azure/install-azure-cli) for keyless authentication with Microsoft Entra ID. |
| 24 | + |
| 25 | +- [Visual Studio Code](https://code.visualstudio.com/download) with the [REST client extension](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) . |
| 26 | + |
| 27 | +## Download file |
| 28 | + |
| 29 | +[Download a .rest file](https://github.com/Azure-Samples/azure-search-rest-samples/tree/main/Quickstart-RAG) from GitHub to send the requests in this quickstart. For more information, see [Downloading files from GitHub](https://docs.github.com/get-started/start-your-journey/downloading-files-from-github). |
| 30 | + |
| 31 | +You can also start a new file on your local system and create requests manually by using the instructions in this article. |
| 32 | + |
| 33 | +## Configure access |
| 34 | + |
| 35 | +Requests to the search endpoint must be authenticated and authorized. You can use [API keys](../../search-security-api-keys.md) or roles for this task. Keys are easier to start with, but roles are more secure. This quickstart assumes roles. |
| 36 | + |
| 37 | +You're setting up two clients, so you need permissions on both resources. |
| 38 | + |
| 39 | +Azure AI Search is receiving the query request from your local system. Assign yourself the **Search Index Data Reader** role assignment if the hotels sample index already exists. If it doesn't exist, assign yourself **Search Service Contributor** and **Search Index Data Contributor** roles so that you can create and query the index. |
| 40 | + |
| 41 | +Azure OpenAI is receiving the query and the search results from your local system. Assign yourself the **Cognitive Services OpenAI User** role on Azure OpenAI. |
| 42 | + |
| 43 | +1. Sign in to the [Azure portal](https://portal.azure.com). |
| 44 | + |
| 45 | +1. Configure Azure AI Search for role-based access: |
| 46 | + |
| 47 | + 1. In the Azure portal, find your Azure AI Search service. |
| 48 | + |
| 49 | + 1. On the left menu, select **Settings** > **Keys**, and then select either **Role-based access control** or **Both**. |
| 50 | + |
| 51 | +1. Assign roles: |
| 52 | + |
| 53 | + 1. On the left menu, select **Access control (IAM)**. |
| 54 | + |
| 55 | + 1. On Azure AI Search, select these roles to create, load, and query a search index, and then assign them to your Microsoft Entra ID user identity: |
| 56 | + |
| 57 | + - **Search Index Data Contributor** |
| 58 | + - **Search Service Contributor** |
| 59 | + |
| 60 | + 1. On Azure OpenAI, select **Access control (IAM)** to assign this role to yourself on Azure OpenAI: |
| 61 | + |
| 62 | + - **Cognitive Services OpenAI User** |
| 63 | + |
| 64 | +It can take several minutes for permissions to take effect. |
| 65 | + |
| 66 | +## Get service endpoints and tokens |
| 67 | + |
| 68 | +In the remaining sections, you set up API calls to Azure OpenAI and Azure AI Search. Get the service endpoints and tokens so that you can provide them as variables in your code. |
| 69 | + |
| 70 | +1. Sign in to the [Azure portal](https://portal.azure.com). |
| 71 | + |
| 72 | +1. [Find your search service](https://portal.azure.com/#blade/HubsExtension/BrowseResourceBlade/resourceType/Microsoft.Search%2FsearchServices). |
| 73 | + |
| 74 | +1. On the **Overview** home page, copy the URL. An example endpoint might look like `https://example.search.windows.net`. |
| 75 | + |
| 76 | +1. [Find your Azure OpenAI service](https://portal.azure.com/#blade/HubsExtension/BrowseResourceBlade/resourceType/Microsoft.CognitiveServices%2Faccounts). |
| 77 | + |
| 78 | +1. On the **Overview** home page, select the link to view the endpoints. Copy the URL. An example endpoint might look like `https://example.openai.azure.com/`. |
| 79 | + |
| 80 | +1. Get personal access tokens from the Azure CLI on a command prompt. Here are the commands for each resource: |
| 81 | + |
| 82 | + - `az account get-access-token --resource https://search.azure.com --query "accessToken" -o tsv` |
| 83 | + - `az account get-access-token --resource https://cognitiveservices.azure.com --query "accessToken" -o tsv` |
| 84 | + |
| 85 | +## Set up the client |
| 86 | + |
| 87 | +In this quickstart, you use a REST client and the [Azure AI Search REST APIs](/rest/api/searchservice) to implement the RAG pattern. |
| 88 | + |
| 89 | +We recommend [Visual Studio Code](https://code.visualstudio.com/download) with a [REST client extension](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) for this quickstart. |
| 90 | + |
| 91 | +> [!TIP] |
| 92 | +> You can [download the source code](https://github.com/Azure-Samples/azure-search-rest-samples/tree/main/Quickstart-rag) to start with a finished project or follow these steps to create your own. |
| 93 | +
|
| 94 | +1. Start Visual Studio Code and open the [quickstart-rag.rest](https://github.com/Azure-Samples/azure-search-rest-samples/blob/main/Quickstart-rag/quickstart-rag.rest) file or create a new file. |
| 95 | + |
| 96 | +1. At the top, set environment variables for your search service, authorization, and index name. |
| 97 | + |
| 98 | + - For @searchUrl, paste in the search endpoint. |
| 99 | + - For @aoaiUrl, paste in the Azure OpenAI endpoint. |
| 100 | + - For @searchAccessToken, paste in the access token scoped to `https://search.azure.com`. |
| 101 | + - For @aoaiAccessToken, paste in the access token scoped to `https://cognitiveservices.azure.com`. |
| 102 | + |
| 103 | +1. To test the connection, send your first request. |
| 104 | + |
| 105 | + ```http |
| 106 | + ### List existing indexes by name (verify the connection) |
| 107 | + GET {{searchUrl}}/indexes?api-version=2025-05-01-preview&$select=name HTTP/1.1 |
| 108 | + Authorization: Bearer {{personalAccessToken}} |
| 109 | + ``` |
| 110 | + |
| 111 | +1. Select **Sent request**. |
| 112 | + |
| 113 | + :::image type="content" source="../../media/search-get-started-semantic/visual-studio-code-send-request.png" alt-text="Screenshot of the REST client send request link."::: |
| 114 | + |
| 115 | +1. Output for this GET request should be a list of indexes. You should see the **hotels-sample-index** among them. |
| 116 | + |
| 117 | +## Set up the query and chat thread |
| 118 | + |
| 119 | +This section uses Visual Studio Code and REST to call the chat completion APIs on Azure OpenAI. |
| 120 | + |
| 121 | +1. Set up a query request on the phrase *"Can you recommend a few hotels with complimentary breakfast?"*. This query uses semantic ranking to return relevant matches, even if the verbatim text isn't an exact match. Results are held in the **searchRequest** variable for reuse on the next request. |
| 122 | + |
| 123 | + ```http |
| 124 | + # @name searchRequest |
| 125 | + POST {{searchUrl}}/indexes/{{index-name}}/docs/search?api-version={{api-version}} HTTP/1.1 |
| 126 | + Content-Type: application/json |
| 127 | + Authorization: Bearer {{searchAccessToken}} |
| 128 | + |
| 129 | + { |
| 130 | + "search": "Can you recommend a few hotels with complimentary breakfast?", |
| 131 | + "queryType": "semantic", |
| 132 | + "semanticConfiguration": "semantic-config", |
| 133 | + "select": "Description,HotelName,Tags", |
| 134 | + "top": 5 |
| 135 | + } |
| 136 | + |
| 137 | + ### 3 - Use search results in Azure OpenAI call to a chat completion model |
| 138 | + POST {{aoaiUrl}}/openai/deployments/{{aoaiGptDeployment}}/chat/completions?api-version=2024-08-01-preview HTTP/1.1 |
| 139 | + Content-Type: application/json |
| 140 | + Authorization: Bearer {{aoaiAccessToken}} |
| 141 | + |
| 142 | + { |
| 143 | + "messages": [ |
| 144 | + { |
| 145 | + "role": "system", |
| 146 | + "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." |
| 147 | + }, |
| 148 | + { |
| 149 | + "role": "user", |
| 150 | + "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." |
| 151 | + } |
| 152 | + ], |
| 153 | + "max_tokens": 1000, |
| 154 | + "temperature": 0.7 |
| 155 | + }` |
| 156 | + ``` |
| 157 | +
|
| 158 | +1. **Send** the request. |
| 159 | +
|
| 160 | +1. Output should look similar to the following example: |
| 161 | +
|
| 162 | + ```json |
| 163 | + "value": [ |
| 164 | + { |
| 165 | + "@search.score": 3.9269178, |
| 166 | + "@search.rerankerScore": 2.380699872970581, |
| 167 | + "HotelName": "Head Wind Resort", |
| 168 | + "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.", |
| 169 | + "Tags": [ |
| 170 | + "coffee in lobby", |
| 171 | + "free wifi", |
| 172 | + "view" |
| 173 | + ] |
| 174 | + }, |
| 175 | + { |
| 176 | + "@search.score": 1.5450059, |
| 177 | + "@search.rerankerScore": 2.1258809566497803, |
| 178 | + "HotelName": "Thunderbird Motel", |
| 179 | + "Description": "Book Now & Save. Clean, Comfortable rooms at the lowest price. Enjoy complimentary coffee and tea in common areas.", |
| 180 | + "Tags": [ |
| 181 | + "coffee in lobby", |
| 182 | + "free parking", |
| 183 | + "free wifi" |
| 184 | + ] |
| 185 | + }, |
| 186 | + { |
| 187 | + "@search.score": 2.2158256, |
| 188 | + "@search.rerankerScore": 2.121671438217163, |
| 189 | + "HotelName": "Swan Bird Lake Inn", |
| 190 | + "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.", |
| 191 | + "Tags": [ |
| 192 | + "continental breakfast", |
| 193 | + "free wifi", |
| 194 | + "24-hour front desk service" |
| 195 | + ] |
| 196 | + }, |
| 197 | + { |
| 198 | + "@search.score": 0.6395861, |
| 199 | + "@search.rerankerScore": 2.116753339767456, |
| 200 | + "HotelName": "Waterfront Scottish Inn", |
| 201 | + "Description": "Newly Redesigned Rooms & airport shuttle. Minutes from the airport, enjoy lakeside amenities, a resort-style pool & stylish new guestrooms with Internet TVs.", |
| 202 | + "Tags": [ |
| 203 | + "24-hour front desk service", |
| 204 | + "continental breakfast", |
| 205 | + "free wifi" |
| 206 | + ] |
| 207 | + }, |
| 208 | + { |
| 209 | + "@search.score": 4.885111, |
| 210 | + "@search.rerankerScore": 2.0008862018585205, |
| 211 | + "HotelName": "Double Sanctuary Resort", |
| 212 | + "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.", |
| 213 | + "Tags": [ |
| 214 | + "view", |
| 215 | + "pool", |
| 216 | + "restaurant", |
| 217 | + "bar", |
| 218 | + "continental breakfast" |
| 219 | + ] |
| 220 | + } |
| 221 | + ] |
| 222 | + ``` |
| 223 | +
|
| 224 | +1. Set up a conversation turn with a chat completion model. This request includes a prompt that provides instructions for the response. The `max_tokens` value is large enough to accommodate the search results from the previous query. |
| 225 | +
|
| 226 | + ```http |
| 227 | + POST {{aoaiUrl}}/openai/deployments/{{aoaiGptDeployment}}/chat/completions?api-version=2024-08-01-preview HTTP/1.1 |
| 228 | + Content-Type: application/json |
| 229 | + Authorization: Bearer {{aoaiAccessToken}} |
| 230 | + |
| 231 | + { |
| 232 | + "messages": [ |
| 233 | + { |
| 234 | + "role": "system", |
| 235 | + "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." |
| 236 | + }, |
| 237 | + { |
| 238 | + "role": "user", |
| 239 | + "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." |
| 240 | + } |
| 241 | + ], |
| 242 | + "max_tokens": 1000, |
| 243 | + "temperature": 0.7 |
| 244 | + } |
| 245 | + ``` |
| 246 | +
|
| 247 | +1. **Send** the request. |
| 248 | +
|
| 249 | +1. Output should be an HTTP 200 Success status message. Included in the output is content that answers the question: |
| 250 | +
|
| 251 | + ```json |
| 252 | + "message": { |
| 253 | + "annotations": [], |
| 254 | + "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!", |
| 255 | + "refusal": null, |
| 256 | + "role": "assistant" |
| 257 | + } |
| 258 | + ``` |
| 259 | +
|
| 260 | +Notice that the output is missing several hotels that mention breakfast in the Tags field. The Tags field is an array, and including this field breaks the JSON structure in the results. Because there are no string conversion capabilities in the REST client, extra code for manually converting the JSON to a string is required if arrays are to be included. We omit this step for this quickstart. |
| 261 | +
|
| 262 | +## Clean up |
| 263 | +
|
| 264 | +When you're working in your own subscription, it's a good idea at the end of a project to identify whether you still need the resources you created. Resources left running can cost you money. You can delete resources individually or delete the resource group to delete the entire set of resources. |
| 265 | +
|
| 266 | +You can find and manage resources in the Azure portal by using the **All resources** or **Resource groups** link in the leftmost pane. |
0 commit comments