|
23 | 23 | "\n", |
24 | 24 | "### TOC\n", |
25 | 25 | "- [0️⃣ Initialize notebook variables](#0)\n", |
26 | | - "- [1️⃣ Create the Azure Resource Group](#1)\n", |
| 26 | + "- [1️⃣ Verify the Azure CLI and the connected Azure subscription](#1)\n", |
27 | 27 | "- [2️⃣ Create deployment using 🦾 Bicep](#2)\n", |
28 | 28 | "- [3️⃣ Get the deployment outputs](#3)\n", |
29 | 29 | "- [🧪 Test the API using a direct HTTP call](#requests)\n", |
|
57 | 57 | }, |
58 | 58 | { |
59 | 59 | "cell_type": "code", |
60 | | - "execution_count": 1, |
| 60 | + "execution_count": null, |
61 | 61 | "metadata": { |
62 | 62 | "metadata": {} |
63 | 63 | }, |
64 | 64 | "outputs": [], |
65 | 65 | "source": [ |
66 | | - "import os\n", |
| 66 | + "import os, sys, json\n", |
| 67 | + "sys.path.insert(1, '../../shared') # add the shared directory to the Python path\n", |
| 68 | + "import utils\n", |
67 | 69 | "\n", |
68 | 70 | "deployment_name = os.path.basename(os.path.dirname(globals()['__vsc_ipynb_file__']))\n", |
69 | 71 | "resource_group_name = f\"lab-{deployment_name}\" # change the name to match your naming style\n", |
70 | 72 | "resource_group_location = \"westeurope\"\n", |
71 | 73 | "\n", |
| 74 | + "apim_sku = 'Basicv2'\n", |
| 75 | + "\n", |
72 | 76 | "openai_resources = [\n", |
73 | 77 | " {\"name\": \"openai1\", \"location\": \"swedencentral\"}\n", |
74 | 78 | "]\n", |
75 | 79 | "\n", |
76 | 80 | "openai_model_name = \"gpt-35-turbo\"\n", |
77 | 81 | "openai_model_version = \"0613\"\n", |
78 | 82 | "openai_deployment_name = \"gpt-35-turbo\"\n", |
79 | | - "openai_api_version = \"2024-02-01\"\n" |
| 83 | + "openai_api_version = \"2024-02-01\"\n", |
| 84 | + "\n", |
| 85 | + "utils.print_ok('Notebook initiaized')" |
80 | 86 | ] |
81 | 87 | }, |
82 | 88 | { |
83 | 89 | "cell_type": "markdown", |
84 | 90 | "metadata": {}, |
85 | 91 | "source": [ |
86 | 92 | "<a id='1'></a>\n", |
87 | | - "### 1️⃣ Create the Azure Resource Group\n", |
88 | | - "All resources deployed in this lab will be created in the specified resource group. Skip this step if you want to use an existing resource group." |
| 93 | + "### 1️⃣ Verify the Azure CLI and the connected Azure subscription\n", |
| 94 | + "\n", |
| 95 | + "The following commands ensure that you have the latest version of the Azure CLI and that the Azure CLI is connected to your Azure subscription." |
89 | 96 | ] |
90 | 97 | }, |
91 | 98 | { |
|
94 | 101 | "metadata": {}, |
95 | 102 | "outputs": [], |
96 | 103 | "source": [ |
97 | | - "# %load ../../shared/snippets/create-az-resource-group.py\n", |
98 | | - "# type: ignore\n", |
99 | | - "\n", |
100 | | - "import datetime\n", |
101 | | - "\n", |
102 | | - "resource_group_stdout = ! az group create --name {resource_group_name} --location {resource_group_location}\n", |
103 | | - "\n", |
104 | | - "if resource_group_stdout.n.startswith(\"ERROR\"):\n", |
105 | | - " print(resource_group_stdout)\n", |
106 | | - "else:\n", |
107 | | - " print(f\"✅ Azure Resource Group {resource_group_name} created ⌚ {datetime.datetime.now().time()}\")\n" |
| 104 | + "output = utils.run(\"az account show\", \"Retrieved az account\", \"Failed to get the current az account\")\n", |
| 105 | + "if output.success and output.json_data:\n", |
| 106 | + " current_user = output.json_data['user']['name']\n", |
| 107 | + " subscription_id = output.json_data['id']\n", |
| 108 | + " tenant_id = output.json_data['tenantId']" |
108 | 109 | ] |
109 | 110 | }, |
110 | 111 | { |
|
114 | 115 | "<a id='2'></a>\n", |
115 | 116 | "### 2️⃣ Create deployment using 🦾 Bicep\n", |
116 | 117 | "\n", |
117 | | - "This lab uses [Bicep](https://learn.microsoft.com/azure/azure-resource-manager/bicep/overview?tabs=bicep) to declarative define all the resources that will be deployed. Change the parameters or the [main.bicep](main.bicep) directly to try different configurations. " |
| 118 | + "This lab uses [Bicep](https://learn.microsoft.com/azure/azure-resource-manager/bicep/overview?tabs=bicep) to declarative define all the resources that will be deployed in the specified resource group. Change the parameters or the [main.bicep](main.bicep) directly to try different configurations. " |
118 | 119 | ] |
119 | 120 | }, |
120 | 121 | { |
|
123 | 124 | "metadata": {}, |
124 | 125 | "outputs": [], |
125 | 126 | "source": [ |
126 | | - "# %load ../../shared/snippets/create-az-deployment.py\n", |
127 | | - "# type: ignore\n", |
128 | | - "\n", |
129 | | - "import json\n", |
130 | | - "\n", |
131 | | - "backend_id = \"openai-backend-pool\" if len(openai_resources) > 1 else openai_resources[0].get(\"name\")\n", |
| 127 | + "# create the resource group if doesn't exist\n", |
| 128 | + "utils.create_resource_group(True, resource_group_name, resource_group_location)\n", |
132 | 129 | "\n", |
| 130 | + "# update the APIM policy file before the deployment\n", |
| 131 | + "policy_xml = None\n", |
133 | 132 | "with open(\"policy.xml\", 'r') as policy_xml_file:\n", |
134 | | - " policy_xml = policy_xml_file.read()\n", |
135 | | - "\n", |
136 | | - " if \"{backend-id}\" in policy_xml:\n", |
137 | | - " policy_xml = policy_xml.replace(\"{backend-id}\", backend_id)\n", |
138 | | - "\n", |
139 | | - " if \"{aad-client-application-id}\" in policy_xml:\n", |
140 | | - " policy_xml = policy_xml.replace(\"{aad-client-application-id}\", client_id)\n", |
141 | | - "\n", |
142 | | - " if \"{aad-tenant-id}\" in policy_xml:\n", |
143 | | - " policy_xml = policy_xml.replace(\"{aad-tenant-id}\", tenant_id)\n", |
144 | | - "\n", |
| 133 | + " policy_template_xml = policy_xml_file.read()\n", |
| 134 | + " if \"{backend-id}\" in policy_template_xml:\n", |
| 135 | + " policy_xml = policy_template_xml.replace(\"{backend-id}\", str(\"openai-backend-pool\" if len(openai_resources) > 1 else openai_resources[0].get(\"name\"))) \n", |
145 | 136 | " policy_xml_file.close()\n", |
146 | | - "open(\"policy-updated.xml\", 'w').write(policy_xml)\n", |
| 137 | + "if policy_xml is not None:\n", |
| 138 | + " open(\"policy.xml\", 'w').write(policy_xml)\n", |
147 | 139 | "\n", |
| 140 | + "# define the BICEP parameters\n", |
148 | 141 | "bicep_parameters = {\n", |
149 | 142 | " \"$schema\": \"https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#\",\n", |
150 | 143 | " \"contentVersion\": \"1.0.0.0\",\n", |
151 | 144 | " \"parameters\": {\n", |
| 145 | + " \"apimSku\": { \"value\": apim_sku },\n", |
152 | 146 | " \"openAIConfig\": { \"value\": openai_resources },\n", |
153 | 147 | " \"openAIDeploymentName\": { \"value\": openai_deployment_name },\n", |
154 | 148 | " \"openAIModelName\": { \"value\": openai_model_name },\n", |
|
157 | 151 | " }\n", |
158 | 152 | "}\n", |
159 | 153 | "\n", |
| 154 | + "# write the parameters to a file \n", |
160 | 155 | "with open('params.json', 'w') as bicep_parameters_file:\n", |
161 | 156 | " bicep_parameters_file.write(json.dumps(bicep_parameters))\n", |
162 | 157 | "\n", |
163 | | - "! az deployment group create --name {deployment_name} --resource-group {resource_group_name} --template-file \"main.bicep\" --parameters \"params.json\"\n" |
| 158 | + "# run the deployment\n", |
| 159 | + "output = utils.run(f\"az deployment group create --name {deployment_name} --resource-group {resource_group_name} --template-file main.bicep --parameters params.json\", \n", |
| 160 | + " f\"Deployment '{deployment_name}' succeeded\", f\"Deployment '{deployment_name}' failed\")\n", |
| 161 | + "open(\"policy.xml\", 'w').write(policy_template_xml)\n" |
164 | 162 | ] |
165 | 163 | }, |
166 | 164 | { |
|
170 | 168 | "<a id='3'></a>\n", |
171 | 169 | "### 3️⃣ Get the deployment outputs\n", |
172 | 170 | "\n", |
173 | | - "We are now at the stage where we only need to retrieve the gateway URL and the subscription before we are ready for testing." |
| 171 | + "Retrieve the required outputs from the Bicep deployment." |
174 | 172 | ] |
175 | 173 | }, |
176 | 174 | { |
|
179 | 177 | "metadata": {}, |
180 | 178 | "outputs": [], |
181 | 179 | "source": [ |
182 | | - "# %load ../../shared/snippets/deployment-outputs.py\n", |
183 | | - "# type: ignore\n", |
184 | | - "\n", |
185 | 180 | "# Obtain all of the outputs from the deployment\n", |
186 | | - "stdout = ! az deployment group show --name {deployment_name} -g {resource_group_name} --query properties.outputs -o json\n", |
187 | | - "outputs = json.loads(stdout.n)\n", |
188 | | - "\n", |
189 | | - "# Extract the individual properties\n", |
190 | | - "apim_service_id = outputs.get('apimServiceId', {}).get('value', '')\n", |
191 | | - "apim_subscription_key = outputs.get('apimSubscriptionKey', {}).get('value', '')\n", |
192 | | - "apim_subscription1_key = outputs.get('apimSubscription1Key', {}).get('value', '')\n", |
193 | | - "apim_subscription2_key = outputs.get('apimSubscription2Key', {}).get('value', '')\n", |
194 | | - "apim_subscription3_key = outputs.get('apimSubscription3Key', {}).get('value', '')\n", |
195 | | - "apim_resource_gateway_url = outputs.get('apimResourceGatewayURL', {}).get('value', '')\n", |
196 | | - "workspace_id = outputs.get('logAnalyticsWorkspaceId', {}).get('value', '')\n", |
197 | | - "app_id = outputs.get('applicationInsightsAppId', {}).get('value', '')\n", |
198 | | - "app_insights_name = outputs.get('applicationInsightsName', {}).get('value', '')\n", |
199 | | - "function_app_resource_name = outputs.get('functionAppResourceName', {}).get('value', '')\n", |
200 | | - "cosmosdb_connection_string = outputs.get('cosmosDBConnectionString', {}).get('value', '')\n", |
201 | | - "\n", |
202 | | - "# Print the extracted properties if they are not empty\n", |
203 | | - "if apim_service_id:\n", |
204 | | - " print(f\"👉🏻 APIM Service Id: {apim_service_id}\")\n", |
205 | | - "\n", |
206 | | - "if apim_subscription_key:\n", |
207 | | - " print(f\"👉🏻 APIM Subscription Key (masked): ****{apim_subscription_key[-4:]}\")\n", |
208 | | - "\n", |
209 | | - "if apim_subscription1_key:\n", |
210 | | - " print(f\"👉🏻 APIM Subscription Key 1 (masked): ****{apim_subscription1_key[-4:]}\")\n", |
211 | | - "\n", |
212 | | - "if apim_subscription2_key:\n", |
213 | | - " print(f\"👉🏻 APIM Subscription Key 2 (masked): ****{apim_subscription2_key[-4:]}\")\n", |
214 | | - "\n", |
215 | | - "if apim_subscription3_key:\n", |
216 | | - " print(f\"👉🏻 APIM Subscription Key 3 (masked): ****{apim_subscription3_key[-4:]}\")\n", |
217 | | - "\n", |
218 | | - "if apim_resource_gateway_url:\n", |
219 | | - " print(f\"👉🏻 APIM API Gateway URL: {apim_resource_gateway_url}\")\n", |
220 | | - "\n", |
221 | | - "if workspace_id:\n", |
222 | | - " print(f\"👉🏻 Workspace ID: {workspace_id}\")\n", |
223 | | - "\n", |
224 | | - "if app_id:\n", |
225 | | - " print(f\"👉🏻 App ID: {app_id}\")\n", |
226 | | - "\n", |
227 | | - "if app_insights_name:\n", |
228 | | - " print(f\"👉🏻 Application Insights Name: {app_insights_name}\")\n", |
229 | | - "\n", |
230 | | - "if function_app_resource_name:\n", |
231 | | - " print(f\"👉🏻 Function Name: {function_app_resource_name}\")\n", |
232 | | - "\n", |
233 | | - "if cosmosdb_connection_string:\n", |
234 | | - " print(f\"👉🏻 Cosmos DB Connection String: {cosmosdb_connection_string}\")\n" |
| 181 | + "output = utils.run(f\"az deployment group show --name {deployment_name} -g {resource_group_name}\", f\"Retrieved deployment: {deployment_name}\", f\"Failed to retrieve deployment: {deployment_name}\")\n", |
| 182 | + "if output.success and output.json_data:\n", |
| 183 | + " apim_service_id = utils.get_deployment_output(output, 'apimServiceId', 'APIM Service Id')\n", |
| 184 | + " apim_subscription1_key = utils.get_deployment_output(output, 'apimSubscription1Key', 'APIM Subscription 1 Key (masked)', True)\n", |
| 185 | + " apim_subscription2_key = utils.get_deployment_output(output, 'apimSubscription2Key', 'APIM Subscription 2 Key (masked)', True)\n", |
| 186 | + " apim_subscription3_key = utils.get_deployment_output(output, 'apimSubscription3Key', 'APIM Subscription 3 Key (masked)', True)\n", |
| 187 | + " apim_resource_gateway_url = utils.get_deployment_output(output, 'apimResourceGatewayURL', 'APIM API Gateway URL')\n", |
| 188 | + " app_insights_name = utils.get_deployment_output(output, 'applicationInsightsName', 'Application Insights Name')\n", |
| 189 | + "\n", |
| 190 | + "\n" |
235 | 191 | ] |
236 | 192 | }, |
237 | 193 | { |
|
464 | 420 | ], |
465 | 421 | "metadata": { |
466 | 422 | "kernelspec": { |
467 | | - "display_name": ".venv", |
| 423 | + "display_name": "Python 3", |
468 | 424 | "language": "python", |
469 | 425 | "name": "python3" |
470 | 426 | }, |
|
0 commit comments