mirror of
https://github.com/Azure-Samples/graphrag-accelerator.git
synced 2025-10-11 08:43:32 +00:00
working version of a managed app
This commit is contained in:
parent
bc24bfad1c
commit
ca0c4890ad
@ -1,17 +1,41 @@
|
||||
# Managed App Instructions
|
||||
|
||||
This guide is a temporary document that walks through the progress made so far to convert the graphrag solution accelerator to a managed app.
|
||||
This guide is a temporary document that walks through the process to convert the graphrag solution accelerator to a managed app.
|
||||
|
||||
1. Auto format the bicep code
|
||||
### 1. Auto format the bicep code
|
||||
|
||||
As a precaution, start by auto-formating and linting the bicep code to detect any mistakes early-on.
|
||||
|
||||
```bash
|
||||
cd <repo_root_directory>/infra
|
||||
find . -type f -name "*.bicep" -exec az bicep format --file {} \;
|
||||
find . -type f -name "*.bicep" -exec az bicep lint --file {} \;
|
||||
```
|
||||
|
||||
2. Convert bicep -> ARM
|
||||
### 2. Convert bicep -> ARM
|
||||
```bash
|
||||
az bicep build --file main.bicep --outfile managed-app/mainTemplate.json
|
||||
```
|
||||
|
||||
3. Test the Portal Interface
|
||||
Use the [Azure Portal Sandbox](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/SandboxBlade) to test and make any UI changes in `managed-app/createUiDefinition.json`. To make additional changes to the Azure portal experience, start by reading some [documentation](https://learn.microsoft.com/en-us/azure/azure-resource-manager/managed-applications/create-uidefinition-overview) and copying the contents of `createUiDefinition.json` into the sandbox environment.
|
||||
### 3. Create & test the Azure portal interface
|
||||
|
||||
Use the [Azure Portal Sandbox](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/SandboxBlade) to test and make any UI changes that are defined in [createUiDefinition.json](createUiDefinition.json). To make additional changes to the Azure portal experience, start by reading some [documentation](https://learn.microsoft.com/en-us/azure/azure-resource-manager/managed-applications/create-uidefinition-overview) and copying the contents of `createUiDefinition.json` into the sandbox environment.
|
||||
|
||||
### 4. Package up the managed app code
|
||||
|
||||
The name of the final two files (`mainTemplate.json` and `createUiDefinition.json`) cannot be changed. The file names are also case-sensitive and cannot be changed at this time. Managed apps require these files to be packaged up into a zip file (where the json files must be at the root directory).
|
||||
|
||||
```bash
|
||||
cd <repo_root_directory>/infra/managed-app
|
||||
zip -rj managed-app.zip .
|
||||
```
|
||||
|
||||
This zip file can then be uploaded to an Azure Storage location when setting up a [Service Catalog Managed Application Definition](https://ms.portal.azure.com/#view/Microsoft_Azure_Marketplace/GalleryItemDetailsBladeNopdl/id/Microsoft.ApplianceDefinition/selectionMode~/false/resourceGroupId//resourceGroupLocation//dontDiscardJourney~/false/selectedMenuId/home/launchingContext~/%7B%22galleryItemId%22%3A%22Microsoft.ApplianceDefinition%22%2C%22source%22%3A%5B%22GalleryFeaturedMenuItemPart%22%2C%22VirtualizedTileDetails%22%5D%2C%22menuItemId%22%3A%22home%22%2C%22subMenuItemId%22%3A%22Search%20results%22%2C%22telemetryId%22%3A%2220409084-39a1-4800-bbce-d0b26a6f46a4%22%7D/searchTelemetryId/d7d20e05-ca16-47f7-bed5-9c7b8d2fa641).
|
||||
|
||||
### 5. Create the Service Catalog Managed App Definition
|
||||
|
||||
In the Azure Portal, go to Marketplace and create a `Service Catalog Managed App Definition`. You must provide a uri link to the uploaded `managed-app.zip` file as part of the creation process.
|
||||
|
||||
### 6. Deploy the managed app
|
||||
|
||||
In the Azure Portal, find and click on the managed app definition resource that was created in the previous step. A button option to `Deploy from definition` will be available. Click on it and proceed through the setup steps (defined by the `createUiDefinitions.json` file) that a consumer would experience when installing the managed app.
|
||||
|
@ -4,17 +4,23 @@ param openAiName string = 'openai${uniqueString(resourceGroup().id)}'
|
||||
@description('Location for the Azure OpenAI instance')
|
||||
param location string = resourceGroup().location
|
||||
|
||||
@description('LLM model deployment name')
|
||||
param llmModelDeploymentName string = 'gpt-4o'
|
||||
@description('LLM model name')
|
||||
param llmModelName string = 'gpt-4o'
|
||||
|
||||
@description('Embedding model deployment name')
|
||||
param embeddingModelDeploymentName string = 'text-embedding-ada-002'
|
||||
@description('LLM Model API version')
|
||||
param llmModelVersion string
|
||||
|
||||
@description('TPM quota for GPT-4o deployment')
|
||||
param gpt4oTpm int = 10
|
||||
@description('Embedding model name')
|
||||
param embeddingModelName string = 'text-embedding-ada-002'
|
||||
|
||||
@description('TPM quota for text-embedding-ada-002 deployment')
|
||||
param textEmbeddingAdaTpm int = 10
|
||||
@description('Embedding Model API version')
|
||||
param embeddingModelVersion string
|
||||
|
||||
@description('TPM quota for llm model deployment (x1000)')
|
||||
param llmTpmQuota int = 10
|
||||
|
||||
@description('TPM quota for embedding model deployment (x1000)')
|
||||
param embeddingTpmQuota int = 10
|
||||
|
||||
@description('Array of objects with fields principalId, roleDefinitionId')
|
||||
param roleAssignments array = []
|
||||
@ -32,39 +38,39 @@ resource aoai 'Microsoft.CognitiveServices/accounts@2024-10-01' = {
|
||||
}
|
||||
}
|
||||
|
||||
resource gpt4oDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = {
|
||||
resource llmDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = {
|
||||
parent: aoai
|
||||
name: llmModelDeploymentName
|
||||
name: llmModelName
|
||||
sku: {
|
||||
name: 'GlobalStandard'
|
||||
capacity: gpt4oTpm
|
||||
capacity: llmTpmQuota
|
||||
}
|
||||
properties: {
|
||||
model: {
|
||||
format: 'OpenAI'
|
||||
name: 'gpt-4o'
|
||||
version: '2024-05-13'
|
||||
name: llmModelName
|
||||
version: llmModelVersion
|
||||
}
|
||||
currentCapacity: gpt4oTpm
|
||||
currentCapacity: llmTpmQuota
|
||||
}
|
||||
}
|
||||
|
||||
resource textEmbeddingAdaDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = {
|
||||
resource embeddingDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = {
|
||||
parent: aoai
|
||||
name: embeddingModelDeploymentName
|
||||
name: embeddingModelName
|
||||
// NOTE: simultaneous model deployments are not supported at this time. As a workaround, use dependsOn to force the models to be deployed in a sequential manner.
|
||||
dependsOn: [gpt4oDeployment]
|
||||
dependsOn: [llmDeployment]
|
||||
sku: {
|
||||
name: 'Standard'
|
||||
capacity: textEmbeddingAdaTpm
|
||||
capacity: embeddingTpmQuota
|
||||
}
|
||||
properties: {
|
||||
model: {
|
||||
format: 'OpenAI'
|
||||
name: 'text-embedding-ada-002'
|
||||
version: '2'
|
||||
name: embeddingModelName
|
||||
version: embeddingModelVersion
|
||||
}
|
||||
currentCapacity: textEmbeddingAdaTpm
|
||||
currentCapacity: embeddingTpmQuota
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,9 +83,9 @@ resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [
|
||||
]
|
||||
|
||||
output openAiEndpoint string = aoai.properties.endpoint
|
||||
output llmModel string = gpt4oDeployment.properties.model.name
|
||||
output llmModelDeploymentName string = gpt4oDeployment.name
|
||||
output llmModelApiVersion string = gpt4oDeployment.apiVersion
|
||||
output textEmbeddingModel string = textEmbeddingAdaDeployment.properties.model.name
|
||||
output textEmbeddingModelDeploymentName string = textEmbeddingAdaDeployment.name
|
||||
output textEmbeddingModelApiVersion string = textEmbeddingAdaDeployment.apiVersion
|
||||
output llmModel string = llmDeployment.properties.model.name
|
||||
output llmModelDeploymentName string = llmDeployment.name
|
||||
output llmModelApiVersion string = llmDeployment.apiVersion
|
||||
output textEmbeddingModel string = embeddingDeployment.properties.model.name
|
||||
output textEmbeddingModelDeploymentName string = embeddingDeployment.name
|
||||
output textEmbeddingModelApiVersion string = embeddingDeployment.apiVersion
|
||||
|
@ -16,7 +16,6 @@ GRAPHRAG_IMAGE=""
|
||||
PUBLISHER_EMAIL=""
|
||||
PUBLISHER_NAME=""
|
||||
RESOURCE_BASE_NAME=""
|
||||
CONTAINER_REGISTRY_NAME=""
|
||||
|
||||
requiredParams=(
|
||||
LOCATION
|
||||
@ -316,7 +315,6 @@ deployAzureResources () {
|
||||
--parameters "apiPublisherName=$PUBLISHER_NAME" \
|
||||
--parameters "apiPublisherEmail=$PUBLISHER_EMAIL" \
|
||||
--parameters "enablePrivateEndpoints=$ENABLE_PRIVATE_ENDPOINTS" \
|
||||
--parameters "acrName=$CONTAINER_REGISTRY_NAME" \
|
||||
--output json)
|
||||
# errors in deployment may not be caught by exitIfCommandFailed function so we also check the output for errors
|
||||
exitIfCommandFailed $? "Error deploying Azure resources..."
|
||||
|
@ -56,6 +56,24 @@ param storageAccountName string = ''
|
||||
param cosmosDbName string = ''
|
||||
param aiSearchName string = ''
|
||||
|
||||
// AOAI parameters
|
||||
@description('Name of the AOAI LLM model to use. Must match official model id. For more information: https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models')
|
||||
@allowed(['gpt-4o', 'gpt-4o-mini'])
|
||||
param llmModelName string = 'gpt-4o'
|
||||
@description('Version of the AOAI LLM model to use.')
|
||||
param llmModelVersion string = '2024-08-06'
|
||||
@description('Quota of the AOAI LLM model to use.')
|
||||
@minValue(1)
|
||||
param llmModelQuota int = 10
|
||||
|
||||
@description('Name of the AOAI embedding model to use. Must match official model id. For more information: https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models')
|
||||
@allowed(['text-embedding-ada-002', 'text-embedding-3-large'])
|
||||
param embeddingModelName string = 'text-embedding-ada-002'
|
||||
param embeddingModelVersion string = '2'
|
||||
@description('Quota of the AOAI embedding model to use.')
|
||||
@minValue(1)
|
||||
param embeddingModelQuota int = 10
|
||||
|
||||
var abbrs = loadJsonContent('abbreviations.json')
|
||||
var tags = { 'azd-env-name': resourceGroup }
|
||||
var workloadIdentityName = '${abbrs.managedIdentityUserAssignedIdentities}${resourceBaseNameFinal}'
|
||||
@ -175,10 +193,12 @@ module aoai 'core/aoai/aoai.bicep' = {
|
||||
params: {
|
||||
openAiName: '${abbrs.cognitiveServicesAccounts}${resourceBaseNameFinal}'
|
||||
location: location
|
||||
llmModelDeploymentName: 'gpt-4o-${uniqueString(resourceBaseNameFinal)}'
|
||||
gpt4oTpm: 10
|
||||
embeddingModelDeploymentName: 'text-embedding-ada-002-${uniqueString(resourceBaseNameFinal)}'
|
||||
textEmbeddingAdaTpm: 10
|
||||
llmModelName: llmModelName
|
||||
llmModelVersion: llmModelVersion
|
||||
llmTpmQuota: llmModelQuota
|
||||
embeddingModelName: embeddingModelName
|
||||
embeddingModelVersion: embeddingModelVersion
|
||||
embeddingTpmQuota: embeddingModelQuota
|
||||
roleAssignments: [
|
||||
{
|
||||
principalId: workloadIdentity.outputs.principalId
|
||||
@ -419,6 +439,11 @@ output azure_ai_search_name string = aiSearch.outputs.name
|
||||
output azure_acr_login_server string = acr.outputs.loginServer
|
||||
output azure_acr_name string = acr.outputs.name
|
||||
|
||||
output azure_aks_name string = aks.outputs.name
|
||||
output azure_aks_controlplanefqdn string = aks.outputs.controlPlaneFqdn
|
||||
output azure_aks_managed_rg string = aks.outputs.managedResourceGroup
|
||||
output azure_aks_service_account_name string = aksServiceAccountName
|
||||
|
||||
output azure_aoai_endpoint string = aoai.outputs.openAiEndpoint
|
||||
output azure_aoai_llm_model string = aoai.outputs.llmModel
|
||||
output azure_aoai_llm_model_deployment_name string = aoai.outputs.llmModelDeploymentName
|
||||
@ -427,32 +452,27 @@ output azure_aoai_embedding_model string = aoai.outputs.textEmbeddingModel
|
||||
output azure_aoai_embedding_model_deployment_name string = aoai.outputs.textEmbeddingModelDeploymentName
|
||||
output azure_aoai_embedding_model_api_version string = aoai.outputs.textEmbeddingModelApiVersion
|
||||
|
||||
output azure_aks_name string = aks.outputs.name
|
||||
output azure_aks_controlplanefqdn string = aks.outputs.controlPlaneFqdn
|
||||
output azure_aks_managed_rg string = aks.outputs.managedResourceGroup
|
||||
output azure_aks_service_account_name string = aksServiceAccountName
|
||||
output azure_apim_name string = apim.outputs.name
|
||||
output azure_apim_gateway_url string = apim.outputs.apimGatewayUrl
|
||||
|
||||
output azure_workload_identity_client_id string = workloadIdentity.outputs.clientId
|
||||
output azure_workload_identity_principal_id string = workloadIdentity.outputs.principalId
|
||||
output azure_workload_identity_name string = workloadIdentity.outputs.name
|
||||
output azure_app_hostname string = appHostname
|
||||
output azure_app_url string = appUrl
|
||||
|
||||
output azure_storage_account string = storage.outputs.name
|
||||
output azure_storage_account_blob_url string = storage.outputs.primaryEndpoints.blob
|
||||
output azure_app_insights_connection_string string = apim.outputs.appInsightsConnectionString
|
||||
|
||||
output azure_cosmosdb_endpoint string = cosmosdb.outputs.endpoint
|
||||
output azure_cosmosdb_name string = cosmosdb.outputs.name
|
||||
output azure_cosmosdb_id string = cosmosdb.outputs.id
|
||||
|
||||
output azure_app_insights_connection_string string = apim.outputs.appInsightsConnectionString
|
||||
|
||||
output azure_apim_name string = apim.outputs.name
|
||||
output azure_apim_gateway_url string = apim.outputs.apimGatewayUrl
|
||||
|
||||
output azure_dns_zone_name string = privateDnsZone.outputs.name
|
||||
|
||||
output azure_app_hostname string = appHostname
|
||||
output azure_app_url string = appUrl
|
||||
|
||||
output azure_private_dns_zones array = enablePrivateEndpoints
|
||||
? union(privatelinkPrivateDns.outputs.privateDnsZones, [privateDnsZone.outputs.name])
|
||||
: []
|
||||
|
||||
output azure_storage_account string = storage.outputs.name
|
||||
output azure_storage_account_blob_url string = storage.outputs.primaryEndpoints.blob
|
||||
|
||||
output azure_workload_identity_client_id string = workloadIdentity.outputs.clientId
|
||||
output azure_workload_identity_principal_id string = workloadIdentity.outputs.principalId
|
||||
output azure_workload_identity_name string = workloadIdentity.outputs.name
|
||||
|
176
infra/managed-app/createUiDefinition.json
Normal file
176
infra/managed-app/createUiDefinition.json
Normal file
@ -0,0 +1,176 @@
|
||||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json#",
|
||||
"handler": "Microsoft.Azure.CreateUIDef",
|
||||
"version": "0.1.2-preview",
|
||||
"parameters": {
|
||||
"basics": [
|
||||
{}
|
||||
],
|
||||
"steps": [
|
||||
{
|
||||
"name": "aoaiSettings",
|
||||
"label": "AOAI Settings",
|
||||
"subLabel": {
|
||||
"preValidation": "Configure the AOAI settings",
|
||||
"postValidation": "Completed"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "llmModel",
|
||||
"type": "Microsoft.Common.DropDown",
|
||||
"label": "LLM Model",
|
||||
"defaultValue": "gpt-4o",
|
||||
"toolTip": "LLM model to use.",
|
||||
"constraints": {
|
||||
"allowedValues": [
|
||||
{
|
||||
"label": "gpt-4o",
|
||||
"value": "gpt-4o"
|
||||
},
|
||||
{
|
||||
"label": "gpt-4o-mini",
|
||||
"value": "gpt-4o-mini"
|
||||
}
|
||||
],
|
||||
"required": true
|
||||
},
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"name": "llmModelVersion",
|
||||
"type": "Microsoft.Common.DropDown",
|
||||
"label": "LLM Model Version",
|
||||
"defaultValue": "2024-08-06",
|
||||
"toolTip": "LLM model version to use.",
|
||||
"constraints": {
|
||||
"allowedValues": [
|
||||
{
|
||||
"label": "2024-08-06",
|
||||
"value": "2024-08-06"
|
||||
},
|
||||
{
|
||||
"label": "2024-07-18",
|
||||
"value": "2024-07-18"
|
||||
}
|
||||
],
|
||||
"required": true
|
||||
},
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"name": "llmModelQuota",
|
||||
"type": "Microsoft.Common.TextBox",
|
||||
"label": "LLM Model Quota (x1000)",
|
||||
"placeholder": "85",
|
||||
"defaultValue": "",
|
||||
"toolTip": "Model quota to use.",
|
||||
"constraints": {
|
||||
"required": true,
|
||||
"regex": "^[1-9][0-9]*$",
|
||||
"validationMessage": "Valid LLM model quota."
|
||||
},
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"name": "embeddingModel",
|
||||
"type": "Microsoft.Common.DropDown",
|
||||
"label": "Embedding Model",
|
||||
"defaultValue": "text-embedding-ada-002",
|
||||
"toolTip": "Embedding model to use",
|
||||
"constraints": {
|
||||
"allowedValues": [
|
||||
{
|
||||
"label": "text-embedding-ada-002",
|
||||
"value": "text-embedding-ada-002"
|
||||
},
|
||||
{
|
||||
"label": "text-embedding-3-large",
|
||||
"value": "text-embedding-3-large"
|
||||
}
|
||||
],
|
||||
"required": true
|
||||
},
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"name": "embeddingModelQuota",
|
||||
"type": "Microsoft.Common.TextBox",
|
||||
"label": "Embedding Model Quota (x1000)",
|
||||
"placeholder": "100",
|
||||
"defaultValue": "",
|
||||
"toolTip": "Model quota to use.",
|
||||
"constraints": {
|
||||
"required": true,
|
||||
"regex": "^[1-9][0-9]*$",
|
||||
"validationMessage": "Valid embedding model quota."
|
||||
},
|
||||
"visible": true
|
||||
},
|
||||
{
|
||||
"name": "embeddingModelVersion",
|
||||
"type": "Microsoft.Common.DropDown",
|
||||
"label": "Embedding Model Version",
|
||||
"defaultValue": "2",
|
||||
"toolTip": "Use a valid embedding model version.",
|
||||
"constraints": {
|
||||
"allowedValues": [
|
||||
{
|
||||
"label": "2",
|
||||
"value": "2"
|
||||
},
|
||||
{
|
||||
"label": "1",
|
||||
"value": "1"
|
||||
}
|
||||
],
|
||||
"required": true
|
||||
},
|
||||
"visible": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "graphragSettings",
|
||||
"label": "GraphRAG Settings",
|
||||
"subLabel": {
|
||||
"preValidation": "Configure the graphrag settings",
|
||||
"postValidation": "Completed"
|
||||
},
|
||||
"elements": [
|
||||
{
|
||||
"name": "apimTier",
|
||||
"type": "Microsoft.Common.DropDown",
|
||||
"label": "APIM Tier",
|
||||
"defaultValue": "StandardV2",
|
||||
"toolTip": "APIM tier to use",
|
||||
"constraints": {
|
||||
"allowedValues": [
|
||||
{
|
||||
"label": "Developer",
|
||||
"value": "Developer"
|
||||
},
|
||||
{
|
||||
"label": "StandardV2",
|
||||
"value": "StandardV2"
|
||||
}
|
||||
],
|
||||
"required": true
|
||||
},
|
||||
"visible": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"outputs": {
|
||||
"resourceGroup": "[resourceGroup().name]",
|
||||
"location": "[location()]",
|
||||
"apimTier": "[steps('graphragSettings').apimTier]",
|
||||
"llmModelName": "[steps('aoaiSettings').llmModel]",
|
||||
"llmModelQuota": "[int(steps('aoaiSettings').llmModelQuota)]",
|
||||
"embeddingModelName": "[steps('aoaiSettings').embeddingModel]",
|
||||
"embeddingModelQuota": "[int(steps('aoaiSettings').embeddingModelQuota)]",
|
||||
"llmModelVersion": "[steps('aoaiSettings').llmModelVersion]",
|
||||
"embeddingModelVersion": "[steps('aoaiSettings').embeddingModelVersion]"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user