diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c868df53b..9e9fa4417 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -16,7 +16,7 @@ ] } }, - "postStartCommand": "git pull origin main && python3 -m pip install -r infra/scripts/index_scripts/requirements.txt", + "postStartCommand": "git pull origin main && python3 -m pip install -r infra/scripts/index_scripts/requirements.txt && curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash && chmod +x ./infra/scripts/quota_check_params.sh", "remoteUser": "vscode", "hostRequirements": { "memory": "4gb" diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7c77274f6..45a720e3e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -11,7 +11,7 @@ updates: open-pull-requests-limit: 100 - package-ecosystem: "pip" - directory: "/App" + directory: "/src/api" schedule: interval: "monthly" commit-message: @@ -20,7 +20,7 @@ updates: open-pull-requests-limit: 100 - package-ecosystem: "npm" - directory: "/App/frontend" + directory: "/src/App" schedule: interval: "monthly" commit-message: diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml new file mode 100644 index 000000000..1ca61df0a --- /dev/null +++ b/.github/workflows/create-release.yml @@ -0,0 +1,66 @@ +name: "Create Release" + +on: + push: + branches: ["main"] + + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + create-release: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: ${{ github.sha }} + + - uses: codfish/semantic-release-action@v3 + id: semantic + with: + tag-format: 'v${version}' + additional-packages: | + ['conventional-changelog-conventionalcommits@7'] + plugins: | + [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits" + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { type: 'feat', section: 'Features', hidden: false }, + { type: 'fix', section: 'Bug Fixes', hidden: false }, + { type: 'perf', section: 'Performance Improvements', hidden: false }, + { type: 'revert', section: 'Reverts', hidden: false }, + { type: 'docs', section: 'Other Updates', hidden: false }, + { type: 'style', section: 'Other Updates', hidden: false }, + { type: 'chore', section: 'Other Updates', hidden: false }, + { type: 'refactor', section: 'Other Updates', hidden: false }, + { type: 'test', section: 'Other Updates', hidden: false }, + { type: 'build', section: 'Other Updates', hidden: false }, + { type: 'ci', section: 'Other Updates', hidden: false } + ] + } + } + ], + '@semantic-release/github' + ] + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - run: echo ${{ steps.semantic.outputs.release-version }} + + - run: echo "$OUTPUTS" + env: + OUTPUTS: ${{ toJson(steps.semantic.outputs) }} \ No newline at end of file diff --git a/README.md b/README.md index 3517a31cc..2fc46d262 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,7 @@ If you're not using one of the above options for opening the project, then you'l * [Python 3.9+](https://www.python.org/downloads/) * [Docker Desktop](https://www.docker.com/products/docker-desktop/) * [Git](https://git-scm.com/downloads) + * [Powershell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.5)
Required for Windows users only. Follow the steps [here](./docs/PowershellSetup.md) to add it to the Windows PATH. 2. Download the project code: diff --git a/docs/Images/git_bash.png b/docs/Images/git_bash.png new file mode 100644 index 000000000..0e9f53a12 Binary files /dev/null and b/docs/Images/git_bash.png differ diff --git a/docs/Images/quota-check-output.png b/docs/Images/quota-check-output.png new file mode 100644 index 000000000..9c80e3298 Binary files /dev/null and b/docs/Images/quota-check-output.png differ diff --git a/docs/PowershellSetup.md b/docs/PowershellSetup.md new file mode 100644 index 000000000..3cdc7912e --- /dev/null +++ b/docs/PowershellSetup.md @@ -0,0 +1,54 @@ +# Add PowerShell 7 to PATH in Windows + +This guide will help you add **PowerShell 7** (PowerShell Core) to your system’s PATH variable on Windows, so you can easily run it from any Command Prompt or Run dialog. + +## Prerequisites + +- You should have **PowerShell 7** installed on your machine. If you haven’t installed it yet, you can download it following the guide here: [Installing PowerShell on Windows | Microsoft Learn](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.5). +- **Administrative privileges are not required** unless you're modifying system-wide environment variables. You can modify your **user-specific PATH** without admin rights. + +## Steps to Add PowerShell 7 to PATH + +### 1. Open **System Properties** + - Press `Win + X` and choose **System**. + - Click on **Advanced system settings** on the left sidebar. This will open the **System Properties** window. + - In the **System Properties** window, click on the **Environment Variables** button at the bottom. + +### 2. Edit User Environment Variables + - In the **Environment Variables** window, under **User variables**, find the `Path` variable. + - Select the `Path` variable and click **Edit**. (If the `Path` variable doesn’t exist, click **New** and name it `Path`.) + +### 3. Check if PowerShell 7 Path is Already in PATH + - Before adding the path, make sure the following path is not already present in the list: + ``` + C:\Program Files\PowerShell\7\ + ``` + - If the path is already there, you don't need to add it again. + +### 4. Add PowerShell 7 Path + - If the path is not already in the list, click **New** in the **Edit Environment Variable** window. + - Add the following path to the list: + + ``` + C:\Program Files\PowerShell\7\ + ``` + + > **Note:** If you installed PowerShell 7 in a custom location, replace the above path with the correct one. + +### 5. Save Changes + - After adding the path, click **OK** to close the **Edit Environment Variable** window. + - Click **OK** again to close the **Environment Variables** window. + - Finally, click **OK** to exit the **System Properties** window. + +### 6. Verify PowerShell 7 in PATH + - Open **Command Prompt** or **Run** (press `Win + R`). + - Type `pwsh` and press Enter. + - If PowerShell 7 opens, you've successfully added it to your PATH! + +--- + +## Troubleshooting + +- **PowerShell 7 not opening:** Ensure the path to PowerShell 7 is entered correctly. If you're using a custom installation folder, check that the correct path is added to the `Path` variable. + +- **Changes not taking effect:** Try restarting your computer or logging out and logging back in for the changes to apply. diff --git a/docs/quota_check.md b/docs/quota_check.md index 2c7d65eb9..24298963e 100644 --- a/docs/quota_check.md +++ b/docs/quota_check.md @@ -1,57 +1,105 @@ ## Check Quota Availability Before Deployment -Before deploying the accelerator, **ensure sufficient quota availability** for the required model. -Use one of the following scripts based on your needs: +Before deploying the accelerator, **ensure sufficient quota availability** for the required model. +> **We recommend increasing the capacity to 100k tokens for optimal performance.** -- **`quota_check_params.sh`** → If you **know the model and capacity** required. -- **`quota_check_all_regions.sh`** → If you **want to check available capacity across all regions** for supported models. +### Login if you have not done so already +``` +azd auth login +``` + + +### Login if you have not done so already +``` +azd auth login +``` + +### 📌 Default Models & Capacities: +``` +gpt-4o:30, gpt-4o-mini:30, gpt-4:30, text-embedding-ada-002:80 +``` +### 📌 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:30,text-embedding-ada-002:80 + ``` +✔️ 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:30 --regions eastus,westus2 + ``` +✔️ All parameters combined: + ``` + ./quota_check_params.sh --models gpt-4:30,text-embedding-ada-002:80 --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/quota-check-output.png) --- -## **If using Azure Portal and Cloud Shell** +### **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 a specific model and capacity:** + **To check quota for the deployment** ```sh curl -L -o quota_check_params.sh "https://raw.githubusercontent.com/microsoft/Conversation-Knowledge-Mining-Solution-Accelerator/main/infra/scripts/quota_check_params.sh" chmod +x quota_check_params.sh - ./quota_check_params.sh [] (e.g., gpt-4o-mini:30,text-embedding-ada-002:20 eastus) + ./quota_check_params.sh ``` - - **To check available quota across all regions for supported models:** - - ```sh - curl -L -o quota_check_all_regions.sh "https://raw.githubusercontent.com/microsoft/Conversation-Knowledge-Mining-Solution-Accelerator/main/infra/scripts/quota_check_all_regions.sh" - chmod +x quota_check_all_regions.sh - ./quota_check_all_regions.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/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 ``` - -## **If using VS Code or Codespaces** - -1. Run the appropriate script based on your requirement: +4. Run the appropriate script based on your requirement: - **To check quota for a specific model and capacity:** + **To check quota for the deployment** ```sh - ./quota_check_params.sh [] (e.g., gpt-4o-mini:30,text-embedding-ada-002:20 eastus) + ./quota_check_params.sh ``` + - Refer to [Input Formats](#input-formats) for detailed commands. - **To check available quota across all regions for supported models:** - - ```sh - ./quota_check_all_regions.sh - ``` -2. If you see the error `_bash: az: command not found_`, install Azure CLI: +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 ``` -3. Rerun the script after installing Azure CLI. - - **Parameters** - - ``: The name and required capacity for each model, in the format model_name:capacity (**e.g., gpt-4o-mini:30,text-embedding-ada-002:20**). - - `[] (optional)`: The Azure region to check first. If not provided, all supported regions will be checked (**e.g., eastus**). +6. Rerun the script after installing Azure CLI. diff --git a/infra/scripts/checkquota_km.sh b/infra/scripts/checkquota_km.sh index b622bd262..438f4b230 100644 --- a/infra/scripts/checkquota_km.sh +++ b/infra/scripts/checkquota_km.sh @@ -32,8 +32,8 @@ echo "✅ Azure subscription set successfully." # Define models and their minimum required capacities declare -A MIN_CAPACITY=( - ["OpenAI.Standard.gpt-4o-mini"]=$GPT_MIN_CAPACITY #km generic - ["OpenAI.Standard.text-embedding-ada-002"]=$TEXT_EMBEDDING_MIN_CAPACITY #km generic + ["OpenAI.GlobalStandard.gpt-4o-mini"]=$GPT_MIN_CAPACITY #km generic + ["OpenAI.GlobalStandard.text-embedding-ada-002"]=$TEXT_EMBEDDING_MIN_CAPACITY #km generic ) VALID_REGION="" diff --git a/infra/scripts/quota_check_all_regions.sh b/infra/scripts/quota_check_all_regions.sh deleted file mode 100644 index 859e07a10..000000000 --- a/infra/scripts/quota_check_all_regions.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/bash - -# Pre-defined list of models to check -MODEL_NAMES=("gpt-4o" "gpt-4o-mini" "text-embedding-ada-002" "gpt-3.5-turbo" "gpt-4") - -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 1 ]; then - AZURE_SUBSCRIPTION_ID=$(echo "$SUBSCRIPTIONS" | awk '{print $2}') - echo "✅ Using the only available subscription: $AZURE_SUBSCRIPTION_ID" -else - 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 - 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 - -az account set --subscription "$AZURE_SUBSCRIPTION_ID" - -echo "🎯 Active Subscription: $(az account show --query '[name, id]' --output tsv)" -echo "🔄 Fetching Azure regions..." - -REGIONS=$(az account list-locations --query "[].name" --output tsv) - -echo "✅ Retrieved Azure regions. Checking availability..." - -# Array to store table data -declare -a TABLE_ROWS -INDEX=1 - -# Loop through all regions -for REGION in $REGIONS; do - REGION=$(echo "$REGION" | xargs) - echo "----------------------------------------" - echo "🔍 Checking region: $REGION" - QUOTA_INFO=$(az cognitiveservices usage list --location "$REGION" --output json) - if [ -z "$QUOTA_INFO" ]; then - echo "⚠️ WARNING: Failed to retrieve quota for region $REGION. Skipping." - continue - fi - - for MODEL_NAME in "${MODEL_NAMES[@]}"; do - for MODEL_PREFIX in "OpenAI.Standard" "OpenAI.GlobalStandard"; do - FULL_MODEL_NAME="${MODEL_PREFIX}.$MODEL_NAME" - MODEL_INFO=$(echo "$QUOTA_INFO" | awk -v model="\"value\": \"$FULL_MODEL_NAME\"" ' - BEGIN { RS="},"; FS="," } - $0 ~ model { print $0 } - ') - if [ -z "$MODEL_INFO" ]; then - continue - fi - - 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)) - - TABLE_ROWS+=("$(printf "| %-4s | %-20s | %-49s | %-9s | %-9s | %-9s |" "$INDEX" "$REGION" "$FULL_MODEL_NAME" "$LIMIT" "$CURRENT_VALUE" "$AVAILABLE")") - - INDEX=$((INDEX + 1)) - done - done - echo "----------------------------------------" -done - -# Print table header -echo "----------------------------------------------------------------------------------------------------------" -printf "| %-4s | %-20s | %-49s | %-9s | %-9s | %-9s |\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" -echo "✅ Script completed." diff --git a/infra/scripts/quota_check_params.sh b/infra/scripts/quota_check_params.sh index 34c05f22d..6929bd736 100644 --- a/infra/scripts/quota_check_params.sh +++ b/infra/scripts/quota_check_params.sh @@ -1,40 +1,71 @@ #!/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 -# Parameters -IFS=',' read -r -a MODEL_CAPACITY_PAIRS <<< "$1" # Split the comma-separated model and capacity pairs into an array -USER_REGION="$2" - -if [ ${#MODEL_CAPACITY_PAIRS[@]} -lt 1 ]; then - echo "❌ ERROR: At least one model and capacity pairs must be provided as arguments." - exit 1 -fi +# Fallback to defaults if not provided +[[ -z "$MODELS" ]] +[[ -z "$REGIONS" ]] -# Extract model names and required capacities into arrays -declare -a MODEL_NAMES -declare -a CAPACITIES +echo "Models: $MODELS" +echo "Regions: $REGIONS" +echo "Verbose: $VERBOSE" -for PAIR in "${MODEL_CAPACITY_PAIRS[@]}"; do - MODEL_NAME=$(echo "$PAIR" | cut -d':' -f1) - CAPACITY=$(echo "$PAIR" | cut -d':' -f2) +for arg in "$@"; do + if [ "$arg" = "--verbose" ]; then + VERBOSE=true + fi +done - 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 +log_verbose() { + if [ "$VERBOSE" = true ]; then + echo "$1" + fi +} - MODEL_NAMES+=("$MODEL_NAME") - CAPACITIES+=("$CAPACITY") -done +# Default Models and Capacities (Comma-separated in "model:capacity" format) +DEFAULT_MODEL_CAPACITY="gpt-4o:30,gpt-4o-mini:30,gpt-4:30,text-embedding-ada-002:80" -echo "🔄 Using Models: ${MODEL_NAMES[*]} with respective Capacities: ${CAPACITIES[*]}" +# 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 1 ]; then +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 @@ -56,104 +87,164 @@ else done fi + # Set the selected subscription az account set --subscription "$AZURE_SUBSCRIPTION_ID" -echo "🎯 Active Subscription: $(az account show --query '[name, id]' --output table)" +echo "🎯 Active Subscription: $(az account show --query '[name, id]' --output tsv)" + +# Default Regions to check (Comma-separated, now configurable) +DEFAULT_REGIONS="eastus,uksouth,eastus2,northcentralus,swedencentral,westus,westus2,southcentralus,canadacentral" +IFS=',' read -r -a DEFAULT_REGION_ARRAY <<< "$DEFAULT_REGIONS" + +# Read parameters (if any) +IFS=',' read -r -a USER_PROVIDED_PAIRS <<< "$MODELS" +USER_REGION="$REGIONS" -# List of regions to check -DEFAULT_REGIONS=("eastus" "uksouth" "eastus2" "northcentralus" "swedencentral" "westus" "westus2" "southcentralus" "canadacentral") +IS_USER_PROVIDED_PAIRS=false -# Prioritize user-provided region if given +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 - # Ensure the user-provided region is checked first - REGIONS=("$USER_REGION" "${DEFAULT_REGIONS[@]}") + echo "🔍 User provided region: $USER_REGION" + IFS=',' read -r -a REGIONS <<< "$USER_REGION" else - REGIONS=("${DEFAULT_REGIONS[@]}") + 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 - echo "----------------------------------------" - echo "🔍 Checking region: $REGION" + log_verbose "----------------------------------------" + log_verbose "🔍 Checking region: $REGION" - # Fetch quota information for the region - QUOTA_INFO=$(az cognitiveservices usage list --location "$REGION" --output json) + QUOTA_INFO=$(az cognitiveservices usage list --location "$REGION" --output json | tr '[:upper:]' '[:lower:]') if [ -z "$QUOTA_INFO" ]; then - echo "⚠️ WARNING: Failed to retrieve quota for region $REGION. Skipping." + log_verbose "⚠️ WARNING: Failed to retrieve quota for region $REGION. Skipping." continue fi - # Initialize a flag to track if both models have sufficient quota in the region - BOTH_MODELS_AVAILABLE=true - - for index in "${!MODEL_NAMES[@]}"; do - MODEL_NAME="${MODEL_NAMES[$index]}" - REQUIRED_CAPACITY="${CAPACITIES[$index]}" - - echo "🔍 Checking model: $MODEL_NAME with required capacity: $REQUIRED_CAPACITY" - - # Extract model quota information - MODEL_INFO=$(echo "$QUOTA_INFO" | awk -v model="\"value\": \"OpenAI.Standard.$MODEL_NAME\"" ' - BEGIN { RS="},"; FS="," } - $0 ~ model { print $0 } - ') - - if [ -z "$MODEL_INFO" ]; then - echo "⚠️ WARNING: No quota information found for model: OpenAI.Standard.$MODEL_NAME in $REGION. Skipping." - BOTH_MODELS_AVAILABLE=false - break # If any model is not available, no need to check further for this region - fi - - 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 ' ') + TEXT_EMBEDDING_AVAILABLE=false + AT_LEAST_ONE_MODEL_AVAILABLE=false + TEMP_TABLE_ROWS=() - CURRENT_VALUE=${CURRENT_VALUE:-0} - LIMIT=${LIMIT:-0} + for index in "${!FINAL_MODEL_NAMES[@]}"; do + MODEL_NAME="${FINAL_MODEL_NAMES[$index]}" + REQUIRED_CAPACITY="${FINAL_CAPACITIES[$index]}" + FOUND=false + INSUFFICIENT_QUOTA=false - CURRENT_VALUE=$(echo "$CURRENT_VALUE" | cut -d'.' -f1) - LIMIT=$(echo "$LIMIT" | cut -d'.' -f1) - - AVAILABLE=$((LIMIT - CURRENT_VALUE)) - - echo "✅ Model: OpenAI.Standard.$MODEL_NAME | Used: $CURRENT_VALUE | Limit: $LIMIT | Available: $AVAILABLE" - - # Check if quota is sufficient - if [ "$AVAILABLE" -lt "$REQUIRED_CAPACITY" ]; then - echo "❌ ERROR: 'OpenAI.Standard.$MODEL_NAME' in $REGION has insufficient quota. Required: $REQUIRED_CAPACITY, Available: $AVAILABLE" - echo "➡️ To request a quota increase, visit: https://aka.ms/oai/stuquotarequest" - BOTH_MODELS_AVAILABLE=false - break + 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 both models have sufficient quota, add region to valid regions - if [ "$BOTH_MODELS_AVAILABLE" = true ]; then - echo "✅ All models have sufficient quota in $REGION." +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 -# Determine final result and display in table format -if [ ${#VALID_REGIONS[@]} -eq 0 ]; then - echo "----------------------------------------" - echo "❌ No region with sufficient quota found for all models. Blocking deployment." - echo "----------------------------------------" - exit 0 +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 "----------------------------------------" - echo "✅ Suggested Regions with Sufficient Quota" - echo "----------------------------------------" - printf "| %-5s | %-20s |\n" "No." "Region" - echo "----------------------------------------" - - INDEX=1 - for REGION in "${VALID_REGIONS[@]}"; do - printf "| %-5s | %-20s |\n" "$INDEX" "$REGION" - INDEX=$((INDEX + 1)) + 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 "----------------------------------------" - exit 0 + echo "---------------------------------------------------------------------------------------------------------------------" + echo "➡️ To request a quota increase, visit: https://aka.ms/oai/stuquotarequest" fi + +echo "✅ Script completed." \ No newline at end of file