diff --git a/Deployment/quota_check_params.sh b/Deployment/quota_check_params.sh new file mode 100644 index 00000000..f5f285d9 --- /dev/null +++ b/Deployment/quota_check_params.sh @@ -0,0 +1,250 @@ +#!/bin/bash +# VERBOSE=false + +MODELS="" +REGIONS="" +VERBOSE=false + +while [[ $# -gt 0 ]]; do + case "$1" in + --models) + MODELS="$2" + shift 2 + ;; + --regions) + REGIONS="$2" + shift 2 + ;; + --verbose) + VERBOSE=true + shift + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +# Fallback to defaults if not provided +[[ -z "$MODELS" ]] +[[ -z "$REGIONS" ]] + +echo "Models: $MODELS" +echo "Regions: $REGIONS" +echo "Verbose: $VERBOSE" + +for arg in "$@"; do + if [ "$arg" = "--verbose" ]; then + VERBOSE=true + fi +done + +log_verbose() { + if [ "$VERBOSE" = true ]; then + echo "$1" + fi +} + +# Default Models and Capacities (Comma-separated in "model:capacity" format) +DEFAULT_MODEL_CAPACITY="gpt-4o-mini:100,text-embedding-3-large:100" + +# Convert the comma-separated string into an array +IFS=',' read -r -a MODEL_CAPACITY_PAIRS <<< "$DEFAULT_MODEL_CAPACITY" + +echo "πŸ”„ Fetching available Azure subscriptions..." +SUBSCRIPTIONS=$(az account list --query "[?state=='Enabled'].{Name:name, ID:id}" --output tsv) +SUB_COUNT=$(echo "$SUBSCRIPTIONS" | wc -l) + +if [ "$SUB_COUNT" -eq 0 ]; then + echo "❌ ERROR: No active Azure subscriptions found. Please log in using 'az login' and ensure you have an active subscription." + exit 1 +elif [ "$SUB_COUNT" -eq 1 ]; then + # If only one subscription, automatically select it + AZURE_SUBSCRIPTION_ID=$(echo "$SUBSCRIPTIONS" | awk '{print $2}') + if [ -z "$AZURE_SUBSCRIPTION_ID" ]; then + echo "❌ ERROR: No active Azure subscriptions found. Please log in using 'az login' and ensure you have an active subscription." + exit 1 + fi + echo "βœ… Using the only available subscription: $AZURE_SUBSCRIPTION_ID" +else + # If multiple subscriptions exist, prompt the user to choose one + echo "Multiple subscriptions found:" + echo "$SUBSCRIPTIONS" | awk '{print NR")", $1, "-", $2}' + + while true; do + echo "Enter the number of the subscription to use:" + read SUB_INDEX + + # Validate user input + if [[ "$SUB_INDEX" =~ ^[0-9]+$ ]] && [ "$SUB_INDEX" -ge 1 ] && [ "$SUB_INDEX" -le "$SUB_COUNT" ]; then + AZURE_SUBSCRIPTION_ID=$(echo "$SUBSCRIPTIONS" | awk -v idx="$SUB_INDEX" 'NR==idx {print $2}') + echo "βœ… Selected Subscription: $AZURE_SUBSCRIPTION_ID" + break + else + echo "❌ Invalid selection. Please enter a valid number from the list." + fi + done +fi + + +# Set the selected subscription +az account set --subscription "$AZURE_SUBSCRIPTION_ID" +echo "🎯 Active Subscription: $(az account show --query '[name, id]' --output tsv)" + +# Default Regions to check (Comma-separated, now configurable) +DEFAULT_REGIONS="australiaeast,eastus,eastus2,francecentral,japaneast,swedencentral,uksouth,westus,westus3" +IFS=',' read -r -a DEFAULT_REGION_ARRAY <<< "$DEFAULT_REGIONS" + +# Read parameters (if any) +IFS=',' read -r -a USER_PROVIDED_PAIRS <<< "$MODELS" +USER_REGION="$REGIONS" + +IS_USER_PROVIDED_PAIRS=false + +if [ ${#USER_PROVIDED_PAIRS[@]} -lt 1 ]; then + echo "No parameters provided, using default model-capacity pairs: ${MODEL_CAPACITY_PAIRS[*]}" +else + echo "Using provided model and capacity pairs: ${USER_PROVIDED_PAIRS[*]}" + IS_USER_PROVIDED_PAIRS=true + MODEL_CAPACITY_PAIRS=("${USER_PROVIDED_PAIRS[@]}") +fi + +declare -a FINAL_MODEL_NAMES +declare -a FINAL_CAPACITIES +declare -a TABLE_ROWS + +for PAIR in "${MODEL_CAPACITY_PAIRS[@]}"; do + MODEL_NAME=$(echo "$PAIR" | cut -d':' -f1 | tr '[:upper:]' '[:lower:]') + CAPACITY=$(echo "$PAIR" | cut -d':' -f2) + + if [ -z "$MODEL_NAME" ] || [ -z "$CAPACITY" ]; then + echo "❌ ERROR: Invalid model and capacity pair '$PAIR'. Both model and capacity must be specified." + exit 1 + fi + + FINAL_MODEL_NAMES+=("$MODEL_NAME") + FINAL_CAPACITIES+=("$CAPACITY") + +done + +echo "πŸ”„ Using Models: ${FINAL_MODEL_NAMES[*]} with respective Capacities: ${FINAL_CAPACITIES[*]}" +echo "----------------------------------------" + +# Check if the user provided a region, if not, use the default regions +if [ -n "$USER_REGION" ]; then + echo "πŸ” User provided region: $USER_REGION" + IFS=',' read -r -a REGIONS <<< "$USER_REGION" +else + echo "No region specified, using default regions: ${DEFAULT_REGION_ARRAY[*]}" + REGIONS=("${DEFAULT_REGION_ARRAY[@]}") + APPLY_OR_CONDITION=true +fi + +echo "βœ… Retrieved Azure regions. Checking availability..." +INDEX=1 + +VALID_REGIONS=() +for REGION in "${REGIONS[@]}"; do + log_verbose "----------------------------------------" + log_verbose "πŸ” Checking region: $REGION" + + QUOTA_INFO=$(az cognitiveservices usage list --location "$REGION" --output json | tr '[:upper:]' '[:lower:]') + if [ -z "$QUOTA_INFO" ]; then + log_verbose "⚠️ WARNING: Failed to retrieve quota for region $REGION. Skipping." + continue + fi + + TEXT_EMBEDDING_AVAILABLE=false + AT_LEAST_ONE_MODEL_AVAILABLE=false + TEMP_TABLE_ROWS=() + + for index in "${!FINAL_MODEL_NAMES[@]}"; do + MODEL_NAME="${FINAL_MODEL_NAMES[$index]}" + REQUIRED_CAPACITY="${FINAL_CAPACITIES[$index]}" + FOUND=false + INSUFFICIENT_QUOTA=false + + if [ "$MODEL_NAME" = "text-embedding-ada-002" ]; then + MODEL_TYPES=("openai.standard.$MODEL_NAME") + else + MODEL_TYPES=("openai.standard.$MODEL_NAME" "openai.globalstandard.$MODEL_NAME") + fi + + for MODEL_TYPE in "${MODEL_TYPES[@]}"; do + FOUND=false + INSUFFICIENT_QUOTA=false + log_verbose "πŸ” Checking model: $MODEL_NAME with required capacity: $REQUIRED_CAPACITY ($MODEL_TYPE)" + + MODEL_INFO=$(echo "$QUOTA_INFO" | awk -v model="\"value\": \"$MODEL_TYPE\"" ' + BEGIN { RS="},"; FS="," } + $0 ~ model { print $0 } + ') + + if [ -z "$MODEL_INFO" ]; then + FOUND=false + log_verbose "⚠️ WARNING: No quota information found for model: $MODEL_NAME in region: $REGION for model type: $MODEL_TYPE." + continue + fi + + if [ -n "$MODEL_INFO" ]; then + FOUND=true + CURRENT_VALUE=$(echo "$MODEL_INFO" | awk -F': ' '/"currentvalue"/ {print $2}' | tr -d ',' | tr -d ' ') + LIMIT=$(echo "$MODEL_INFO" | awk -F': ' '/"limit"/ {print $2}' | tr -d ',' | tr -d ' ') + + CURRENT_VALUE=${CURRENT_VALUE:-0} + LIMIT=${LIMIT:-0} + + CURRENT_VALUE=$(echo "$CURRENT_VALUE" | cut -d'.' -f1) + LIMIT=$(echo "$LIMIT" | cut -d'.' -f1) + + AVAILABLE=$((LIMIT - CURRENT_VALUE)) + log_verbose "βœ… Model: $MODEL_TYPE | Used: $CURRENT_VALUE | Limit: $LIMIT | Available: $AVAILABLE" + + if [ "$AVAILABLE" -ge "$REQUIRED_CAPACITY" ]; then + FOUND=true + if [ "$MODEL_NAME" = "text-embedding-ada-002" ]; then + TEXT_EMBEDDING_AVAILABLE=true + fi + AT_LEAST_ONE_MODEL_AVAILABLE=true + TEMP_TABLE_ROWS+=("$(printf "| %-4s | %-20s | %-43s | %-10s | %-10s | %-10s |" "$INDEX" "$REGION" "$MODEL_TYPE" "$LIMIT" "$CURRENT_VALUE" "$AVAILABLE")") + else + INSUFFICIENT_QUOTA=true + fi + fi + + if [ "$FOUND" = false ]; then + log_verbose "❌ No models found for model: $MODEL_NAME in region: $REGION (${MODEL_TYPES[*]})" + + elif [ "$INSUFFICIENT_QUOTA" = true ]; then + log_verbose "⚠️ Model $MODEL_NAME in region: $REGION has insufficient quota (${MODEL_TYPES[*]})." + fi + done + done + +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 + VALID_REGIONS+=("$REGION") + TABLE_ROWS+=("${TEMP_TABLE_ROWS[@]}") + INDEX=$((INDEX + 1)) + elif [ ${#USER_PROVIDED_PAIRS[@]} -eq 0 ]; then + echo "🚫 Skipping $REGION as it does not meet quota requirements." + fi + +done + +if [ ${#TABLE_ROWS[@]} -eq 0 ]; then + echo "--------------------------------------------------------------------------------------------------------------------" + + echo "❌ No regions have sufficient quota for all required models. Please request a quota increase: https://aka.ms/oai/stuquotarequest" +else + echo "---------------------------------------------------------------------------------------------------------------------" + printf "| %-4s | %-20s | %-43s | %-10s | %-10s | %-10s |\n" "No." "Region" "Model Name" "Limit" "Used" "Available" + echo "---------------------------------------------------------------------------------------------------------------------" + for ROW in "${TABLE_ROWS[@]}"; do + echo "$ROW" + done + echo "---------------------------------------------------------------------------------------------------------------------" + echo "➑️ To request a quota increase, visit: https://aka.ms/oai/stuquotarequest" +fi + +echo "βœ… Script completed." \ No newline at end of file diff --git a/README.md b/README.md index fb94e87e..20345674 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ Follow the quick deploy steps on theΒ deployment guideΒ to deploy this solution > ⚠️ **Important: Check Azure OpenAI Quota Availability** -
To ensure sufficient quota is available in your subscription, please follow [quota check instructions guide](./docs/DeploymentGuide.md#regional-availability) before you deploy the solution. +
To ensure sufficient quota is available in your subscription, please follow [quota check instructions guide](./docs/QuotaCheck.md) before you deploy the solution.
diff --git a/docs/QuotaCheck.md b/docs/QuotaCheck.md new file mode 100644 index 00000000..f7e6767e --- /dev/null +++ b/docs/QuotaCheck.md @@ -0,0 +1,100 @@ +## Check Quota Availability Before Deployment + +Before deploying the accelerator, **ensure sufficient quota availability** for the required model. +> **For Global Standard | GPT-4o-mini - increase the capacity to at least 150K tokens for optimal performance.** + +### Login if you have not done so already +``` +azd auth login +``` + + +### πŸ“Œ Default Models & Capacities: +``` +gpt-4o-mini:100, text-embedding-3-large:100 +``` +### πŸ“Œ Default Regions: +``` +eastus, uksouth, eastus2, northcentralus, swedencentral, westus, westus2, southcentralus, canadacentral +``` +### Usage Scenarios: +- No parameters passed β†’ Default models and capacities will be checked in default regions. +- Only model(s) provided β†’ The script will check for those models in the default regions. +- Only region(s) provided β†’ The script will check default models in the specified regions. +- Both models and regions provided β†’ The script will check those models in the specified regions. +- `--verbose` passed β†’ Enables detailed logging output for debugging and traceability. + +### **Input Formats** +> Use the --models, --regions, and --verbose options for parameter handling: + +βœ”οΈ Run without parameters to check default models & regions without verbose logging: + ``` + ./quota_check_params.sh + ``` +βœ”οΈ Enable verbose logging: + ``` + ./quota_check_params.sh --verbose + ``` +βœ”οΈ Check specific model(s) in default regions: + ``` + ./quota_check_params.sh --models gpt-4o-mini:100,text-embedding-3-large:100 + ``` +βœ”οΈ Check default models in specific region(s): + ``` +./quota_check_params.sh --regions eastus,westus + ``` +βœ”οΈ Passing Both models and regions: + ``` + ./quota_check_params.sh --models gpt-4o-mini:100 --regions eastus,westus2 + ``` +βœ”οΈ All parameters combined: + ``` + ./quota_check_params.sh --models gpt-4o-mini:100,text-embedding-3-large:100 --regions eastus,westus --verbose + ``` + +### **Sample Output** +The final table lists regions with available quota. You can select any of these regions for deployment. + +![quota-check-ouput](images/readme/quota-check-output.png) + +--- +### **If using Azure Portal and Cloud Shell** + +1. Navigate to the [Azure Portal](https://portal.azure.com). +2. Click on **Azure Cloud Shell** in the top right navigation menu. +3. Run the appropriate command based on your requirement: + + **To check quota for the deployment** + + ```sh + curl -L -o quota_check_params.sh "https://raw.githubusercontent.com/microsoft/Document-Knowledge-Mining-Solution-Accelerator/main/Deployment/quota_check_params.sh" + chmod +x quota_check_params.sh + ./quota_check_params.sh + ``` + - Refer to [Input Formats](#input-formats) for detailed commands. + +### **If using VS Code or Codespaces** +1. Open the terminal in VS Code or Codespaces. +2. If you're using VS Code, click the dropdown on the right side of the terminal window, and select `Git Bash`. + ![git_bash](images/readme/git_bash.png) +3. Navigate to the `scripts` folder where the script files are located and make the script as executable: + ```sh + cd infra/scripts + chmod +x quota_check_params.sh + ``` +4. Run the appropriate script based on your requirement: + + **To check quota for the deployment** + + ```sh + ./quota_check_params.sh + ``` + - Refer to [Input Formats](#input-formats) for detailed commands. + +5. If you see the error `_bash: az: command not found_`, install Azure CLI: + + ```sh + curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash + az login + ``` +6. Rerun the script after installing Azure CLI. diff --git a/docs/images/readme/git_bash.png b/docs/images/readme/git_bash.png new file mode 100644 index 00000000..0e9f53a1 Binary files /dev/null and b/docs/images/readme/git_bash.png differ diff --git a/docs/images/readme/quota-check-output.png b/docs/images/readme/quota-check-output.png new file mode 100644 index 00000000..9c80e329 Binary files /dev/null and b/docs/images/readme/quota-check-output.png differ