Skip to content

Commit 4c5e538

Browse files
authored
Merge pull request #126 from HeidiSteen/main
Added CMK example
2 parents cefea9c + d5b64a0 commit 4c5e538

File tree

2 files changed

+295
-0
lines changed

2 files changed

+295
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This repository contains Python code samples used in Azure AI Search documentati
66
|--------|-------------|
77
| [azure-function-search](azure-function-search/readme.md) | This sample is an Azure Function that sends query requests to an Azure AI Search service. You can substitute this code to replace the contents of the `api` folder in the C# sample [azure-search-static-web-app](https://github.com/Azure-Samples/azure-search-static-web-app). |
88
| [bulk-insert](bulk-insert/readme.md) | This sample shows you how to create and load an index using the push APIs and sample data. You can substitute this code to replace the contents of the `bulk-insert` folder in the C# sample [azure-search-static-web-app](https://github.com/Azure-Samples/azure-search-static-web-app) |
9+
| cmk-encryption | This example shows you how to encrypt content using customer-managed keys.|
910
| quickstart | "Day One" introduction to the fundamental tasks of working with a search index: create, load, and query. This sample is a notebook .ipynb file. The index is modeled on a subset of the Hotels dataset, widely used in Azure AI Search samples, but reduced here for readability and comprehension. |
1011
| quickstart-semantic-search | Extends the quickstart through modifications that invoke semantic search. This notebook adds a semantic configuration to the index and semantic query options that formulate the query and response. |
1112
| quickstart-rag | "Day One" introduction to LLM integration with a chat model such as GPT-3.5-turbo or equivalent. |

cmk-example/cmk-example.ipynb

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Python example for CMK-encryption in Azure AI Search\n",
8+
"\n",
9+
"This notebook provides sample script for [adding customer-managed key (CMK) encryption](https://learn.microsoft.com/azure/search/search-security-manage-encryption-keys) to objects on Azure AI Search."
10+
]
11+
},
12+
{
13+
"cell_type": "markdown",
14+
"metadata": {},
15+
"source": [
16+
"## Prerequisites\n",
17+
"\n",
18+
"\n",
19+
"- [Azure AI Search](https://learn.microsoft.com/azure/search/search-create-service-portal)\n",
20+
"- [Azure Key Vault]()\n",
21+
"- [Azure Storage](https://learn.microsoft.com/azure/storage/common/storage-account-create) or [Azure Log Analytics](https://learn.microsoft.com/azure/azure-monitor/logs/quick-create-workspace?tabs=azure-portal) for data retention of audit logs.\n"
22+
]
23+
},
24+
{
25+
"cell_type": "markdown",
26+
"metadata": {},
27+
"source": [
28+
"## Sign in to Azure\n",
29+
"\n",
30+
"You might not need this step, but if downstream connections fail with a 401 during indexer pipeline execution, it could be because you're using the wrong tenant or subscription. You can avoid this issue by signing in from the command line, explicitly setting the tenant ID and choosing the right subscription.\n",
31+
"\n",
32+
"This section assumes you have the [Azure CLI](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).\n",
33+
"\n",
34+
"1. Open a command line prompt.\n",
35+
"\n",
36+
"1. Run this command to get a list of Azure tenants: `az account tenant list`\n",
37+
"\n",
38+
"1. If you have multiple tenants, set the tenant: `az login --tenant <YOUR-TENANT_ID>`\n",
39+
"\n",
40+
"If you have multiple subscriptions, a list is provided so that you can select one."
41+
]
42+
},
43+
{
44+
"cell_type": "markdown",
45+
"metadata": {},
46+
"source": [
47+
"## Create a virtual environment in Visual Studio Code\n",
48+
"\n",
49+
"Create a virtual environment so that you can install the dependencies in isolation.\n",
50+
"\n",
51+
"1. In Visual Studio Code, open the folder containing tutorial-rag.ipynb.\n",
52+
"\n",
53+
"1. Press Ctrl-shift-P to open the command palette, search for \"Python: Create Environment\", and then select `Venv` to create a virtual environment in the current workspace.\n",
54+
"\n",
55+
"1. Select Tutorial-RAG\\tutorial-rag-requirements.txt for the dependencies.\n",
56+
"\n",
57+
"It takes several minutes to create the environment. When the environment is ready, continue to the next step."
58+
]
59+
},
60+
{
61+
"cell_type": "markdown",
62+
"metadata": {},
63+
"source": [
64+
"## Install packages"
65+
]
66+
},
67+
{
68+
"cell_type": "code",
69+
"execution_count": null,
70+
"metadata": {},
71+
"outputs": [],
72+
"source": [
73+
"! pip install python-dotenv\n",
74+
"! pip install azure-core\n",
75+
"! pip install azure-search-documents\n",
76+
"! pip install azure-storage-blob\n",
77+
"! pip install azure-identity\n",
78+
"! pip install openai\n",
79+
"! pip install aiohttp"
80+
]
81+
},
82+
{
83+
"cell_type": "markdown",
84+
"metadata": {},
85+
"source": [
86+
"## CREATE INDEX"
87+
]
88+
},
89+
{
90+
"cell_type": "code",
91+
"execution_count": 26,
92+
"metadata": {},
93+
"outputs": [],
94+
"source": [
95+
"# Set variables\n",
96+
"AZURE_SEARCH_SERVICE: str = \"<PUT_YOUR_AZURE_SEARCH_SERVICE_URL_HERE>\"\n",
97+
"AZURE_KEY_VAULT_NAME: str = \"<PUT_YOUR_AZURE_KEY_VAULT_NAME_HERE>\"\n",
98+
"AZURE_KEY_VAULT_URI: str = \"<PUT_YOUR_AZURE_KEY_VAULT_URI_HERE>\"\n",
99+
"AZURE_KEY_VAULT_VERSION: str = \"<PUT-YOUR-AZURE_KEY_VAULT_VERSION_HERE>\""
100+
]
101+
},
102+
{
103+
"cell_type": "code",
104+
"execution_count": 24,
105+
"metadata": {},
106+
"outputs": [
107+
{
108+
"name": "stdout",
109+
"output_type": "stream",
110+
"text": [
111+
" test-cmk-index-qs created\n"
112+
]
113+
}
114+
],
115+
"source": [
116+
"from azure.search.documents.indexes import SearchIndexClient\n",
117+
"from azure.search.documents.indexes.models import (\n",
118+
" SimpleField,\n",
119+
" SearchFieldDataType,\n",
120+
" SearchableField,\n",
121+
" SearchIndex,\n",
122+
" SearchResourceEncryptionKey\n",
123+
")\n",
124+
"from azure.identity import DefaultAzureCredential\n",
125+
"\n",
126+
"credential = DefaultAzureCredential()\n",
127+
"\n",
128+
"# Create a search index \n",
129+
"index_name = \"test-cmk-index\"\n",
130+
"index_client = SearchIndexClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential) \n",
131+
"fields = [\n",
132+
" SimpleField(name=\"Id\", type=SearchFieldDataType.String, key=True),\n",
133+
" SearchableField(name=\"Description\", type=SearchFieldDataType.String)\n",
134+
" ]\n",
135+
"\n",
136+
"scoring_profiles = []\n",
137+
"suggester = []\n",
138+
"encryption_key = SearchResourceEncryptionKey(\n",
139+
" key_name=AZURE_KEY_VAULT_NAME,\n",
140+
" key_version=AZURE_KEY_VAULT_VERSION,\n",
141+
" vault_uri=AZURE_KEY_VAULT_URI\n",
142+
")\n",
143+
"\n",
144+
"# Create the search index=\n",
145+
"index = SearchIndex(name=index_name, fields=fields, encryption_key=encryption_key)\n",
146+
"result = index_client.create_or_update_index(index)\n",
147+
"print(f' {result.name} created')"
148+
]
149+
},
150+
{
151+
"cell_type": "markdown",
152+
"metadata": {},
153+
"source": [
154+
"## GET INDEX DEFINITION\n"
155+
]
156+
},
157+
{
158+
"cell_type": "code",
159+
"execution_count": null,
160+
"metadata": {},
161+
"outputs": [],
162+
"source": [
163+
"index_name = \"test-cmk-index\"\n",
164+
"index_client = SearchIndexClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential) \n",
165+
"\n",
166+
"result = index_client.get_index(index_name) \n",
167+
"print(f\"{result}\") "
168+
]
169+
},
170+
{
171+
"cell_type": "markdown",
172+
"metadata": {},
173+
"source": [
174+
"## LOAD INDEX"
175+
]
176+
},
177+
{
178+
"cell_type": "code",
179+
"execution_count": 29,
180+
"metadata": {},
181+
"outputs": [
182+
{
183+
"name": "stdout",
184+
"output_type": "stream",
185+
"text": [
186+
"Upload of new document succeeded: True\n"
187+
]
188+
}
189+
],
190+
"source": [
191+
"from azure.search.documents import SearchClient\n",
192+
"\n",
193+
"# Create a documents payload\n",
194+
"documents = [\n",
195+
" {\n",
196+
" \"@search.action\": \"upload\",\n",
197+
" \"Id\": \"1\",\n",
198+
" \"Description\": \"The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.\"\n",
199+
" },\n",
200+
" {\n",
201+
" \"@search.action\": \"upload\",\n",
202+
" \"Id\": \"2\",\n",
203+
" \"Description\": \"The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.\"\n",
204+
" },\n",
205+
" {\n",
206+
" \"@search.action\": \"upload\",\n",
207+
" \"Id\": \"3\",\n",
208+
" \"Description\": \"The hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services.\"\n",
209+
" },\n",
210+
" {\n",
211+
" \"@search.action\": \"upload\",\n",
212+
" \"Id\": \"4\",\n",
213+
" \"Description\": \"The hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.\"\n",
214+
" }\n",
215+
"]\n",
216+
"\n",
217+
"search_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, index_name=index_name, credential=credential)\n",
218+
"try:\n",
219+
" result = search_client.upload_documents(documents=documents)\n",
220+
" print(\"Upload of new document succeeded: {}\".format(result[0].succeeded))\n",
221+
"except Exception as ex:\n",
222+
" print (ex.message)\n",
223+
"\n",
224+
" index_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)"
225+
]
226+
},
227+
{
228+
"cell_type": "markdown",
229+
"metadata": {},
230+
"source": [
231+
"## QUERY ENCRYPTED CONTENT"
232+
]
233+
},
234+
{
235+
"cell_type": "code",
236+
"execution_count": 31,
237+
"metadata": {},
238+
"outputs": [
239+
{
240+
"name": "stdout",
241+
"output_type": "stream",
242+
"text": [
243+
"Score: 0.6130029\n",
244+
"Id: 4\n",
245+
"Description: The hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.\n",
246+
"Score: 0.26286605\n",
247+
"Id: 1\n",
248+
"Description: The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.\n"
249+
]
250+
}
251+
],
252+
"source": [
253+
"from azure.search.documents import SearchClient\n",
254+
"\n",
255+
"query = \"historic\" \n",
256+
"\n",
257+
"search_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential, index_name=index_name)\n",
258+
" \n",
259+
"results = search_client.search( \n",
260+
" query_type='simple',\n",
261+
" search_text=query, \n",
262+
" select=[\"Id\", \"Description\"],\n",
263+
" include_total_count=True\n",
264+
" )\n",
265+
" \n",
266+
"for result in results: \n",
267+
" print(f\"Score: {result['@search.score']}\")\n",
268+
" print(f\"Id: {result['Id']}\")\n",
269+
" print(f\"Description: {result['Description']}\")\n"
270+
]
271+
}
272+
],
273+
"metadata": {
274+
"kernelspec": {
275+
"display_name": ".venv",
276+
"language": "python",
277+
"name": "python3"
278+
},
279+
"language_info": {
280+
"codemirror_mode": {
281+
"name": "ipython",
282+
"version": 3
283+
},
284+
"file_extension": ".py",
285+
"mimetype": "text/x-python",
286+
"name": "python",
287+
"nbconvert_exporter": "python",
288+
"pygments_lexer": "ipython3",
289+
"version": "3.11.9"
290+
}
291+
},
292+
"nbformat": 4,
293+
"nbformat_minor": 2
294+
}

0 commit comments

Comments
 (0)