Skip to content

Commit e290de9

Browse files
authored
Merge pull request #5876 from alexwolfmsft/search-rag-quickstart
Search rag quickstart
2 parents 25d6387 + ffff37b commit e290de9

File tree

3 files changed

+370
-0
lines changed

3 files changed

+370
-0
lines changed
Lines changed: 362 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,362 @@
1+
---
2+
manager: nitinme
3+
author: haileytap
4+
ms.author: haileytapia
5+
ms.service: azure-ai-search
6+
ms.topic: include
7+
ms.date: 06/05/2025
8+
---
9+
## Prerequisites
10+
11+
- An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/?WT.mc_id=A261C142F).
12+
13+
- An [Azure OpenAI resource](/azure/ai-services/openai/how-to/create-resource).
14+
- [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).
15+
- [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).
16+
- An [Azure AI Search resource](../../search-create-service-portal.md).
17+
- We recommend using the Basic tier or higher.
18+
- [Enable semantic ranking](../../semantic-how-to-enable-disable.md).
19+
- [Visual Studio Code](https://code.visualstudio.com/download) or [Visual Studio](https://visualstudio.com).
20+
- [.NET 9.0](https://dotnet.microsoft.com/download) installed.
21+
22+
## Configure access
23+
24+
Requests to the search endpoint must be authenticated and authorized. You can use API keys or roles for this task. Keys are easier to start with, but roles are more secure. This quickstart assumes roles.
25+
26+
You're setting up two clients, so you need permissions on both resources.
27+
28+
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.
29+
30+
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.
31+
32+
1. Sign in to the [Azure portal](https://portal.azure.com).
33+
34+
1. Configure Azure AI Search for role-based access:
35+
36+
1. In the Azure portal, find your Azure AI Search service.
37+
38+
1. On the left menu, select **Settings** > **Keys**, and then select either **Role-based access control** or **Both**.
39+
40+
1. Assign roles:
41+
42+
1. On the left menu, select **Access control (IAM)**.
43+
44+
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:
45+
46+
- **Search Index Data Contributor**
47+
- **Search Service Contributor**
48+
49+
1. On Azure OpenAI, select **Access control (IAM)** to assign this role to yourself on Azure OpenAI:
50+
51+
- **Cognitive Services OpenAI User**
52+
53+
It can take several minutes for permissions to take effect.
54+
55+
## Create an index
56+
57+
A search index provides grounding data for the chat model. We recommend the hotels-sample-index, which can be created in minutes and runs on any search service tier. This index is created using built-in sample data.
58+
59+
1. In the Azure portal, [find your search service](https://portal.azure.com/#blade/HubsExtension/BrowseResourceBlade/resourceType/Microsoft.Search%2FsearchServices).
60+
61+
1. On the **Overview** home page, select [**Import data**](../../search-get-started-portal.md) to start the wizard.
62+
63+
1. On the **Connect to your data** page, select **Samples** from the dropdown list.
64+
65+
1. Choose the **hotels-sample**.
66+
67+
1. Select **Next** through the remaining pages, accepting the default values.
68+
69+
1. Once the index is created, select **Search management** > **Indexes** from the left menu to open the index.
70+
71+
1. Select **Edit JSON**.
72+
73+
1. Scroll to the end of the index, where you can find placeholders for constructs that can be added to an index.
74+
75+
```json
76+
"analyzers": [],
77+
"tokenizers": [],
78+
"tokenFilters": [],
79+
"charFilters": [],
80+
"normalizers": [],
81+
```
82+
83+
1. On a new line after "normalizers", paste in the following semantic configuration. This example specifies a `"defaultConfiguration"`, which is important to the running of this quickstart.
84+
85+
```json
86+
"semantic":{
87+
"defaultConfiguration":"semantic-config",
88+
"configurations":[
89+
{
90+
"name":"semantic-config",
91+
"prioritizedFields":{
92+
"titleField":{
93+
"fieldName":"HotelName"
94+
},
95+
"prioritizedContentFields":[
96+
{
97+
"fieldName":"Description"
98+
}
99+
],
100+
"prioritizedKeywordsFields":[
101+
{
102+
"fieldName":"Category"
103+
},
104+
{
105+
"fieldName":"Tags"
106+
}
107+
]
108+
}
109+
}
110+
]
111+
},
112+
```
113+
114+
1. **Save** your changes.
115+
116+
1. Run the following query in [Search Explorer](../../search-explorer.md) to test your index: `complimentary breakfast`.
117+
118+
Output should look similar to the following example. Results that are returned directly from the search engine consist of fields and their verbatim values, along with metadata like a search score and a semantic ranking score and caption if you use semantic ranker. We used a [select statement](../../search-query-odata-select.md) to return just the HotelName, Description, and Tags fields.
119+
120+
```
121+
{
122+
"@odata.count": 18,
123+
"@search.answers": [],
124+
"value": [
125+
{
126+
"@search.score": 2.2896252,
127+
"@search.rerankerScore": 2.506816864013672,
128+
"@search.captions": [
129+
{
130+
"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..",
131+
"highlights": ""
132+
}
133+
],
134+
"HotelName": "Head Wind Resort",
135+
"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.",
136+
"Tags": [
137+
"coffee in lobby",
138+
"free wifi",
139+
"view"
140+
]
141+
},
142+
{
143+
"@search.score": 2.2158256,
144+
"@search.rerankerScore": 2.288334846496582,
145+
"@search.captions": [
146+
{
147+
"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..",
148+
"highlights": ""
149+
}
150+
],
151+
"HotelName": "Swan Bird Lake Inn",
152+
"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.",
153+
"Tags": [
154+
"continental breakfast",
155+
"free wifi",
156+
"24-hour front desk service"
157+
]
158+
},
159+
{
160+
"@search.score": 0.92481667,
161+
"@search.rerankerScore": 2.221315860748291,
162+
"@search.captions": [
163+
{
164+
"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..",
165+
"highlights": ""
166+
}
167+
],
168+
"HotelName": "White Mountain Lodge & Suites",
169+
"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.",
170+
"Tags": [
171+
"continental breakfast",
172+
"pool",
173+
"restaurant"
174+
]
175+
},
176+
. . .
177+
]}
178+
```
179+
180+
## Get service endpoints
181+
182+
In the remaining sections, you set up API calls to Azure OpenAI and Azure AI Search. Get the service endpoints so that you can provide them as variables in your code.
183+
184+
1. Sign in to the [Azure portal](https://portal.azure.com).
185+
186+
1. [Find your search service](https://portal.azure.com/#blade/HubsExtension/BrowseResourceBlade/resourceType/Microsoft.Search%2FsearchServices).
187+
188+
1. On the **Overview** home page, copy the URL. An example endpoint might look like `https://example.search.windows.net`.
189+
190+
1. [Find your Azure OpenAI service](https://portal.azure.com/#blade/HubsExtension/BrowseResourceBlade/resourceType/Microsoft.CognitiveServices%2Faccounts).
191+
192+
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/`.
193+
194+
## Sign in to Azure
195+
196+
You're using Microsoft Entra ID and role assignments for the connection. Make sure you're logged in to the same tenant and subscription as Azure AI Search and Azure OpenAI. You can use the Azure CLI on the command line to show current properties, change properties, and to sign in. For more information, see [Connect without keys](../../search-get-started-rbac.md).
197+
198+
Run each of the following commands in sequence.
199+
200+
```azure-cli
201+
az account show
202+
203+
az account set --subscription <PUT YOUR SUBSCRIPTION ID HERE>
204+
205+
az login --tenant <PUT YOUR TENANT ID HERE>
206+
```
207+
208+
You should now be logged in to Azure from your local device.
209+
210+
## Set up the .NET app
211+
212+
To follow along with the steps ahead, you can either clone the completed sample app from GitHub, or create the app yourself.
213+
214+
### Clone the sample app
215+
216+
To access the completed sample app for this article:
217+
218+
1. Clone the [azure-search-dotnet-samples](https://github.com/Azure-Samples/azure-search-dotnet-samples) repo from GitHub.
219+
220+
```bash
221+
git clone https://github.com/Azure-Samples/azure-search-dotnet-samples
222+
```
223+
224+
1. Navigate into the `quickstart-rag` folder.
225+
1. Open the `quickstart-rag` folder in Visual Studio Code or open the solution file using Visual Studio.
226+
227+
### Create the sample app
228+
229+
Complete the following steps to create a .NET console app to connect to an AI model.
230+
231+
1. In an empty directory on your computer, use the `dotnet new` command to create a new console app:
232+
233+
```dotnetcli
234+
dotnet new console -o AISearchRag
235+
```
236+
237+
1. Change directory into the app folder:
238+
239+
```dotnetcli
240+
cd AISearchRag
241+
```
242+
243+
1. Install the required packages:
244+
245+
```bash
246+
dotnet add package Azure.AI.OpenAI
247+
dotnet add package Azure.Identity
248+
dotnet add package Azure.Search.Documents
249+
```
250+
251+
1. Open the app in Visual Studio Code (or your editor of choice).
252+
253+
```bash
254+
code .
255+
```
256+
257+
## Set up the query and chat thread
258+
259+
The following example demonstrates how to set up a minimal RAG scenario using Azure AI Search to provide an OpenAI model with contextual resources to improve the generated responses.
260+
261+
1. In the `minimal-query` project of the sample repo, open the `Program.cs` file to view the first example. If you created the project yourself, add the following code to connect to and query the Azure AI Search and Azure OpenAI services.
262+
263+
> [!NOTE]
264+
> Make sure to replace the placeholders for the Azure OpenAI endpoint and model name, as well as the Azure AI Search endpoint and index name.
265+
266+
:::code language="csharp" source="~/azure-search-dotnet-samples/quickstart-rag/minimal-query/Program.cs" :::
267+
268+
The preceding code accomplishes the following:
269+
270+
- Searches an Azure Search index for hotels matching a user query about complimentary breakfast, retrieving hotel name, description, and tags.
271+
- Formats the search results into a structured list to serve as contextual sources for the generative AI model.
272+
- Constructs a prompt instructing the Azure OpenAI model to answer using only the provided sources.
273+
- Sends the prompt to the AI model and streams the generated response.
274+
- Outputs the AI’s response to the console, displaying both the role and content as it streams.
275+
276+
1. Run the project to initiate a basic RAG scenario. The output from Azure OpenAI consists of recommendations for several hotels, such as the following example:
277+
278+
```output
279+
Sure! Here are a few hotels that offer complimentary breakfast:
280+
281+
- **Head Wind Resort**
282+
- Complimentary continental breakfast in the lobby
283+
- Free Wi-Fi throughout the hotel
284+
285+
- **Double Sanctuary Resort**
286+
- Continental breakfast included
287+
288+
- **White Mountain Lodge & Suites**
289+
- Continental breakfast available
290+
291+
- **Swan Bird Lake Inn**
292+
- Continental-style breakfast each morning with a variety of food and drinks
293+
such as caramel cinnamon rolls, coffee, orange juice, milk, cereal,
294+
instant oatmeal, bagels, and muffins
295+
```
296+
297+
To experiment further, change the query and rerun the last step to better understand how the model works with the grounding data. You can also modify the prompt to change the tone or structure of the output.
298+
299+
### Troubleshooting
300+
301+
You might receive any of the following errors while testing:
302+
303+
- **Forbidden**: Check Azure AI Search configuration to make sure role-based access is enabled.
304+
- **Authorization failed**: Wait a few minutes and try again. It can take several minutes for role assignments to become operational.
305+
- **Resource not found**: Check the resource URIs and make sure the API version on the chat model is valid.
306+
307+
## Send a complex RAG query
308+
309+
Azure AI Search supports [complex types](../../search-howto-complex-data-types.md) for nested JSON structures. In the hotels-sample-index, `Address` is an example of a complex type, consisting of `Address.StreetAddress`, `Address.City`, `Address.StateProvince`, `Address.PostalCode`, and `Address.Country`. The index also has complex collection of `Rooms` for each hotel. If your index has complex types, your query can provide those fields if you first convert the search results output to JSON, and then pass the JSON to the chat model.
310+
311+
1. In the `complex-query` project of the sample repo, open the `Program.cs` file. If you created the project yourself, replace your code with the following:
312+
313+
:::code language="csharp" source="~/azure-search-dotnet-samples/quickstart-rag/complex-query/Program.cs" :::
314+
315+
2. Run the project to initiate a basic RAG scenario. The output from Azure OpenAI consists of recommendations for several hotels, such as the following example:
316+
317+
```output
318+
1. **Double Sanctuary Resort**
319+
- **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.
320+
- **Address**: 2211 Elliott Ave, Seattle, WA, 98121, USA
321+
- **Tags**: view, pool, restaurant, bar, continental breakfast
322+
- **Room Rate for 4 People**:
323+
- Suite, 2 Queen Beds: $254.99 per night
324+
325+
2. **Starlight Suites**
326+
- **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.
327+
- **Address**: 19575 Biscayne Blvd, Aventura, FL, 33180, USA
328+
- **Tags**: pool, coffee in lobby, free wifi
329+
- **Room Rate for 4 People**:
330+
- Suite, 2 Queen Beds (Cityside): $231.99 per night
331+
- Deluxe Room, 2 Queen Beds (Waterfront View): $148.99 per night
332+
333+
3. **Good Business Hotel**
334+
- **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.
335+
- **Address**: 4400 Ashford Dunwoody Rd NE, Atlanta, GA, 30346, USA
336+
- **Tags**: pool, continental breakfast, free parking
337+
- **Room Rate for 4 People**:
338+
- Budget Room, 2 Queen Beds (Amenities): $60.99 per night
339+
- Deluxe Room, 2 Queen Beds (Amenities): $139.99 per night
340+
```
341+
342+
## Troubleshooting
343+
344+
If you see output messages while debugging related to `ManagedIdentityCredential` and token acquisition failures, it could be that you have multiple tenants, and your Azure sign-in is using a tenant that doesn't have your search service. To get your tenant ID, search the Azure portal for "tenant properties" or run `az login tenant list`.
345+
346+
Once you have your tenant ID, run `az login --tenant <YOUR-TENANT-ID>` at a command prompt, and then rerun the script.
347+
348+
You can also log errors in your code by creating an instance of `ILogger`:
349+
350+
```csharp
351+
using var loggerFactory = LoggerFactory.Create(builder =>
352+
{
353+
builder.AddConsole();
354+
});
355+
ILogger logger = loggerFactory.CreateLogger<Program>();
356+
```
357+
358+
## Clean up
359+
360+
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.
361+
362+
You can find and manage resources in the Azure portal by using the **All resources** or **Resource groups** link in the leftmost pane.

articles/search/search-get-started-rag.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ In this quickstart, you send queries to a chat completion model for a conversati
3535

3636
::: zone-end
3737

38+
::: zone pivot="csharp"
39+
40+
[!INCLUDE [.NET quickstart](includes/quickstarts/search-get-started-rag-dotnet.md)]
41+
42+
::: zone-end
43+
3844
## Related content
3945

4046
- [Tutorial: Build a RAG solution in Azure AI Search](tutorial-rag-build-solution.md)

zone-pivots/zone-pivot-groups.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ groups:
285285
title: Python
286286
- id: typescript
287287
title: TypeScript
288+
- id: csharp
289+
title: C#
288290
# Owner: diberry
289291
- id: programming-languages-rest-ps-py-js
290292
title: Programming languages

0 commit comments

Comments
 (0)