Skip to content

Commit

Permalink
Update to a new GPT model (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
vieiraae authored Feb 6, 2025
1 parent 2334c01 commit f8fe369
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 361 deletions.
333 changes: 51 additions & 282 deletions labs/token-rate-limiting/main.bicep
Original file line number Diff line number Diff line change
@@ -1,296 +1,65 @@
@description('List of Mock webapp names used to simulate OpenAI behavior.')
param mockWebApps array = []
// ------------------
// PARAMETERS
// ------------------

@description('The name of the OpenAI mock backend pool')
param mockBackendPoolName string = 'openai-backend-pool'
// Typically, parameters would be decorated with appropriate metadata and attributes, but as they are very repetetive in these labs we omit them for brevity.

@description('The description of the OpenAI mock backend pool')
param mockBackendPoolDescription string = 'Load balancer for multiple OpenAI Mocking endpoints'

@description('List of OpenAI resources to create. Add pairs of name and location.')
param apimSku string
param openAIConfig array = []

@description('Deployment Name')
param openAIDeploymentName string

@description('Azure OpenAI Sku')
@allowed([
'S0'
])
param openAISku string = 'S0'

@description('Model Name')
param openAIModelName string

@description('Model Version')
param openAIModelVersion string

@description('Model Capacity')
param openAIModelCapacity int = 20

@description('The name of the API Management resource')
param apimResourceName string

@description('Location for the APIM resource')
param apimResourceLocation string = resourceGroup().location

@description('The pricing tier of this API Management service')
@allowed([
'Consumption'
'Developer'
'Basic'
'Basicv2'
'Standard'
'Standardv2'
'Premium'
])
param apimSku string = 'Consumption'

@description('The instance size of this API Management service.')
@allowed([
0
1
2
])
param apimSkuCount int = 1

@description('The email address of the owner of the service')
param apimPublisherEmail string = '[email protected]'

@description('The name of the owner of the service')
param apimPublisherName string = 'Microsoft'

@description('The name of the APIM API for OpenAI API')
param openAIAPIName string = 'openai'

@description('The relative path of the APIM API for OpenAI API')
param openAIAPIPath string = 'openai'

@description('The display name of the APIM API for OpenAI API')
param openAIAPIDisplayName string = 'OpenAI'

@description('The description of the APIM API for OpenAI API')
param openAIAPIDescription string = 'Azure OpenAI API inferencing API'

@description('Full URL for the OpenAI API spec')
param openAIAPISpecURL string = 'https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cognitiveservices/data-plane/AzureOpenAI/inference/stable/2024-02-01/inference.json'

@description('The name of the APIM Subscription for OpenAI API')
param openAISubscriptionName string = 'openai-subscription'

@description('The description of the APIM Subscription for OpenAI API')
param openAISubscriptionDescription string = 'OpenAI Subscription'

@description('The name of the OpenAI backend pool')
param openAIBackendPoolName string = 'openai-backend-pool'

@description('The description of the OpenAI backend pool')
param openAIBackendPoolDescription string = 'Load balancer for multiple OpenAI endpoints'

var resourceSuffix = uniqueString(subscription().id, resourceGroup().id)

resource cognitiveServices 'Microsoft.CognitiveServices/accounts@2021-10-01' = [for config in openAIConfig: if(length(openAIConfig) > 0) {
name: '${config.name}-${resourceSuffix}'
location: config.location
sku: {
name: openAISku
}
kind: 'OpenAI'
properties: {
apiProperties: {
statisticsEnabled: false
}
customSubDomainName: toLower('${config.name}-${resourceSuffix}')
}
}]

resource deployment 'Microsoft.CognitiveServices/accounts/deployments@2023-05-01' = [for (config, i) in openAIConfig: if(length(openAIConfig) > 0) {
name: openAIDeploymentName
parent: cognitiveServices[i]
properties: {
model: {
format: 'OpenAI'
name: openAIModelName
version: openAIModelVersion
}
}
sku: {
name: 'Standard'
capacity: openAIModelCapacity
}
}]

resource apimService 'Microsoft.ApiManagement/service@2023-05-01-preview' = {
name: '${apimResourceName}-${resourceSuffix}'
location: apimResourceLocation
sku: {
name: apimSku
capacity: (apimSku == 'Consumption') ? 0 : ((apimSku == 'Developer') ? 1 : apimSkuCount)
}
properties: {
publisherEmail: apimPublisherEmail
publisherName: apimPublisherName
}
identity: {
type: 'SystemAssigned'
}
}

var roleDefinitionID = resourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd')
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (config, i) in openAIConfig: if(length(openAIConfig) > 0) {
scope: cognitiveServices[i]
name: guid(subscription().id, resourceGroup().id, config.name, roleDefinitionID)
properties: {
roleDefinitionId: roleDefinitionID
principalId: apimService.identity.principalId
principalType: 'ServicePrincipal'
}
}]

resource api 'Microsoft.ApiManagement/service/apis@2023-05-01-preview' = {
name: openAIAPIName
parent: apimService
properties: {
apiType: 'http'
description: openAIAPIDescription
displayName: openAIAPIDisplayName
format: 'openapi-link'
path: openAIAPIPath
protocols: [
'https'
]
subscriptionKeyParameterNames: {
header: 'api-key'
query: 'api-key'
}
subscriptionRequired: true
type: 'http'
value: openAIAPISpecURL
}
}

resource apiPolicy 'Microsoft.ApiManagement/service/apis/policies@2021-12-01-preview' = {
name: 'policy'
parent: api
properties: {
format: 'rawxml'
value: loadTextContent('policy.xml')
}
dependsOn: [
backendOpenAI
]
}

resource backendOpenAI 'Microsoft.ApiManagement/service/backends@2023-05-01-preview' = [for (config, i) in openAIConfig: if(length(openAIConfig) > 0) {
name: config.name
parent: apimService
properties: {
description: 'backend description'
url: '${cognitiveServices[i].properties.endpoint}/openai'
protocol: 'http'
circuitBreaker: {
rules: [
{
failureCondition: {
count: 3
errorReasons: [
'Server errors'
]
interval: 'PT5M'
statusCodeRanges: [
{
min: 429
max: 429
}
]
}
name: 'openAIBreakerRule'
tripDuration: 'PT1M'
}
]
}
}
}]

resource backendMock 'Microsoft.ApiManagement/service/backends@2023-05-01-preview' = [for (mock, i) in mockWebApps: if(length(openAIConfig) == 0 && length(mockWebApps) > 0) {
name: mock.name
parent: apimService
properties: {
description: 'backend description'
url: '${mock.endpoint}/openai'
protocol: 'http'
circuitBreaker: {
rules: [
{
failureCondition: {
count: 3
errorReasons: [
'Server errors'
]
interval: 'PT5M'
statusCodeRanges: [
{
min: 429
max: 429
}
]
}
name: 'mockBreakerRule'
tripDuration: 'PT1M'
}
]
}
}
}]

resource backendPoolOpenAI 'Microsoft.ApiManagement/service/backends@2023-05-01-preview' = if(length(openAIConfig) > 1) {
name: openAIBackendPoolName
parent: apimService
properties: {
description: openAIBackendPoolDescription
type: 'Pool'
// protocol: 'http' // the protocol is not needed in the Pool type
// url: '${cognitiveServices[0].properties.endpoint}/openai' // the url is not needed in the Pool type
pool: {
services: [for (config, i) in openAIConfig: {
id: '/backends/${backendOpenAI[i].name}'
}
]
}
param openAIDeploymentName string
param openAIModelSKU string
param openAIModelCapacity int
param openAIAPIVersion string

// ------------------
// VARIABLES
// ------------------

// Account for all placeholders in the polixy.xml file.
var policyXml = loadTextContent('policy.xml')
var updatedPolicyXml = replace(policyXml, '{backend-id}', (length(openAIConfig) > 1) ? 'openai-backend-pool' : openAIConfig[0].name)

// ------------------
// RESOURCES
// ------------------

// 1. API Management
module apimModule '../../modules/apim/v1/apim.bicep' = {
name: 'apimModule'
params: {
apimSku: apimSku
}
}

resource backendPoolMock 'Microsoft.ApiManagement/service/backends@2023-05-01-preview' = if(length(openAIConfig) == 0 && length(mockWebApps) > 1) {
name: mockBackendPoolName
parent: apimService
properties: {
description: mockBackendPoolDescription
type: 'Pool'
// protocol: 'http' // the protocol is not needed in the Pool type
// url: '${mockWebApps[0].endpoint}/openai' // the url is not needed in the Pool type
pool: {
services: [for (webApp, i) in mockWebApps: {
id: '/backends/${backendMock[i].name}'
}
]
}
// 2. Cognitive Services
module openAIModule '../../modules/cognitive-services/v1/openai.bicep' = {
name: 'openAIModule'
params: {
openAIConfig: openAIConfig
openAIDeploymentName: openAIDeploymentName
openAIModelName: openAIModelName
openAIModelVersion: openAIModelVersion
openAIModelSKU: openAIModelSKU
openAIModelCapacity: openAIModelCapacity
apimPrincipalId: apimModule.outputs.principalId
}
}

resource apimSubscription 'Microsoft.ApiManagement/service/subscriptions@2023-05-01-preview' = {
name: openAISubscriptionName
parent: apimService
properties: {
allowTracing: true
displayName: openAISubscriptionDescription
scope: '/apis/${api.id}'
state: 'active'
// 3. APIM OpenAI API
module openAIAPIModule '../../modules/apim/v1/openai-api.bicep' = {
name: 'openAIAPIModule'
params: {
policyXml: updatedPolicyXml
openAIConfig: openAIModule.outputs.extendedOpenAIConfig
openAIAPIVersion: openAIAPIVersion
}
}

output apimServiceId string = apimService.id

output apimResourceGatewayURL string = apimService.properties.gatewayUrl

#disable-next-line outputs-should-not-contain-secrets
output apimSubscriptionKey string = apimSubscription.listSecrets().primaryKey
// ------------------
// MARK: OUTPUTS
// ------------------
output apimServiceId string = apimModule.outputs.id
output apimResourceGatewayURL string = apimModule.outputs.gatewayUrl
output apimSubscriptionKey string = openAIAPIModule.outputs.subscriptionPrimaryKey
Loading

0 comments on commit f8fe369

Please sign in to comment.