1+ #! /bin/bash
2+ # VERBOSE=false
3+
4+ MODELS=" "
5+ REGIONS=" "
6+ VERBOSE=false
7+
8+ while [[ $# -gt 0 ]]; do
9+ case " $1 " in
10+ --models)
11+ MODELS=" $2 "
12+ shift 2
13+ ;;
14+ --regions)
15+ REGIONS=" $2 "
16+ shift 2
17+ ;;
18+ --verbose)
19+ VERBOSE=true
20+ shift
21+ ;;
22+ * )
23+ echo " Unknown option: $1 "
24+ exit 1
25+ ;;
26+ esac
27+ done
28+
29+ # Fallback to defaults if not provided
30+ [[ -z " $MODELS " ]]
31+ [[ -z " $REGIONS " ]]
32+
33+ echo " Models: $MODELS "
34+ echo " Regions: $REGIONS "
35+ echo " Verbose: $VERBOSE "
36+
37+ for arg in " $@ " ; do
38+ if [ " $arg " = " --verbose" ]; then
39+ VERBOSE=true
40+ fi
41+ done
42+
43+ log_verbose () {
44+ if [ " $VERBOSE " = true ]; then
45+ echo " $1 "
46+ fi
47+ }
48+
49+ # Default Models and Capacities (Comma-separated in "model:capacity" format)
50+ DEFAULT_MODEL_CAPACITY=" gpt-4o-mini:30,text-embedding-ada-002:80"
51+
52+ # Convert the comma-separated string into an array
53+ IFS=' ,' read -r -a MODEL_CAPACITY_PAIRS <<< " $DEFAULT_MODEL_CAPACITY"
54+
55+ echo " 🔄 Fetching available Azure subscriptions..."
56+ SUBSCRIPTIONS=$( az account list --query " [?state=='Enabled'].{Name:name, ID:id}" --output tsv)
57+ SUB_COUNT=$( echo " $SUBSCRIPTIONS " | wc -l)
58+
59+ if [ " $SUB_COUNT " -eq 0 ]; then
60+ echo " ❌ ERROR: No active Azure subscriptions found. Please log in using 'az login' and ensure you have an active subscription."
61+ exit 1
62+ elif [ " $SUB_COUNT " -eq 1 ]; then
63+ # If only one subscription, automatically select it
64+ AZURE_SUBSCRIPTION_ID=$( echo " $SUBSCRIPTIONS " | awk ' {print $2}' )
65+ if [ -z " $AZURE_SUBSCRIPTION_ID " ]; then
66+ echo " ❌ ERROR: No active Azure subscriptions found. Please log in using 'az login' and ensure you have an active subscription."
67+ exit 1
68+ fi
69+ echo " ✅ Using the only available subscription: $AZURE_SUBSCRIPTION_ID "
70+ else
71+ # If multiple subscriptions exist, prompt the user to choose one
72+ echo " Multiple subscriptions found:"
73+ echo " $SUBSCRIPTIONS " | awk ' {print NR")", $1, "-", $2}'
74+
75+ while true ; do
76+ echo " Enter the number of the subscription to use:"
77+ read SUB_INDEX
78+
79+ # Validate user input
80+ if [[ " $SUB_INDEX " =~ ^[0-9]+$ ]] && [ " $SUB_INDEX " -ge 1 ] && [ " $SUB_INDEX " -le " $SUB_COUNT " ]; then
81+ AZURE_SUBSCRIPTION_ID=$( echo " $SUBSCRIPTIONS " | awk -v idx=" $SUB_INDEX " ' NR==idx {print $2}' )
82+ echo " ✅ Selected Subscription: $AZURE_SUBSCRIPTION_ID "
83+ break
84+ else
85+ echo " ❌ Invalid selection. Please enter a valid number from the list."
86+ fi
87+ done
88+ fi
89+
90+
91+ # Set the selected subscription
92+ az account set --subscription " $AZURE_SUBSCRIPTION_ID "
93+ echo " 🎯 Active Subscription: $( az account show --query ' [name, id]' --output tsv) "
94+
95+ # Default Regions to check (Comma-separated, now configurable)
96+ DEFAULT_REGIONS=" australiaeast,eastus,eastus2,francecentral,japaneast,swedencentral,uksouth,westus,westus3"
97+ IFS=' ,' read -r -a DEFAULT_REGION_ARRAY <<< " $DEFAULT_REGIONS"
98+
99+ # Read parameters (if any)
100+ IFS=' ,' read -r -a USER_PROVIDED_PAIRS <<< " $MODELS"
101+ USER_REGION=" $REGIONS "
102+
103+ IS_USER_PROVIDED_PAIRS=false
104+
105+ if [ ${# USER_PROVIDED_PAIRS[@]} -lt 1 ]; then
106+ echo " No parameters provided, using default model-capacity pairs: ${MODEL_CAPACITY_PAIRS[*]} "
107+ else
108+ echo " Using provided model and capacity pairs: ${USER_PROVIDED_PAIRS[*]} "
109+ IS_USER_PROVIDED_PAIRS=true
110+ MODEL_CAPACITY_PAIRS=(" ${USER_PROVIDED_PAIRS[@]} " )
111+ fi
112+
113+ declare -a FINAL_MODEL_NAMES
114+ declare -a FINAL_CAPACITIES
115+ declare -a TABLE_ROWS
116+
117+ for PAIR in " ${MODEL_CAPACITY_PAIRS[@]} " ; do
118+ MODEL_NAME=$( echo " $PAIR " | cut -d' :' -f1 | tr ' [:upper:]' ' [:lower:]' )
119+ CAPACITY=$( echo " $PAIR " | cut -d' :' -f2)
120+
121+ if [ -z " $MODEL_NAME " ] || [ -z " $CAPACITY " ]; then
122+ echo " ❌ ERROR: Invalid model and capacity pair '$PAIR '. Both model and capacity must be specified."
123+ exit 1
124+ fi
125+
126+ FINAL_MODEL_NAMES+=(" $MODEL_NAME " )
127+ FINAL_CAPACITIES+=(" $CAPACITY " )
128+
129+ done
130+
131+ echo " 🔄 Using Models: ${FINAL_MODEL_NAMES[*]} with respective Capacities: ${FINAL_CAPACITIES[*]} "
132+ echo " ----------------------------------------"
133+
134+ # Check if the user provided a region, if not, use the default regions
135+ if [ -n " $USER_REGION " ]; then
136+ echo " 🔍 User provided region: $USER_REGION "
137+ IFS=' ,' read -r -a REGIONS <<< " $USER_REGION"
138+ else
139+ echo " No region specified, using default regions: ${DEFAULT_REGION_ARRAY[*]} "
140+ REGIONS=(" ${DEFAULT_REGION_ARRAY[@]} " )
141+ APPLY_OR_CONDITION=true
142+ fi
143+
144+ echo " ✅ Retrieved Azure regions. Checking availability..."
145+ INDEX=1
146+
147+ VALID_REGIONS=()
148+ for REGION in " ${REGIONS[@]} " ; do
149+ log_verbose " ----------------------------------------"
150+ log_verbose " 🔍 Checking region: $REGION "
151+
152+ QUOTA_INFO=$( az cognitiveservices usage list --location " $REGION " --output json | tr ' [:upper:]' ' [:lower:]' )
153+ if [ -z " $QUOTA_INFO " ]; then
154+ log_verbose " ⚠️ WARNING: Failed to retrieve quota for region $REGION . Skipping."
155+ continue
156+ fi
157+
158+ TEXT_EMBEDDING_AVAILABLE=false
159+ AT_LEAST_ONE_MODEL_AVAILABLE=false
160+ TEMP_TABLE_ROWS=()
161+
162+ for index in " ${! FINAL_MODEL_NAMES[@]} " ; do
163+ MODEL_NAME=" ${FINAL_MODEL_NAMES[$index]} "
164+ REQUIRED_CAPACITY=" ${FINAL_CAPACITIES[$index]} "
165+ FOUND=false
166+ INSUFFICIENT_QUOTA=false
167+
168+ if [ " $MODEL_NAME " = " text-embedding-ada-002" ]; then
169+ MODEL_TYPES=(" openai.standard.$MODEL_NAME " )
170+ else
171+ MODEL_TYPES=(" openai.standard.$MODEL_NAME " " openai.globalstandard.$MODEL_NAME " )
172+ fi
173+
174+ for MODEL_TYPE in " ${MODEL_TYPES[@]} " ; do
175+ FOUND=false
176+ INSUFFICIENT_QUOTA=false
177+ log_verbose " 🔍 Checking model: $MODEL_NAME with required capacity: $REQUIRED_CAPACITY ($MODEL_TYPE )"
178+
179+ MODEL_INFO=$( echo " $QUOTA_INFO " | awk -v model=" \" value\" : \" $MODEL_TYPE \" " '
180+ BEGIN { RS="},"; FS="," }
181+ $0 ~ model { print $0 }
182+ ' )
183+
184+ if [ -z " $MODEL_INFO " ]; then
185+ FOUND=false
186+ log_verbose " ⚠️ WARNING: No quota information found for model: $MODEL_NAME in region: $REGION for model type: $MODEL_TYPE ."
187+ continue
188+ fi
189+
190+ if [ -n " $MODEL_INFO " ]; then
191+ FOUND=true
192+ CURRENT_VALUE=$( echo " $MODEL_INFO " | awk -F' : ' ' /"currentvalue"/ {print $2}' | tr -d ' ,' | tr -d ' ' )
193+ LIMIT=$( echo " $MODEL_INFO " | awk -F' : ' ' /"limit"/ {print $2}' | tr -d ' ,' | tr -d ' ' )
194+
195+ CURRENT_VALUE=${CURRENT_VALUE:- 0}
196+ LIMIT=${LIMIT:- 0}
197+
198+ CURRENT_VALUE=$( echo " $CURRENT_VALUE " | cut -d' .' -f1)
199+ LIMIT=$( echo " $LIMIT " | cut -d' .' -f1)
200+
201+ AVAILABLE=$(( LIMIT - CURRENT_VALUE))
202+ log_verbose " ✅ Model: $MODEL_TYPE | Used: $CURRENT_VALUE | Limit: $LIMIT | Available: $AVAILABLE "
203+
204+ if [ " $AVAILABLE " -ge " $REQUIRED_CAPACITY " ]; then
205+ FOUND=true
206+ if [ " $MODEL_NAME " = " text-embedding-ada-002" ]; then
207+ TEXT_EMBEDDING_AVAILABLE=true
208+ fi
209+ AT_LEAST_ONE_MODEL_AVAILABLE=true
210+ TEMP_TABLE_ROWS+=(" $( printf " | %-4s | %-20s | %-43s | %-10s | %-10s | %-10s |" " $INDEX " " $REGION " " $MODEL_TYPE " " $LIMIT " " $CURRENT_VALUE " " $AVAILABLE " ) " )
211+ else
212+ INSUFFICIENT_QUOTA=true
213+ fi
214+ fi
215+
216+ if [ " $FOUND " = false ]; then
217+ log_verbose " ❌ No models found for model: $MODEL_NAME in region: $REGION (${MODEL_TYPES[*]} )"
218+
219+ elif [ " $INSUFFICIENT_QUOTA " = true ]; then
220+ log_verbose " ⚠️ Model $MODEL_NAME in region: $REGION has insufficient quota (${MODEL_TYPES[*]} )."
221+ fi
222+ done
223+ done
224+
225+ if { [ " $IS_USER_PROVIDED_PAIRS " = true ] && [ " $INSUFFICIENT_QUOTA " = false ] && [ " $FOUND " = true ]; } || { [ " $TEXT_EMBEDDING_AVAILABLE " = true ] && { [ " $APPLY_OR_CONDITION " != true ] || [ " $AT_LEAST_ONE_MODEL_AVAILABLE " = true ]; }; }; then
226+ VALID_REGIONS+=(" $REGION " )
227+ TABLE_ROWS+=(" ${TEMP_TABLE_ROWS[@]} " )
228+ INDEX=$(( INDEX + 1 ))
229+ elif [ ${# USER_PROVIDED_PAIRS[@]} -eq 0 ]; then
230+ echo " 🚫 Skipping $REGION as it does not meet quota requirements."
231+ fi
232+
233+ done
234+
235+ if [ ${# TABLE_ROWS[@]} -eq 0 ]; then
236+ echo " --------------------------------------------------------------------------------------------------------------------"
237+
238+ echo " ❌ No regions have sufficient quota for all required models. Please request a quota increase: https://aka.ms/oai/stuquotarequest"
239+ else
240+ echo " ---------------------------------------------------------------------------------------------------------------------"
241+ printf " | %-4s | %-20s | %-43s | %-10s | %-10s | %-10s |\n" " No." " Region" " Model Name" " Limit" " Used" " Available"
242+ echo " ---------------------------------------------------------------------------------------------------------------------"
243+ for ROW in " ${TABLE_ROWS[@]} " ; do
244+ echo " $ROW "
245+ done
246+ echo " ---------------------------------------------------------------------------------------------------------------------"
247+ echo " ➡️ To request a quota increase, visit: https://aka.ms/oai/stuquotarequest"
248+ fi
249+
250+ echo " ✅ Script completed."
0 commit comments