Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Deploy, evaluate, and manage AI agents end-to-end on Microsoft Azure AI Foundry
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
models/deploy-model/capacity/scripts/discover_and_rank.sh
1#!/bin/bash2# discover_and_rank.sh3# Discovers available capacity for an Azure OpenAI model across all regions,4# cross-references with existing projects and subscription quota, and outputs a ranked table.5#6# Usage: ./discover_and_rank.sh <model-name> <model-version> [min-capacity]7# Example: ./discover_and_rank.sh o3-mini 2025-01-31 2008#9# Output: Ranked table of regions with capacity, quota, project counts, and match status1011set -euo pipefail1213MODEL_NAME="${1:?Usage: $0 <model-name> <model-version> [min-capacity]}"14MODEL_VERSION="${2:?Usage: $0 <model-name> <model-version> [min-capacity]}"15MIN_CAPACITY="${3:-0}"1617SUB_ID=$(az account show --query id -o tsv)1819# Query model capacity across all regions (GlobalStandard SKU)20CAPACITY_JSON=$(az rest --method GET \21--url "https://management.azure.com/subscriptions/${SUB_ID}/providers/Microsoft.CognitiveServices/modelCapacities" \22--url-parameters api-version=2024-10-01 modelFormat=OpenAI modelName="$MODEL_NAME" modelVersion="$MODEL_VERSION" \232>/dev/null)2425# Query all AI Services projects26PROJECTS_JSON=$(az rest --method GET \27--url "https://management.azure.com/subscriptions/${SUB_ID}/providers/Microsoft.CognitiveServices/accounts" \28--url-parameters api-version=2024-10-01 \29--query "value[?kind=='AIServices'].{name:name, location:location}" \302>/dev/null)3132# Get unique regions from capacity results for quota checking33REGIONS=$(echo "$CAPACITY_JSON" | jq -r '.value[] | select(.properties.skuName=="GlobalStandard" and .properties.availableCapacity > 0) | .location' | sort -u)3435# Build quota map: check subscription quota per region36declare -A QUOTA_MAP37for region in $REGIONS; do38usage_json=$(az cognitiveservices usage list --location "$region" --subscription "$SUB_ID" -o json 2>/dev/null || echo "[]")39quota_avail=$(echo "$usage_json" | jq -r --arg name "OpenAI.GlobalStandard.$MODEL_NAME" \40'[.[] | select(.name.value == $name)] | if length > 0 then .[0].limit - .[0].currentValue else 0 end')41QUOTA_MAP[$region]="${quota_avail:-0}"42done4344# Export quota map as JSON for Python45QUOTA_JSON="{"46first=true47for region in "${!QUOTA_MAP[@]}"; do48if [ "$first" = true ]; then first=false; else QUOTA_JSON+=","; fi49QUOTA_JSON+="\"$region\":${QUOTA_MAP[$region]}"50done51QUOTA_JSON+="}"5253# Combine, rank, and output using inline Python (available on all Azure CLI installs)54python3 -c "55import json, sys5657capacity = json.loads('''${CAPACITY_JSON}''')58projects = json.loads('''${PROJECTS_JSON}''')59quota = json.loads('''${QUOTA_JSON}''')60min_cap = int('${MIN_CAPACITY}')6162# Build capacity map (GlobalStandard only)63cap_map = {}64for item in capacity.get('value', []):65props = item.get('properties', {})66if props.get('skuName') == 'GlobalStandard' and props.get('availableCapacity', 0) > 0:67region = item.get('location', '')68cap_map[region] = max(cap_map.get(region, 0), props['availableCapacity'])6970# Build project count map71proj_map = {}72proj_sample = {}73for p in (projects if isinstance(projects, list) else []):74loc = p.get('location', '')75proj_map[loc] = proj_map.get(loc, 0) + 176if loc not in proj_sample:77proj_sample[loc] = p.get('name', '')7879# Combine and rank80results = []81for region, cap in cap_map.items():82meets = cap >= min_cap83q = quota.get(region, 0)84quota_ok = q > 085results.append({86'region': region,87'available': cap,88'meets': meets,89'projects': proj_map.get(region, 0),90'sample': proj_sample.get(region, '(none)'),91'quota': q,92'quota_ok': quota_ok93})9495# Sort: meets target first, then quota available, then by project count, then by capacity96results.sort(key=lambda x: (-x['meets'], -x['quota_ok'], -x['projects'], -x['available']))9798# Output99total = len(results)100matching = sum(1 for r in results if r['meets'])101with_quota = sum(1 for r in results if r['meets'] and r['quota_ok'])102with_projects = sum(1 for r in results if r['meets'] and r['projects'] > 0)103104print(f'Model: {\"${MODEL_NAME}\"} v{\"${MODEL_VERSION}\"} | SKU: GlobalStandard | Min Capacity: {min_cap}K TPM')105print(f'Regions with capacity: {total} | Meets target: {matching} | With quota: {with_quota} | With projects: {with_projects}')106print()107print(f'{\"Region\":<22} {\"Available\":<12} {\"Meets Target\":<14} {\"Quota\":<12} {\"Projects\":<10} {\"Sample Project\"}')108print('-' * 100)109for r in results:110mark = 'YES' if r['meets'] else 'no'111q_display = f'{r[\"quota\"]}K' if r['quota'] > 0 else '0 (none)'112print(f'{r[\"region\"]:<22} {r[\"available\"]}K{\"\":.<10} {mark:<14} {q_display:<12} {r[\"projects\"]:<10} {r[\"sample\"]}')113"114