Skip to content

Commit f50ad23

Browse files
authored
Merge pull request #281392 from HeidiSteen/heidist-qs-rag
[azure search] RAG quickstart
2 parents bccfe67 + b6abf0d commit f50ad23

File tree

3 files changed

+284
-4
lines changed

3 files changed

+284
-4
lines changed

articles/search/TOC.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@
1515
items:
1616
- name: Vector search
1717
href: search-get-started-vector.md
18+
- name: Generative search (RAG)
19+
href: search-get-started-rag.md
1820
- name: Full text search
1921
href: search-get-started-text.md
20-
- name: Semantic reranking
22+
- name: Semantic ranking
2123
href: search-get-started-semantic.md
22-
- name: Chat with your data (Azure OpenAI Studio)
23-
href: /azure/ai-services/openai/use-your-data-quickstart?context=/azure/search/context/context
24+
- name: Azure OpenAI Studio
25+
items:
26+
- name: Chat with your data
27+
href: /azure/ai-services/openai/use-your-data-quickstart?context=/azure/search/context/context
2428
- name: Portal
2529
items:
2630
- name: Keyword search wizard
Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
---
2+
title: Quickstart RAG
3+
titleSuffix: Azure AI Search
4+
description: In this quickstart, learn how to use grounding data from Azure AI Search with a chat model on Azure OpenAI.
5+
author: HeidiSteen
6+
ms.author: heidist
7+
ms.service: cognitive-search
8+
ms.topic: quickstart
9+
ms.date: 07/22/2024
10+
---
11+
12+
# Quickstart: Generative search (RAG) with grounding data from Azure AI Search
13+
14+
This quickstart shows you how to send queries to a Large Language Model (LLM) for a conversational search experience over your indexed content on Azure AI Search. You use the Azure portal to set up the resources, and then run Python code to call the APIs.
15+
16+
## Prerequisites
17+
18+
- An Azure subscription. [Create one for free](https://azure.microsoft.com/free/).
19+
20+
- [Azure AI Search](search-create-service-portal.md), Basic tier or higher so that you can [enable semantic ranking](semantic-how-to-enable-disable.md). Region must be the same one used for Azure OpenAI.
21+
22+
- [Azure OpenAI](https://aka.ms/oai/access) resource with a deployment of `gpt-35-turbo`, `gpt-4`, or equivalent model, in the same region as Azure AI Search.
23+
24+
- [Visual Studio Code](https://code.visualstudio.com/download) with the [Python extension](https://marketplace.visualstudio.com/items?itemName=ms-python.python) and the [Jupyter package](https://pypi.org/project/jupyter/). For more information, see [Python in Visual Studio Code](https://code.visualstudio.com/docs/languages/python).
25+
26+
## Download file
27+
28+
[Download a Jupyter notebook](https://github.com/Azure-Samples/azure-search-python-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).
29+
30+
You can also start a new file on your local system and create requests manually by using the instructions in this article.
31+
32+
## Configure access
33+
34+
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.
35+
36+
1. Configure Azure OpenAI to use a system-assigned managed identity:
37+
38+
1. In the Azure portal, find your Azure OpenAI resource.
39+
40+
1. On the left menu, select **Resource management** > **Identity**.
41+
42+
1. On the System assigned tab, set status to **On**.
43+
44+
1. Configure Azure AI Search for role-based access and assign roles:
45+
46+
1. In the Azure portal, find your Azure AI Search service.
47+
48+
1. On the left menu, select **Settings** > **Keys**, and then select either **Role-based access control** or **Both**.
49+
50+
1. On the left menu, select **Access control (IAM)**.
51+
52+
1. Add the following role assignments for the Azure OpenAI managed identity: **Search Index Data Reader**, **Search Service Contributor**.
53+
54+
1. Assign yourself to the **Cognitive Services OpenAI User** role on Azure OpenAI. This is the only role you need for query workloads.
55+
56+
It can take several minutes for permissions to take effect.
57+
58+
## Create an index
59+
60+
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.
61+
62+
1. In the Azure portal, find your search service.
63+
64+
1. On the **Overview** home page, select [**Import data**](search-get-started-portal.md) to start the wizard.
65+
66+
1. On the **Connect to your data** page, select **Samples** from the dropdown list.
67+
68+
1. Choose the **hotels-sample**.
69+
70+
1. Select **Next** through the remaining pages, accepting the default values.
71+
72+
1. Once the index is created, select **Search management** > **Indexes** from the left menu to open the index.
73+
74+
1. Select **Edit JSON**.
75+
76+
1. Search for "semantic" to find the section in the index for a semantic configuration. Replace the "semantic" line with the following semantic configuration. This example specifies a `"defaultConfiguration"`, which is important to the running of this quickstart.
77+
78+
```json
79+
"semantic": {
80+
"defaultConfiguration": "semantic-config",
81+
"configurations": [
82+
{
83+
"name": "semantic-config",
84+
"prioritizedFields": {
85+
"titleField": {
86+
"fieldName": "HotelName"
87+
},
88+
"prioritizedContentFields": [
89+
{
90+
"fieldName": "Description"
91+
}
92+
],
93+
"prioritizedKeywordsFields": [
94+
{
95+
"fieldName": "Category"
96+
},
97+
{
98+
"fieldName": "Tags"
99+
}
100+
]
101+
}
102+
}
103+
]
104+
},
105+
```
106+
107+
1. **Save** your changes.
108+
109+
1. Run the following query to test your index: `hotels near the ocean with beach access and good views`.
110+
111+
## Get service endpoints
112+
113+
1. Sign in to the [Azure portal](https://portal.azure.com).
114+
115+
1. [Find your search service](https://portal.azure.com/#blade/HubsExtension/BrowseResourceBlade/resourceType/Microsoft.Search%2FsearchServices).
116+
117+
1. On the **Overview** home page, copy the URL. An example endpoint might look like `https://example.search.windows.net`.
118+
119+
1. [Find your Azure OpenAI service](https://portal.azure.com/#blade/HubsExtension/BrowseResourceBlade/resourceType/Microsoft.CognitiveServices%2Faccounts).
120+
121+
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/`.
122+
123+
## Set up the query and chat thread
124+
125+
This section uses Visual Studio Code and Python to call the chat APIs on Azure OpenAI.
126+
127+
1. Install the following Python packages.
128+
129+
```python
130+
! pip install azure-search-documents==11.6.0b4 --quiet
131+
! pip install azure-identity==1.16.0 --quiet
132+
! pip install openai --quiet
133+
```
134+
135+
1. Set the following variables, substituting placeholders with the endpoints you collected in the previous step.
136+
137+
```python
138+
AZURE_SEARCH_SERVICE: str = "PUT YOUR SEARCH SERVICE ENDPOINT HERE"
139+
AZURE_OPENAI_ACCOUNT: str = "PUT YOUR AZURE OPENAI ENDPOINT HERE"
140+
AZURE_DEPLOYMENT_MODEL: str = "gpt-35-turbo"
141+
```
142+
143+
1. Specify query parameters. The query is a keyword search using semantic ranking. The search engine returns up to 50 matches, but the model returns just the top 5 in the response. If you can't enable semantic ranking on your search service, set the value to false.
144+
145+
```python
146+
# Set query parameters for grounding the conversation on your search index
147+
k=50
148+
search_type="text"
149+
use_semantic_reranker=True
150+
sources_to_include=5
151+
```
152+
153+
1. Set up clients, a search functions prompts, and a chat. The function retrieves selected fields from the search index.
154+
155+
```python
156+
# Set up the query for generating responses
157+
from azure.core.credentials_async import AsyncTokenCredential
158+
from azure.identity.aio import get_bearer_token_provider
159+
from azure.search.documents.aio import SearchClient
160+
from azure.search.documents.models import VectorizableTextQuery, HybridSearch
161+
from openai import AsyncAzureOpenAI
162+
from enum import Enum
163+
from typing import List, Optional
164+
165+
def create_openai_client(credential: AsyncTokenCredential) -> AsyncAzureOpenAI:
166+
token_provider = get_bearer_token_provider(credential, "https://cognitiveservices.azure.com/.default")
167+
return AsyncAzureOpenAI(
168+
api_version="2024-04-01-preview",
169+
azure_endpoint=AZURE_OPENAI_ACCOUNT,
170+
azure_ad_token_provider=token_provider
171+
)
172+
173+
def create_search_client(credential: AsyncTokenCredential) -> SearchClient:
174+
return SearchClient(
175+
endpoint=AZURE_SEARCH_SERVICE,
176+
index_name="hotels-sample-index",
177+
credential=credential
178+
)
179+
180+
# This quickstart is only using text at the moment
181+
class SearchType(Enum):
182+
TEXT = "text"
183+
VECTOR = "vector"
184+
HYBRID = "hybrid"
185+
186+
# This function retrieves the selected fields from the search index
187+
async def get_sources(search_client: SearchClient, query: str, search_type: SearchType, use_semantic_reranker: bool = True, sources_to_include: int = 5, k: int = 50) -> List[str]:
188+
search_type == SearchType.TEXT,
189+
response = await search_client.search(
190+
search_text=query,
191+
query_type="semantic" if use_semantic_reranker else "simple",
192+
top=sources_to_include,
193+
select="Description,HotelName,Tags"
194+
)
195+
196+
return [ document async for document in response ]
197+
198+
# This prompt provides instructions to the model
199+
GROUNDED_PROMPT="""
200+
You are a friendly assistant that recommends hotels based on activities and amenities.
201+
Answer the query using only the sources provided below in a friendly and concise bulleted manner.
202+
Answer ONLY with the facts listed in the list of sources below.
203+
If there isn't enough information below, say you don't know.
204+
Do not generate answers that don't use the sources below.
205+
Query: {query}
206+
Sources:\n{sources}
207+
"""
208+
209+
# This class instantiates the chat
210+
class ChatThread:
211+
def __init__(self):
212+
self.messages = []
213+
self.search_results = []
214+
215+
def append_message(self, role: str, message: str):
216+
self.messages.append({
217+
"role": role,
218+
"content": message
219+
})
220+
221+
async def append_grounded_message(self, search_client: SearchClient, query: str, search_type: SearchType, use_semantic_reranker: bool = True, sources_to_include: int = 5, k: int = 50):
222+
sources = await get_sources(search_client, query, search_type, use_semantic_reranker, sources_to_include, k)
223+
sources_formatted = "\n".join([f'{document["HotelName"]}:{document["Description"]}:{document["Tags"]}' for document in sources])
224+
self.append_message(role="user", message=GROUNDED_PROMPT.format(query=query, sources=sources_formatted))
225+
self.search_results.append(
226+
{
227+
"message_index": len(self.messages) - 1,
228+
"query": query,
229+
"sources": sources
230+
}
231+
)
232+
233+
async def get_openai_response(self, openai_client: AsyncAzureOpenAI, model: str):
234+
response = await openai_client.chat.completions.create(
235+
messages=self.messages,
236+
model=model
237+
)
238+
self.append_message(role="assistant", message=response.choices[0].message.content)
239+
240+
def get_last_message(self) -> Optional[object]:
241+
return self.messages[-1] if len(self.messages) > 0 else None
242+
243+
def get_last_message_sources(self) -> Optional[List[object]]:
244+
return self.search_results[-1]["sources"] if len(self.search_results) > 0 else None
245+
```
246+
247+
1. Invoke the chat and call the search function, passing in a query string to search for.
248+
249+
```python
250+
import azure.identity.aio
251+
252+
chat_thread = ChatThread()
253+
chat_deployment = AZURE_DEPLOYMENT_MODEL
254+
255+
async with azure.identity.aio.DefaultAzureCredential() as credential, create_search_client(credential) as search_client, create_openai_client(credential) as openai_client:
256+
await chat_thread.append_grounded_message(
257+
search_client=search_client,
258+
query="Can you recommend a few hotels near the ocean with beach access and good views",
259+
search_type=SearchType(search_type),
260+
use_semantic_reranker=use_semantic_reranker,
261+
sources_to_include=sources_to_include,
262+
k=k)
263+
await chat_thread.get_openai_response(openai_client=openai_client, model=chat_deployment)
264+
265+
print(chat_thread.get_last_message()["content"])
266+
```
267+
268+
## Clean up
269+
270+
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.
271+
272+
You can find and manage resources in the portal by using the **All resources** or **Resource groups** link in the leftmost pane.
273+
274+
## Next steps
275+
276+
As a next step, we recommend that you review the demo code for [Python](https://github.com/Azure/azure-search-vector-samples/tree/main/demo-python), [C#](https://github.com/Azure/azure-search-vector-samples/tree/main/demo-dotnet), or [JavaScript](https://github.com/Azure/azure-search-vector-samples/tree/main/demo-javascript).

articles/search/semantic-how-to-enable-disable.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Follow these steps to enable [semantic ranker](semantic-search-overview.md) at t
3131

3232
1. Navigate to your search service. On the **Overview** page, make sure the service is a billable tier, Basic or higher.
3333

34-
1. On the left-nav pane, select **Semantic ranking**.
34+
1. On the left-nav pane, select **Settings** > **Semantic ranking**.
3535

3636
1. Select either the **Free plan** or the **Standard plan**. You can switch between the free plan and the standard plan at any time.
3737

0 commit comments

Comments
 (0)