Almost every lesson of this course can be worked through as a design; much of it can be run only with an Azure account, because there is no local substitute (Agent Service, image and video models, speech, Content Understanding, Azure AI Search). This lesson creates the account for the exercises: resource ai-nordlicht and project reiseassistent of Nordlicht Reisen GmbH (R-08), the role for your account, the check of quota and availability, the budget and the cleanup. Running it stays optional.

Prior knowledge. The test account, costs, groups as containers of an exercise and "quota and regions" are taught by "AZ-104, lesson 0.1". A budget warns and stops nothing: "K3, lesson 3.1.2". Groups and az group delete: "K3, lesson 3.1.3". Resource, project, deployment and roles as Bicep are shown by "AI track, lesson T10.1"; the complete Bicep version of this course is in lesson 1.2, quotas and their monitoring in lesson 1.3, the roles in lesson 1.4. Here is only the minimum for the first start.

New in this lesson. The exercise of this lesson lives in the group rg-ai103-start. If the name ai-nordlicht is taken worldwide (Learn names the error CustomDomainInUse), the script takes another name; that changes nothing about R-08.

The requirement

All numbers are assumptions of the task.

No. Requirement Type Measure Weight Source
0.2-01 Resource and project come from a script, not from clicks. F 1 script, 0 manual steps Must Exercise
0.2-02 Your account has the role Foundry User on the project. R 1 role assignment Must R-07
0.2-03 Before the first deployment it is known whether quota and model are available. Q check per region and subscription Should R-06
0.2-04 A cost warning exists before the first resource is created. R 1 budget Must R-09
0.2-05 After the exercise everything is gone, and the name is free again. R check of the group and of the deleted resource Must Costs

Account and budget

You need a subscription of your own: the test account from AZ-104 lesson 0.1 or an empty one with a budget. Quotas and model availability differ per subscription and region; the course does not promise that a particular model can be deployed in your account. The budget comes before the first resource, as a warning (K3, lesson 3.1.2): It stops nothing, and the mail arrives hours after the costs are incurred. The monthly cap of the case (R-09) is therefore code in the assistant (AI track, lesson T10.3), the Azure budget only the second warning.

Cost drivers of the exercises (no amounts; pricing pages of the services): tokens per million for standard deployments, capacity per hour for reserved ones, images and videos per generation, speech per hour of audio, the search service per hour and tier, Content Understanding per page, Application Insights per gigabyte, Voice Live per use. Whatever runs by time is deleted as soon as the exercise is finished.

Resource and project: the minimum

The page "Create a project for Microsoft Foundry" shows the way in the portal, with Python, with the Azure CLI and through templates. We take the CLI because it can be captured as a script. The sequence:

  1. Create the group (a new one for every exercise, rg-ai103-<exercise>).
  2. Create the Foundry resource: az cognitiveservices account create with --kind AIServices, --sku S0, --custom-domain (globally unique), --assign-identity and --allow-project-management true. According to Learn, project management needs the managed identity, and the setting cannot be changed after creation. Without the identity, creating the project fails.
  3. Create the project: az cognitiveservices account project create.
  4. Assign the role: Foundry User on the project (formerly Azure AI User; the role IDs stayed). Learn advises using the role ID instead of the name while the renaming is rolled out: 53ca6127-db72-4b80-b1b0-d745d6d5456d.

Prerequisites according to Learn: Azure CLI from 2.80.0, Contributor or Owner on the group, for the role assignment roughly Owner. The project endpoint (the address that the examples from lesson 2.1 on read) is on the project's home page in the portal. Whether germanywestcentral offers projects of the resource at all is listed by Learn in the table "Foundry Agent Service limits, quotas, and regional support": The row Germany West Central lists Responses API and Agents as supported. Which models are available there is another question (next section).

Checking quota and availability

Before a lesson asks for a deployment, check it for your subscription and your region. Three ways according to Learn:

  • Portal: the quota page of Foundry (ai.azure.com/resource/quota).
  • CLI: az cognitiveservices usage list --location <region> shows the quota of the region for the active subscription. One unit of capacity stands for 1,000 tokens per minute.
  • REST: Two interfaces of Azure Resource Manager. The Usages API answers "How much of the quota is used?" (per region, every line of the quota with usage and limit). The Model Capacities API answers "Where can this model be deployed, and how much capacity is free?" (per subscription, for a model with version and format, across all locations). Both also name retired models.

Which models a region knows is listed by az cognitiveservices model list --location <region> --kind OpenAI (this is how a Learn page shows it; for other kinds of models the option is open). The role for the quota view is Cognitive Services Usages Reader at subscription level (lesson 1.3). Open remains what Learn provides for models from third parties or for speech and image services: Each lesson checks its services itself.

Cleanup, soft delete and purge

Every exercise has its group; at the end there is az group delete --name rg-ai103-<exercise> --yes --no-wait and the check that it is gone (az group exists). For the Foundry resource, what Learn says on the page "Recover or purge deleted Microsoft Foundry resources" applies in addition:

  • Deleted Foundry resources initially remain soft-deleted. During this time they can be restored: according to Learn 48 hours, and the group must still exist for that (a deleted group must be created again).
  • The same name is blocked for 48 hours. Anyone who needs it sooner must purge the deleted resource: az cognitiveservices account purge --location <region> --name <name> --resource-group <group>. Deleted resources are listed by az cognitiveservices account list-deleted.
  • Purge is final: all data and keys of the resource are gone. It is allowed with Cognitive Services Contributor or with Contributor, in the second case only if the role is assigned at the subscription.
  • Provisioned deployments of a deleted resource keep costing money until it is purged. So delete the deployments first, then the resource.
  • Projects have no soft delete: A deleted project is gone.

Open: Whether deleting the group also sends the resource into soft delete and blocks the name is not stated explicitly by the page that was read; the check list-deleted after the deletion answers it for your account.

State of the checks

Both scripts of the exercises are PowerShell. They were not run against Azure: no account, no sign-in. What was checked: the syntax and the dry run -WhatIf, which showed with a stand-in for az that no changing command is called. That proves only that the scripts are built as described; whether the commands run against your CLI version is shown only by a run. Bicep: none in this lesson, not compiled (the complete version is in lesson 1.2). Open: model availability in germanywestcentral, soft delete after deleting the group, quota query for non-OpenAI models.

Exercise 1

Write the script uebung-start.ps1: It creates the group rg-ai103-start, the Foundry resource (name as a parameter, default ai-nordlicht), the project reiseassistent and the role Foundry User for an account. Every change sits behind ShouldProcess so that -WhatIf changes nothing. At first you call it only with -WhatIf.

Solution 1

PowerShell
#Requires -Version 7.4
[CmdletBinding(SupportsShouldProcess)]
param(
    [Parameter(Mandatory)] [string] $Assignee,
    [string] $Name = 'ai-nordlicht',
    [string] $Location = 'germanywestcentral'
)
$gruppe = 'rg-ai103-start'
$foundryUser = '53ca6127-db72-4b80-b1b0-d745d6d5456d'

if ($PSCmdlet.ShouldProcess($gruppe, 'Create group')) {
    az group create --name $gruppe --location $Location --tags kurs=ai103 | Out-Null
}
if ($PSCmdlet.ShouldProcess($Name, 'Create Foundry resource')) {
    az cognitiveservices account create --name $Name --resource-group $gruppe `
        --kind AIServices --sku S0 --location $Location --custom-domain $Name `
        --assign-identity --allow-project-management true | Out-Null
}
if ($PSCmdlet.ShouldProcess('reiseassistent', 'Create project')) {
    az cognitiveservices account project create --name $Name `
        --resource-group $gruppe --project-name reiseassistent `
        --location $Location | Out-Null
}
if ($PSCmdlet.ShouldProcess($Assignee, 'Foundry User role on the project')) {
    $projektId = az cognitiveservices account project show --name $Name `
        --resource-group $gruppe --project-name reiseassistent --query id -o tsv
    az role assignment create --role $foundryUser --assignee $Assignee `
        --assignee-principal-type User --scope $projektId | Out-Null
}

The script can be repeated except for the resource: A second run with the same name and the same group reports what is already there; the setting --allow-project-management does not change. The name of the group is fixed so that the cleanup does not have to guess it.

Exercise 2

Write the counterpart uebung-ende.ps1: It first deletes the deployments of the resource, then the group, waits, checks with az group exists that it is gone, and lists the deleted Foundry resources. Every change asks for confirmation (ConfirmImpact High); it purges only with the switch -Purge.

Solution 2

PowerShell
#Requires -Version 7.4
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
param(
    [string] $Name = 'ai-nordlicht',
    [string] $Location = 'germanywestcentral',
    [switch] $Purge
)
$gruppe = 'rg-ai103-start'

if ($PSCmdlet.ShouldProcess($Name, 'Delete deployments')) {
    $namen = az cognitiveservices account deployment list -n $Name -g $gruppe `
        --query '[].name' -o tsv
    foreach ($d in $namen) {
        az cognitiveservices account deployment delete -n $Name -g $gruppe `
            --deployment-name $d
    }
}
if ($PSCmdlet.ShouldProcess($gruppe, 'Delete group with everything in it')) {
    az group delete --name $gruppe --yes --no-wait
    az group wait --name $gruppe --deleted
}
Write-Host "Group exists: $(az group exists --name $gruppe)"
az cognitiveservices account list-deleted --query "[?name=='$Name']" -o table
if ($Purge -and $PSCmdlet.ShouldProcess($Name, 'Delete PERMANENTLY (purge)')) {
    az cognitiveservices account purge --location $Location --name $Name `
        --resource-group $gruppe
}

The check after the deletion sits outside the confirmation because it only reads. The purge is a decision of its own, not part of the cleanup: Without it nothing costs money anymore, only the name is blocked.

Typical mistakes

  • "Group deleted, so everything is gone." The Foundry resource can stand soft-deleted and block the name; provisioned deployments cost money until the purge.
  • "Purge to be safe, then everything is clean." Purge is final; restoring works only before it and only for 48 hours.
  • "The budget keeps costs in check." It warns, late and only by mail; the cap is code.
  • "The quota is in the documentation." It applies per subscription and region and is found only in your account.

Further reading

  • https://learn.microsoft.com/azure/foundry/how-to/create-projects
  • https://learn.microsoft.com/azure/ai-services/recover-purge-resources
  • https://learn.microsoft.com/azure/foundry/openai/how-to/quota
  • https://learn.microsoft.com/azure/foundry/openai/how-to/automate-quota-deployments
  • https://learn.microsoft.com/azure/foundry/agents/concepts/limits-quotas-regions
  • https://learn.microsoft.com/azure/foundry/concepts/rbac-foundry