Skip to content

Commit 2844cc3

Browse files
feat: dev downmerge, updated for existing AI Foundry in Bicep and scripts
2 parents faa3e6e + 5acd3af commit 2844cc3

38 files changed

+1809
-882
lines changed

.github/workflows/deploy.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ on:
1414
- cron: '0 9,21 * * *' # Runs at 9:00 AM and 9:00 PM GMT
1515

1616
env:
17-
GPT_MIN_CAPACITY: 250
18-
TEXT_EMBEDDING_MIN_CAPACITY: 40
17+
GPT_MIN_CAPACITY: 150
18+
TEXT_EMBEDDING_MIN_CAPACITY: 80
1919
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
2020

2121
jobs:
@@ -148,6 +148,7 @@ jobs:
148148
gptDeploymentCapacity=${{ env.GPT_MIN_CAPACITY }} \
149149
embeddingModel="text-embedding-ada-002" \
150150
embeddingDeploymentCapacity=${{ env.TEXT_EMBEDDING_MIN_CAPACITY }} \
151+
aiDeploymentsLocation=${{ env.AZURE_LOCATION }} \
151152
imageTag="${IMAGE_TAG}"
152153
153154
- name: Get Deployment Output and extract Values
@@ -169,6 +170,8 @@ jobs:
169170
echo "COSMOSDB_ACCOUNT_NAME=$COSMOSDB_ACCOUNT_NAME" >> $GITHUB_ENV
170171
AI_FOUNDRY_NAME=$(echo $BICEP_OUTPUT | jq -r '.aI_FOUNDRY_NAME.value')
171172
echo "AI_FOUNDRY_NAME=$AI_FOUNDRY_NAME" >> $GITHUB_ENV
173+
AI_SEARCH_SERVICE_NAME=$(echo $BICEP_OUTPUT | jq -r '.aI_SEARCH_SERVICE_NAME.value')
174+
echo "AI_SEARCH_SERVICE_NAME=$AI_SEARCH_SERVICE_NAME" >> $GITHUB_ENV
172175
echo "Deployment output: $BICEP_OUTPUT"
173176
174177
- name: Run Post-Deployment Script
@@ -186,6 +189,7 @@ jobs:
186189
"${{ env.KEY_VAULT_NAME }}" \
187190
"${{ env.RESOURCE_GROUP_NAME }}" \
188191
"${{ env.AI_FOUNDRY_NAME }}" \
192+
"${{ env.AI_SEARCH_SERVICE_NAME }}" \
189193
"${{ secrets.AZURE_CLIENT_ID }}"
190194
191195
- name: Logout from Azure

.github/workflows/pylint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ jobs:
2929
- name: Pylint
3030
run: |
3131
echo "Running Pylint..."
32-
python -m flake8 --config=.flake8 --verbose .
32+
python -m flake8 --config=.flake8 --exclude=tests --verbose .
3333
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: validate template property for telemetry
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
paths:
8+
- 'azure.yaml'
9+
10+
jobs:
11+
validate-template-property:
12+
name: validate-template-property
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v4
18+
19+
- name: Check for required metadata template line
20+
run: |
21+
if grep -E '^\s*#\s*template:\s*document-generation@1\.0' azure.yaml; then
22+
echo "ERROR: 'template' line is commented out in azure.yaml! Please uncomment template line."
23+
exit 1
24+
fi
25+
26+
if ! grep -E '^\s*template:\s*document-generation@1\.0' azure.yaml; then
27+
echo "ERROR: Required 'template' line is missing in azure.yaml! Please add template line for telemetry."
28+
exit 1
29+
fi
30+
echo "template line is present and not commented."

azure.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ name: document-generation
66
metadata:
77
88

9+
requiredVersions:
10+
azd: '>= 1.15.0'
11+
912
parameters:
1013
solutionPrefix:
1114
type: string

docs/DeploymentGuide.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ If you're not using one of the above options for opening the project, then you'l
7474

7575
1. Make sure the following tools are installed:
7676
- [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.5) <small>(v7.0+)</small> - available for Windows, macOS, and Linux. (Required for Windows users only. Follow the steps [here](./PowershellSetup.md) to add it to the Windows PATH.)
77-
- [Azure Developer CLI (azd)](https://aka.ms/install-azd)
77+
- [Azure Developer CLI (azd)](https://aka.ms/install-azd) <small>(v1.15.0+)</small> - version
7878
- [Python 3.9+](https://www.python.org/downloads/)
7979
- [Docker Desktop](https://www.docker.com/products/docker-desktop/)
8080
- [Git](https://git-scm.com/downloads)
@@ -175,7 +175,7 @@ Once you've opened the project in [Codespaces](#github-codespaces), [Dev Contain
175175
```
176176
If you don't have azd env then you need to pass parameters along with the command. Then the command will look like the following:
177177
```shell
178-
bash ./infra/scripts/process_sample_data.sh <Storage-Account-name> <Storage-Account-container-name> <Key-Vault-name> <CosmosDB-Account-name> <Resource-Group-name> <aiFoundryResourceName>
178+
bash ./infra/scripts/process_sample_data.sh <Storage-Account-name> <Storage-Account-container-name> <Key-Vault-name> <CosmosDB-Account-name> <Resource-Group-name> <AI-Foundry-Name> <AI-Foundry-Resource-Group-Name> <Search-Service-Name>
179179
```
180180

181181
6. Open the [Azure Portal](https://portal.azure.com/), go to the deployed resource group, find the App Service and get the app URL from `Default domain`.

docs/QuotaCheck.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ azd auth login
1414

1515
### 📌 Default Models & Capacities:
1616
```
17-
gpt-4.1:30, text-embedding-ada-002:80, gpt-4:30
17+
gpt4.1:150, text-embedding-ada-002:80, gpt-4:150
1818
```
1919
### 📌 Default Regions:
2020
```
21-
eastus, uksouth, eastus2, northcentralus, swedencentral, westus, westus2, southcentralus, canadacentral
21+
francecentral, australiaeast, uksouth, eastus2, northcentralus, swedencentral, westus, westus2, southcentralus
2222
```
2323
### Usage Scenarios:
2424
- No parameters passed → Default models and capacities will be checked in default regions.
@@ -40,19 +40,19 @@ eastus, uksouth, eastus2, northcentralus, swedencentral, westus, westus2, southc
4040
```
4141
✔️ Check specific model(s) in default regions:
4242
```
43-
./quota_check_params.sh --models gpt-4.1:30,text-embedding-ada-002:80
43+
./quota_check_params.sh --models gpt4.1:150,text-embedding-ada-002:80
4444
```
4545
✔️ Check default models in specific region(s):
4646
```
47-
./quota_check_params.sh --regions eastus,westus
47+
./quota_check_params.sh --regions eastus2,westus
4848
```
4949
✔️ Passing Both models and regions:
5050
```
51-
./quota_check_params.sh --models gpt-4.1:30 --regions eastus,westus2
51+
./quota_check_params.sh --models gpt4.1:150 --regions eastus2,westus2
5252
```
5353
✔️ All parameters combined:
5454
```
55-
./quota_check_params.sh --models gpt-4:30,text-embedding-ada-002:80 --regions eastus,westus --verbose
55+
./quota_check_params.sh --models gpt-4:150,text-embedding-ada-002:80 --regions eastus2,westus --verbose
5656
```
5757

5858
### **Sample Output**

docs/README_LOCAL.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ NOTE: You may find you need to set: MacOS: `export NODE_OPTIONS="--max-old-space
3232
- `DATASOURCE_TYPE` (should be set to `AzureCognitiveSearch`)
3333
- `AZURE_SEARCH_SERVICE`
3434
- `AZURE_SEARCH_INDEX`
35-
- `AZURE_SEARCH_KEY`
3635

3736
These variables are optional:
3837
- `AZURE_SEARCH_USE_SEMANTIC_SEARCH`
@@ -178,7 +177,6 @@ Note: settings starting with `AZURE_SEARCH` are only needed when using Azure Ope
178177
|AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME||The name of the gpt model|
179178
|AZURE_SEARCH_SERVICE||The name of your Azure AI Search resource|
180179
|AZURE_SEARCH_INDEX||The name of your Azure AI Search Index|
181-
|AZURE_SEARCH_KEY||An **admin key** for your Azure AI Search resource|
182180
|AZURE_SEARCH_USE_SEMANTIC_SEARCH|False|Whether or not to use semantic search|
183181
|AZURE_SEARCH_QUERY_TYPE|simple|Query type: simple, semantic, vector, vectorSimpleHybrid, or vectorSemanticHybrid. Takes precedence over AZURE_SEARCH_USE_SEMANTIC_SEARCH|
184182
|AZURE_SEARCH_SEMANTIC_SEARCH_CONFIG||The name of the semantic search configuration to use if using semantic search.|
@@ -212,7 +210,6 @@ Note: settings starting with `AZURE_SEARCH` are only needed when using Azure Ope
212210
|UI_SHOW_SHARE_BUTTON|True|Share button (right-top)
213211
|SANITIZE_ANSWER|False|Whether to sanitize the answer from Azure OpenAI. Set to True to remove any HTML tags from the response.|
214212
|USE_PROMPTFLOW|False|Use existing Promptflow deployed endpoint. If set to `True` then both `PROMPTFLOW_ENDPOINT` and `PROMPTFLOW_API_KEY` also need to be set.|
215-
|USE_AI_FOUNDRY_SDK|False|Boolean flag to determine whether to use the AI Foundry SDK instead of the OpenAI SDK.|
216213
|PROMPTFLOW_ENDPOINT||URL of the deployed Promptflow endpoint e.g. https://pf-deployment-name.region.inference.ml.azure.com/score|
217214
|PROMPTFLOW_API_KEY||Auth key for deployed Promptflow endpoint. Note: only Key-based authentication is supported.|
218215
|PROMPTFLOW_RESPONSE_TIMEOUT|120|Timeout value in seconds for the Promptflow endpoint to respond.|

infra/deploy_ai_foundry.bicep

Lines changed: 57 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var aiProjectFriendlyName = aiProjectName
2424
var aiProjectDescription = 'AI Foundry Project'
2525
var aiSearchName = '${abbrs.ai.aiSearch}${solutionName}'
2626
var workspaceName = '${abbrs.managementGovernance.logAnalyticsWorkspace}${solutionName}'
27+
// var aiSearchConnectionName = 'myVectorStoreProjectConnectionName-${solutionName}'
2728

2829
var useExisting = !empty(existingLogAnalyticsWorkspaceId)
2930
var existingLawSubscription = useExisting ? split(existingLogAnalyticsWorkspaceId, '/')[2] : ''
@@ -111,6 +112,11 @@ resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
111112
}
112113
}
113114

115+
resource existingAiFoundry 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' existing = if (!empty(azureExistingAIProjectResourceId)) {
116+
name: existingAIFoundryName
117+
scope: resourceGroup(existingAIServiceSubscription, existingAIServiceResourceGroup)
118+
}
119+
114120
resource aiFoundry 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = if (empty(azureExistingAIProjectResourceId)) {
115121
name: aiFoundryName
116122
location: location
@@ -148,49 +154,50 @@ resource aiFoundryProject 'Microsoft.CognitiveServices/accounts/projects@2025-04
148154
}
149155

150156
@batchSize(1)
151-
resource aiFModelDeployments 'Microsoft.CognitiveServices/accounts/deployments@2025-04-01-preview' = [for aiModeldeployment in aiModelDeployments: if (empty(azureExistingAIProjectResourceId)) {
152-
parent: aiFoundry
153-
name: aiModeldeployment.name
154-
properties: {
155-
model: {
156-
format: 'OpenAI'
157-
name: aiModeldeployment.model
157+
resource aiFModelDeployments 'Microsoft.CognitiveServices/accounts/deployments@2025-04-01-preview' = [
158+
for aiModeldeployment in aiModelDeployments: if (empty(azureExistingAIProjectResourceId)) {
159+
parent: aiFoundry
160+
name: aiModeldeployment.name
161+
properties: {
162+
model: {
163+
format: 'OpenAI'
164+
name: aiModeldeployment.model
165+
}
166+
raiPolicyName: aiModeldeployment.raiPolicyName
167+
}
168+
sku: {
169+
name: aiModeldeployment.sku.name
170+
capacity: aiModeldeployment.sku.capacity
158171
}
159-
raiPolicyName: aiModeldeployment.raiPolicyName
160-
}
161-
sku:{
162-
name: aiModeldeployment.sku.name
163-
capacity: aiModeldeployment.sku.capacity
164172
}
165-
}]
173+
]
166174

167175
resource aiSearch 'Microsoft.Search/searchServices@2024-06-01-preview' = {
168-
name: aiSearchName
169-
location: solutionLocation
170-
sku: {
171-
name: 'basic'
176+
name: aiSearchName
177+
location: solutionLocation
178+
sku: {
179+
name: 'basic'
180+
}
181+
identity: {
182+
type: 'SystemAssigned'
183+
}
184+
properties: {
185+
replicaCount: 1
186+
partitionCount: 1
187+
hostingMode: 'default'
188+
publicNetworkAccess: 'enabled'
189+
networkRuleSet: {
190+
ipRules: []
172191
}
173-
properties: {
174-
replicaCount: 1
175-
partitionCount: 1
176-
hostingMode: 'default'
177-
publicNetworkAccess: 'enabled'
178-
networkRuleSet: {
179-
ipRules: []
180-
}
181-
encryptionWithCmk: {
182-
enforcement: 'Unspecified'
183-
}
184-
disableLocalAuth: false
185-
authOptions: {
186-
apiKeyOnly: {}
187-
}
188-
semanticSearch: 'free'
192+
encryptionWithCmk: {
193+
enforcement: 'Unspecified'
189194
}
195+
disableLocalAuth: true
196+
semanticSearch: 'free'
190197
}
198+
}
191199

192200
resource aiSearchFoundryConnection 'Microsoft.CognitiveServices/accounts/projects/connections@2025-04-01-preview' = if (empty(azureExistingAIProjectResourceId)) {
193-
// name: 'foundry-search-connection'
194201
name: aiSearchConnectionName
195202
parent: aiFoundryProject
196203
properties: {
@@ -308,7 +315,7 @@ resource azureOpenAIApiVersionEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-0
308315
parent: keyVault
309316
name: 'AZURE-OPENAI-PREVIEW-API-VERSION'
310317
properties: {
311-
value: azureOpenaiAPIVersion //'2024-02-15-preview'
318+
value: azureOpenaiAPIVersion //'2024-02-15-preview'
312319
}
313320
}
314321

@@ -322,12 +329,11 @@ resource azureOpenAIEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-
322329
}
323330
}
324331

325-
326-
resource azureSearchAdminKeyEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
332+
resource azureOpenAIEmbeddingDeploymentModel 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
327333
parent: keyVault
328-
name: 'AZURE-SEARCH-KEY'
334+
name: 'AZURE-OPENAI-EMBEDDING-MODEL'
329335
properties: {
330-
value: aiSearch.listAdminKeys().primaryKey
336+
value: embeddingModel
331337
}
332338
}
333339

@@ -359,23 +365,27 @@ resource cogServiceEndpointEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-p
359365
parent: keyVault
360366
name: 'COG-SERVICES-ENDPOINT'
361367
properties: {
362-
value: aiFoundry.properties.endpoint
368+
value: !empty(existingOpenAIEndpoint)
369+
? existingOpenAIEndpoint
370+
: aiFoundry.properties.endpoint
363371
}
364372
}
365373

366374
resource cogServiceKeyEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
367375
parent: keyVault
368376
name: 'COG-SERVICES-KEY'
369377
properties: {
370-
value: aiFoundry.listKeys().key1
378+
value: !empty(existingOpenAIEndpoint)
379+
? existingAiFoundry.listKeys().key1
380+
: aiFoundry.listKeys().key1
371381
}
372382
}
373383

374384
resource cogServiceNameEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview' = {
375385
parent: keyVault
376386
name: 'COG-SERVICES-NAME'
377387
properties: {
378-
value: aiFoundryName
388+
value: !empty(existingAIFoundryName) ? existingAIFoundryName : aiFoundryName
379389
}
380390
}
381391

@@ -406,14 +416,15 @@ resource azureLocatioEntry 'Microsoft.KeyVault/vaults/secrets@2021-11-01-preview
406416
output keyvaultName string = keyvaultName
407417
output keyvaultId string = keyVault.id
408418

409-
output aiServicesTarget string = aiFoundry.properties.endpoint //aiServices_m.properties.endpoint
410-
output aiServicesName string = aiFoundryName //aiServicesName_m
411-
output aiServicesId string = aiFoundry.id //aiServices_m.id
419+
// output aiServicesTarget string = aiFoundry.properties.endpoint //aiServices_m.properties.endpoint
420+
// output aiServicesName string = aiFoundryName //aiServicesName_m
421+
// output aiServicesId string = aiFoundry.id //aiServices_m.id
412422

413423
output aiSearchName string = aiSearchName
414424
output aiSearchId string = aiSearch.id
415425
output aiSearchTarget string = 'https://${aiSearch.name}.search.windows.net'
416426
output aiSearchService string = aiSearch.name
427+
output aiSearchConnectionName string = aiSearchConnectionName
417428
output aiFoundryProjectName string = !empty(existingAIProjectName) ? existingAIProjectName : aiFoundryProject.name
418429
// output aiFoundryProjectEndpoint string = aiFoundryProject.properties.endpoints['AI Foundry API']
419430
output aiFoundryProjectEndpoint string = !empty(existingProjEndpoint)
@@ -424,6 +435,7 @@ output aoaiEndpoint string = !empty(existingOpenAIEndpoint)
424435
? existingOpenAIEndpoint
425436
: aiFoundry.properties.endpoints['OpenAI Language Model Instance API']
426437
output aiFoundryName string = !empty(existingAIFoundryName) ? existingAIFoundryName : aiFoundryName
438+
output aiFoundryRgName string = !empty(existingAIServiceResourceGroup) ? existingAIServiceResourceGroup : resourceGroup().name
427439

428440
output applicationInsightsId string = applicationInsights.id
429441
output logAnalyticsWorkspaceResourceName string = useExisting ? existingLogAnalyticsWorkspace.name : logAnalytics.name

0 commit comments

Comments
 (0)