Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build and deploy AI applications on Azure AI Foundry using Microsoft's model catalog and AI services
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