Skip to content

Commit dd9b906

Browse files
authored
Merge pull request #99 from Azure-Samples/feature/add-progressive-policies-1-lab
Feature/add zero-to-production lab
2 parents 4932d72 + 2984105 commit dd9b906

File tree

11 files changed

+1372
-1
lines changed

11 files changed

+1372
-1
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ __pycache__/
99
.azure/
1010

1111
labs-in-progress/
12-
params.json
12+
params*.json
1313
policy-updated.xml
1414

1515
.vscode/**/*

labs/zero-to-production/README.MD

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# APIM ❤️ OpenAI
2+
3+
## [Zero-to-Production lab](zero-to-production.ipynb)
4+
5+
Playground to create a combination of several policies in an iterative approach. We start with load balancing, then progressively add token emitting, rate limiting, and, eventually, semantic caching. Each of these sets of policies is derived from other labs in this repo.
6+
7+
[View policy configuration](policy.xml)
8+
9+
### Prerequisites
10+
11+
- [Python 3.12 or later version](https://www.python.org/) installed
12+
- [Pandas Library](https://pandas.pydata.org) installed
13+
- [VS Code](https://code.visualstudio.com/) installed with the [Jupyter notebook extension](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter) enabled
14+
- [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) installed
15+
- [An Azure Subscription](https://azure.microsoft.com/free/) with Contributor permissions
16+
- [Access granted to Azure OpenAI](https://aka.ms/oai/access)
17+
- [Sign in to Azure with Azure CLI](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively)
18+
19+
### 🚀 Get started
20+
21+
Proceed by opening the [Jupyter notebook](zero-to-production.ipynb), and follow the steps provided.
22+
23+
### 🗑️ Clean up resources
24+
25+
When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered.
26+
Use the [clean-up-resources notebook](clean-up-resources.ipynb) for that.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"### 🗑️ Clean up resources\n",
8+
"\n",
9+
"When you're finished with the lab, you should remove all your deployed resources from Azure to avoid extra charges and keep your Azure subscription uncluttered."
10+
]
11+
},
12+
{
13+
"cell_type": "code",
14+
"execution_count": null,
15+
"metadata": {},
16+
"outputs": [],
17+
"source": [
18+
"import os, sys\n",
19+
"sys.path.insert(1, '../../shared') # add the shared directory to the Python path\n",
20+
"import utils\n",
21+
"\n",
22+
"deployment_name = os.path.basename(os.path.dirname(globals()['__vsc_ipynb_file__']))\n",
23+
"utils.cleanup_resources(deployment_name)"
24+
]
25+
}
26+
],
27+
"metadata": {
28+
"kernelspec": {
29+
"display_name": "Python 3",
30+
"language": "python",
31+
"name": "python3"
32+
},
33+
"language_info": {
34+
"codemirror_mode": {
35+
"name": "ipython",
36+
"version": 3
37+
},
38+
"file_extension": ".py",
39+
"mimetype": "text/x-python",
40+
"name": "python",
41+
"nbconvert_exporter": "python",
42+
"pygments_lexer": "ipython3",
43+
"version": "3.12.8"
44+
}
45+
},
46+
"nbformat": 4,
47+
"nbformat_minor": 2
48+
}

labs/zero-to-production/main.bicep

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
// ------------------
2+
// PARAMETERS
3+
// ------------------
4+
5+
// Typically, parameters would be decorated with appropriate metadata and attributes, but as they are very repetetive in these labs we omit them for brevity.
6+
7+
param apimSku string
8+
param openAIConfig array = []
9+
param openAIModelName string
10+
param openAIModelVersion string
11+
param openAIDeploymentName string
12+
param openAIModelCapacity int
13+
param openAIAPIVersion string = '2024-02-01'
14+
param policyXml string
15+
16+
// ------------------
17+
// VARIABLES
18+
// ------------------
19+
20+
var resourceSuffix = uniqueString(subscription().id, resourceGroup().id)
21+
var apiManagementName = 'apim-${resourceSuffix}'
22+
var openAISubscriptionName = 'openai-subscription'
23+
var openAISubscriptionDescription = 'OpenAI Subscription'
24+
var openAIAPIName = 'openai'
25+
26+
// ------------------
27+
// RESOURCES
28+
// ------------------
29+
30+
// 1. Log Analytics Workspace
31+
module lawModule '../../modules/operational-insights/v1/workspaces.bicep' = {
32+
name: 'lawModule'
33+
}
34+
35+
var lawId = lawModule.outputs.id
36+
37+
// 2. Application Insights
38+
module appInsightsModule '../../modules/monitor/v1/appinsights.bicep' = {
39+
name: 'appInsightsModule'
40+
params: {
41+
workbookJson: loadTextContent('openai-usage-analysis-workbook.json')
42+
lawId: lawId
43+
customMetricsOptedInType: 'WithDimensions'
44+
}
45+
}
46+
47+
var appInsightsId = appInsightsModule.outputs.id
48+
var appInsightsInstrumentationKey = appInsightsModule.outputs.instrumentationKey
49+
50+
// 3. API Management
51+
module apimModule '../../modules/apim/v1/apim.bicep' = {
52+
name: 'apimModule'
53+
params: {
54+
apimSku: apimSku
55+
appInsightsInstrumentationKey: appInsightsInstrumentationKey
56+
appInsightsId: appInsightsId
57+
}
58+
}
59+
60+
// 4. Cognitive Services
61+
module openAIModule '../../modules/cognitive-services/v1/openai.bicep' = {
62+
name: 'openAIModule'
63+
params: {
64+
openAIConfig: openAIConfig
65+
openAIDeploymentName: openAIDeploymentName
66+
openAIModelName: openAIModelName
67+
openAIModelVersion: openAIModelVersion
68+
openAIModelCapacity: openAIModelCapacity
69+
apimPrincipalId: apimModule.outputs.principalId
70+
lawId: lawId
71+
}
72+
}
73+
74+
// 5. APIM OpenAI API
75+
module openAIAPIModule '../../modules/apim/v1/openai-api.bicep' = {
76+
name: 'openAIAPIModule'
77+
params: {
78+
policyXml: policyXml
79+
openAIConfig: openAIModule.outputs.extendedOpenAIConfig
80+
openAIAPIVersion: openAIAPIVersion
81+
appInsightsInstrumentationKey: appInsightsInstrumentationKey
82+
appInsightsId: appInsightsId
83+
}
84+
}
85+
86+
// 6. Create New APIM Subscriptions
87+
88+
// We presume the APIM resource has been created as part of this bicep flow.
89+
resource apim 'Microsoft.ApiManagement/service@2024-06-01-preview' existing = {
90+
name: apiManagementName
91+
dependsOn: [
92+
apimModule
93+
]
94+
}
95+
96+
resource api 'Microsoft.ApiManagement/service/apis@2024-06-01-preview' existing = {
97+
parent: apim
98+
name: openAIAPIName
99+
dependsOn: [
100+
openAIAPIModule
101+
]
102+
}
103+
104+
// Ignore the subscription that gets created in the APIM module and create three new ones for this lab.
105+
resource apimSubscriptions 'Microsoft.ApiManagement/service/subscriptions@2024-06-01-preview' = [for i in range(1, 3): {
106+
name: '${openAISubscriptionName}${i}'
107+
parent: apim
108+
properties: {
109+
allowTracing: true
110+
displayName: '${openAISubscriptionDescription} ${i}'
111+
scope: '/apis/${api.id}'
112+
state: 'active'
113+
}
114+
dependsOn: [
115+
api
116+
]
117+
}]
118+
119+
// ------------------
120+
// MARK: OUTPUTS
121+
// ------------------
122+
123+
output applicationInsightsAppId string = appInsightsModule.outputs.appId
124+
output applicationInsightsName string = appInsightsModule.outputs.applicationInsightsName
125+
output logAnalyticsWorkspaceId string = lawModule.outputs.customerId
126+
output apimServiceId string = apimModule.outputs.id
127+
output apimResourceGatewayURL string = apimModule.outputs.gatewayUrl
128+
129+
#disable-next-line outputs-should-not-contain-secrets
130+
output apimSubscription1Key string = apimSubscriptions[0].listSecrets().primaryKey
131+
#disable-next-line outputs-should-not-contain-secrets
132+
output apimSubscription2Key string = apimSubscriptions[1].listSecrets().primaryKey
133+
#disable-next-line outputs-should-not-contain-secrets
134+
output apimSubscription3Key string = apimSubscriptions[2].listSecrets().primaryKey

0 commit comments

Comments
 (0)