├── .azdo └── pipelines │ ├── azure-dev.yml │ ├── deploy-template.yml │ └── service-endpoint-config-template.json ├── .github └── workflows │ ├── azure-dev.yml │ ├── deploy-template.yml │ └── loadtest.yaml ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── TROUBLESHOOTING.md ├── azure.yaml ├── datasources ├── 2013_contoso_products.pdf ├── product_specification.docx └── surface-pro-4-user-guide-EN.pdf ├── devcontainer.json ├── docs ├── AI_INTEGRATION_HUB.md ├── API_Management_Integration.md ├── ARCHITECTURE.md ├── AUTOMATED_INSTALLATION.md ├── AZDO-SETUP.md ├── CALCULATOR.md ├── CUSTOMIZATIONS.md ├── CUSTOMIZATIONS_BYOR.md ├── CUSTOMIZATIONS_CONTENT_FILTERING.md ├── CUSTOMIZATIONS_LANGUAGE.md ├── CUSTOMIZATIONS_RESOURCE_NAMES.md ├── CUSTOMIZATIONS_SEARCH_TRIMMING.md ├── EXTENDING_APP_COMPONENTS.md ├── GH-SETUP.md ├── GUIDE.md ├── INGESTION_SHAREPOINT_SETUP.md ├── INSTALLATION_CHECKLIST.md ├── LOAD_TESTING.md ├── MANUAL_CUSTOM_ROLE.md ├── MANUAL_ENVIRONMENT.md ├── MANUAL_INSTALLATION.md ├── MULTIMODAL_RAG.md ├── NL2SQL_GUIDE.md ├── PERFTEST.md ├── PROVISION_DEPLOYMENT.md ├── PYRIT_SECURITY_TESTING.md ├── QUERYING_CONVERSATIONS.md ├── RAG_CONCEPTS.md ├── SECURITY_HUB.md ├── TEAMS_INTEGRATION_MAIN.md ├── TEAMS_INTEGRATION_STEP1.md ├── TEAMS_INTEGRATION_STEP2.md ├── TEAMS_INTEGRATION_STEP3.md ├── TEAMS_INTEGRATION_STEP4.md ├── TEAMS_INTEGRATION_STEP5.md ├── TROUBLESHOOTING.md └── pull_request_template.md ├── infra ├── core │ ├── ai │ │ └── aiservices.bicep │ ├── db │ │ └── cosmos.bicep │ ├── host │ │ ├── appinsights.bicep │ │ ├── appservice.bicep │ │ ├── appserviceenvironment.bicep │ │ ├── appserviceplan.bicep │ │ └── functions.bicep │ ├── loadtesting │ │ └── loadtesting.bicep │ ├── network │ │ ├── private-dns-zones.bicep │ │ ├── private-endpoint.bicep │ │ └── vnet.bicep │ ├── search │ │ ├── search-private-link.bicep │ │ └── search-services.bicep │ ├── security │ │ ├── aiservices-access.bicep │ │ ├── blobstorage-contributor-access.bicep │ │ ├── blobstorage-dataowner-access.bicep │ │ ├── blobstorage-reader-access.bicep │ │ ├── cosmos-access.bicep │ │ ├── functions-access.bicep │ │ ├── keyvault-access.bicep │ │ ├── keyvault-secrets.bicep │ │ ├── keyvault.bicep │ │ ├── openai-access.bicep │ │ ├── search-index-contributor-access.bicep │ │ ├── search-index-read-access.bicep │ │ └── search-service-contributor.bicep │ ├── storage │ │ ├── function-storage-account.bicep │ │ └── storage-account.bicep │ ├── util │ │ └── delay.bicep │ └── vm │ │ └── dsvm.bicep ├── main.bicep └── main.parameters.json ├── loadtest ├── config.yaml ├── dataset.csv ├── loadtest.jmx └── user.properties ├── media ├── admin-guide-ai-search-management.png ├── admin-guide-ai-search-reindex.png ├── admin-guide-architecture-scope.png ├── admin-guide-authorization-consent.png ├── admin-guide-authorization-example.png ├── admin-guide-datasource-configuration.png ├── admin-guide-datasource-secrets.png ├── admin-guide-document-upload-portal-select-storage-account.png ├── admin-guide-document-upload-portal-storage-account-section.png ├── admin-guide-document-upload-portal.png ├── admin-guide-homepage.png ├── admin-guide-ip-allowlist.png ├── admin-guide-private-dns.png ├── admin-guide-private-endpoints-diagram.png ├── admin-guide-vnet-peering-diagram.png ├── admin-guide-vnet.png ├── architecture-GPT-RAG-Basic.png ├── architecture-GPT-RAG-Inbound.png ├── architecture-GPT-RAG-SCALE-MultiProject-2.0.jpeg.jpg ├── architecture-GPT-RAG-SCALE-MultiProject-2.0.png ├── architecture-GPT-RAG-SCALE-MultiProject.jpeg ├── architecture-GPT-RAG-ZeroTrust-LZ.png ├── architecture-GPT-RAG-ZeroTrust.png ├── contributing-workflow.png ├── custom-role-allow.png ├── custom-role-assign.png ├── custom-role-create.png ├── custom-role-details.png ├── custom-role-finalize.png ├── custom-role-iam.png ├── custom-role-list.png ├── extending-download.png ├── extending-forking.png ├── extending-use-as-template.png ├── logo.png ├── nlsql-architecture.png ├── perftest-GPT-RAG-Basic-communication.png ├── perftest-GPT-RAG-Basic.png ├── perftest-analysis.png ├── perftest-aoai-response-time.png ├── perftest-app-component.png ├── perftest-architecture.png ├── perftest-azure-diagnostics.png ├── perftest-azure-load-testing.png ├── perftest-github-environment.png ├── perftest-github-var-secrets.png ├── perftest-llmlifecycle-with-tests.png ├── perftest-llmlifecycle.png ├── perftest-portal.png ├── perftest-response-time.png ├── perftest-running.png ├── perftest-sample-sequence-diagram.png ├── perftest-server-metrics.png ├── perftest-starting.png ├── perftest-users-per-hour.png ├── querying-conversations.png ├── ragconcepts-RAG1.PNG ├── ragconcepts-RAG2.PNG ├── readme-keyvault-login.png ├── readme-search_trimming_sample.png ├── readme-storage_sample.png ├── semantic-model-configuration.png ├── semantic-model-configuration02.png ├── sharepoint-record-app-id.png ├── sharepoint-register-app.png ├── sharepoint-secret-app.png ├── sharepoint-site-id.png ├── sharepoint-site-permissions-403-02.png ├── sharepoint-site-permissions-403.png ├── sharepoint-site-permissions-created.png ├── sharepoint-site-selected-app.png ├── sharepoint-site-url.png ├── teams-guide-Step1a.png ├── teams-guide-Step1b.png ├── teams-guide-Step1c.png ├── teams-guide-Step1d.png ├── teams-guide-Step1e.png ├── teams-guide-Step2b.png ├── teams-guide-Step3a.png ├── teams-guide-Step3b.png ├── teams-guide-Step3c.png ├── teams-guide-Step3d.png ├── teams-guide-Step3e.png ├── teams-guide-Step3f.png ├── teams-guide-Step3g.png ├── teams-guide-Step3h.png ├── teams-guide-Step3i.png ├── teams-guide-Step3j.png ├── teams-guide-Step3k.png ├── teams-guide-Step3l.png ├── teams-guide-Step3m.png ├── teams-guide-Step3n.png ├── teams-guide-Step4a.png ├── teams-guide-Step4b.png ├── teams-guide-Step4c.png ├── teams-guide-Step4d.png ├── teams-guide-Step4e.png ├── teams-guide-Step5a.png ├── teams-guide-Step5b.png ├── teams-guide-Step5c.png ├── teams-guide-Step5d.png ├── teams-guide-Step5e.png ├── teams-guide-Step5f.png ├── teams-guide-Step5g.png └── teams-guide-Step5h.png ├── misc ├── GPT-RAG-PowerBI-Report.pbit └── gptrag_resources_and_permissions.xlsx └── scripts ├── cleanComponents.ps1 ├── cleanComponents.sh ├── fetchComponents.ps1 ├── fetchComponents.sh ├── postprovision.ps1 ├── postprovision.sh ├── preDeploy.ps1 ├── preDeploy.sh ├── preprovision.ps1 ├── preprovision.sh └── rai ├── raiblocklist.json ├── raipolicies.json ├── raipolicies.ps1 └── raipolicies.sh /.azdo/pipelines/azure-dev.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | # - main 3 | # - master 4 | - none 5 | 6 | pool: 7 | vmImage: ubuntu-latest 8 | 9 | # edit these to match the names of your environments 10 | variables: 11 | dev_env: 12 | test_env: 13 | prod_env: 14 | 15 | stages: 16 | - stage: "DeployDev" 17 | displayName: "Deploy to the dev environment" 18 | jobs: 19 | - deployment: DeployDev 20 | environment: $(dev_env) 21 | strategy: 22 | runOnce: 23 | deploy: 24 | steps: 25 | - template: ./deploy-template.yml 26 | parameters: 27 | azureEnvName: "$(dev_env)" 28 | serviceConnection: "$(dev_env)" # if your service connection name is different from the environment name, change this 29 | 30 | - stage: "DeployTest" 31 | displayName: "Deploy to the test environment" 32 | dependsOn: DeployDev 33 | condition: succeeded('DeployDev') 34 | jobs: 35 | - deployment: DeployTest 36 | environment: $(test_env) 37 | strategy: 38 | runOnce: 39 | deploy: 40 | steps: 41 | - template: ./deploy-template.yml 42 | parameters: 43 | azureEnvName: "$(test_env)" 44 | serviceConnection: "$(test_env)" # if your service connection name is different from the environment name, change this 45 | 46 | - stage: "DeployProd" 47 | displayName: "Deploy to the prod environment" 48 | dependsOn: DeployTest 49 | condition: succeeded('DeployTest') 50 | jobs: 51 | - deployment: DeployProd 52 | environment: $(prod_env) 53 | strategy: 54 | runOnce: 55 | deploy: 56 | steps: 57 | - template: ./deploy-template.yml 58 | parameters: 59 | azureEnvName: "$(prod_env)" 60 | serviceConnection: "$(prod_env)" # if your service connection name is different from the environment name, change this 61 | -------------------------------------------------------------------------------- /.azdo/pipelines/deploy-template.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: azureEnvName 3 | type: string 4 | default: "dev" 5 | displayName: "Azure Environment Name" 6 | - name: serviceConnection 7 | type: string 8 | default: "dev" 9 | displayName: "Azure Service Connection Name" 10 | 11 | steps: 12 | - checkout: self 13 | 14 | - task: Bash@3 15 | displayName: Install azd 16 | inputs: 17 | targetType: "inline" 18 | script: | 19 | curl -fsSL https://aka.ms/install-azd.sh | bash 20 | 21 | - pwsh: | 22 | azd config set auth.useAzCliAuth "true" 23 | displayName: Configure AZD to Use AZ CLI Authentication. 24 | 25 | - task: AzureCLI@2 26 | displayName: Provision Infrastructure 27 | inputs: 28 | addSpnToEnvironment: true 29 | azureSubscription: ${{ parameters.serviceConnection }} 30 | scriptType: bash 31 | scriptLocation: inlineScript 32 | inlineScript: | 33 | chmod -R 755 ./scripts 34 | az login --service-principal -u $servicePrincipalId --tenant $tenantId --federated-token $idToken -o none 35 | azd provision --no-prompt 36 | env: 37 | AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) 38 | AZURE_ENV_NAME: ${{ parameters.azureEnvName }} 39 | AZURE_LOCATION: $(AZURE_LOCATION) 40 | AZURE_SERVICE_CONNECTION: ${{ parameters.serviceConnection }} 41 | 42 | - task: AzureCLI@2 43 | displayName: Package Services 44 | inputs: 45 | addSpnToEnvironment: true 46 | azureSubscription: ${{ parameters.serviceConnection }} 47 | scriptType: bash 48 | scriptLocation: inlineScript 49 | inlineScript: | 50 | chmod -R 755 ./scripts 51 | az login --service-principal -u $servicePrincipalId --tenant $tenantId --federated-token $idToken -o none 52 | azd package --no-prompt 53 | env: 54 | AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) 55 | AZURE_ENV_NAME: ${{ parameters.azureEnvName }} 56 | AZURE_LOCATION: $(AZURE_LOCATION) 57 | AZURE_SERVICE_CONNECTION: ${{ parameters.serviceConnection }} 58 | 59 | - task: AzureCLI@2 60 | displayName: Deploy Services 61 | inputs: 62 | addSpnToEnvironment: true 63 | azureSubscription: ${{ parameters.serviceConnection }} 64 | scriptType: bash 65 | scriptLocation: inlineScript 66 | inlineScript: | 67 | chmod -R 755 ./scripts 68 | az login --service-principal -u $servicePrincipalId --tenant $tenantId --federated-token $idToken -o none 69 | azd deploy --no-prompt 70 | env: 71 | AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) 72 | AZURE_ENV_NAME: ${{ parameters.azureEnvName }} 73 | AZURE_LOCATION: $(AZURE_LOCATION) 74 | AZURE_SERVICE_CONNECTION: ${{ parameters.serviceConnection }} 75 | -------------------------------------------------------------------------------- /.azdo/pipelines/service-endpoint-config-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "subscriptionId": "$SUBSCRIPTION_ID", 4 | "subscriptionName": "$SUBSCRIPTION_NAME" 5 | }, 6 | "name": "$NAME", 7 | "type": "azurerm", 8 | "url": "https://management.azure.com/", 9 | "authorization": { 10 | "parameters": { 11 | "serviceprincipalid": "$SERVICE_PRINCIPAL_ID", 12 | "tenantid": "$TENANT_ID" 13 | }, 14 | "scheme": "WorkloadIdentityFederation" 15 | }, 16 | "isShared": false, 17 | "isReady": true, 18 | "serviceEndpointProjectReferences": [ 19 | { 20 | "projectReference": { 21 | "id": "$PROJECT_ID", 22 | "name": "$PROJECT_NAME" 23 | }, 24 | "name": "$NAME" 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /.github/workflows/azure-dev.yml: -------------------------------------------------------------------------------- 1 | name: Multi-Environment Build and Deploy 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | # Run when commits are pushed to mainline branch (main or master) 7 | # Set this to the mainline branch you are using 8 | branches: 9 | # - main 10 | # - master 11 | - none 12 | 13 | permissions: 14 | id-token: write 15 | contents: read 16 | 17 | jobs: 18 | deploy-dev: 19 | uses: ./.github/workflows/deploy-template.yml 20 | secrets: inherit 21 | with: 22 | AZURE_ENV_NAME: EDIT-dev # edit to match the name of your environment 23 | 24 | deploy-test: 25 | uses: ./.github/workflows/deploy-template.yml 26 | secrets: inherit 27 | needs: [deploy-dev] 28 | with: 29 | AZURE_ENV_NAME: EDIT-test # edit to match the name of your environment 30 | 31 | deploy-prod: 32 | uses: ./.github/workflows/deploy-template.yml 33 | secrets: inherit 34 | needs: [deploy-test] 35 | with: 36 | AZURE_ENV_NAME: EDIT-ghprod # edit to match the name of your environment 37 | -------------------------------------------------------------------------------- /.github/workflows/deploy-template.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | AZURE_ENV_NAME: 7 | required: true 8 | type: string 9 | 10 | permissions: 11 | id-token: write 12 | contents: read 13 | 14 | jobs: 15 | deploy: 16 | runs-on: ubuntu-latest 17 | environment: ${{ inputs.AZURE_ENV_NAME }} 18 | env: 19 | AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }} 20 | AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }} 21 | AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} 22 | AZURE_ENV_NAME: ${{ inputs.AZURE_ENV_NAME }} 23 | AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} 24 | # AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} # uncomment when using client credentials 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v4 28 | 29 | - name: Install azd 30 | uses: Azure/setup-azd@v2 31 | 32 | - name: Log in with Azure (Federated Credentials) 33 | run: | 34 | azd auth login ` 35 | --client-id "$Env:AZURE_CLIENT_ID" ` 36 | --federated-credential-provider "github" ` 37 | --tenant-id "$Env:AZURE_TENANT_ID" 38 | shell: pwsh 39 | 40 | # uncomment the following block to use client credentials 41 | # - name: Log in with Azure (Client Credentials) 42 | # run: | 43 | # azd auth login ` 44 | # --client-id "$Env:AZURE_CLIENT_ID" ` 45 | # --client-secret "$Env:AZURE_CLIENT_SECRET" ` 46 | # --tenant-id "$Env:AZURE_TENANT_ID" 47 | # shell: pwsh 48 | 49 | - name: Provision Infrastructure 50 | run: azd provision --no-prompt 51 | env: 52 | AZURE_ENV_NAME: ${{ inputs.AZURE_ENV_NAME }} 53 | AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} 54 | AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} 55 | 56 | - name: Package Services 57 | run: azd package --no-prompt 58 | env: 59 | AZURE_ENV_NAME: ${{ inputs.AZURE_ENV_NAME }} 60 | AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} 61 | AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} 62 | 63 | - name: Deploy Services 64 | run: azd deploy --no-prompt 65 | env: 66 | AZURE_ENV_NAME: ${{ inputs.AZURE_ENV_NAME }} 67 | AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} 68 | AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} 69 | -------------------------------------------------------------------------------- /.github/workflows/loadtest.yaml: -------------------------------------------------------------------------------- 1 | name: Load Testing 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | test_run: 8 | runs-on: ubuntu-latest 9 | environment: loadtest 10 | steps: 11 | - name: Check for ENV_NAME and AZURE_CREDENTIALS 12 | run: | 13 | if [ -z "${{ vars.ENV_NAME }}" ] || [ -z "${{ secrets.AZURE_CREDENTIALS }}" ]; then 14 | echo "ENV_NAME or AZURE_CREDENTIALS is not set in the repo settings. Please set them and try again." 15 | exit 1 16 | else 17 | echo "ENV_NAME is set to ${{ vars.ENV_NAME }}" 18 | fi 19 | 20 | - name: Checkout code 21 | uses: actions/checkout@v2 22 | 23 | - name: Login to Azure 24 | uses: azure/login@v1 25 | with: 26 | creds: ${{ secrets.AZURE_CREDENTIALS }} 27 | 28 | - name: Install azd 29 | uses: Azure/setup-azd@v2 30 | 31 | - name: Login to Azure Developer CLI 32 | run: | 33 | echo "Logging to AZD..." 34 | AZURE_CREDENTIALS=$(echo '${{ secrets.AZURE_CREDENTIALS }}' | jq -r .) 35 | CLIENT_ID=$(echo $AZURE_CREDENTIALS | jq -r .clientId) 36 | CLIENT_SECRET=$(echo $AZURE_CREDENTIALS | jq -r .clientSecret) 37 | TENANT_ID=$(echo $AZURE_CREDENTIALS | jq -r .tenantId) 38 | azd auth login --client-id $CLIENT_ID --client-secret $CLIENT_SECRET --tenant-id $TENANT_ID 39 | 40 | - name: Get environment variables from AZD 41 | run: | 42 | AZURE_CREDENTIALS=$(echo '${{ secrets.AZURE_CREDENTIALS }}' | jq -r .) 43 | SUBSCRIPTION_ID=$(echo $AZURE_CREDENTIALS | jq -r .subscriptionId) 44 | echo "SUBSCRIPTION_ID=$SUBSCRIPTION_ID" >> $GITHUB_ENV 45 | echo "SUBSCRIPTION_ID=$SUBSCRIPTION_ID" 46 | export LOCATION=$(az group show --name rg-${{ vars.ENV_NAME }} --query location --output tsv) 47 | echo "LOCATION=$LOCATION" >> $GITHUB_ENV 48 | echo "LOCATION=$LOCATION" 49 | azd init -e ${{ vars.ENV_NAME }} -l $LOCATION -s $SUBSCRIPTION_ID 50 | azd env refresh 51 | echo "AZD ${{ vars.ENV_NAME }} environment variables" 52 | export RESOURCE_GROUP_NAME=$(azd env get-values -e ${{ vars.ENV_NAME }} | grep AZURE_RESOURCE_GROUP_NAME | cut -d'=' -f2 | tr -d '"') 53 | echo "RESOURCE_GROUP_NAME=$RESOURCE_GROUP_NAME" >> $GITHUB_ENV 54 | echo "RESOURCE_GROUP_NAME=$RESOURCE_GROUP_NAME" 55 | export KEY_VAULT_NAME=$(azd env get-values -e ${{ vars.ENV_NAME }} | grep AZURE_KEY_VAULT_NAME | cut -d'=' -f2 | tr -d '"') 56 | echo "KEY_VAULT_NAME=$KEY_VAULT_NAME" >> $GITHUB_ENV 57 | echo "KEY_VAULT_NAME=$KEY_VAULT_NAME" 58 | export LOAD_TESTING_SERVICE_NAME=$(azd env get-values -e ${{ vars.ENV_NAME }} | grep AZURE_LOAD_TESTING_NAME | cut -d'=' -f2 | tr -d '"') 59 | echo "LOAD_TESTING_SERVICE_NAME=$LOAD_TESTING_SERVICE_NAME" >> $GITHUB_ENV 60 | echo "LOAD_TESTING_SERVICE_NAME=$LOAD_TESTING_SERVICE_NAME" 61 | export ORCHESTRATOR_FUNC_NAME=$(azd env get-values -e ${{ vars.ENV_NAME }} | grep AZURE_ORCHESTRATOR_FUNC_NAME | cut -d'=' -f2 | tr -d '"') 62 | echo "ORCHESTRATOR_FUNC_NAME=$ORCHESTRATOR_FUNC_NAME" >> $GITHUB_ENV 63 | echo "ORCHESTRATOR_FUNC_NAME=$ORCHESTRATOR_FUNC_NAME" 64 | 65 | - name: Update config.yaml 66 | run: | 67 | sed -i "s/KEY_VAULT_NAME/${{ env.KEY_VAULT_NAME }}/g" loadtest/config.yaml 68 | 69 | - name: Update user.properties 70 | run: | 71 | sed -i "s/ORCHESTRATOR_FUNC_NAME/${{ env.ORCHESTRATOR_FUNC_NAME }}/g" loadtest/user.properties 72 | # 73 | - name: 'Azure Load Testing' 74 | uses: azure/load-testing@v1.1.25 75 | with: 76 | loadtestConfigFile: 'loadtest/config.yaml' 77 | loadtestResource: ${{ env.LOAD_TESTING_SERVICE_NAME }} 78 | resourceGroup: ${{ env.RESOURCE_GROUP_NAME }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .azure 2 | .devcontainer 3 | local/ 4 | results/ 5 | **azdoenv.json 6 | **federated_id.json 7 | **service_connection.json -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # Change Log 3 | All notable changes to this project will be documented in this file. 4 | 5 | ## Changelog 6 | 7 | ### 2024-06-15 8 | - **Added**: Option to install just some specific GPT-RAG components: data ingestion, orchestrator and frontend. 9 | 10 | ### 2024-06-10 11 | - **Added**: Optional Reuse of Pre-Created Resources: You can now optionally reuse existing resources such as VNets, Azure OpenAI instances, etc. 12 | - **Added**: Use five subnets to align with the idealized architecture. 13 | - **Added**: Custom Addressing to allow specifying custom addressing for VNets and subnets, providing greater flexibility in network configuration. 14 | - **Added**: AI Integration Hub to leverage the power of various external data sources to enhance its capabilities. Currently, we have integrated the following products: 15 | - **AI Search**: Enables access to vast online databases, providing precise and up-to-date information. 16 | - **Bing Custom Services**: Customizes search results for specific business needs, ensuring relevance and quality. 17 | - **SQL Service**: Queries extensive internal databases for accurate and current organizational data, performing analytical functions like count, sum, average, and more. 18 | - **Teradata**: Integrates large-scale data warehousing capabilities, enhancing data retrieval and analysis. 19 | 20 | ### 2024-05-22 21 | - **Added**: AOAI content filtering and blocklist configuration. 22 | - **Changed**: Changed sample documents and test dataset. 23 | 24 | ### 2024-04-15 25 | - **Added**: Load testing. 26 | - **Changed**: Increased Zero Trust VM SKU to 4vCPU and 16GB. 27 | 28 | ### 2024-03-18 29 | - **Added**: Blob storage data source soft deletion support. 30 | - **Changed**: Disabled blob anonymous access. 31 | - **Changed**: AI Search API version defaults to 2023-10-01-Preview for indexProjections and MIS authResourceId support. -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We appreciate contributions and suggestions for this project! Before contributing, you'll need to sign a Contributor License Agreement (CLA) to confirm that you have the rights to, and do, grant us permission to use your contribution. More details can be found at [Microsoft CLA](https://cla.opensource.microsoft.com). 4 | 5 | This project adheres to the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information, please visit the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any questions or comments. 6 | 7 | Below, you'll find details on how our code update process works and instructions on how to contribute. 8 | 9 | ## Contribution Guidelines 10 | 11 | Follow these guidelines to ensure smooth integration and maintain the quality of the project. Adhering to these best practices will streamline the review process and keep the codebase clean. 12 | 13 | - **Target the `insiders` Branch:** Always direct your pull request to the `insiders` branch to ensure that changes are properly integrated into the project's development workflow. 14 | 15 | - **Keep Pull Requests Small:** Aim to make your pull requests as focused and concise as possible. This makes it easier to review and ensures quicker integration into the codebase. 16 | 17 | - **Associate with Prioritized Issues:** Ensure that each pull request is linked to a specific, prioritized issue in the project backlog. This helps maintain alignment with project goals and ensures that work is being done on tasks of the highest importance. 18 | 19 | - **Bugs and Documentation Corrections:** Pull requests that address bugs or correct documentation do not need to be associated with prioritized issues. These can be submitted directly to maintain the quality and accuracy of the project. 20 | 21 | - **Multi-Repo Dependencies:** If your pull request has dependencies on updates in other repositories, make sure to mention this in the pull request description. Additionally, create a corresponding pull request in the other repository to ensure synchronized updates across all related projects. 22 | 23 | ## Code Update Workflow 24 | 25 | We use a simplified version of the [Fork and Branch Workflow](https://blog.scottlowe.org/2015/01/27/using-fork-branch-git-workflow/) alongside [Git Flow](https://nvie.com/posts/a-successful-git-branching-model/). The `main` branch always contains deployment-ready code, while the `insiders` branch serves as our integration branch. 26 | 27 | Contributors create feature branches from `insiders` in their forks. Once changes are completed, they submit a pull request to the `insiders` branch in the upstream repository. After review and approval, reviewers merge the changes into `insiders`. Weekly, maintainers group these changes into a pull request from `insiders` to `main` for final review and merging. 28 | 29 | ### Step-by-Step Process Overview 30 | 31 | This section outlines the contribution process, highlighting the key actions for both contributors and reviewers. The accompanying diagram visually represents the workflow. 32 | 33 | ![git workflow](media/contributing-workflow.png) 34 | 35 | #### Contributor 36 | 37 | 1. **Fork the Repository**: Create a copy of the original repository in your GitHub account. 38 | 2. **Clone Locally**: Download the forked repository to your machine. 39 | 3. **Add Upstream**: Link the original repository as "upstream" to keep your fork synced. 40 | 4. **Create a Feature Branch**: Start a new branch for your changes. 41 | 5. **Commit and Push Changes**: Implement your changes and push them to your GitHub fork. 42 | 6. **Open a Pull Request**: Propose your changes to the original repository. 43 | 44 | #### Reviewers 45 | 46 | 7. **Review Pull Request**: Review the pull request, approve it, and merge it into the `insiders` branch. 47 | 8. **Merge to Main**: Include changes from merged pull requests into a pull request from `insiders` to `main`. 48 | 9. **Final Review and Merge**: Reviewers conduct a final assessment of the pull request for `main` and merge it into `main`. 49 | 50 | #### Contributor 51 | 52 | 10. **Keep Your Fork Updated**: Regularly sync your fork with the original repository to stay current. 53 | 54 | ## Contributor's Step-by-Step Guide 55 | 56 | Here’s an example of how to implement a feature called `conversation-metadata` in the `gpt-rag-orchestrator` repository. The process is similar for other repositories, such as `gpt-rag-ingestion`. 57 | 58 | 1. **Create a Fork** by clicking the **Fork** button on the repository page on GitHub. Be sure to include all branches. 59 | 60 | `https://github.com/placerda/gpt-rag-orchestrator.git` 61 | 62 | 2. **Clone Your Fork Locally** using the standard clone command. 63 | 64 | `git clone https://github.com/placerda/gpt-rag-orchestrator.git` 65 | 66 | 3. **Set Upstream Remote**: Link the original repository as "upstream" for future use. 67 | 68 | `git remote add upstream git@github.com:Azure/gpt-rag-orchestrator.git` 69 | 70 | 4. **Create a Feature Branch** in your forked repository. 71 | 72 | `git checkout -b conversation-metadata` 73 | 74 | 5. **Make Changes Locally**: Modify the code in your local clone. Commit your changes and push them to your fork on GitHub. 75 | 76 | ```bash 77 | git add . 78 | git commit -m 'Implemented conversation metadata' 79 | git push origin conversation-metadata 80 | ``` 81 | 82 | 6. **Create a Pull Request**: Go to your fork on GitHub and click "Pull Request." This request, aimed at the `insiders` branch, will be reviewed and potentially merged by the repository maintainers. 83 | 84 | **Done!** Now, wait for the review and approval of your pull request. Changes may be requested. 85 | 86 | #### Keeping Your Fork Updated 87 | 88 | It’s recommended that you update your local clone after your pull request is approved. Follow these steps: 89 | 90 | ```bash 91 | git pull upstream main 92 | git push origin main 93 | git pull upstream insiders 94 | git push origin insiders 95 | ``` 96 | 97 | #### Cleaning Your Repo After PR Acceptance 98 | 99 | Once your changes are merged, you can delete the feature branch from your local clone using these commands: 100 | 101 | ```bash 102 | git switch insiders 103 | git branch -d conversation-metadata 104 | git push origin main 105 | git push --delete origin conversation-metadata 106 | ``` -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ## How to file issues and get help 4 | 5 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing 6 | issues before filing new issues to avoid duplicates. For new issues, file your bug or 7 | feature request as a new Issue. 8 | 9 | For help and questions about using this project, please use our [Discord Channel](https://discord.gg/28VMVKawgk) Enterprise RAG - Connected Community. 10 | 11 | ## Microsoft Support Policy 12 | 13 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above. 14 | -------------------------------------------------------------------------------- /TROUBLESHOOTING.md: -------------------------------------------------------------------------------- 1 | ### Troubleshooting 2 | 3 | **Powershell 7+ with AZ module are not installed** (Windows only) 4 | 5 | *Symptoms:* 6 | 7 | ERROR: failed running pre/post hooks: 'prepackage' hook failed with exit code: '1', Path: 'scripts\fetchComponents.ps1'. : exit code: 1, stdout: , stderr: 'pwsh' is not recognized as an internal or external command, 8 | operable program or batch file. 9 | 10 | *Cause:* 11 | 12 | You do not have the correct Powershell version. You need to install the appropriate version of PowerShell on the machine that azd up is running on.\ 13 | You do not have [AZ PowerShell module](https://learn.microsoft.com/en-us/powershell/azure/what-is-azure-powershell?view=azps-11.6.0#the-az-powershell-module) installed. You need to install AZ PowerShell module on the machine `Install-Module -Name Az -Repository PSGallery -Force` that azd up is running on. 14 | 15 | **Azure OpenAI model is not available in the selected region.** 16 | 17 | *Symptoms:* 18 | 19 | ERROR: deployment failed: failing invoking action 'provision', error deploying infrastructure: deploying to subscription: 20 | Deployment Error Details: 21 | RetryableError: A retryable error occurred. 22 | 23 | *Cause:* 24 | 25 | The error message indicates that the deployment failed to provision an infrastructure resource. It may have occurred with another resource that is not Azure OpenAI, but this is a common cause. Therefore, in this case, [check if the gpt model selected in the deployment is available in the selected region](https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models). You can check the gpt model selected in the deployment looking at the chatGptModelName and chatGptModelVersion parameters of the main.parameters.json file. 26 | 27 | **The subscription's home tenant differs from the tenant of the identity executing the 'azd' command** 28 | 29 | *Symptoms:* 30 | 31 | While running post-provisioning scripts, you encounter the following error: 32 | 33 | `ERROR: No subscription found. Run 'az account set' to select a subscription.` 34 | 35 | or 36 | 37 | `ERROR: Get-AzAccessToken: Run Connect-AzAccount to login.` 38 | 39 | *Cause:* 40 | 41 | This issue can occur if you have subscriptions whose home tenant is not the same as the tenant where your user is registered and authenticated. 42 | In this case, using `azd auth login` may not sufficient to enable your subscription for the Azure CLI commands we run in the azd hooks. 43 | You will need to log in using `az login --tenant TENANT_ID` or `Connect-AzAccount -Tenant 'TENANT_ID' -SubscriptionId 'SUBSCRIPTION_ID'` (PowerShell) to run the post-provisioning scripts. 44 | 45 | ****Your user account does not have permissions to run `az` or `azd` CLI commands due to a policy in Entra ID.**** 46 | 47 | *Symptoms:* 48 | 49 | When running post-provisioning scripts, you encounter errors like this one (external users are not allowed to access resources): 50 | 51 | `ERROR: AADSTS530004: AcceptCompliantDevice setting isn't configured for this organization. The admin needs to configure this setting to allow external users access to protected resources. Trace ID: c6d5b92a-0559-4477-a7e7-e42ae19d3200 Correlation ID: b95cc6b5-4bef-4c35-9261-688c481f8dbc Timestamp: 2024-06-03 20:25:56Z` 52 | 53 | *Cause:* 54 | 55 | In this case, you can choose to create a service principal, grant it contributor permission on the subscription, and log in with the service principal using the [AZD CLI](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/reference#azd-auth-login), [AZ CLI](https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli-service-principal) and [Connect-AzAccount](https://learn.microsoft.com/en-us/powershell/azure/authenticate-noninteractive?view=azps-12.0.0&viewFallbackFrom=azps-11.1.0#password-based-authentication) if using powershell (windows). 56 | 57 | **Zero-trust deployment from a machine outside its vnet** 58 | 59 | *Symptoms:* 60 | 61 | Deploying services (azd deploy) 62 | 63 | (x) Failed: Deploying service dataIngest 64 | 65 | ERROR: failed deploying service 'dataIngest': failing invoking action 'deploy', POST https://...scm.azurewebsites.net/api/zipdeploy 66 | -------------------------------------------------------------------------------- 67 | RESPONSE 403: 403 Ip Forbidden 68 | ERROR CODE UNAVAILABLE 69 | 70 | *Cause:* 71 | 72 | For deployment of the zero trust components, it is necessary to perform it from the VM created during the process. 73 | -------------------------------------------------------------------------------- /azure.yaml: -------------------------------------------------------------------------------- 1 | # yaml-language-server: $schema=https://raw.githubusercontent.com/Azure/azure-dev/main/schemas/v1.0/azure.yaml.json 2 | 3 | name: azure-gpt-rag 4 | metadata: 5 | template: azure-gpt-rag 6 | services: 7 | dataIngest: 8 | # project is temporally pulled fro its repo during deployment. 9 | project: ./.azure/gpt-rag-ingestion 10 | language: python 11 | host: function 12 | hooks: 13 | postdeploy: 14 | posix: 15 | # this path is relative to ./.azure/gpt-rag-ingestion 16 | run: scripts/postdeploy.sh 17 | interactive: true 18 | windows: 19 | # this path is relative to ./.azure/gpt-rag-ingestion 20 | run: scripts/postdeploy.ps1 21 | interactive: true 22 | orchestrator: 23 | project: ./.azure/gpt-rag-orchestrator 24 | language: python 25 | host: function 26 | frontend: 27 | # backend is python and frontend is Vite app. The frontend is built with Vite settings to output into the backend's static folder. 28 | project: ./.azure/gpt-rag-frontend/backend 29 | language: python 30 | host: appservice 31 | hooks: 32 | prepackage: 33 | windows: 34 | shell: pwsh 35 | run: cd ../frontend;npm install;npm run build 36 | interactive: true 37 | continueOnError: false 38 | posix: 39 | shell: sh 40 | run: cd ../frontend;npm install;npm run build 41 | interactive: true 42 | continueOnError: false 43 | hooks: 44 | prepackage: 45 | posix: 46 | run: scripts/fetchComponents.sh 47 | interactive: false 48 | windows: 49 | run: scripts/fetchComponents.ps1 50 | interactive: false 51 | preprovision: 52 | posix: 53 | shell: sh 54 | run: scripts/preprovision.sh 55 | interactive: true 56 | windows: 57 | shell: pwsh 58 | run: scripts/preprovision.ps1 59 | interactive: true 60 | postprovision: 61 | posix: 62 | shell: sh 63 | run: scripts/postprovision.sh 64 | interactive: true 65 | windows: 66 | shell: pwsh 67 | run: scripts/postprovision.ps1 68 | interactive: true 69 | # Components are pulled from their own repo for deployment but are not persisted to this repo. 70 | predeploy: 71 | posix: 72 | shell: sh 73 | run: scripts/preDeploy.sh; scripts/fetchComponents.sh 74 | interactive: true 75 | windows: 76 | shell: pwsh 77 | run: scripts/preDeploy.ps1; scripts/fetchComponents.ps1 78 | interactive: true 79 | postdeploy: 80 | posix: 81 | shell: sh 82 | run: scripts/cleanComponents.sh 83 | interactive: false 84 | windows: 85 | shell: pwsh 86 | run: scripts/cleanComponents.ps1 87 | interactive: false -------------------------------------------------------------------------------- /datasources/2013_contoso_products.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/datasources/2013_contoso_products.pdf -------------------------------------------------------------------------------- /datasources/product_specification.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/datasources/product_specification.docx -------------------------------------------------------------------------------- /datasources/surface-pro-4-user-guide-EN.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/datasources/surface-pro-4-user-guide-EN.pdf -------------------------------------------------------------------------------- /devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "customizations": { 3 | "codespaces": { 4 | "repositories": { 5 | "Azure/GPT-RAG": { 6 | "permissions": "read-all" 7 | }, 8 | "Azure/gpt-rag-ingestion": { 9 | "permissions": "read-all" 10 | }, 11 | "Azure/gpt-rag-orchestrator": { 12 | "permissions": "read-all" 13 | }, 14 | "Azure/gpt-rag-frontend": { 15 | "permissions": "read-all" 16 | } 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /docs/API_Management_Integration.md: -------------------------------------------------------------------------------- 1 | # APIM (Azure API Management) 2 | Azure API Management (APIM) is a comprehensive platform for managing APIs (Application Programming Interfaces). It provides a range of tools and services to help you create, publish, secure, monitor, and analyze APIs in a centralized manner. 3 | 4 | ## Benefits of API Management 5 | 1. Centralized Management: APIM provides a unified platform to manage all your APIs, regardless of where they are hosted. This centralization simplifies monitoring, security, and versioning1. 6 | 2. Security: It helps secure your APIs by providing features like authentication, authorization, and IP filtering. You can also enforce policies to control access and protect your backend services. 7 | 3. Scalability: APIM can handle high traffic loads and scale as needed, ensuring that your APIs remain responsive even under heavy usage. 8 | 4. Analytics and Monitoring: It offers detailed analytics and monitoring capabilities, allowing you to track usage patterns, performance metrics, and detect anomalies. 9 | 5. Policy Management: You can apply policies to transform and manipulate requests and responses, such as rate limiting, caching, and format conversion, without changing the backend code. 10 | 11 | ## API Management Integration Procedure 12 | 13 | 1. **Activate Managed Identity for APIM** 14 | Enable managed identity for APIM for secure authentication and access. 15 | 16 | 17 | 2. **Add "apimSubscriptionKey" entry in Key Vault** 18 | Include the built-in all-access subscription key in the Key Vault for use in APIM. 19 | 20 | 21 | 3. **Import secrets "contentSafetyKey", "bingapikey", "azureSearchKey" into Named Values** 22 | Import these named values containing secret keys from your key vault resource for various services. Import "bingapikey" or "azureSearchKey" depending on your retrieval method. Add "contentSafetyKey" if using security hub. 23 | 24 | 25 | 4. **Add OpenAI resource to APIs with the API URL suffix "openai"** 26 | In section "Create from Azure resource",include the OpenAI resource to existing APIs, using the suffix "openai" for identification. 27 | 28 | 29 | 5. **Add orchestrator and securityhub functions to APIs under API URL suffix /orc and /** 30 | In section "Create from Azure resource",include function apps orchestrator and securityhub(optional) functions in APIs, assigning them the specified paths. 31 | 32 | 33 | 6. **Manually add Bing API to APIM** 34 | If using bing retrieval,manually create the Bing API with a GET endpoint "search" pointing to "https://api.bing.microsoft.com/v7.0/custom" and use the API URL suffix "/bingCustomSearch". In the inbound process, add the header "Ocp-Apim-Subscription-Key" with the value of {{bingApiKey}} and the action to override. 35 | 36 | 37 | 7. **Add Content Safety API** 38 | If using security hub,add the Content Safety API with the corresponding JSON (Download [here](https://azure-ai-content-safety-api-docs.developer.azure-api.net/api-details#api=content-safety-service-2024-02-15-preview&operation=ImageIncidents_AddIncidentSamples)), pointing to "https://{your-content-safety-resource}.cognitiveservices.azure.com/contentSafety" and using the API URL suffix "/contentSafety". In the inbound process, include the header "Ocp-Apim-Subscription-Key" with the value of {{bingApiKey}} and the action to override. 39 | 40 | 41 | 8. **Add SearchIndexClient API** 42 | If using AI search,incorporate the SearchIndexClient API with the appropriate JSON (Download [here](https://github.com/Azure/azure-rest-api-specs/blob/main/specification/search/data-plane/Azure.Search/stable/2023-11-01/searchindex.json)), directing it to "https://{your-search-resource}.search.windows.net/indexes/ragindex" and with the API URL suffix "/searchIndex". In the inbound process, add the header "api-key" with the value of {{azureSearchKey}} and the action to override. Change the subscription input to "api-key". 43 | 44 | 45 | 9. **Add Enviroment Variables** 46 | In the orchestrator add this env variables: 47 | "APIM_ENABLED": "true", 48 | "APIM_AZURE_OPENAI_ENDPOINT": "https://{apim-resource}.azure-api.net", 49 | "APIM_BING_CUSTOM_SEARCH_URL": "https://{apim-resource}.azure-api.net/bingCustomSearch", 50 | "APIM_AZURE_SEARCH_URL": "https://{apim-resource}.azure-api.net/searchIndex", 51 | "APIM_SECURITY_HUB_ENDPOINT": "https://{apim-resource}.azure-api.net/securityHub" 52 | 53 | If using security hub, add this env variables in the security hub function: 54 | "APIM_ENABLED": "true", 55 | "APIM_ENDPOINT": "https://{apim-resource}.azure-api.net" -------------------------------------------------------------------------------- /docs/CALCULATOR.md: -------------------------------------------------------------------------------- 1 | # Estimated Monthly Cost for Running the Accelerator 2 | 3 | This page provides reference estimates for the cost of running the accelerator for one month. 4 | 5 | ## 1. Default GPT-RAG Zero Trust Deployment 6 | 7 | To view the cost estimate for this scenario, visit the [Azure Pricing Calculator](https://azure.com/e/75c446632f8c4c4ba613610d9fb0f68b). The link provides a breakdown of all solution components and their respective costs. 8 | 9 | ### Usage Parameters Used for the Estimate: 10 | 11 | #### Document Intelligence 12 | - **Number of documents**: 500 13 | - **Pages per document**: 20 14 | - **Total pages**: 10,000 15 | 16 | #### CosmosDB 17 | - **Data stored**: 500 GB 18 | - **Operations per second**: 19 | - **Creates**: 20 20 | - **Reads**: 20 21 | - **Updates**: 20 22 | 23 | 24 | #### Azure OpenAI 25 | - **Number of user conversations per day**: 100 26 | - **Average interactions per conversation**: 5 27 | - **Total Azure GPT requests per month**: 15,000 28 | 29 | --- 30 | 31 | ### Token Calculation for Azure OpenAI 32 | 33 | #### **Prompt Tokens** 34 | 1. **Triage**: 450 tokens 35 | 2. **Answer**: 221 tokens + Sources = 2,221 tokens 36 | 3. **Is Grounded**: 99 tokens + Sources = 2,099 tokens 37 | 38 | **Total prompt tokens per 1,000 requests**: 39 | ``` 40 | (2099 + 2221 + 450) * 15000 / 1000 = 71,550 tokens 41 | ``` 42 | 43 | #### **Completion Tokens** 44 | 1. **Is Grounded**: 4 tokens 45 | 2. **Triage**: 10 tokens 46 | 3. **Answer**: 800 tokens 47 | 48 | **Total completion tokens per 1,000 requests**: 49 | ``` 50 | (4 + 800 + 10) * 15000 / 1000 = 12,210 tokens 51 | ``` 52 | --- 53 | 54 | ### Note on Embeddings 55 | For **Ada embeddings**, considering the volume of 500 documents used to generate embeddings, estimate an additional cost of approximately **$100**. 56 | 57 | --- 58 | 59 | ### References 60 | 1. [CosmosDB Capacity Calculator](https://cosmos.azure.com/capacitycalculator/) 61 | 2. [Azure Pricing Calculator](https://azure.microsoft.com/en-us/pricing/calculator/) 62 | -------------------------------------------------------------------------------- /docs/CUSTOMIZATIONS.md: -------------------------------------------------------------------------------- 1 | # Custom deployment 2 | 3 | On this page, you will find some options to configure your deployment: 4 | 5 | - [Configuring Language settings](#configuring-language-settings) 6 | - [Configuring AOAI content filters](#configuring-aoai-content-filters) 7 | - [Setting Custom Names for Resources](#defining-resources-names) 8 | - [Applying Tags to All Resources](#adding-tags-for-all-resources) 9 | - [Bringing Your Own Resources](#bring-your-own-resources) 10 | - [Accessing Data Ingest function using AI Search Managed Identity](#accessing-the-data-ingest-function-from-ai-search-using-a-managed-identity) 11 | - [Extending Enteprise RAG components](#extending-solution-components) 12 | 13 | 14 | 15 | 16 | **Note on Environment Variables** 17 | 18 | Most of the customizations described on this page involve the use of environment variables. Therefore, it's worth noting the following about using `azd` environment variables: 19 | - By utilizing the `azd env` to set [environment variables](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/manage-environment-variables), you can specify resource names for each environment. 20 | - If you work across multiple devices, you can take advantage of `azd`'s support for [remote environments](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/remote-environments-support). This feature allows you to save your environment settings in Azure Storage and restore them on any device. 21 | 22 | ## Configuring Language Settings 23 | 24 | Enterprise RAG leverages Large Language Models (LLMs) and supports multiple languages by default. However, it provides parameters to fine-tune the language settings across its three main components. For detailed instructions, refer to [Configuring Language Settings](CUSTOMIZATIONS_LANGUAGE.md). 25 | 26 | ## Configuring AOAI content filters 27 | 28 | Provisioning an Azure OpenAI resource with `azd` automatically creates a content filtering profile with a default severity threshold (Medium) for all content harm categories (Hate, Violence, Sexual, Self-Harm) and assigns it to the provisioned Azure OpenAI model through a post-deployment script. If you wish to customize these settings to be more or less restrictive, please refer to the [Customize Content Filtering Policies](CUSTOMIZATIONS_CONTENT_FILTERING.md) page. 29 | 30 | ## Defining resources names 31 | 32 | By default, `azd` will automatically generate a unique name for each resource. The unique name is created based on the azd-environment name, the subscription name and the location. However, you can also manually define the name for each resource as described in [Customizing resources names](CUSTOMIZATIONS_RESOURCE_NAMES.md). 33 | 34 | ## Adding tags for all resources 35 | 36 | The [main.parameters.json](../infra/main.parameters.json) contains an empty object where you can define tags to apply to all your resources before you run `azd up` or `azd provision`. Look for the entry: 37 | 38 | ```json 39 | "deploymentTags":{ 40 | "value": {} 41 | } 42 | ``` 43 | 44 | Define your tags as `"key":value`, for example: 45 | 46 | ```json 47 | "deploymentTags":{ 48 | "value": { 49 | "business-unit": "foo", 50 | "cost-center": "bar" 51 | } 52 | } 53 | ``` 54 | 55 | While you are defining your deployment tags, you can create your own environment mappings (in case you want to set different tag's values per environment). For example: 56 | 57 | Creating your own azd-env mapping: 58 | ```json 59 | "deploymentTags":{ 60 | "value": { 61 | "business-unit": "${MY_DEPLOYMENT_BUSINESS_UNIT}", 62 | "cost-center": "${COST_CENTER}" 63 | } 64 | } 65 | ``` 66 | 67 | Then, define the values for your environment: 68 | ```sh 69 | azd env set MY_DEPLOYMENT_BUSINESS_UNIT foo 70 | azd env set COST_CENTER bar 71 | ``` 72 | 73 | > Note: Since the input parameter is an object, azd won't prompt the user for a value if the env-var is not set (how it happens when the input argument is a string). The values would be resolved and applied as empty strings when missing. 74 | 75 | ## Bring Your Own Resources 76 | 77 | In some cases, you may want to use one or more pre-existing resources in your subscription instead of creating new ones. Our Bicep template allows you to do this. For detailed instructions on how this can be achieved, please take a look at the [Bring Your Own Resources](CUSTOMIZATIONS_BYOR.md) page. 78 | 79 | 107 | 108 | ## Accessing the data ingest function from AI Search using a Managed Identity 109 | 110 | In the AI Search indexing process, a skillset incorporates a custom web app skill. This skill is powered by the data ingestion Azure Function, which is responsible for chunking the data. By default, the AI Search service establishes a connection with the Azure Function via an API key. 111 | 112 | However, for enhanced security and simplified credentials management, you have the option to utilize a managed identity for this connection. To switch to using a managed identity, simply set the environment variable `AZURE_SEARCH_USE_MIS` to `true`. 113 | 114 | ```sh 115 | azd env set AZURE_SEARCH_USE_MIS true 116 | ``` 117 | 118 | After setting this variable, you need to deploy again using the azd up command. 119 | 120 | ```sh 121 | azd up 122 | ``` 123 | 124 | > **Important**: In order for the data ingestion function to be accessed with a managed identity, it needs to be configured to use Microsoft Entra Sign-in, as indicated [in this link](https://learn.microsoft.com/en-us/azure/app-service/configure-authentication-provider-aad). 125 | 126 | ## Extending solution components 127 | 128 | Azd automatically provisions the infrastructure and deploys the three components. However, you may want to change and customize parts of the code to meet a specific requirement. Our Solution Accelerator allows you to do this. For detailed instructions on how this can be achieved, please take a look at the [Extending Application Components](EXTENDING_APP_COMPONENTS.md) page. 129 | 130 | ## Filter Files with AI Search Using Security Trimming 131 | 132 | This customization is particularly valuable in scenarios where sensitive documents need to be accessed by specific groups or individuals within an organization. With this feature you can ensure that AI Search returns results tailored to each user’s access (no RBAC permissions), please take a look at the [Filter Files with AI Search Using Security Trimming](CUSTOMIZATIONS_SEARCH_TRIMMING.md) page. -------------------------------------------------------------------------------- /docs/CUSTOMIZATIONS_CONTENT_FILTERING.md: -------------------------------------------------------------------------------- 1 | # Configuring AOAI content filters 2 | 3 | - [Overview of Responsible AI practices for AOAI models](https://learn.microsoft.com/en-us/legal/cognitive-services/openai/overview?context=%2Fazure%2Fai-services%2Fopenai%2Fcontext%2Fcontext) 4 | - [AOAI Content filtering categories](https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/content-filter?tabs=warning%2Cpython-new#content-filtering-categories) 5 | - [Apply for unrestricted content filters via this form](https://customervoice.microsoft.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR7en2Ais5pxKtso_Pz4b1_xUMlBQNkZMR0lFRldORTdVQzQ0TEI5Q1ExOSQlQCN0PWcu) 6 | 7 | Azd automatically creates content filters profile with default severity threshold *(Medium)* for all content harms categories *(Hate, Violence, Sexual, Self-Harm)* and assignes it to provisioned AOAI model through post deployment script. However, if you want to customize them to be more or less restrictive, you can make changes to [raipolicies.json](../scripts/rai/raipolicies.json) file. 8 | 9 | **Example**: Changing filters threshold for violence (prompt) and self-harm (completion) categories 10 | ```json 11 | { 12 | "name": "violence", 13 | "blocking": true, 14 | "enabled": true, 15 | "allowedContentLevel": "high", 16 | "source": "prompt" 17 | }, 18 | { 19 | "name": "selfharm", 20 | "blocking": true, 21 | "enabled": true, 22 | "allowedContentLevel": "low", 23 | "source": "completion" 24 | } 25 | ``` 26 | 27 | (Optional) Content filters also support additional safety models *(Jailbreak, Material Protection for Text or Code)* that can be run on top of the main content filters. 28 | 29 | **Example**: Enabling Jailbreak and Text Material protection 30 | ```json 31 | { 32 | 33 | "name": "jailbreak", 34 | "blocking": true, 35 | "source": "prompt", 36 | "enabled": true 37 | }, 38 | { 39 | "name": "protected_material_text", 40 | "blocking": true, 41 | "source": "completion", 42 | "enabled": true 43 | }, 44 | { 45 | "name": "protected_material_code", 46 | "blocking": false, 47 | "source": "completion", 48 | "enabled": false 49 | } 50 | ``` 51 | 52 | Then, follow regular installation & deployment process. 53 | 54 | >Note: You need to make changes in raipolicies.json file before executting ```azd up``` command, if you want to provision and deploy all in once. 55 | 56 | In order you update content filters policies for already deployed model, run the following command. 57 | 58 | ```sh 59 | azd provision 60 | ``` -------------------------------------------------------------------------------- /docs/CUSTOMIZATIONS_LANGUAGE.md: -------------------------------------------------------------------------------- 1 | # Configuring Language Settings 2 | 3 | The solution utilizes Large Language Models (LLMs) and inherently supports multiple languages by default. However, each component has certain aspects that can be customized in terms of language. Let's explore each of them. 4 | 5 | ## Data Ingestion 6 | 7 | Data ingestion supports multiple languages. However, if you wish, you can specify the search index **Analyzer** to be tailored for a specific language. An analyzer is a crucial component of the full-text search engine, playing a key role in processing text strings during both the indexing and query execution phases. 8 | 9 | By default, the configuration uses a standard, language-agnostic analyzer that works well for most languages. However, if your deployment is targeted at a non-Western language, customizing this parameter for that specific language could be advantageous. 10 | 11 | This customization can be easily achieved by setting the `SEARCH_ANALYZER_NAME` parameter before executing `azd up` or `azd provision`. The example below shows how to configure the analyzer for Vietnamese. 12 | 13 | ```sh 14 | azd env set SEARCH_ANALYZER_NAME vi.microsoft 15 | ``` 16 | 17 | Here's a [List of supported language analyzers](https://learn.microsoft.com/en-us/azure/search/index-add-language-analyzers#supported-language-analyzers) available. 18 | 19 | ## Orchestrator 20 | 21 | The orchestrator's prompts are crafted in English and include instructions that guide the model to generate content in the same language as the user, ensuring multilingual functionality. Therefore, there's no need for customization in this aspect. 22 | 23 | However, for certain error scenarios, such as server errors or when the Azure OpenAI service is unavailable, we utilize predefined error messages. These messages are available in English, Portuguese, and Spanish, and can be found in [this folder](https://github.com/Azure/gpt-rag-orchestrator/tree/main/orc/messages) within the orchestrator's repository. 24 | 25 | By default, the language for error messages is set to English (en). You can switch to another available language by setting the `ORCHESTRATOR_MESSAGES_LANGUAGE` environment variable before executing `azd provision` or `azd up`. For example, to select Spanish, use the following command: 26 | 27 | ```sh 28 | azd env set ORCHESTRATOR_MESSAGES_LANGUAGE es 29 | ``` 30 | 31 | If you wish to use your own error messages or add messages in a new language, you can modify the orchestrator's code. This involves either altering the content of the current JSON files or, to introduce a new language, adding a file akin to the existing `en.json`. For example, to add French, simply create a `fr.json` file in the same [folder](https://github.com/Azure/gpt-rag-orchestrator/tree/main/orc/messages) within the orchestrator's repository. 32 | 33 | ## Front-end 34 | 35 | The front-end allows users to utilize voice synthesis and recognition features to provide a voice interaction experience using the Azure AI Speech Service. You can define three environment variables to customize this experience. 36 | 37 | `AZURE_SPEECH_RECOGNITION_LANGUAGE`: sets the language for transcribing user voice in the frontend UI, with the default being 'en-US'. To select a different language, refer to the list of supported [speech recognition languages](https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support?tabs=stt#supported-languages). 38 | 39 | `AZURE_SPEECH_SYNTHESIS_LANGUAGE`: determines the language used for speech synthesis in the frontend, with the default also being 'en-US'. For available options, consult the list of supported [speech synthesis languages](https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support?tabs=tts#supported-languages). 40 | 41 | `AZURE_SPEECH_SYNTHESIS_VOICE_NAME`: specifies the voice used for speech synthesis, with the default set to 'en-US-RyanMultilingualNeural'. To choose a different voice, check the list of supported [speech synthesis voices](https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support?tabs=tts#multilingual-voices). 42 | 43 | To configure these settings, set the corresponding environment variable before executing `azd provision` or `azd up`. For example, to select 'pt-BR-FranciscaNeural' as the voice for speech synthesis, use the following command: 44 | 45 | ```sh 46 | azd env set AZURE_SPEECH_SYNTHESIS_VOICE_NAME pt-BR-FranciscaNeural 47 | ``` -------------------------------------------------------------------------------- /docs/CUSTOMIZATIONS_RESOURCE_NAMES.md: -------------------------------------------------------------------------------- 1 | # Customizing resources names 2 | 3 | By default, `azd` will automatically generate a unique name for each resource. The unique name is created based on the azd-environment name, the subscription name and the location. However, you can also manually define the name for each resource. 4 | 5 | Each resource name has a direct mapping to an environment variable, for example, Storage Account name is defined by the `AZURE_STORAGE_ACCOUNT_NAME` variable. 6 | 7 | So you can set `AZURE_STORAGE_ACCOUNT_NAME` to define the name for the storage account, by running the command before provisioning your resources: 8 | 9 | ``` 10 | azd env set AZURE_STORAGE_ACCOUNT_NAME 11 | ``` 12 | 13 | This is the full list of resource names variables: 14 | 15 | - AZURE_AI_SERVICES_NAME 16 | - AZURE_AI_SERVICES_PE 17 | - AZURE_AI_SUBNET_NAME 18 | - AZURE_APP_INSIGHTS_NAME 19 | - AZURE_APP_INT_SUBNET_NAME 20 | - AZURE_APP_SERVICE_NAME 21 | - AZURE_APP_SERVICE_PLAN_NAME 22 | - AZURE_APP_SERVICES_SUBNET_NAME 23 | - AZURE_BASTION_KV_NAME 24 | - AZURE_DATABASE_SUBNET_NAME 25 | - AZURE_DATA_INGEST_FUNC_NAME 26 | - AZURE_DATA_INGESTION_PE 27 | - AZURE_DB_ACCOUNT_NAME 28 | - AZURE_DB_ACCOUNT_PE 29 | - AZURE_FRONTEND_PE 30 | - AZURE_KEY_VAULT_NAME 31 | - AZURE_KEYVAULT_PE 32 | - AZURE_LOAD_TESTING_NAME 33 | - AZURE_OPENAI_SERVICE_NAME 34 | - AZURE_OPEN_AI_PE 35 | - AZURE_ORCHESTRATOR_FUNCTION_APP_NAME 36 | - AZURE_ORCHESTRATOR_PE 37 | - AZURE_RESOURCE_GROUP_NAME 38 | - AZURE_SEARCH_PE 39 | - AZURE_SEARCH_SERVICE_NAME 40 | - AZURE_STORAGE_ACCOUNT_NAME 41 | - AZURE_STORAGE_ACCOUNT_PE 42 | - AZURE_VM_NAME 43 | - AZURE_VNET_NAME 44 | 45 | 46 | > The resource related to the name can be directly inferred from the variable name. However, if you have any doubts, you can visit the [main.bicep](../infra/main.bicep) file and look for the resource associated with this variable (the variables can be found at the end of the file in the template outputs section). -------------------------------------------------------------------------------- /docs/CUSTOMIZATIONS_SEARCH_TRIMMING.md: -------------------------------------------------------------------------------- 1 | # Filter Files with AI Search Using Security Trimming 2 | 3 | This customization allows the GPT-RAG solution to filter information during searches in AI Search based on a specific field defined in the index schema. **AI Search security trimming** ensures that only authorized users or groups can access specific search results by enforcing access control at query time. It checks the `metadata_security_id` field in the index against the user or group identifiers provided during the search. 4 | 5 | The AI Search setup automatically creates an index with a `metadata_security_id` field. This field is mapped in the skillset for use during indexing, enabling secure and targeted searches while protecting sensitive information. 6 | 7 | ## General Instructions 8 | 9 | In the following sections, we will provide detailed instructions on how to configure and use this functionality. 10 | 11 | ### Pre-requisites: 12 | 13 | - **Storage Metadata**: Ensure that the files in the storage container to be indexed include a `metadata_security_id` field in their metadata. This field should contain a list of values, which may include: 14 | - Entra ID `object_ids` of authorized users. 15 | - Entra ID group names. 16 | 17 | - **Orchestrator Payload**: The following attributes must be included in the JSON payload sent to the Orchestrator to enable the search trimming functionality: 18 | - `"client_principal_id"`: Unique identifier of the client. 19 | - `"client_principal_name"`: Principal name of the client. 20 | - `"client_group_names"`: List of group names associated with the client. 21 | 22 | > [!NOTE] 23 | > Orchestrator Payload: These attributes are already added by the Frontend and populated correctly if authentication is properly configured. 24 | 25 | By default, the Security Trimming feature is activated and always returns documents where the `metadata_security_id` field is blank, ensuring broad accessibility when no specific restrictions are defined. 26 | 27 | ### Setup Steps: 28 | 29 | 1. **Deploy the Solution**: 30 | Deploy the GPT-RAG solution. The Function Apps for Ingestion and Orchestration will be set up to handle security trimming by default. This ensures that the AI Search index includes the `metadata_security_id` field and that the skillset is correctly mapped. 31 | 32 | 2. **Verify Metadata**: 33 | Ensure that all files in the storage container have the `metadata_security_id` metadata field populated with the relevant values, such as Entra ID `object_ids` and/or group names. This step is crucial for restricting document access to authorized users only. 34 | 35 | ![Storage Metadata - Search Trimming](../media/readme-search_trimming_sample.png) 36 | 37 | 3. **Check Deployment**: 38 | After deployment, verify that the AI Search index has been created with the `metadata_security_id` field and that the skillset mappings are functioning correctly. 39 | 40 | > [!NOTE] 41 | > For step 2, ensure that the `metadata_security_id` field follows this format: `['00000000-0000-0000-0000-000000000123', 'Group Name', '00000000-0000-0000-0000-000000000456']`. This field specifies who or which group can access the blob. Leave it blank if there are no access restrictions. 42 | 43 | ## References: 44 | 45 | * [Azure AI Search - Search Trimming Documentation](https://learn.microsoft.com/en-us/azure/search/search-security-trimming-for-azure-search) 46 | -------------------------------------------------------------------------------- /docs/EXTENDING_APP_COMPONENTS.md: -------------------------------------------------------------------------------- 1 | # Extending application components 2 | 3 | Azd provisions the infrastructure and deploys the components. To meet specific needs, you can customize the code, such as updating the [bot description](https://github.com/Azure/gpt-rag-orchestrator/blob/main/orc/bot_description.prompt) in the orchestrator to better define the bot's scope. 4 | 5 | This accelerator repositories are public, here are some options for extending its code in your projects: 6 | 7 | - **Forking the GitHub repository**: Choose this option if you want to contribute to the original project or keep your version connected. If you fork into a private GitHub repository, you can’t submit pull requests back unless you make your fork public or create a public branch. 8 | 9 | ![Extending Forking](../media/extending-forking.png) 10 | 11 | - **Using as a GitHub Template**: Select this option if you want to copy repo code in a new, independent GitHUb repository. This lets you start fresh with a private repository, without linking it to the original. 12 | 13 | ![Extending as a Template](../media/extending-use-as-template.png) 14 | 15 | - **Download the repo code then work on it locally**: If you prefer to work offline or in a local environment, you can download the repository code to your machine and customize it as needed before deployment. 16 | 17 | ![Extending as a Template](../media/extending-download.png) 18 | 19 | - **Download the repo code then create a repo in other tools like Azure DevOps**: If you want to use a different version control system, you can download the repository code and then create a new repository in tools like Azure DevOps to manage your project. 20 | 21 | That said, if you want to manually deploy and customize the components, you can follow the deployment instructions for each component, as described in the following sections. 22 | 23 | > [!NOTE] 24 | > To deploy, you will only need the Contributor role in the resource group where the solution's resources are located. 25 | 26 | ## **1) Data Ingestion Application** 27 | 28 | Fork, copy or download the original [Data ingestion](https://github.com/Azure/gpt-rag-ingestion) repo to create your own data ingestion code then follow the steps in its **What if I want to redeploy just the ingestion component?** section to learn how to redeploy the component. 29 | 30 | If you want to run the component locally, which is interesting for testing your modifications before deploying, check out the **Running Locally with VS Code** section in the component's repository. 31 | 32 | ## **2) Orchestrator Application** 33 | 34 | Fork, copy or download the original [Orchestrator](https://github.com/Azure/gpt-rag-orchestrator) repo to create your own orchestrator git repo and follow the steps in its **Cloud Deployment** section to learn how to redeploy the component. 35 | 36 | If you want to run the component locally, which is interesting for testing your modifications before deploying, check out the **Running Locally with VS Code** section in the component's repository. 37 | 38 | ## **3) Front-end Application** 39 | 40 | Fork, copy or download the original [App Front-end](https://github.com/Azure/gpt-rag-frontend) repo to create your own frontend code and follow the steps in its **Deploy (quickstart)** section to learn how to redeploy the component. 41 | 42 | If you want to run the component locally, which is interesting for testing your modifications before deploying, check out the **Test locally** section in the component's repository. 43 | 44 | ## **(Optional) Integrate custom component repo to the main gpt-rag** 45 | 46 | Customizing the components of your project allows for a tailored experience, but `gpt-rag` solution repository won't automatically detect your custom component repos. 47 | 48 | Integrating your custom component repository with the gpt-rag project enhances workflow efficiency, allowing you to directly use azd commands like `azd up` and `azd deploy` within the gpt-rag repository. 49 | 50 | To achieve this integration, simply follow these steps: 51 | 52 | 1. **Create Your Own `gpt-rag` Repository**: Start by forking or copying the original `gpt-rag` repository. This will be the foundation for integrating your custom components. 53 | 54 | 2. **Point to Your Custom Component Repositories**: 55 | - Navigate to the `scripts` folder within your newly created `gpt-rag` repository. 56 | - Open and edit the `fetchComponents.ps1` and `fetchComponents.sh` scripts. 57 | - Adjust these scripts to reference your custom component repositories, replacing the original repository links. 58 | 59 | 3. **Initialize Your Customized Setup**: 60 | - With your `gpt-rag` repository scripts pointing to your component repositories, initialize the environment. 61 | - Run the `azd init -t /` using your own github org and repository. -------------------------------------------------------------------------------- /docs/INSTALLATION_CHECKLIST.md: -------------------------------------------------------------------------------- 1 | # Zero Trust Architecture Installation Checklist 2 | 3 | Ensure a successful deployment of your Zero Trust Architecture by following this objective checklist. The checklist is divided into **Pre-Installation** and **Post-Installation** sections to guide you through the verification process. 4 | 5 | --- 6 | 7 | ## Table of Contents 8 | 9 | 1. [Pre-Installation Checks](#pre-installation-checks) 10 | 2. [Post-Installation Checks](#post-installation-checks) 11 | 3. [Additional Resources](#additional-resources) 12 | 13 | --- 14 | 15 | ## 1. Pre-Installation Checks 16 | 17 | Complete all the following tasks before starting the installation to ensure a smooth deployment process. 18 | 19 | ### 1.1. **Deployment Planning** 20 | 21 | - [ ] **Basic Information Gathered** 22 | - [ ] Subscription Name is documented. 23 | - [ ] Resource Group Name is recorded. 24 | - [ ] Azure Region is selected and confirmed. 25 | - [ ] Azure Environment Name (e.g., `gpt-rag-dev`, `gpt-rag-poc`) is defined. 26 | 27 | - [ ] **Network Setup Scenario Selected** 28 | - [ ] Chosen network setup option (Automatic with Default Address Range, Automatic with Custom Address Ranges, or Manual) is identified. 29 | - [ ] Address ranges do not overlap with existing networks. 30 | 31 | - [ ] **Existing Resources Reviewed** 32 | - [ ] Decision to reuse non-networking resources (e.g., Azure OpenAI, Cosmos DB, Key Vault) is made. 33 | - [ ] Names and resource group details of existing resources are documented. 34 | 35 | - [ ] **Resource Naming and Tagging Prepared** 36 | - [ ] Naming conventions for resources are established. 37 | - [ ] Tags (e.g., `business-unit`, `cost-center`) are defined for resource management. 38 | 39 | ### 1.2. **Repository Setup** 40 | 41 | - [ ] **Repository Initialized** 42 | - [ ] Ran `azd init -t azure/gpt-rag` successfully. 43 | - [ ] If using Agentic AutoGen-based orchestrator, ran `azd init -t azure/gpt-rag -b agentic` without errors. 44 | 45 | ### 1.3. **Configuration Settings** 46 | 47 | - [ ] **Network Isolation Enabled** 48 | - [ ] Executed `azd env set AZURE_NETWORK_ISOLATION true` successfully. 49 | 50 | - [ ] **Network Setup Option Defined** 51 | - [ ] Selected network setup option is configured (e.g., set `VNET_REUSE` for manual setup). 52 | 53 | - [ ] **Custom Address Ranges Configured** (If applicable) 54 | - [ ] Executed all necessary `azd env set` commands for custom address ranges. 55 | - [ ] Verified custom address ranges to prevent overlaps. 56 | 57 | - [ ] **Resource Names Customized** (If applicable) 58 | - [ ] Set environment variables for custom resource names (e.g., `AZURE_STORAGE_ACCOUNT_NAME`). 59 | 60 | - [ ] **Azure Resources Reuse Configured** (If applicable) 61 | - [ ] Set environment variables for resource reuse (e.g., `AI_SERVICES_REUSE`, `AI_SERVICES_RESOURCE_GROUP_NAME`). 62 | 63 | ### 1.4. **Authentication** 64 | 65 | - [ ] **Azure CLI Authentication** 66 | - [ ] Ran `azd auth login` successfully. 67 | - [ ] Ran `az login` without issues. 68 | 69 | --- 70 | 71 | ## 2. Post-Installation Checks 72 | 73 | After completing the installation, verify that all components are correctly deployed and configured to ensure the Zero Trust Architecture functions as intended. 74 | 75 | ### 2.1. **Infrastructure Deployment Verification** 76 | 77 | - [ ] **Infrastructure Components Deployed** 78 | - [ ] Ran `azd provision` successfully. 79 | - [ ] Verified all infrastructure components in the Azure Portal (resource groups, VNets, subnets, etc.). 80 | 81 | ### 2.2. **Network Configuration Verification** 82 | 83 | - [ ] **Virtual Networks and Subnets** 84 | - [ ] Confirmed VNets are created with correct address ranges. 85 | - [ ] Verified all required subnets (`ai-vnet`, `ai-subnet`, `app-services-subnet`, etc.) are present and correctly configured. 86 | 87 | - [ ] **Private Endpoints Setup** 88 | - [ ] Created private endpoints for all specified Azure services (e.g., Data Ingestion Function App, Azure Storage Account). 89 | - [ ] Ensured private endpoints are associated with the correct subnets. 90 | - [ ] Verified Private DNS Zones are correctly configured for name resolution. 91 | 92 | - [ ] **Network Security Groups (NSGs)** 93 | - [ ] Created NSGs with rules aligned to security policies. 94 | - [ ] Applied NSGs to all relevant subnets. 95 | 96 | - [ ] **Shared Private Access Configurations** 97 | - [ ] Configured shared private links for Azure AI Search with Blob Storage Account. 98 | - [ ] Configured shared private links for Azure AI Search with Function App. 99 | 100 | - [ ] **App Service Plan VNet Integration** 101 | - [ ] Integrated App Service Plan with `ai-vnet`. 102 | - [ ] Verified connectivity between App Service and VNet. 103 | 104 | - [ ] **Data Science Virtual Machine (Test VM)** 105 | - [ ] Provisioned VM with correct OS, SKU, and image. 106 | - [ ] Configured Bastion for secure VM access. 107 | - [ ] Connected to VM using Azure Bastion. 108 | - [ ] Verified VM performance and accessibility. 109 | 110 | ### 2.3. **Access Controls and Security Verification** 111 | 112 | - [ ] **Access Controls Alignment** 113 | - [ ] Verified that access controls adhere to Zero Trust principles. 114 | - [ ] Tested role-based access controls (RBAC) and conditional access policies. 115 | 116 | - [ ] **Network Security Groups (NSGs) Rules** 117 | - [ ] Verified NSG rules are correctly enforcing traffic flow restrictions. 118 | - [ ] Ensured only authorized traffic is allowed. 119 | 120 | ### 2.4. **Resource Naming and Tagging Validation** 121 | 122 | - [ ] **Resource Names** 123 | - [ ] Checked that all resources have correct and consistent names following conventions. 124 | 125 | - [ ] **Tags** 126 | - [ ] Verified that tags (e.g., `business-unit`, `cost-center`) are applied correctly to all resources. 127 | 128 | ### 2.5. **Connectivity and Integration Tests** 129 | 130 | - [ ] **Component Connectivity** 131 | - [ ] Confirmed connectivity between all deployed components. 132 | - [ ] Tested VNet peering, VPN gateways, or ExpressRoute connections as applicable. 133 | 134 | - [ ] **Service Integrations** 135 | - [ ] Verified integrations between components (e.g., AI Services with Cosmos DB). 136 | 137 | ### 2.6. **Application Functionality Verification** 138 | 139 | - [ ] **Operational Components** 140 | - [ ] Tested all deployed application components to ensure they are operational. 141 | - [ ] Verified that services like Azure OpenAI, Cosmos DB, and Key Vault are functioning as expected. 142 | 143 | ### 2.7. **Monitoring and Logging Setup** 144 | 145 | - [ ] **Monitoring Configuration** 146 | - [ ] Confirmed that monitoring tools (e.g., Azure Monitor) are configured. 147 | - [ ] Verified that metrics and logs are being collected. 148 | 149 | - [ ] **Alerting Setup** 150 | - [ ] Ensured that alerts are set up for critical events and anomalies. 151 | 152 | --- 153 | 154 | ## 3. Additional Resources 155 | 156 | - [Customizing Resource Names](CUSTOMIZATIONS_RESOURCE_NAMES.md) 157 | - [Bring Your Own Resources](CUSTOMIZATIONS_BYOR.md) 158 | - [Orchestrator Repository](https://github.com/azure/gpt-rag-agentic) 159 | - [Front-end Repository](https://github.com/azure/gpt-rag-frontend) 160 | - [Data Ingestion Repository](https://github.com/Azure/gpt-rag-ingestion) 161 | 162 | --- 163 | 164 | ## 4. Congratulations 165 | 166 | 🎉 **Congratulations! Your Zero Trust Architecture deployment has been successfully validated.** 167 | 168 | --- 169 | 170 | > **Note:** After the initial deployment, consider performing periodic reviews and updates to maintain security posture and incorporate new best practices. 171 | 172 | -------------------------------------------------------------------------------- /docs/MULTIMODAL_RAG.md: -------------------------------------------------------------------------------- 1 | # Multimodal RAG Overview 2 | 3 | This document outlines the architecture and workflow for our **multimodal Retrieval Augmented Generation (RAG)** solution, integrating **AI Search Service**, **Azure OpenAI embeddings**, and **Azure Functions**. The goal is to enrich responses with **textual and visual content** (e.g., images) extracted from ingested documents, all managed within a unified search index. 4 | 5 | ## Key Components 6 | 7 | - **Azure Blob Storage**: Stores original documents, extracted text, and associated images. 8 | - **Azure Functions**: Orchestrates ingestion, text and image extraction, embedding generation, indexing, and data cleanup. 9 | - **Azure Document Processing Service**: Extracts text segments and identifies images from source documents, enabling multimodal content association. 10 | - **Azure OpenAI**: Generates semantic embeddings for both text and image descriptions. 11 | - **AI Search Service**: Hosts a unified index for both textual embeddings and image descriptions. 12 | 13 | ## Multimodal End-to-End Workflow 14 | 15 | 1. **Data Ingestion** 16 | - Documents files are uploaded to Azure Blob Storage. 17 | - An Azure Function triggers upon new file uploads. 18 | 19 | 2. **Preprocessing & Content Extraction** 20 | - The Azure Function invokes the Azure Document Processing Service to extract: 21 | - Text segments (e.g., paragraphs, sections). 22 | - Associated images, stored separately in Blob Storage. 23 | - For each text segment with related images, a GPT model generates a **combined textual description** of the images. 24 | 25 | 3. **Embedding Generation** 26 | - Azure OpenAI generates: 27 | - Text embeddings stored in `contentVector`. 28 | - Embeddings for combined image descriptions stored in a new field, `captionVector`. 29 | 30 | 4. **Unified Multimodal Indexing** 31 | The search index is extended to include multimodal data: 32 | - **Fields**: 33 | - `content` & `contentVector`: Original text and its embeddings. 34 | - `imageCaptions` & `captionVector`: Descriptions of associated images and their embeddings. 35 | - `relatedImages`: URLs pointing to images in Blob Storage. 36 | - Each document represents a text segment and its associated images, forming a complete multimodal unit. 37 | 38 | 5. **Query & Retrieval** 39 | When a user submits a query: 40 | - Convert the query to embeddings using Azure OpenAI. 41 | - Perform retrieval, searching both `contentVector` and `captionVector` fields. 42 | - Results include both textual context and references to relevant images. 43 | 44 | 6. **Response Generation (GPT-4o)** 45 | - Build a multimodal prompt that includes retrieved text, image descriptions, and image URLs. 46 | - GPT-4 generates a final enriched response, referencing both textual and visual elements. 47 | 48 | 7. **Document & Image Lifecycle Management** 49 | - Deleting a document from the index triggers an Azure Function to remove associated images from Blob Storage. 50 | - This ensures synchronization between the index and storage. 51 | 52 | ## Architectural Decisions 53 | 54 | - **Multimodal Unified Index**: A single index consolidates both text and image data, simplifying retrieval and management. 55 | - **Single Embedding Model**: Azure OpenAI embeddings are reused for both text and image descriptions, reducing complexity. 56 | - **Combined Image Captions**: Related images are grouped into one descriptive field for easier retrieval. 57 | - **Two Vector Fields**: 58 | - `contentVector`: For text embeddings. 59 | - `captionVector`: For image description embeddings. 60 | 61 | ## Benefits 62 | 63 | - **Multimodal Capabilities**: Supports text-only, image-focused, or hybrid queries seamlessly. 64 | - **Simplified Architecture**: Reuses the same embedding model and index for multimodal data. 65 | - **Enhanced User Experience**: Delivers enriched responses combining textual and visual elements. 66 | - **Scalability**: Leverages Azure-native services (Functions, Storage, AI Search Service, and Azure OpenAI) for robust and scalable performance. 67 | -------------------------------------------------------------------------------- /docs/PERFTEST.md: -------------------------------------------------------------------------------- 1 | # Performance Testing 2 | 3 | When developing Language Model (LLM) applications, a significant amount of time is invested in development and evaluation to ensure high-quality, reliable, and safe user responses. However, the effectiveness of an LLM application's user experience is also determined by the response speed. 4 | 5 | 6 | To learn more about performance testing, please take a look at this blog post [Load Testing RAG based Generative AI Applications](https://techcommunity.microsoft.com/t5/ai-azure-ai-services-blog/load-testing-rag-based-generative-ai-applications/ba-p/4086993) where we describe the concepts, tools, and techniques used ahead. 7 | 8 | **How do I execute the load tests?** 9 | 10 | Enterprise RAG has three components: data ingestion, frontend, and orchestrator. The orchestrator manages conversation flow and interacts with services like the LLM and search service for data retrieval, and works across channels like web and Teams. 11 | 12 | We've developed a load test suite for the **Orchestrator** using Azure Load Testing, executable via a Github Action workflow. For detailed instructions, see [**Load Testing GPT-RAG's orchestrator**](./LOAD_TESTING.md) page. -------------------------------------------------------------------------------- /docs/PYRIT_SECURITY_TESTING.md: -------------------------------------------------------------------------------- 1 | # PyRIT Security Testing 2 | 3 | ### Introduction 4 | The Python Risk Identification Tool for generative AI ([PyRIT](https://github.com/Azure/PyRIT)) is an open-access automation framework developed by the AI Red Team at Microsoft. It is designed to empower security professionals and machine learning engineers to red team foundation models and their applications. PyRIT helps assess the robustness of large language model (LLM) endpoints against various harm categories, such as fabrication, misuse, and prohibited content. 5 | 6 | ### Key Features 7 | - **Automation of Red Teaming Tasks**: PyRIT automates routine red teaming tasks, enabling security professionals to concentrate on more intricate issues. 8 | - **Harm Identification**: It identifies various security and privacy harms, including misuse and prohibited content. 9 | - **Iterative Improvement**: Researchers can use PyRIT to iterate and improve their mitigations against different harms, such as prompt injection attacks. 10 | 11 | ### PyRIT in GPT-RAG 12 | In this repository, PyRIT is used to test the orchestrator's ability to respond to safety scenarios, including jailbreaking attempts. The tool is integrated into the testing framework to ensure that the generative AI system can handle and mitigate potential risks effectively. 13 | 14 | ### Test Descriptions 15 | 16 | ### Benchmark 17 | The objective of this test is to assert that the Retrieval-Augmented Generation (RAG) model can successfully respond to questions it was designed to answer. 18 | 19 | ### Unsafe Questions Test 20 | The objective of this test is to evaluate the behavior of the RAG model when presented with forbidden questions. 21 | 22 | ### Jailbreak Test 23 | The objective of this test is to attempt to break the RAG model's rules and make it respond in ways it was not originally designed to. 24 | 25 | ### Response Injection Test 26 | The objective of this test is to evaluate the defender model's resistance to persuasion attempts by the attacker model. 27 | 28 | ### Personality Change Test 29 | The objective of this test is to evaluate the defender model's ability to maintain appropriate responses when prompted to elicit aggressive responses. 30 | 31 | ### Conclusion 32 | PyRIT is a powerful tool for assessing and improving the security of generative AI systems. For more details on how to run these tests or implement your own, please visit the [GPT-RAG Orchestrator repository](https://github.com/Azure/gpt-rag-orchestrator). -------------------------------------------------------------------------------- /docs/QUERYING_CONVERSATIONS.md: -------------------------------------------------------------------------------- 1 | # Querying Conversations from CosmosDB 2 | 3 | This page provides you with SQL queries to extract specific information about conversations stored in CosmosDB. 4 | 5 | To execute these queries, access your CosmosDB resource through the Azure Portal, then select the 'New SQL Query' option in the Data Explorer, as shown in the following screen: 6 | 7 | ![Querying CosmosDB](../media/querying-conversations.png) 8 | 9 | #### 1) Retrieve Conversation by ID 10 | 11 | To retrieve a specific conversation using its ID, use the following query: 12 | 13 | ``` 14 | SELECT * FROM c WHERE c.id = 'replace_with_the_id' 15 | ``` 16 | 17 | #### 2) Last Conversation 18 | 19 | To retrieve the last conversation, you can use the following query: 20 | 21 | ``` 22 | SELECT TOP 1 * 23 | FROM c 24 | ORDER BY c.conversation_data.start_date DESC 25 | ``` 26 | 27 | #### 3) Number of Conversations in a Specific Period 28 | 29 | To count the number of conversations within a specific date range, use the query below: 30 | 31 | ``` 32 | SELECT COUNT(1) AS total_conversations 33 | FROM c 34 | WHERE 35 | c.conversation_data.start_date >= '2024-05-09 00:00:00' 36 | AND c.conversation_data.start_date <= '2025-12-31 23:59:59' 37 | ``` 38 | 39 | #### 4) Number of ungrounded answers 40 | 41 | To find out how many ungrounded answers where filtered during a specified period, use this query: 42 | 43 | ``` 44 | SELECT COUNT(c) AS ungrounded_answers 45 | FROM c 46 | JOIN i IN c.conversation_data.interactions 47 | WHERE i.gpt_groundedness < 5 48 | AND c.conversation_data.start_date >= '2024-05-09 00:00:00' 49 | AND c.conversation_data.start_date <= '2025-12-31 23:59:59' 50 | ``` 51 | 52 | #### 5) Top Longest Response Times in a Specific Period 53 | 54 | To retrieve the top 10 longest response times within a particular period, you can use the following query: 55 | 56 | ``` 57 | SELECT TOP 10 c.conversation_data.interactions 58 | FROM c 59 | WHERE c.conversation_data.start_date >= '2024-05-09 00:00:00' 60 | AND c.conversation_data.start_date <= '2025-12-31 23:59:59' 61 | ORDER BY c.conversation_data.interactions.response_time DESC 62 | ``` -------------------------------------------------------------------------------- /docs/RAG_CONCEPTS.md: -------------------------------------------------------------------------------- 1 | This section provides information about the Retrieval-Augmented Generation (RAG) pattern. It includes a description of the pattern, reasons for starting with it, and technical references related to RAG. 2 | 3 | ## What is a RAG pattern? 4 | 5 | Retrieval-Augmented Generation (RAG) pattern 6 | 7 | Reference implementation of the Retrieval-Augmented Generation (RAG) pattern. 8 | 9 | ## Why to start with RAG pattern? 10 | 11 | Why RAG? 12 | 13 | ### Technical References 14 | 15 | * [Retrieval Augmented Generation (RAG) Paper](https://arxiv.org/abs/2005.11401) 16 | 17 | * [Retrieval Augmented Generation (RAG) in Azure AI Search](https://learn.microsoft.com/en-us/azure/search/retrieval-augmented-generation-overview) 18 | 19 | * [Build and maintain your company Copilot with Azure ML and GPT-4](https://www.youtube.com/watch?si=B2tjsq4z4R7rksEw&v=2meEvuWAyXs) 20 | 21 | * [Revolutionize your Enterprise Data with ChatGPT: Next-gen Apps w/ Azure OpenAI and AI Search](https://aka.ms/entgptsearchblog) 22 | 23 | * [Introducing Azure OpenAI Service On Your Data in Public Preview](https://techcommunity.microsoft.com/t5/ai-cognitive-services-blog/introducing-azure-openai-service-on-your-data-in-public-preview/ba-p/3847000) 24 | 25 | * [Grounding LLMs](https://techcommunity.microsoft.com/t5/fasttrack-for-azure/grounding-llms/ba-p/3843857#:~:text=What%20is%20Grounding%3F,relevance%20of%20the%20generated%20output.) 26 | 27 | * [Check Your Facts and Try Again: Improving Large Language Models with External Knowledge and Automated Feedback](https://www.microsoft.com/en-us/research/group/deep-learning-group/articles/check-your-facts-and-try-again-improving-large-language-models-with-external-knowledge-and-automated-feedback/) 28 | 29 | * [Microsoft Guidance Validation and Robustness of responses](https://lnkd.in/ggeSQmsV) 30 | 31 | * [RAG vs Finetuning](https://towardsdatascience.com/rag-vs-finetuning-which-is-the-best-tool-to-boost-your-llm-application-94654b1eaba7) 32 | -------------------------------------------------------------------------------- /docs/SECURITY_HUB.md: -------------------------------------------------------------------------------- 1 | # Security Hub Function 2 | 3 | ## Overview 4 | The Security Hub Function integrates with Azure Content Safety and centralizes GPT Responsible AI checks. This function ensures that AI-generated content adheres to safety and ethical standards. 5 | 6 | ## Features 7 | 8 | ### Groundedness Detection 9 | The Groundedness Detection evaluates whether the text responses of large language models (LLMs) are grounded in the source materials provided by users. Ungroundedness refers to instances where LLMs produce information that is non-factual or inaccurate compared to the source materials. 10 | 11 | ### Prompt Shields 12 | Generative AI models can be exploited by malicious actors. To mitigate these risks, safety mechanisms are integrated to restrict the behavior of LLMs within a safe operational scope. Despite these safeguards, LLMs can still be vulnerable to adversarial inputs that bypass the integrated safety protocols. Prompt Shields analyzes LLM inputs and detects User Prompt Attacks 13 | 14 | ### Protected Material Detection 15 | The Protected Material Text check flags known text content (e.g., song lyrics, articles, recipes, and selected web content) that might be output by large language models. 16 | 17 | ### Harm Categories 18 | Content Safety recognizes four distinct categories of objectionable content: 19 | 20 | #### Hate and Fairness 21 | Hate and fairness-related harms refer to any content that attacks or uses pejorative or discriminatory language with reference to a person or identity group based on certain differentiating attributes, including but not limited to race, ethnicity, nationality, gender identity and expression, sexual orientation, religion, immigration status, ability status, personal appearance, and body size. 22 | 23 | Fairness is concerned with ensuring that AI systems treat all groups of people equitably without contributing to existing societal inequities. Similar to hate speech, fairness-related harms hinge upon disparate treatment of identity groups. 24 | 25 | #### Sexual 26 | Sexual content describes language related to anatomical organs and genitals, romantic relationships, acts portrayed in erotic or affectionate terms, pregnancy, physical sexual acts (including those portrayed as assault or forced sexual violent acts against one's will), prostitution, pornography, and abuse. 27 | 28 | #### Violence 29 | Violence describes language related to physical actions intended to hurt, injure, damage, or kill someone or something. It also includes descriptions of weapons, guns, and related entities, such as manufacturers, associations, and legislation. 30 | 31 | #### Self-Harm 32 | Self-harm describes language related to physical actions intended to purposely hurt, injure, or damage one's body or kill oneself. 33 | 34 | ### Block lists 35 | Create lists of words that should never be used and filter queries and answers that include them. 36 | 37 | ### Responsible AI 38 | Conduct comprehensive evaluations to ensure that the AI system adheres to responsible AI principles. These principles are designed to guide the development and deployment of AI technologies in a manner that is ethical, transparent, and fair. 39 | 40 | #### Fairness 41 | This check is dedicated to ensuring that the AI system treats all groups of people equitably. It aims to prevent the AI from contributing to or exacerbating existing societal inequities. The fairness check evaluates the AI's decision-making processes to ensure that they do not favor or discriminate against any particular group based on attributes such as race, gender, age, or socioeconomic status. 42 | 43 | ### Auditing 44 | This feature provides an endpoint that logs all interactions with the orchestrator. The purpose of this auditing capability is to maintain a detailed record of all activities and decisions made by the AI system. These logs are crucial for transparency and accountability, allowing for thorough reviews and analyses of the AI's behavior and ensuring compliance with ethical standards and regulatory requirements. 45 | 46 | ## Security hub implementation 47 | - Deploy the [security hub function](https://github.com/Azure/gpt-rag-securityhub) 48 | - Create a content safety resource 49 | - Give the security hub function the roles of Cognitive Services Users and Reader in the content safety resource. 50 | - Add eviroment variables to security hub: 51 | "CONTENT_SAFETY_ENDPOINT": "https://{your-content-safety-resource}.cognitiveservices.azure.com/", 52 | - Add enviroment variables to orchestrator: 53 | "SECURITY_HUB_ENDPOINT": "https://{your-securityHub-function-url}/api", 54 | "SECURITY_HUB_CHECK": "true", 55 | 56 | - OPTIONAL: 57 | - To customize threshholds of harm and groundedness checks, add these env variables to orchestrator with your prefered values: 58 | "SECURITY_HUB_HATE_THRESHHOLD": "0", 59 | "SECURITY_HUB_SELFHARM_THRESHHOLD": "0", 60 | "SECURITY_HUB_SEXUAL_THRESHHOLD": ""0, 61 | "SECURITY_HUB_VIOLENCE_THRESHHOLD": "0", 62 | "SECURITY_HUB_UNGROUNDED_PERCENTAGE_THRESHHOLD":"0.0 63 | 64 | Harm categories must be an int value beetween 0 and 4 65 | Ungroundedness percentage must be a float value beetween 0 and 1 66 | 67 | - If responsible AI checks are to be conducted, the following environment variables must be set with correct values, and the Cognitive Services OpenAI User role is needed in the AOAI service: 68 | "RESPONSIBLE_AI_CHECK": "True", 69 | "AZURE_OPENAI_RESOURCE": "", 70 | "AZURE_OPENAI_CHATGPT_DEPLOYMENT": "", 71 | "AZURE_OPENAI_CHATGPT_MODEL": "" 72 | 73 | - If the content safety service is consumed via APIM, you need to have a Key Vault with a secret that contains the APIM key named "apimSubscriptionKey" and set these environment variables: 74 | "APIM_ENABLED": "true", 75 | "AZURE_KEY_VAULT_NAME": "", 76 | "APIM_ENDPOINT": "" 77 | 78 | Additionally, roles are needed to read the secret from the Key Vault. 79 | 80 | - You can also add this optional variables if you want to add your blocklists(you should first [create and fill the blocklist](https://learn.microsoft.com/en-us/azure/ai-services/content-safety/how-to/use-blocklist?tabs=windows%2Crest#create-or-modify-a-blocklist)): 81 | "BLOCK_LIST_CHECK": "true", 82 | "BLOCK_LISTS_NAMES": [names] -------------------------------------------------------------------------------- /docs/TEAMS_INTEGRATION_MAIN.md: -------------------------------------------------------------------------------- 1 | # Guide for Building a Teams App Interface for the Enterprise GPT-RAG Solution Accelerator 2 | 3 | ## Introduction 4 | This is a guide for building a Teams App Interface for the Enterprise GPT-RAG Solution Accelerator using Teams toolkit. 5 | 6 | ## Key Solution Components 7 | The following Azure resources will be deployed in addition to those already deployed in the Enterprise RAG Solution Accelerator. 8 | - Azure Bot Framework service 9 | - Azure App Service Plan & Azure App Service 10 | - Managed Identity 11 | 12 | ## Prerequisites 13 | Before proceeding with the steps in the subsequent sections, ensure you have completed the following: 14 | - An Azure subscription to deploy the required resources. 15 | - A Microsoft 365 account. Read more on developer program that can be used for testing purposes. [here](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/tools-prerequisites#microsoft-365-developer-program). 16 | - The Enterprise GPT-RAG Solution Accelerator deployed in your Azure subscription. 17 | - For publishing, access to a Teams admin who can approve the app deployment within your organization. Alternatively, you can test locally on your development machine and/or use [custom upload](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/apps-upload) option if enabled for your organization. 18 | - Note: When deploying Azure resources for the Teams app, such as the App Service Plan and App Service, you can utilize the resources already provisioned in the GPT-RAG Solution Accelerator. 19 | - Note: The App Service uses a public endpoint for the Teams App to connect to the service. 20 | 21 | Set up the following prerequisites on the machine to be used for development: 22 | - Download and install [Visual Studio Code](https://code.visualstudio.com/Download). 23 | - Install [NodeJS](https://nodejs.org/) version 16 or later. 24 | 25 | ## Step 1: [Create a new Teams App](TEAMS_INTEGRATION_STEP1.md). 26 | 27 | ## Step 2: [Connect to GPT-RAG Orchestrator and test locally](TEAMS_INTEGRATION_STEP2.md). 28 | 29 | ## Step 3: [Provision and Deploy the Azure resources for the Teams App](TEAMS_INTEGRATION_STEP3.md). 30 | 31 | ## Step 4: [Build the Teams App](TEAMS_INTEGRATION_STEP4.md). 32 | 33 | ## Step 5: [Publish the Teams App](TEAMS_INTEGRATION_STEP5.md). 34 | 35 | ## External Resources 36 | - [Microsoft Teams Toolkit Overview](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/teams-toolkit-fundamentals). 37 | - [Visual Studio Code](https://code.visualstudio.com/Download). 38 | - [Install Teams Toolkit](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/install-teams-toolkit?tabs=vscode). 39 | - [Microsoft 365 developer program](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/tools-prerequisites#microsoft-365-developer-program). 40 | 41 | -------------------------------------------------------------------------------- /docs/TEAMS_INTEGRATION_STEP1.md: -------------------------------------------------------------------------------- 1 | # Guide for Building a Teams App Interface for Enterprise GPT-RAG Solution Accelerator 2 | 3 | *Ensure all prerequisites mentioned [here](TEAMS_INTEGRATION_MAIN.md) are completed before proceeding with the steps below.* 4 | 5 | ## Step 1: Create a new Teams App. 6 | 7 | 1. Open **Visual Studio Code**. 8 | 9 | 2. Select the **Teams Toolkit** > **Create a New App**. 10 | 11 | ![Teams Toolkit, Create New App](../media/teams-guide-Step1a.png) 12 | 13 | 2. Select **Bot** as app capability. 14 | 15 | ![Bot](../media/teams-guide-Step1b.png) 16 | 17 | 3. Select **Basic Bot** as app capability. 18 | 19 | ![Basic Bot](../media/teams-guide-Step1c.png) 20 | 21 | 4. Choose a programming language. For this guide, we will use **TypeScript**. 22 | 23 | ![Typescript](../media/teams-guide-Step1d.png) 24 | 25 | 5. Select **Browse** and select the location for project workspace. 26 | 27 | 6. Enter a suitable name for your app, such as *GPTRAGTeams*, as the application name. Ensure that you use only alphanumeric characters. Press **Enter**. 28 | 29 | ![Application Name](../media/teams-guide-Step1e.png) 30 | 31 | Proceed to Step 2: [Connect to GPT-RAG Orchestrator and test locally](TEAMS_INTEGRATION_STEP2.md). 32 | 33 | ## Additional Resources 34 | - [Prerequisites - Guide for Building a Teams App Interface for the Enterprise GPT-RAG Solution Accelerator](TEAMS_INTEGRATION_MAIN.md#prerequisites). 35 | - [Step 2: Connect to GPT-RAG Orchestrator and test locally](TEAMS_INTEGRATION_STEP2.md). 36 | 37 | ## External Resources 38 | - [Install Teams Toolkit](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/install-teams-toolkit?tabs=vscode). 39 | - [Prepare to build apps using Teams Toolkit](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/build-environments). 40 | - [Prerequisites for creating your Teams app](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/tools-prerequisites). 41 | - [Directory structure for different app types](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/create-new-project#directory-structure-for-different-app-types). 42 | -------------------------------------------------------------------------------- /docs/TEAMS_INTEGRATION_STEP2.md: -------------------------------------------------------------------------------- 1 | # Guide for Building a Teams App Interface for Enterprise GPT-RAG Solution Accelerator 2 | 3 | *Ensure all steps mentioned in [Step 1](TEAMS_INTEGRATION_STEP1.md) are completed before proceeding with the steps below.* 4 | 5 | ## Step 2: Connect to GPT-RAG Orchestrator and test locally 6 | 7 | 1. Navigate to the `teamsBot.ts` file. Modify the code to pass the message to the Orchestrator and obtain a response. Below is a sample code snippet to guide you: 8 | 9 | ```typescript 10 | //await context.sendActivity(`Echo: ${txt}`); 11 | 12 | // Obtain the orchestrator endpoint securely from Azure KeyVault 13 | const orchestratorEndpoint = //Obtained from Azure KeyVault; 14 | 15 | // Retrieve the unique conversation ID from the activity context 16 | const conversation_id = context.activity.conversation.id; 17 | 18 | // Construct the request body to send to the orchestrator 19 | const requestBody = { 20 | "question": txt, // The user's input text, which will be sent as the 'question' 21 | "conversation_id": conversation_id 22 | }; 23 | 24 | try { 25 | // Make a POST request to the orchestrator endpoint 26 | const response = await fetch(orchestratorEndpoint, { 27 | method: 'POST', // HTTP method to send the request 28 | headers: { 29 | 'Content-Type': 'application/json' // Specifies that the body of the request is in JSON format 30 | }, 31 | body: JSON.stringify(requestBody) // Convert the request body into a JSON string 32 | }); 33 | 34 | // Check if the response was successful 35 | if (!response.ok) { 36 | throw new Error(`HTTP error! status: ${response.status}`); 37 | } 38 | 39 | // Parse the JSON response from the orchestrator 40 | const data = await response.json(); 41 | // Send the answer from the orchestrator back to the user 42 | await context.sendActivity(`${data.answer}`); 43 | 44 | } catch (error) { 45 | //Error posting question to Azure Function, handle gracefully. 46 | } 47 | ``` 48 | 2. Select **Run** and then **Start Debugging**. Test the bot by asking questions relevant to the files uploaded to the GPT-RAG Solution Accelerator. 49 | 50 | ![Debug Teams Chat Locally](../media/teams-guide-Step2b.png) 51 | 52 | Proceed to Step 3: [Provision and Deploy the Azure resources for the Teams App](TEAMS_INTEGRATION_STEP3.md). 53 | 54 | ## Additional Resources 55 | - [Step 1: Create a new Teams App](TEAMS_INTEGRATION_STEP1.md). 56 | - [Step 3: Provision and Deploy the Azure resources for the Teams App](TEAMS_INTEGRATION_STEP3.md). 57 | 58 | ## External Resources 59 | - [Teams App Test Tool](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/debug-your-teams-app-test-tool?tabs=vscode%2Cclijs). 60 | -------------------------------------------------------------------------------- /docs/TEAMS_INTEGRATION_STEP3.md: -------------------------------------------------------------------------------- 1 | # Guide for Building a Teams App Interface for Enterprise GPT-RAG Solution Accelerator 2 | 3 | *Ensure all steps mentioned in [Step 2](TEAMS_INTEGRATION_STEP2.md) are completed before proceeding with the steps below.* 4 | 5 | - Note: When deploying Azure resources for the Teams app, such as the App Service Plan and App Service, you can utilize the resources already provisioned in the GPT-RAG Solution Accelerator. 6 | 7 | ## Step 3: Provision and Deploy the Azure resources for the Teams App 8 | 1. Select the **Teams Toolkit** icon in the sidebar. Select **Sign in to Microsoft 365**. 9 | 10 | ![Microsoft 365 Signin](../media/teams-guide-Step3a.png) 11 | 12 | 2. Your default web browser opens to let you sign in to the account. Sign in with Microsoft 365 account. Close the browser when prompted and return to Visual Studio Code. 13 | 14 | ![VS Code Signin](../media/teams-guide-Step3b.png) 15 | 16 | 3. Select the **Teams Toolkit** icon in the sidebar. Select **Sign in to Azure**. 17 | 18 | ![Azure Signin](../media/teams-guide-Step3c.png) 19 | 20 | 4. Your default web browser opens to let you sign in to the account. Sign in to your Azure account. Close the browser when prompted and return to Visual Studio Code. 21 | 22 | 5. Select Provision from the LIFECYCLE section in the left pane. 23 | 24 | ![Lifecycle Provision](../media/teams-guide-Step3d.png) 25 | 26 | 6. Select the Azure subscription. 27 | 28 | ![Azure Subscription Selection](../media/teams-guide-Step3e.png) 29 | 30 | 7. Select an existing resource group or create a new resource group. Press **Enter**. 31 | 32 | ![Resource group selection](../media/teams-guide-Step3f.png) 33 | 34 | ![Resource group creation](../media/teams-guide-Step3g.png) 35 | 36 | 8. Select the Azure location. 37 | 38 | 9. Review the message and select **Provision**. 39 | 40 | ![Provision button](../media/teams-guide-Step3h.png) 41 | 42 | 10. Wait for the provisioning process to complete. 43 | 44 | ![Provisioning status](../media/teams-guide-Step3i.png) 45 | 46 | ![Provision complete](../media/teams-guide-Step3j.png) 47 | 48 | 11. You can review the deployed Azure resources on the Azure portal. 49 | 50 | ![Azure resources on portal](../media/teams-guide-Step3k.png) 51 | 52 | 12. Select Deploy from the LIFECYCLE section in the left pane. 53 | 54 | ![Teams Deploy](../media/teams-guide-Step3l.png) 55 | 56 | 13. Select Deploy. 57 | 58 | ![Deploy button](../media/teams-guide-Step3m.png) 59 | 60 | 13. Wait for the deployment to complete. 61 | 62 | ![Deployment status](../media/teams-guide-Step3n.png) 63 | 64 | Proceed to Step 4: [Build the Teams App](TEAMS_INTEGRATION_STEP4.md). 65 | 66 | 67 | ## Additional Resources 68 | - [Step 2: Connect to GPT-RAG Orchestrator and test locally](TEAMS_INTEGRATION_STEP2.md). 69 | - [Step 4: Build the Teams App](TEAMS_INTEGRATION_STEP4.md). 70 | 71 | ## External Resources 72 | - [Provision cloud resources](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/provision). 73 | - [Deploy Microsoft Teams app to the cloud](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/deploy). 74 | -------------------------------------------------------------------------------- /docs/TEAMS_INTEGRATION_STEP4.md: -------------------------------------------------------------------------------- 1 | # Guide for Building a Teams App Interface for Enterprise GPT-RAG Solution Accelerator 2 | 3 | *Ensure all steps mentioned in [Step 3](TEAMS_INTEGRATION_STEP3.md) are completed before proceeding with the steps below.* 4 | 5 | ## Step 4: Build the Teams App 6 | 7 | 1. Select the **Teams Toolkit** icon in the sidebar. Select **Utility** and then, **Zip Teams App Package**. 8 | 9 | ![Zip Teams App Package](../media/teams-guide-Step4a.png) 10 | 11 | 2. Select the Teams Manifest JSON file. 12 | 13 | ![Manifest file selection](../media/teams-guide-Step4b.png) 14 | 15 | 3. Choose the environment. The Teams Toolkit supports running and testing your app in different deployment targets such as development, staging, production, or locally. It utilizes environment files to handle configurations and automate resource provisioning for various environments. Learn more about environments [here](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/teamsfx-multi-env). 16 | 17 | ![Teams Toolkit environment selection](../media/teams-guide-Step4c.png) 18 | 19 | 4. Wait for the build to complete. Once finished, navigate to the folder. You can click on the **local address** link to go directly to the folder. 20 | 21 | ![Local Address link](../media/teams-guide-Step4d.png) 22 | 23 | 5. Review the files generated in the folder. These files will be used for deployment in the subsequent section. 24 | 25 | ![Teams App Files](../media/teams-guide-Step4e.png) 26 | 27 | Proceed to Step 5: [Publish the Teams App](TEAMS_INTEGRATION_STEP5.md). 28 | 29 | ## Additional Resources 30 | - [Step 3: Provision and Deploy the Azure resources for the Teams App](TEAMS_INTEGRATION_STEP3.md). 31 | - [Step 5: Publish the Teams App](TEAMS_INTEGRATION_STEP5.md). 32 | 33 | ## External Resources 34 | - [Teams app package](https://learn.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/apps-package). 35 | - [Environments in Microsoft Teams Toolkit](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/teamsfx-multi-env). 36 | -------------------------------------------------------------------------------- /docs/TEAMS_INTEGRATION_STEP5.md: -------------------------------------------------------------------------------- 1 | # Guide for Building a Teams App Interface for Enterprise GPT-RAG Solution Accelerator 2 | 3 | *Ensure all steps mentioned in Step 4: [Build the Teams App](TEAMS_INTEGRATION_STEP4.md) are completed before proceeding with the steps below.* 4 | 5 | ## Step 5: Publish the Teams App 6 | 7 | You can follow the below steps to publish the Teams app at an individual level for testing purposes using the custom upload option: 8 | 9 | 1. In the Teams client or Teams web version, select **Apps** > **Manage your apps** > **Upload an app**. 10 | 11 | ![Upload Teams App](../media/teams-guide-Step5a.png) 12 | 13 | 2. The Upload an app window appears. Select Upload a custom app. 14 | 15 | ![Upload a custom app](../media/teams-guide-Step5b.png) 16 | 17 | 3. Select the zip file generated in the previous section. 18 | 19 | ![Select Zip File](../media/teams-guide-Step5c.png) 20 | 21 | 4. Select the **Add** button. 22 | 23 | ![Add button](../media/teams-guide-Step5d.png) 24 | 25 | 5. Wait for the app to be added successfully. 26 | 27 | ![App Added Success](../media/teams-guide-Step5f.png) 28 | 29 | 6. Test the app by asking a question. 30 | 31 | ![Test prompt](../media/teams-guide-Step5g.png) 32 | 33 | ![Chat Response](../media/teams-guide-Step5h.png) 34 | 35 | To publish the Teams App to the developer portal, follow the steps outlined [here](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/publish-your-teams-apps-using-developer-portal). 36 | 37 | 38 | ## Additional Resources 39 | - [Step 4: Build the Teams App](TEAMS_INTEGRATION_STEP4.md). 40 | 41 | ## External Resources 42 | - [Publish Teams apps using Teams Toolkit](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/publish#upload-app-package). 43 | - [Integrate with Developer Portal](https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/publish-your-teams-apps-using-developer-portal). -------------------------------------------------------------------------------- /docs/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Purpose 2 | 3 | 4 | 5 | ## Type of change 6 | 7 | ``` 8 | [ ] Bugfix 9 | [ ] Feature 10 | [ ] Code style update (formatting, local variables) 11 | [ ] Refactoring (no functional changes, no api changes) 12 | [ ] Documentation content changes 13 | [ ] Other... Please describe: 14 | ``` 15 | 16 | ## Related Backlog Item or Issue 17 | 18 | If applicable, provide a link to the relevant backlog item or issue. 19 | 20 | 21 | 22 | ## Is this change disruptive or does it break existing applications? 23 | 24 | If deploying this change could impact existing applications, please specify. 25 | 26 | ``` 27 | [ ] Yes 28 | [ ] No 29 | ``` 30 | 31 | ## Cross-Repository Dependencies 32 | 33 | If this change depends on pull requests in other repositories within the solution, provide the links below. 34 | 35 | - [ ] [gpt-rag-orchestrator](https://github.com/azure/gpt-rag-orchestrator) 36 | - [ ] [gpt-rag-agentic](https://github.com/azure/gpt-rag-agentic) 37 | - [ ] [gpt-rag-ingestion](https://github.com/azure/gpt-rag-ingestion) 38 | - [ ] [gpt-rag-frontend](https://github.com/azure/gpt-rag-frontend) 39 | 40 | ## Does this require changes to project documentation? 41 | 42 | If the changes add new functionality, update the documentation accordingly. 43 | 44 | ``` 45 | [ ] Yes 46 | [ ] No 47 | ``` 48 | 49 | ## Documentation Link 50 | 51 | If this change adds a new functionality, provide a link to its documentation. 52 | 53 | 54 | 55 | ## Code quality checklist 56 | 57 | - [ ] I verified the changes locally to ensure they work as expected 58 | - [ ] I have tested the new functionality and ensured existing features still work 59 | - [ ] I have updated the CHANGELOG.md file to document these changes 60 | - [ ] I have reviewed the code for readability, maintainability, and adherence to project conventions 61 | - [ ] I have added at least two reviewers to the Pull Request 62 | 63 | ## Contributing guidelines 64 | 65 | See [CONTRIBUTING.md](../CONTRIBUTING.md) for more details. 66 | -------------------------------------------------------------------------------- /infra/core/ai/aiservices.bicep: -------------------------------------------------------------------------------- 1 | param name string 2 | param location string = resourceGroup().location 3 | param tags object = {} 4 | param aiServicesReuse bool 5 | param existingAiServicesResourceGroupName string 6 | 7 | param aiServicesDeploy bool = true 8 | 9 | param secretsNames object = {} 10 | param keyVaultName string 11 | 12 | param customSubDomainName string = name 13 | param deployments array = [] 14 | param kind string = 'OpenAI' 15 | param publicNetworkAccess string = 'Enabled' 16 | param sku object = { 17 | name: 'S0' 18 | } 19 | 20 | resource existingAccount 'Microsoft.CognitiveServices/accounts@2024-10-01' existing = if (aiServicesReuse && aiServicesDeploy) { 21 | scope: resourceGroup(existingAiServicesResourceGroupName) 22 | name: name 23 | } 24 | 25 | resource newAccount 'Microsoft.CognitiveServices/accounts@2024-10-01' = if (!aiServicesReuse && aiServicesDeploy) { 26 | name: name 27 | location: location 28 | tags: tags 29 | kind: kind 30 | properties: { 31 | customSubDomainName: customSubDomainName 32 | publicNetworkAccess: publicNetworkAccess 33 | } 34 | sku: sku 35 | } 36 | 37 | @batchSize(1) 38 | resource deployment 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01' = [for deployment in deployments: if (!aiServicesReuse && aiServicesDeploy) { 39 | parent: newAccount 40 | name: deployment.name 41 | properties: { 42 | model: deployment.model 43 | raiPolicyName: contains(deployment, 'raiPolicyName') ? deployment.raiPolicyName : null 44 | } 45 | sku: contains(deployment, 'sku') ? deployment.sku : { 46 | name: 'Standard' 47 | capacity: 40 48 | } 49 | }] 50 | 51 | resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { 52 | name: keyVaultName 53 | } 54 | 55 | resource keyVaultSecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = [for secretName in items(secretsNames): { 56 | name: secretName.value 57 | tags: tags 58 | parent: keyVault 59 | properties: { 60 | attributes: { 61 | enabled: true 62 | exp: 0 63 | nbf: 0 64 | } 65 | contentType: 'string' 66 | value: aiServicesReuse ? existingAccount.listKeys().key1 : newAccount.listKeys().key1 67 | } 68 | }] 69 | 70 | output name string = !aiServicesDeploy ? '' : aiServicesReuse? existingAccount.name : newAccount.name 71 | output id string = !aiServicesDeploy ? '' : aiServicesReuse? existingAccount.id : newAccount.id 72 | output endpoint string = !aiServicesDeploy ? '' : aiServicesReuse? existingAccount.properties.endpoint : newAccount.properties.endpoint 73 | -------------------------------------------------------------------------------- /infra/core/db/cosmos.bicep: -------------------------------------------------------------------------------- 1 | @description('Cosmos DB account name, max length 44 characters, lowercase') 2 | param accountName string 3 | 4 | @description('Enable/disable public network access for the Cosmos DB account.') 5 | param publicNetworkAccess string = 'Disabled' 6 | 7 | @description('Location for the Cosmos DB account.') 8 | param location string = resourceGroup().location 9 | 10 | param cosmosDbReuse bool 11 | param existingCosmosDbResourceGroupName string 12 | param existingCosmosDbAccountName string 13 | 14 | param deployCosmosDb bool = true 15 | 16 | 17 | param conversationContainerName string 18 | param datasourcesContainerName string 19 | 20 | param tags object = {} 21 | 22 | @description('The default consistency level of the Cosmos DB account.') 23 | @allowed([ 24 | 'Eventual' 25 | 'ConsistentPrefix' 26 | 'Session' 27 | 'BoundedStaleness' 28 | 'Strong' 29 | ]) 30 | param defaultConsistencyLevel string = 'Session' 31 | 32 | @description('Max stale requests. Required for BoundedStaleness. Valid ranges, Single Region: 10 to 2147483647. Multi Region: 100000 to 2147483647.') 33 | @minValue(10) 34 | @maxValue(2147483647) 35 | param maxStalenessPrefix int = 100000 36 | 37 | @description('Max lag time (minutes). Required for BoundedStaleness. Valid ranges, Single Region: 5 to 84600. Multi Region: 300 to 86400.') 38 | @minValue(5) 39 | @maxValue(86400) 40 | param maxIntervalInSeconds int = 300 41 | 42 | @description('Enable system managed failover for regions') 43 | param systemManagedFailover bool = true 44 | 45 | @description('The name for the database') 46 | param databaseName string 47 | 48 | @description('Maximum autoscale throughput for the container') 49 | @minValue(1000) 50 | @maxValue(1000000) 51 | param autoscaleMaxThroughput int = 1000 52 | 53 | @description('Time to Live for data in analytical store. (-1 no expiry)') 54 | @minValue(-1) 55 | @maxValue(2147483647) 56 | param analyticalStoreTTL int = -1 57 | 58 | param secretName string = 'azureDBkey' 59 | 60 | param keyVaultName string 61 | 62 | var consistencyPolicy = { 63 | Eventual: { 64 | defaultConsistencyLevel: 'Eventual' 65 | } 66 | ConsistentPrefix: { 67 | defaultConsistencyLevel: 'ConsistentPrefix' 68 | } 69 | Session: { 70 | defaultConsistencyLevel: 'Session' 71 | } 72 | BoundedStaleness: { 73 | defaultConsistencyLevel: 'BoundedStaleness' 74 | maxStalenessPrefix: maxStalenessPrefix 75 | maxIntervalInSeconds: maxIntervalInSeconds 76 | } 77 | Strong: { 78 | defaultConsistencyLevel: 'Strong' 79 | } 80 | } 81 | var locations = [ 82 | { 83 | locationName: location 84 | failoverPriority: 0 85 | isZoneRedundant: false 86 | } 87 | ] 88 | 89 | resource existingAccount 'Microsoft.DocumentDB/databaseAccounts@2022-05-15' existing = if (cosmosDbReuse && deployCosmosDb) { 90 | scope: resourceGroup(existingCosmosDbResourceGroupName) 91 | name: existingCosmosDbAccountName 92 | } 93 | 94 | resource newAccount 'Microsoft.DocumentDB/databaseAccounts@2022-05-15' = if (!cosmosDbReuse && deployCosmosDb) { 95 | name: toLower(accountName) 96 | kind: 'GlobalDocumentDB' 97 | location: location 98 | tags: tags 99 | properties: { 100 | consistencyPolicy: consistencyPolicy[defaultConsistencyLevel] 101 | locations: locations 102 | databaseAccountOfferType: 'Standard' 103 | enableAutomaticFailover: systemManagedFailover 104 | publicNetworkAccess: publicNetworkAccess 105 | enableAnalyticalStorage: true 106 | } 107 | } 108 | 109 | resource database 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2022-05-15' = if (!cosmosDbReuse && deployCosmosDb) { 110 | parent: newAccount 111 | name: databaseName 112 | properties: { 113 | resource: { 114 | id: databaseName 115 | } 116 | } 117 | } 118 | 119 | resource conversationsContainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2022-05-15' = if (!cosmosDbReuse && deployCosmosDb) { 120 | parent: database 121 | name: conversationContainerName 122 | properties: { 123 | resource: { 124 | id: conversationContainerName 125 | partitionKey: { 126 | paths: [ 127 | '/id' 128 | ] 129 | kind: 'Hash' 130 | } 131 | analyticalStorageTtl: analyticalStoreTTL 132 | indexingPolicy: { 133 | indexingMode: 'consistent' 134 | includedPaths: [ 135 | { 136 | path: '/*' 137 | } 138 | ] 139 | } 140 | defaultTtl: 86400 141 | } 142 | options: { 143 | autoscaleSettings: { 144 | maxThroughput: autoscaleMaxThroughput 145 | } 146 | } 147 | } 148 | } 149 | 150 | resource modelsContainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2022-05-15' = if (!cosmosDbReuse && deployCosmosDb) { 151 | parent: database 152 | name: datasourcesContainerName 153 | properties: { 154 | resource: { 155 | id: datasourcesContainerName 156 | partitionKey: { 157 | paths: [ 158 | '/id' 159 | ] 160 | kind: 'Hash' 161 | } 162 | analyticalStorageTtl: analyticalStoreTTL 163 | indexingPolicy: { 164 | indexingMode: 'none' 165 | automatic: false 166 | } 167 | } 168 | options: { 169 | autoscaleSettings: { 170 | maxThroughput: autoscaleMaxThroughput 171 | } 172 | } 173 | } 174 | } 175 | 176 | resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { 177 | name: keyVaultName 178 | } 179 | 180 | resource keyVaultSecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = { 181 | name: secretName 182 | tags: tags 183 | parent: keyVault 184 | properties: { 185 | attributes: { 186 | enabled: true 187 | exp: 0 188 | nbf: 0 189 | } 190 | contentType: 'string' 191 | value: !deployCosmosDb ? '' : cosmosDbReuse ? existingAccount.listKeys().primaryMasterKey : newAccount.listKeys().primaryMasterKey 192 | } 193 | } 194 | 195 | 196 | output id string = !deployCosmosDb ? '' : cosmosDbReuse ? existingAccount.id : newAccount.id 197 | output name string = !deployCosmosDb ? '' : cosmosDbReuse ? existingAccount.name : newAccount.name 198 | -------------------------------------------------------------------------------- /infra/core/host/appinsights.bicep: -------------------------------------------------------------------------------- 1 | param applicationInsightsName string 2 | param appInsightsLocation string 3 | param appInsightsReuse bool 4 | param existingAppInsightsResourceGroupName string 5 | param logAnalyticsWorkspaceResourceId string = '' 6 | 7 | // Only deploy a new Log Analytics workspace when: 8 | // - We are creating a new Application Insights resource (i.e. not reusing an existing one) 9 | // - No workspace resource ID was provided 10 | 11 | resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' = if ( !appInsightsReuse && empty(logAnalyticsWorkspaceResourceId) ) { 12 | name: '${applicationInsightsName}-law' 13 | location: appInsightsLocation 14 | properties: { 15 | sku: { 16 | name: 'pergb2018' 17 | } 18 | retentionInDays: 30 19 | } 20 | } 21 | 22 | // If reusing an existing App Insights resource, reference it (assumed to already be workspace‐based) 23 | resource existingApplicationInsights 'Microsoft.Insights/components@2020-02-02' existing = if (appInsightsReuse) { 24 | scope: resourceGroup(existingAppInsightsResourceGroupName) 25 | name: applicationInsightsName 26 | } 27 | 28 | // Create a new Application Insights resource in workspace‐based mode. 29 | // we set WorkspaceResourceId to empty. Otherwise, the value comes either from the parameter 30 | // (if one was provided) or from the newly deployed Log Analytics workspace. 31 | resource newApplicationInsights 'Microsoft.Insights/components@2020-02-02' = if (!appInsightsReuse) { 32 | name: applicationInsightsName 33 | location: appInsightsLocation 34 | kind: 'web' 35 | properties: { 36 | Application_Type: 'web' 37 | Request_Source: 'rest' 38 | WorkspaceResourceId: empty(logAnalyticsWorkspaceResourceId) ? logAnalyticsWorkspace.id : logAnalyticsWorkspaceResourceId 39 | } 40 | } 41 | 42 | output id string = appInsightsReuse ? existingApplicationInsights.id : newApplicationInsights.id 43 | output name string = appInsightsReuse ? existingApplicationInsights.name : newApplicationInsights.name 44 | output instrumentationKey string = appInsightsReuse ? existingApplicationInsights.properties.InstrumentationKey : newApplicationInsights.properties.InstrumentationKey 45 | output connectionString string = appInsightsReuse ? existingApplicationInsights.properties.ConnectionString : newApplicationInsights.properties.ConnectionString 46 | -------------------------------------------------------------------------------- /infra/core/host/appservice.bicep: -------------------------------------------------------------------------------- 1 | param name string 2 | param location string = resourceGroup().location 3 | param tags object = {} 4 | 5 | // Reference Properties 6 | param applicationInsightsName string = '' 7 | param applicationInsightsResourceGroupName string = '' 8 | param appServicePlanId string 9 | 10 | // KeyVault Properties 11 | param keyVaultName string 12 | param flaskSecretName string = 'flaskSecretKey' 13 | 14 | // Runtime Properties 15 | @allowed([ 16 | 'dotnet', 'dotnetcore', 'dotnet-isolated', 'node', 'python', 'java', 'powershell', 'custom' 17 | ]) 18 | param runtimeName string 19 | param runtimeNameAndVersion string = '${runtimeName}|${runtimeVersion}' 20 | param runtimeVersion string 21 | 22 | // Microsoft.Web/sites Properties 23 | param kind string = 'app,linux' 24 | 25 | // Microsoft.Web/sites/config 26 | param allowedOrigins array = [] 27 | param alwaysOn bool = true 28 | param appCommandLine string = '' 29 | param appSettings array = [] 30 | param clientAffinityEnabled bool = false 31 | param enableOryxBuild bool = contains(kind, 'linux') 32 | param functionAppScaleLimit int = -1 33 | param linuxFxVersion string = runtimeNameAndVersion 34 | param minimumElasticInstanceCount int = -1 35 | param numberOfWorkers int = -1 36 | param scmDoBuildDuringDeployment bool = false 37 | param use32BitWorkerProcess bool = false 38 | param ftpsState string = 'FtpsOnly' 39 | param healthCheckPath string = '' 40 | param basicPublishingCredentials bool = false 41 | param networkIsolation bool 42 | param vnetName string = '' 43 | param subnetId string = '' 44 | 45 | param appServiceReuse bool 46 | param deployAppService bool = true 47 | 48 | param existingAppServiceResourceGroupName string 49 | 50 | resource existingAppService 'Microsoft.Web/sites@2022-09-01' existing = if (appServiceReuse && deployAppService) { 51 | scope: resourceGroup(existingAppServiceResourceGroupName) 52 | name: name 53 | } 54 | 55 | resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = if (!empty(applicationInsightsName)) { 56 | scope: resourceGroup(applicationInsightsResourceGroupName) 57 | name: applicationInsightsName 58 | } 59 | 60 | 61 | resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { 62 | name: keyVaultName 63 | } 64 | 65 | var flaskSecretValue = uniqueString(resourceGroup().id, flaskSecretName, 'salt') 66 | 67 | resource keyVaultSecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = { 68 | name: flaskSecretName 69 | tags: tags 70 | parent: keyVault 71 | properties: { 72 | attributes: { 73 | enabled: true 74 | exp: 0 75 | nbf: 0 76 | } 77 | contentType: 'string' 78 | value: flaskSecretValue 79 | } 80 | } 81 | 82 | resource newAppService 'Microsoft.Web/sites@2022-09-01' = if (!appServiceReuse && deployAppService) { 83 | name: name 84 | location: location 85 | tags: tags 86 | kind: kind 87 | properties: { 88 | serverFarmId: appServicePlanId 89 | virtualNetworkSubnetId: networkIsolation?subnetId:null 90 | vnetRouteAllEnabled: true 91 | siteConfig: { 92 | vnetName: networkIsolation?vnetName:null 93 | linuxFxVersion: linuxFxVersion 94 | alwaysOn: alwaysOn 95 | ftpsState: ftpsState 96 | minTlsVersion: '1.2' 97 | appCommandLine: appCommandLine 98 | numberOfWorkers: numberOfWorkers != -1 ? numberOfWorkers : null 99 | minimumElasticInstanceCount: minimumElasticInstanceCount != -1 ? minimumElasticInstanceCount : null 100 | use32BitWorkerProcess: use32BitWorkerProcess 101 | functionAppScaleLimit: functionAppScaleLimit != -1 ? functionAppScaleLimit : null 102 | healthCheckPath: healthCheckPath 103 | appSettings: concat( 104 | appSettings, 105 | empty(applicationInsightsName) ? [] : [ 106 | { 107 | name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' 108 | value: applicationInsights.properties.ConnectionString 109 | } 110 | ], 111 | [ 112 | { 113 | name: 'SCM_DO_BUILD_DURING_DEPLOYMENT' 114 | value: string(scmDoBuildDuringDeployment) 115 | } 116 | { 117 | name: 'ENABLE_ORYX_BUILD' 118 | value: string(enableOryxBuild) 119 | } 120 | ] 121 | ) 122 | cors: { 123 | allowedOrigins: union([ 'https://portal.azure.com', 'https://ms.portal.azure.com' ], allowedOrigins) 124 | } 125 | } 126 | clientAffinityEnabled: clientAffinityEnabled 127 | httpsOnly: true 128 | } 129 | identity: { 130 | type: 'SystemAssigned' 131 | } 132 | resource configLogs 'config' = { 133 | name: 'logs' 134 | properties: { 135 | applicationLogs: { fileSystem: { level: 'Verbose' } } 136 | detailedErrorMessages: { enabled: true } 137 | failedRequestsTracing: { enabled: true } 138 | httpLogs: { fileSystem: { enabled: true, retentionInDays: 1, retentionInMb: 35 } } 139 | } 140 | } 141 | 142 | resource basicPublishingCredentialsPoliciesFtp 'basicPublishingCredentialsPolicies' = { 143 | name: 'ftp' 144 | properties: { 145 | allow: basicPublishingCredentials 146 | } 147 | } 148 | 149 | resource basicPublishingCredentialsPoliciesScm 'basicPublishingCredentialsPolicies' = { 150 | name: 'scm' 151 | properties: { 152 | allow: basicPublishingCredentials 153 | } 154 | } 155 | } 156 | 157 | output identityPrincipalId string = !deployAppService ? '' : appServiceReuse ? existingAppService.identity.principalId : newAppService.identity.principalId 158 | output name string = !deployAppService ? '' : appServiceReuse ? existingAppService.name : newAppService.name 159 | output uri string = !deployAppService ? '' : 'https://${appServiceReuse ? existingAppService.properties.defaultHostName : newAppService.properties.defaultHostName }' 160 | output id string = !deployAppService ? '' : appServiceReuse ? existingAppService.id : newAppService.id 161 | // output key string = listKeys(appService.id, appService.apiVersion).default 162 | -------------------------------------------------------------------------------- /infra/core/host/appserviceenvironment.bicep: -------------------------------------------------------------------------------- 1 | param name string 2 | param resourceGroupName string 3 | 4 | resource AppServiceEnvironment 'Microsoft.Web/hostingEnvironments@2021-02-01' existing = { 5 | scope: resourceGroup(resourceGroupName) 6 | name: name 7 | } 8 | 9 | output id string = AppServiceEnvironment.id 10 | output name string = AppServiceEnvironment.name 11 | -------------------------------------------------------------------------------- /infra/core/host/appserviceplan.bicep: -------------------------------------------------------------------------------- 1 | param name string 2 | param location string = resourceGroup().location 3 | param tags object = {} 4 | 5 | param appServicePlanReuse bool 6 | param existingAppServicePlanResourceGroupName string 7 | 8 | param kind string = '' 9 | param reserved bool = true 10 | param sku object 11 | 12 | resource existingAppServicePlan 'Microsoft.Web/serverfarms@2022-03-01' existing = if (appServicePlanReuse) { 13 | scope: resourceGroup(existingAppServicePlanResourceGroupName) 14 | name: name 15 | } 16 | 17 | 18 | resource newAppServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = if (!appServicePlanReuse) { 19 | name: name 20 | location: location 21 | tags: tags 22 | sku: sku 23 | kind: kind 24 | properties: { 25 | reserved: reserved 26 | } 27 | } 28 | 29 | output id string = appServicePlanReuse ? existingAppServicePlan.id: newAppServicePlan.id 30 | output name string = appServicePlanReuse ? existingAppServicePlan.name: newAppServicePlan.name 31 | output resourceGroupName string = appServicePlanReuse ? existingAppServicePlanResourceGroupName : resourceGroup().name 32 | -------------------------------------------------------------------------------- /infra/core/host/functions.bicep: -------------------------------------------------------------------------------- 1 | param networkIsolation bool 2 | param vnetName string 3 | param subnetId string 4 | param runtimeName string 5 | param runtimeVersion string 6 | var runtimeNameAndVersion = '${runtimeName}|${runtimeVersion}' 7 | param alwaysOn bool = true 8 | param appCommandLine string = '' 9 | param numberOfWorkers int = -1 10 | param minimumElasticInstanceCount int = -1 11 | param use32BitWorkerProcess bool = false 12 | param functionAppScaleLimit int = -1 13 | param healthCheckPath string = '' 14 | param allowedOrigins array = [] 15 | 16 | param name string 17 | param functionAppReuse bool 18 | param functionAppResourceGroupName string 19 | param location string = resourceGroup().location 20 | param tags object = {} 21 | param keyVaultResourceGroupName string 22 | param keyVaultName string = '' 23 | 24 | // Reference Properties 25 | param applicationInsightsName string = '' 26 | param applicationInsightsResourceGroupName string 27 | 28 | param appServicePlanId string 29 | 30 | param storageAccountName string 31 | param storageResourceGroupName string 32 | 33 | param clientAffinityEnabled bool = false 34 | @allowed(['SystemAssigned', 'UserAssigned']) 35 | param identityType string 36 | // @description('User assigned identity name') 37 | // param identityId string 38 | 39 | // Runtime Properties 40 | param kind string = 'functionapp,linux' 41 | 42 | // Microsoft.Web/sites/config 43 | param appSettings array = [] 44 | 45 | resource stg 'Microsoft.Storage/storageAccounts@2022-09-01' existing = { 46 | scope: resourceGroup(storageResourceGroupName) 47 | name: storageAccountName 48 | } 49 | 50 | resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = if (!(empty(keyVaultName))) { 51 | scope: resourceGroup(keyVaultResourceGroupName) 52 | name: keyVaultName 53 | } 54 | 55 | resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = if (!empty(applicationInsightsName)) { 56 | scope: resourceGroup(applicationInsightsResourceGroupName) 57 | name: applicationInsightsName 58 | } 59 | 60 | resource existingFunction 'Microsoft.Web/sites@2022-09-01' existing = if (functionAppReuse) { 61 | scope: resourceGroup(functionAppResourceGroupName) 62 | name: name 63 | } 64 | 65 | resource newFunction 'Microsoft.Web/sites@2022-03-01' = { 66 | name: name 67 | location: location 68 | tags: tags 69 | kind: kind 70 | 71 | identity: { 72 | type: identityType 73 | } 74 | 75 | properties: { 76 | serverFarmId: appServicePlanId 77 | clientAffinityEnabled: clientAffinityEnabled 78 | virtualNetworkSubnetId: networkIsolation ? subnetId : null 79 | httpsOnly: true 80 | siteConfig: { 81 | vnetName: networkIsolation ? vnetName : null 82 | linuxFxVersion: runtimeNameAndVersion 83 | alwaysOn: alwaysOn 84 | ftpsState: 'FtpsOnly' 85 | minTlsVersion: '1.2' 86 | appCommandLine: appCommandLine 87 | numberOfWorkers: numberOfWorkers 88 | minimumElasticInstanceCount: minimumElasticInstanceCount 89 | use32BitWorkerProcess: use32BitWorkerProcess 90 | functionAppScaleLimit: functionAppScaleLimit 91 | healthCheckPath: healthCheckPath 92 | appSettings: union( 93 | appSettings, 94 | empty(applicationInsightsName) ? [] : [ 95 | { 96 | name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' 97 | value: applicationInsights.properties.ConnectionString 98 | } 99 | ], 100 | [ 101 | { 102 | name: 'AzureWebJobsStorage__accountName' 103 | value: stg.name 104 | } 105 | { 106 | name: 'AzureWebJobsStorage__credential' 107 | value: 'managedidentity' 108 | } 109 | { 110 | name: 'AZURE_KEY_VAULT_ENDPOINT' 111 | value: keyVault.properties.vaultUri 112 | } 113 | { 114 | name: 'FUNCTIONS_WORKER_RUNTIME' 115 | value: 'python' 116 | } 117 | { 118 | name: 'FUNCTIONS_EXTENSION_VERSION' 119 | value: '~4' 120 | } 121 | ] 122 | ) 123 | cors: { 124 | allowedOrigins: union([ 'https://portal.azure.com', 'https://ms.portal.azure.com' ], allowedOrigins) 125 | } 126 | 127 | } 128 | } 129 | } 130 | 131 | output id string = functionAppReuse ? existingFunction.id : newFunction.id 132 | output name string = functionAppReuse ? existingFunction.name : newFunction.name 133 | output uri string = functionAppReuse ? 'https://${existingFunction.properties.defaultHostName}' : 'https://${newFunction.properties.defaultHostName}' 134 | output identityPrincipalId string = identityType == 'SystemAssigned' ? functionAppReuse ? existingFunction.identity.principalId : newFunction.identity.principalId : '' 135 | output location string = functionAppReuse ? existingFunction.location : newFunction.location 136 | -------------------------------------------------------------------------------- /infra/core/loadtesting/loadtesting.bicep: -------------------------------------------------------------------------------- 1 | param name string 2 | param location string = resourceGroup().location 3 | param tags object = {} 4 | 5 | // Define the resource for Azure Load Testing 6 | resource loadTestingService 'Microsoft.LoadTestService/loadTests@2022-12-01' = { 7 | name: name 8 | tags: tags 9 | location: location 10 | identity: { 11 | type: 'SystemAssigned' 12 | } 13 | } 14 | 15 | output id string = loadTestingService.identity.principalId 16 | output name string = loadTestingService.name 17 | -------------------------------------------------------------------------------- /infra/core/network/private-dns-zones.bicep: -------------------------------------------------------------------------------- 1 | param dnsZoneName string 2 | param virtualNetworkName string 3 | param tags object = {} 4 | 5 | resource vnet 'Microsoft.Network/virtualNetworks@2020-06-01' existing = { 6 | name: virtualNetworkName 7 | } 8 | 9 | resource dnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { 10 | name: dnsZoneName 11 | location: 'global' 12 | tags: tags 13 | dependsOn: [ 14 | vnet 15 | ] 16 | } 17 | 18 | resource privateDnsZoneLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = { 19 | name: '${virtualNetworkName}-dnslink' 20 | parent: dnsZone 21 | location: 'global' 22 | tags: tags 23 | properties: { 24 | virtualNetwork: { 25 | id:vnet.id 26 | } 27 | registrationEnabled: false 28 | } 29 | } 30 | 31 | 32 | output privateDnsZoneName string = dnsZone.name 33 | output id string = dnsZone.id 34 | -------------------------------------------------------------------------------- /infra/core/network/private-endpoint.bicep: -------------------------------------------------------------------------------- 1 | param location string 2 | param name string 3 | param tags object = {} 4 | param serviceId string 5 | param subnetId string 6 | param groupIds array = [] 7 | param dnsZoneId string 8 | 9 | resource privateEndpoint 'Microsoft.Network/privateEndpoints@2021-02-01' = { 10 | name: name 11 | location: location 12 | tags: tags 13 | properties: { 14 | subnet: { 15 | id: subnetId 16 | } 17 | privateLinkServiceConnections: [ 18 | { 19 | name: 'privatelinkServiceonnection' 20 | properties: { 21 | privateLinkServiceId: serviceId 22 | groupIds: groupIds 23 | } 24 | } 25 | ] 26 | } 27 | } 28 | 29 | resource privateDnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2020-06-01' = { 30 | parent: privateEndpoint 31 | name: '${name}-group' 32 | properties:{ 33 | privateDnsZoneConfigs:[ 34 | { 35 | name:'config1' 36 | properties:{ 37 | privateDnsZoneId: dnsZoneId 38 | } 39 | } 40 | ] 41 | } 42 | } 43 | 44 | output name string = privateEndpoint.name 45 | -------------------------------------------------------------------------------- /infra/core/search/search-private-link.bicep: -------------------------------------------------------------------------------- 1 | param name string 2 | param searchName string 3 | param resourceId string 4 | param groupId string 5 | 6 | resource search 'Microsoft.Search/searchServices@2024-03-01-preview' existing = { 7 | name: searchName 8 | } 9 | 10 | resource sharedPrivateLinkResources 'Microsoft.Search/searchServices/sharedPrivateLinkResources@2024-03-01-preview' = { 11 | name: name 12 | parent: search 13 | properties: { 14 | groupId: groupId 15 | status: 'Approved' 16 | provisioningState: 'Succeeded' 17 | requestMessage: 'automatically created by the system' 18 | privateLinkResourceId: resourceId 19 | 20 | } 21 | } 22 | 23 | output name string = sharedPrivateLinkResources.name 24 | output id string = sharedPrivateLinkResources.id 25 | -------------------------------------------------------------------------------- /infra/core/search/search-services.bicep: -------------------------------------------------------------------------------- 1 | param name string 2 | param location string = resourceGroup().location 3 | 4 | param aiSearchReuse bool 5 | param existingAiSearchResourceGroupName string 6 | 7 | param deployAiSearch bool = true 8 | 9 | param tags object = {} 10 | param publicNetworkAccess string 11 | param sku object = { 12 | name: 'standard' 13 | } 14 | param secretName string = 'azureSearchKey' 15 | param keyVaultName string 16 | 17 | param authOptions object = {} 18 | param semanticSearch string = 'free' 19 | 20 | 21 | resource existingSearch 'Microsoft.Search/searchServices@2021-04-01-preview' existing = if (aiSearchReuse && deployAiSearch) { 22 | scope: resourceGroup(existingAiSearchResourceGroupName) 23 | name: name 24 | } 25 | 26 | resource newSearch 'Microsoft.Search/searchServices@2021-04-01-preview' = if (!aiSearchReuse && deployAiSearch) { 27 | name: name 28 | location: location 29 | tags: tags 30 | identity: { 31 | type: 'SystemAssigned' 32 | } 33 | properties: { 34 | authOptions: authOptions 35 | disableLocalAuth: false 36 | disabledDataExfiltrationOptions: [] 37 | encryptionWithCmk: { 38 | enforcement: 'Unspecified' 39 | } 40 | hostingMode: 'default' 41 | networkRuleSet: { 42 | bypass: 'None' 43 | ipRules: [] 44 | } 45 | partitionCount: 1 46 | publicNetworkAccess: publicNetworkAccess 47 | replicaCount: 1 48 | semanticSearch: semanticSearch 49 | } 50 | sku: sku 51 | } 52 | 53 | resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { 54 | name: keyVaultName 55 | } 56 | 57 | resource keyVaultSecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = { 58 | name: secretName 59 | tags: tags 60 | parent: keyVault 61 | properties: { 62 | attributes: { 63 | enabled: true 64 | exp: 0 65 | nbf: 0 66 | } 67 | contentType: 'string' 68 | value: aiSearchReuse ? existingSearch.listAdminKeys().primaryKey : newSearch.listAdminKeys().primaryKey 69 | } 70 | } 71 | 72 | output id string = !deployAiSearch ? '' : aiSearchReuse ? existingSearch.id : newSearch.id 73 | output name string = !deployAiSearch ? '' : aiSearchReuse ? existingSearch.name : newSearch.name 74 | output principalId string = !deployAiSearch ? '' : aiSearchReuse ? existingSearch.identity.principalId : newSearch.identity.principalId 75 | output endpoint string = !deployAiSearch ? '' : 'https://${aiSearchReuse ? existingSearch.name: newSearch.name}.search.windows.net/' 76 | -------------------------------------------------------------------------------- /infra/core/security/aiservices-access.bicep: -------------------------------------------------------------------------------- 1 | param principalId string 2 | param resourceName string 3 | 4 | resource resource 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = { 5 | name: resourceName 6 | } 7 | 8 | var roleDefinitionId = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a97b65f3-24c7-4388-baec-2e87135dc908') // Cognitive Services User 9 | 10 | resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { 11 | name: guid(resourceGroup().id, principalId, roleDefinitionId) 12 | scope: resource 13 | properties: { 14 | roleDefinitionId: roleDefinitionId 15 | principalId: principalId 16 | principalType: 'ServicePrincipal' 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /infra/core/security/blobstorage-contributor-access.bicep: -------------------------------------------------------------------------------- 1 | param principalId string 2 | param resourceName string 3 | 4 | resource resource 'Microsoft.Storage/storageAccounts@2021-04-01' existing = { 5 | name: resourceName 6 | } 7 | 8 | var roleDefinitionId = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe') // Storage Blob Data Contributor role 9 | 10 | resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { 11 | name: guid(resourceGroup().id, principalId, resourceName, roleDefinitionId) 12 | scope: resource 13 | properties: { 14 | roleDefinitionId: roleDefinitionId 15 | principalId: principalId 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /infra/core/security/blobstorage-dataowner-access.bicep: -------------------------------------------------------------------------------- 1 | param principalID string 2 | param resourceName string 3 | 4 | resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' existing = { 5 | name: resourceName 6 | } 7 | 8 | var storageBlobDataOwnerRoleId = 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b' // Storage Blob Data Owner role 9 | var ownerRoleId = '8e3af657-a8ff-443c-a75c-2fe8c4bcb635' // Owner role 10 | 11 | // Assign Storage Blob Data Owner role 12 | resource storageBlobDataOwnerAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { 13 | name: guid(storageAccount.id, principalID, storageBlobDataOwnerRoleId) 14 | scope: storageAccount 15 | properties: { 16 | roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', storageBlobDataOwnerRoleId) 17 | principalId: principalID 18 | principalType: 'ServicePrincipal' 19 | } 20 | } 21 | 22 | // Assign Owner role 23 | resource ownerRoleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { 24 | name: guid(storageAccount.id, principalID, ownerRoleId) 25 | scope: storageAccount 26 | properties: { 27 | roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', ownerRoleId) 28 | principalId: principalID 29 | principalType: 'ServicePrincipal' 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /infra/core/security/blobstorage-reader-access.bicep: -------------------------------------------------------------------------------- 1 | param principalId string 2 | param resourceName string 3 | 4 | resource resource 'Microsoft.Storage/storageAccounts@2021-04-01' existing = { 5 | name: resourceName 6 | } 7 | 8 | var roleDefinitionId = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1') // Storage Blob Data Reader role 9 | 10 | resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { 11 | name: guid(resourceGroup().id, principalId, roleDefinitionId) 12 | scope: resource 13 | properties: { 14 | roleDefinitionId: roleDefinitionId 15 | principalId: principalId 16 | principalType: 'ServicePrincipal' 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /infra/core/security/cosmos-access.bicep: -------------------------------------------------------------------------------- 1 | param principalId string 2 | param accountName string 3 | param resourceGroupName string 4 | 5 | resource account 'Microsoft.DocumentDB/databaseAccounts@2022-05-15' existing = { 6 | name: toLower(accountName) 7 | } 8 | 9 | var roleDefinitionId = '/${subscription().id}/resourceGroups/${resourceGroupName}/providers/Microsoft.DocumentDB/databaseAccounts/${account.name}/sqlRoleDefinitions/00000000-0000-0000-0000-000000000002' 10 | 11 | resource sqlRoleAssignment 'Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments@2023-04-15' = { 12 | name: guid(resourceGroup().id, account.id, principalId) 13 | parent: account 14 | properties:{ 15 | roleDefinitionId: roleDefinitionId 16 | principalId: principalId 17 | scope: account.id 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /infra/core/security/functions-access.bicep: -------------------------------------------------------------------------------- 1 | param principalId string 2 | param resourceName string 3 | 4 | resource resource 'Microsoft.Web/sites@2021-02-01' existing = { 5 | name: resourceName 6 | } 7 | 8 | var roleDefinitionId = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor role 9 | 10 | // Create a role assignment for the web app managed identity to access the function app 11 | resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { 12 | name: guid(resource.id, principalId, 'Contributor') 13 | scope: resource 14 | properties: { 15 | roleDefinitionId: roleDefinitionId 16 | principalId: principalId 17 | principalType: 'ServicePrincipal' 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /infra/core/security/keyvault-access.bicep: -------------------------------------------------------------------------------- 1 | param permissions object = { secrets: [ 'get', 'list' ] } 2 | // param permissions object = { secrets: [ 'get', 'list', 'set', 'delete' ] } 3 | param principalId string 4 | param resourceName string 5 | 6 | resource resource 'Microsoft.KeyVault/vaults@2022-07-01' existing = { 7 | name: resourceName 8 | } 9 | 10 | resource keyVaultAccessPolicies 'Microsoft.KeyVault/vaults/accessPolicies@2022-07-01' = { 11 | parent: resource 12 | name: 'add' 13 | properties: { 14 | accessPolicies: [ { 15 | objectId: principalId 16 | tenantId: subscription().tenantId 17 | permissions: permissions 18 | } ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /infra/core/security/keyvault-secrets.bicep: -------------------------------------------------------------------------------- 1 | param tags object = {} 2 | param keyVaultName string 3 | param contentType string = 'string' 4 | 5 | param enabled bool = true 6 | param exp int = 0 7 | param nbf int = 0 8 | 9 | @description('The value of the secret. storage access, but do not hard code any secrets in your templates') 10 | @secure() 11 | param secretValues object = {} 12 | 13 | resource keyVaultSecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = [for secret in items(secretValues): { 14 | name: secret.value.name 15 | tags: tags 16 | parent: keyVault 17 | properties: { 18 | attributes: { 19 | enabled: enabled 20 | exp: exp 21 | nbf: nbf 22 | } 23 | contentType: contentType 24 | value: secret.value.value 25 | } 26 | }] 27 | 28 | resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = { 29 | name: keyVaultName 30 | } 31 | -------------------------------------------------------------------------------- /infra/core/security/keyvault.bicep: -------------------------------------------------------------------------------- 1 | param name string 2 | param location string = resourceGroup().location 3 | param tags object = {} 4 | param publicNetworkAccess string 5 | 6 | param keyVaultReuse bool 7 | param existingKeyVaultResourceGroupName string 8 | 9 | // @secure() 10 | // param vmUserPasswordKey string 11 | // @secure() 12 | // param vmUserPassword string 13 | 14 | param principalId string = '' 15 | 16 | resource existingKeyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = if (keyVaultReuse) { 17 | scope: resourceGroup(existingKeyVaultResourceGroupName) 18 | name: name 19 | } 20 | 21 | resource newKeyVault 'Microsoft.KeyVault/vaults@2022-07-01' = if (!keyVaultReuse) { 22 | name: name 23 | location: location 24 | tags: tags 25 | properties: { 26 | tenantId: subscription().tenantId 27 | sku: { family: 'A', name: 'standard' } 28 | enableSoftDelete: true 29 | publicNetworkAccess: publicNetworkAccess 30 | enablePurgeProtection: true 31 | accessPolicies: !empty(principalId) ? [ 32 | { 33 | objectId: principalId 34 | permissions: { secrets: [ 'get', 'list', 'set'] } 35 | tenantId: subscription().tenantId 36 | } 37 | ] : [] 38 | } 39 | } 40 | 41 | output id string = keyVaultReuse ? existingKeyVault.id: newKeyVault.id 42 | output name string = keyVaultReuse ? existingKeyVault.name: newKeyVault.name 43 | output endpoint string = keyVaultReuse ? existingKeyVault.properties.vaultUri: newKeyVault.properties.vaultUri 44 | -------------------------------------------------------------------------------- /infra/core/security/openai-access.bicep: -------------------------------------------------------------------------------- 1 | param principalId string 2 | param resourceName string 3 | 4 | resource resource 'Microsoft.CognitiveServices/accounts@2023-05-01' existing = { 5 | name: resourceName 6 | } 7 | 8 | var roleDefinitionId = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5e0bd9bd-7b93-4f28-af87-19fc36ad61bd') 9 | 10 | resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { 11 | name: guid(resourceGroup().id, principalId, roleDefinitionId) 12 | scope: resource 13 | properties: { 14 | roleDefinitionId: roleDefinitionId 15 | principalId: principalId 16 | principalType: 'ServicePrincipal' 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /infra/core/security/search-index-contributor-access.bicep: -------------------------------------------------------------------------------- 1 | param principalId string 2 | param resourceName string 3 | 4 | resource resource 'Microsoft.Search/searchServices@2021-04-01-preview' existing = { 5 | name: resourceName 6 | } 7 | 8 | resource roleAssignmentSIDC 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { 9 | name: guid(resourceGroup().id, resource.id, principalId, 'SIDC') 10 | scope: resource 11 | properties: { 12 | roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8ebe5a00-799e-43f5-93ac-243d3dce84a7') // Search Index Data Contributor 13 | principalId: principalId 14 | principalType: 'ServicePrincipal' 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /infra/core/security/search-index-read-access.bicep: -------------------------------------------------------------------------------- 1 | param principalId string 2 | param resourceName string 3 | 4 | resource resource 'Microsoft.Search/searchServices@2021-04-01-preview' existing = { 5 | name: resourceName 6 | } 7 | 8 | resource roleAssignmentSIDC 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { 9 | name: guid(resourceGroup().id, resource.id, principalId, 'SIDC') 10 | scope: resource 11 | properties: { 12 | roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1407120a-92aa-4202-b7e9-c0e197c71c8f') // Search Index Data Reader 13 | principalId: principalId 14 | principalType: 'ServicePrincipal' 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /infra/core/security/search-service-contributor.bicep: -------------------------------------------------------------------------------- 1 | param principalId string 2 | param resourceName string 3 | 4 | resource resource 'Microsoft.Search/searchServices@2021-04-01-preview' existing = { 5 | name: resourceName 6 | } 7 | 8 | resource roleAssignmentSSC 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = { 9 | name: guid(resourceGroup().id, resource.id, principalId, 'SSC') 10 | scope: resource 11 | properties: { 12 | roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ca78c08-252a-4471-8644-bb5ff32d4ba0') // Search Service Contributor 13 | principalId: principalId 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /infra/core/storage/function-storage-account.bicep: -------------------------------------------------------------------------------- 1 | param name string 2 | param location string = resourceGroup().location 3 | param tags object = {} 4 | 5 | param allowBlobPublicAccess bool = true 6 | @allowed(['Enabled', 'Disabled']) 7 | param publicNetworkAccess string = 'Enabled' 8 | param containers array = [] 9 | param kind string = 'StorageV2' 10 | param minimumTlsVersion string = 'TLS1_2' 11 | param sku object = { name: 'Standard_LRS' } 12 | 13 | resource storage 'Microsoft.Storage/storageAccounts@2023-01-01' = { 14 | name: name 15 | location: location 16 | tags: tags 17 | kind: kind 18 | sku: sku 19 | properties: { 20 | minimumTlsVersion: minimumTlsVersion 21 | allowBlobPublicAccess: allowBlobPublicAccess 22 | publicNetworkAccess: publicNetworkAccess 23 | allowSharedKeyAccess: false 24 | networkAcls: { 25 | bypass: 'AzureServices' 26 | defaultAction: 'Allow' 27 | } 28 | } 29 | 30 | resource blobServices 'blobServices' = if (!empty(containers)) { 31 | name: 'default' 32 | resource container 'containers' = [for container in containers: { 33 | name: container.name 34 | properties: { 35 | publicAccess: contains(container, 'publicAccess') ? container.publicAccess : 'None' 36 | } 37 | }] 38 | } 39 | } 40 | 41 | output name string = storage.name 42 | output id string = storage.id 43 | output primaryEndpoints object = storage.properties.primaryEndpoints 44 | -------------------------------------------------------------------------------- /infra/core/storage/storage-account.bicep: -------------------------------------------------------------------------------- 1 | param name string 2 | param location string = resourceGroup().location 3 | param tags object = {} 4 | param existingStorageResourceGroupName string 5 | param storageReuse bool 6 | param deployStorageAccount bool = true 7 | 8 | @allowed([ 'Hot', 'Cool', 'Premium' ]) 9 | param accessTier string = 'Hot' 10 | param allowBlobPublicAccess bool = false 11 | param allowCrossTenantReplication bool = true 12 | param allowSharedKeyAccess bool = false 13 | param defaultToOAuthAuthentication bool = false 14 | param deleteRetentionPolicy object = {} 15 | @allowed([ 'AzureDnsZone', 'Standard' ]) 16 | param dnsEndpointType string = 'Standard' 17 | param kind string = 'StorageV2' 18 | param minimumTlsVersion string = 'TLS1_2' 19 | @allowed([ 'Enabled', 'Disabled' ]) 20 | param publicNetworkAccess string = 'Disabled' 21 | param sku object = { name: 'Standard_LRS' } 22 | param containers array = [] 23 | 24 | 25 | resource existingStorage 'Microsoft.Storage/storageAccounts@2022-05-01' existing = if (storageReuse && deployStorageAccount) { 26 | scope: resourceGroup(existingStorageResourceGroupName) 27 | name: name 28 | } 29 | 30 | resource newStorage 'Microsoft.Storage/storageAccounts@2022-05-01' = if (!storageReuse && deployStorageAccount) { 31 | name: name 32 | location: location 33 | tags: tags 34 | kind: kind 35 | sku: sku 36 | properties: { 37 | accessTier: accessTier 38 | allowBlobPublicAccess: allowBlobPublicAccess 39 | allowCrossTenantReplication: allowCrossTenantReplication 40 | allowSharedKeyAccess: allowSharedKeyAccess 41 | defaultToOAuthAuthentication: defaultToOAuthAuthentication 42 | dnsEndpointType: dnsEndpointType 43 | minimumTlsVersion: minimumTlsVersion 44 | supportsHttpsTrafficOnly: true 45 | networkAcls: { 46 | bypass: 'AzureServices' 47 | defaultAction: 'Allow' 48 | } 49 | publicNetworkAccess: publicNetworkAccess 50 | } 51 | 52 | resource blobServices 'blobServices' = if (!empty(containers)) { 53 | name: 'default' 54 | properties: { 55 | deleteRetentionPolicy: deleteRetentionPolicy 56 | } 57 | resource container 'containers' = [for container in containers: { 58 | name: container.name 59 | properties: { 60 | publicAccess: contains(container, 'publicAccess') ? container.publicAccess : 'None' 61 | } 62 | }] 63 | } 64 | } 65 | 66 | output name string = !deployStorageAccount ? '' : storageReuse ? existingStorage.name : newStorage.name 67 | output id string = !deployStorageAccount ? '' : storageReuse ? existingStorage.id : newStorage.id 68 | output primaryEndpoints object = !deployStorageAccount ? {} : storageReuse ? existingStorage.properties.primaryEndpoints: newStorage.properties.primaryEndpoints 69 | -------------------------------------------------------------------------------- /infra/core/util/delay.bicep: -------------------------------------------------------------------------------- 1 | param location string = resourceGroup().location 2 | param utcValue string = utcNow() 3 | param sleepName string = 'sleep-1' 4 | param sleepSeconds int = 120 5 | resource sleepDelay 'Microsoft.Resources/deploymentScripts@2020-10-01' = { 6 | name: sleepName 7 | location: location 8 | kind: 'AzurePowerShell' 9 | properties: { 10 | forceUpdateTag: utcValue 11 | azPowerShellVersion: '8.3' 12 | timeout: 'PT10M' 13 | arguments: '-seconds ${sleepSeconds}' 14 | scriptContent: ''' 15 | param ( [string] $seconds ) 16 | Write-Output Sleeping for: $seconds .... 17 | Start-Sleep -Seconds $seconds 18 | Write-Output Sleep over - resuming .... 19 | ''' 20 | cleanupPreference: 'OnSuccess' 21 | retentionInterval: 'P1D' 22 | } 23 | } 24 | output location string = sleepDelay.location 25 | -------------------------------------------------------------------------------- /infra/core/vm/dsvm.bicep: -------------------------------------------------------------------------------- 1 | param location string 2 | param name string 3 | param tags object = {} 4 | param subnetId string 5 | param bastionSubId string 6 | @secure() 7 | param vmUserPassword string 8 | param vmUserName string 9 | param authenticationType string = 'password' //'sshPublicKey' 10 | @secure() 11 | param vmUserPasswordKey string 12 | param keyVaultName string 13 | param principalId string 14 | 15 | var vmSize = { 16 | 'CPU-4GB': 'Standard_B2s' 17 | 'CPU-7GB': 'Standard_D2s_v3' 18 | 'CPU-8GB': 'Standard_D2s_v3' 19 | 'CPU-14GB': 'Standard_D4s_v3' 20 | 'CPU-16GB': 'Standard_D4s_v3' 21 | 'GPU-56GB': 'Standard_NC6_Promo' 22 | } 23 | var publicIpName = '${name}PublicIp' 24 | var nicName = '${name}Nic' 25 | var diskName = '${name}Disk' 26 | var bastionName = '${name}Bastion' 27 | 28 | var linuxConfiguration = { 29 | disablePasswordAuthentication: true 30 | ssh: { 31 | publicKeys: [ 32 | { 33 | path: '/home/${vmUserName}/.ssh/authorized_keys' 34 | keyData: vmUserPassword 35 | } 36 | ] 37 | } 38 | } 39 | 40 | resource bastionPublicIp 'Microsoft.Network/publicIPAddresses@2020-05-01' = { 41 | name: publicIpName 42 | location: location 43 | sku: { 44 | name: 'Standard' 45 | } 46 | properties: { 47 | publicIPAllocationMethod: 'Static' 48 | } 49 | } 50 | 51 | resource nic 'Microsoft.Network/networkInterfaces@2020-06-01' = { 52 | name: nicName 53 | location: location 54 | properties: { 55 | ipConfigurations: [ 56 | { 57 | name: 'ipconfig1' 58 | properties: { 59 | privateIPAddressVersion: 'IPv4' 60 | privateIPAllocationMethod: 'Dynamic' 61 | subnet: { 62 | id: subnetId 63 | } 64 | } 65 | } 66 | ] 67 | } 68 | } 69 | 70 | resource virtualMachine 'Microsoft.Compute/virtualMachines@2021-03-01' = { 71 | name: name 72 | location: location 73 | tags: tags 74 | identity: { 75 | type: 'SystemAssigned' 76 | } 77 | properties: { 78 | hardwareProfile: { 79 | vmSize: vmSize['CPU-16GB'] 80 | } 81 | storageProfile: { 82 | imageReference: { 83 | publisher: 'microsoft-dsvm' 84 | offer: 'dsvm-win-2019' 85 | sku: 'winserver-2019' 86 | version: 'latest' 87 | } 88 | osDisk: { 89 | name: diskName 90 | createOption: 'FromImage' 91 | } 92 | } 93 | osProfile: { 94 | computerName: 'gptragvm' 95 | adminUsername: vmUserName 96 | adminPassword: vmUserPassword 97 | linuxConfiguration: ((authenticationType == 'password') ? json('null') : linuxConfiguration) 98 | } 99 | networkProfile: { 100 | networkInterfaces: [ 101 | { 102 | id: nic.id 103 | } 104 | ] 105 | } 106 | } 107 | } 108 | 109 | output vmPrincipalId string = virtualMachine.identity.principalId 110 | 111 | resource cy 'Microsoft.Network/bastionHosts@2023-04-01' = { 112 | name: bastionName 113 | location: location 114 | sku: { 115 | name: 'Standard' 116 | } 117 | properties: { 118 | ipConfigurations: [ 119 | { 120 | name: 'ipconfig1' 121 | properties: { 122 | privateIPAllocationMethod: 'Dynamic' 123 | subnet: { 124 | id: bastionSubId 125 | } 126 | publicIPAddress: { 127 | id: bastionPublicIp.id // use a public IP address for the bastion 128 | } 129 | } 130 | } 131 | ] 132 | } 133 | } 134 | 135 | 136 | resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { 137 | name: guid(subscription().id, resourceGroup().id, 'Contributor') 138 | scope: resourceGroup() 139 | properties: { 140 | roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') 141 | principalId: virtualMachine.identity.principalId 142 | } 143 | } 144 | 145 | // Using key vault to store the password. 146 | // Not using the application key vault as it is set with no public network access for zero trust, but Bastion need the public network access 147 | // to pul the secret from the key vault. 148 | resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' = { 149 | name: keyVaultName 150 | location: location 151 | tags: tags 152 | properties: { 153 | sku: { 154 | name: 'standard' 155 | family: 'A' 156 | } 157 | tenantId: subscription().tenantId 158 | accessPolicies: [ 159 | ] 160 | enableRbacAuthorization: true 161 | } 162 | } 163 | 164 | resource vmUserPasswordSecret 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = { 165 | parent: keyVault 166 | name: vmUserPasswordKey 167 | properties: { 168 | value: vmUserPassword 169 | } 170 | } 171 | 172 | resource KeyVaultAccessRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = { 173 | name: guid(subscription().id, resourceGroup().id, principalId, keyVault.id, 'Key Vault Secrets Officer') 174 | scope: keyVault 175 | properties: { 176 | principalId: principalId 177 | roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7') 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /loadtest/config.yaml: -------------------------------------------------------------------------------- 1 | displayName: Enterprise RAG Load Test 2 | testPlan: loadtest.jmx 3 | description: '' 4 | engineInstances: 1 5 | testId: gptrag-load-test 6 | testType: JMX 7 | splitAllCSVs: False 8 | configurationFiles: 9 | - dataset.csv 10 | failureCriteria: 11 | - HTTP Request: p95(response_time_ms) > 10000 12 | secrets: 13 | - name: functionKey 14 | value: https://KEY_VAULT_NAME.vault.azure.net/secrets/orchestrator-host--functionKey 15 | properties: 16 | userPropertyFile: user.properties 17 | autoStop: 18 | errorPercentage: 90 19 | timeWindow: 60 20 | -------------------------------------------------------------------------------- /loadtest/dataset.csv: -------------------------------------------------------------------------------- 1 | What is the new title of the document? 2 | What is the version number of the document? 3 | Who is developing the software solution described in the document? 4 | What type of services does Contoso provide? 5 | What is the main purpose of the document? 6 | What is the scope of the product described in the document? 7 | How does the product aim to simplify cloud management? 8 | What types of cloud resources can users manage with the product? 9 | How will the product be integrated with Contoso's existing platform? 10 | What type of user interface will the product have? 11 | What will the dashboard display in the product? 12 | What actions can users perform with the resource manager? 13 | What insights will the resource analyzer provide? 14 | How will the resource planner help users? 15 | What types of notifications will the system provide? 16 | How will the security system protect cloud resources and data? 17 | Which major web browsers must the product be compatible with? 18 | How will the product support multiple languages and regions? 19 | What standards and regulations must the product comply with? 20 | What are the scalability and reliability requirements for the product? 21 | What measures will ensure the product's security and resilience? 22 | What documentation and support will the product provide? 23 | What methodologies will be used to develop the product? 24 | How will the product be tested and verified during development? 25 | On what type of platform will the product be deployed? 26 | How will the product handle changes and enhancements based on user feedback? 27 | What legal and ethical regulations must the product comply with? 28 | Who will maintain and support the product after deployment? 29 | What is the first step in the next steps for launching the product? 30 | Who will participate in the pilot phase of the product launch? 31 | What will be done with the feedback from the pilot phase? 32 | How will the product team prioritize feedback and suggestions? 33 | What will happen after the necessary changes are made based on feedback? 34 | How will the product team's performance and impact be evaluated? 35 | What is the main goal of the new product feature? 36 | How will the new feature enhance user experience and satisfaction? 37 | What strategic goals will the new feature help achieve? 38 | When is the feature expected to be launched? 39 | What types of feedback will be solicited during the development cycle? 40 | What will the design specifications include for the new feature? 41 | What is the expected business value of the new feature? 42 | How will the feature differentiate Contoso from competitors? 43 | What is the final step in the feature development process? 44 | How will the product team communicate with users and stakeholders? 45 | What regular updates will be provided to users and stakeholders? 46 | How will the product team ensure the quality of the product? 47 | What is the overall vision for the new product? 48 | What are the assumptions and dependencies mentioned in the document? 49 | What agile methodologies will be used in the product development? 50 | What is the importance of the pilot phase in the product launch? 51 | How will the product comply with GDPR and HIPAA regulations? 52 | Who are the target users and stakeholders for the product? -------------------------------------------------------------------------------- /loadtest/user.properties: -------------------------------------------------------------------------------- 1 | # peak-load.properties 2 | # User properties for testing peak load 3 | threadCount=10 4 | rampUpSeconds=30 5 | durationSeconds=360 6 | delaySeconds=10 7 | loopCount=1 8 | randomDelayMillis=1000 9 | constantDelayMillis=1000 10 | functionApp=ORCHESTRATOR_FUNC_NAME 11 | 12 | # Override default JMeter properties 13 | jmeter.save.saveservice.thread_name=false -------------------------------------------------------------------------------- /media/admin-guide-ai-search-management.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-ai-search-management.png -------------------------------------------------------------------------------- /media/admin-guide-ai-search-reindex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-ai-search-reindex.png -------------------------------------------------------------------------------- /media/admin-guide-architecture-scope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-architecture-scope.png -------------------------------------------------------------------------------- /media/admin-guide-authorization-consent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-authorization-consent.png -------------------------------------------------------------------------------- /media/admin-guide-authorization-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-authorization-example.png -------------------------------------------------------------------------------- /media/admin-guide-datasource-configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-datasource-configuration.png -------------------------------------------------------------------------------- /media/admin-guide-datasource-secrets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-datasource-secrets.png -------------------------------------------------------------------------------- /media/admin-guide-document-upload-portal-select-storage-account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-document-upload-portal-select-storage-account.png -------------------------------------------------------------------------------- /media/admin-guide-document-upload-portal-storage-account-section.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-document-upload-portal-storage-account-section.png -------------------------------------------------------------------------------- /media/admin-guide-document-upload-portal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-document-upload-portal.png -------------------------------------------------------------------------------- /media/admin-guide-homepage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-homepage.png -------------------------------------------------------------------------------- /media/admin-guide-ip-allowlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-ip-allowlist.png -------------------------------------------------------------------------------- /media/admin-guide-private-dns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-private-dns.png -------------------------------------------------------------------------------- /media/admin-guide-private-endpoints-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-private-endpoints-diagram.png -------------------------------------------------------------------------------- /media/admin-guide-vnet-peering-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-vnet-peering-diagram.png -------------------------------------------------------------------------------- /media/admin-guide-vnet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/admin-guide-vnet.png -------------------------------------------------------------------------------- /media/architecture-GPT-RAG-Basic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/architecture-GPT-RAG-Basic.png -------------------------------------------------------------------------------- /media/architecture-GPT-RAG-Inbound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/architecture-GPT-RAG-Inbound.png -------------------------------------------------------------------------------- /media/architecture-GPT-RAG-SCALE-MultiProject-2.0.jpeg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/architecture-GPT-RAG-SCALE-MultiProject-2.0.jpeg.jpg -------------------------------------------------------------------------------- /media/architecture-GPT-RAG-SCALE-MultiProject-2.0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/architecture-GPT-RAG-SCALE-MultiProject-2.0.png -------------------------------------------------------------------------------- /media/architecture-GPT-RAG-SCALE-MultiProject.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/architecture-GPT-RAG-SCALE-MultiProject.jpeg -------------------------------------------------------------------------------- /media/architecture-GPT-RAG-ZeroTrust-LZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/architecture-GPT-RAG-ZeroTrust-LZ.png -------------------------------------------------------------------------------- /media/architecture-GPT-RAG-ZeroTrust.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/architecture-GPT-RAG-ZeroTrust.png -------------------------------------------------------------------------------- /media/contributing-workflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/contributing-workflow.png -------------------------------------------------------------------------------- /media/custom-role-allow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/custom-role-allow.png -------------------------------------------------------------------------------- /media/custom-role-assign.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/custom-role-assign.png -------------------------------------------------------------------------------- /media/custom-role-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/custom-role-create.png -------------------------------------------------------------------------------- /media/custom-role-details.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/custom-role-details.png -------------------------------------------------------------------------------- /media/custom-role-finalize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/custom-role-finalize.png -------------------------------------------------------------------------------- /media/custom-role-iam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/custom-role-iam.png -------------------------------------------------------------------------------- /media/custom-role-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/custom-role-list.png -------------------------------------------------------------------------------- /media/extending-download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/extending-download.png -------------------------------------------------------------------------------- /media/extending-forking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/extending-forking.png -------------------------------------------------------------------------------- /media/extending-use-as-template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/extending-use-as-template.png -------------------------------------------------------------------------------- /media/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/logo.png -------------------------------------------------------------------------------- /media/nlsql-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/nlsql-architecture.png -------------------------------------------------------------------------------- /media/perftest-GPT-RAG-Basic-communication.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-GPT-RAG-Basic-communication.png -------------------------------------------------------------------------------- /media/perftest-GPT-RAG-Basic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-GPT-RAG-Basic.png -------------------------------------------------------------------------------- /media/perftest-analysis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-analysis.png -------------------------------------------------------------------------------- /media/perftest-aoai-response-time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-aoai-response-time.png -------------------------------------------------------------------------------- /media/perftest-app-component.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-app-component.png -------------------------------------------------------------------------------- /media/perftest-architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-architecture.png -------------------------------------------------------------------------------- /media/perftest-azure-diagnostics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-azure-diagnostics.png -------------------------------------------------------------------------------- /media/perftest-azure-load-testing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-azure-load-testing.png -------------------------------------------------------------------------------- /media/perftest-github-environment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-github-environment.png -------------------------------------------------------------------------------- /media/perftest-github-var-secrets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-github-var-secrets.png -------------------------------------------------------------------------------- /media/perftest-llmlifecycle-with-tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-llmlifecycle-with-tests.png -------------------------------------------------------------------------------- /media/perftest-llmlifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-llmlifecycle.png -------------------------------------------------------------------------------- /media/perftest-portal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-portal.png -------------------------------------------------------------------------------- /media/perftest-response-time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-response-time.png -------------------------------------------------------------------------------- /media/perftest-running.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-running.png -------------------------------------------------------------------------------- /media/perftest-sample-sequence-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-sample-sequence-diagram.png -------------------------------------------------------------------------------- /media/perftest-server-metrics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-server-metrics.png -------------------------------------------------------------------------------- /media/perftest-starting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-starting.png -------------------------------------------------------------------------------- /media/perftest-users-per-hour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/perftest-users-per-hour.png -------------------------------------------------------------------------------- /media/querying-conversations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/querying-conversations.png -------------------------------------------------------------------------------- /media/ragconcepts-RAG1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/ragconcepts-RAG1.PNG -------------------------------------------------------------------------------- /media/ragconcepts-RAG2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/ragconcepts-RAG2.PNG -------------------------------------------------------------------------------- /media/readme-keyvault-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/readme-keyvault-login.png -------------------------------------------------------------------------------- /media/readme-search_trimming_sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/readme-search_trimming_sample.png -------------------------------------------------------------------------------- /media/readme-storage_sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/readme-storage_sample.png -------------------------------------------------------------------------------- /media/semantic-model-configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/semantic-model-configuration.png -------------------------------------------------------------------------------- /media/semantic-model-configuration02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/semantic-model-configuration02.png -------------------------------------------------------------------------------- /media/sharepoint-record-app-id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/sharepoint-record-app-id.png -------------------------------------------------------------------------------- /media/sharepoint-register-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/sharepoint-register-app.png -------------------------------------------------------------------------------- /media/sharepoint-secret-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/sharepoint-secret-app.png -------------------------------------------------------------------------------- /media/sharepoint-site-id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/sharepoint-site-id.png -------------------------------------------------------------------------------- /media/sharepoint-site-permissions-403-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/sharepoint-site-permissions-403-02.png -------------------------------------------------------------------------------- /media/sharepoint-site-permissions-403.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/sharepoint-site-permissions-403.png -------------------------------------------------------------------------------- /media/sharepoint-site-permissions-created.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/sharepoint-site-permissions-created.png -------------------------------------------------------------------------------- /media/sharepoint-site-selected-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/sharepoint-site-selected-app.png -------------------------------------------------------------------------------- /media/sharepoint-site-url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/sharepoint-site-url.png -------------------------------------------------------------------------------- /media/teams-guide-Step1a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step1a.png -------------------------------------------------------------------------------- /media/teams-guide-Step1b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step1b.png -------------------------------------------------------------------------------- /media/teams-guide-Step1c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step1c.png -------------------------------------------------------------------------------- /media/teams-guide-Step1d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step1d.png -------------------------------------------------------------------------------- /media/teams-guide-Step1e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step1e.png -------------------------------------------------------------------------------- /media/teams-guide-Step2b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step2b.png -------------------------------------------------------------------------------- /media/teams-guide-Step3a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3a.png -------------------------------------------------------------------------------- /media/teams-guide-Step3b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3b.png -------------------------------------------------------------------------------- /media/teams-guide-Step3c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3c.png -------------------------------------------------------------------------------- /media/teams-guide-Step3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3d.png -------------------------------------------------------------------------------- /media/teams-guide-Step3e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3e.png -------------------------------------------------------------------------------- /media/teams-guide-Step3f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3f.png -------------------------------------------------------------------------------- /media/teams-guide-Step3g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3g.png -------------------------------------------------------------------------------- /media/teams-guide-Step3h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3h.png -------------------------------------------------------------------------------- /media/teams-guide-Step3i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3i.png -------------------------------------------------------------------------------- /media/teams-guide-Step3j.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3j.png -------------------------------------------------------------------------------- /media/teams-guide-Step3k.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3k.png -------------------------------------------------------------------------------- /media/teams-guide-Step3l.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3l.png -------------------------------------------------------------------------------- /media/teams-guide-Step3m.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3m.png -------------------------------------------------------------------------------- /media/teams-guide-Step3n.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step3n.png -------------------------------------------------------------------------------- /media/teams-guide-Step4a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step4a.png -------------------------------------------------------------------------------- /media/teams-guide-Step4b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step4b.png -------------------------------------------------------------------------------- /media/teams-guide-Step4c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step4c.png -------------------------------------------------------------------------------- /media/teams-guide-Step4d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step4d.png -------------------------------------------------------------------------------- /media/teams-guide-Step4e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step4e.png -------------------------------------------------------------------------------- /media/teams-guide-Step5a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step5a.png -------------------------------------------------------------------------------- /media/teams-guide-Step5b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step5b.png -------------------------------------------------------------------------------- /media/teams-guide-Step5c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step5c.png -------------------------------------------------------------------------------- /media/teams-guide-Step5d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step5d.png -------------------------------------------------------------------------------- /media/teams-guide-Step5e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step5e.png -------------------------------------------------------------------------------- /media/teams-guide-Step5f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step5f.png -------------------------------------------------------------------------------- /media/teams-guide-Step5g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step5g.png -------------------------------------------------------------------------------- /media/teams-guide-Step5h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/media/teams-guide-Step5h.png -------------------------------------------------------------------------------- /misc/GPT-RAG-PowerBI-Report.pbit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/misc/GPT-RAG-PowerBI-Report.pbit -------------------------------------------------------------------------------- /misc/gptrag_resources_and_permissions.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Azure/GPT-RAG/74653b53d93c1ae5001a3d46c0143c7294870169/misc/gptrag_resources_and_permissions.xlsx -------------------------------------------------------------------------------- /scripts/cleanComponents.ps1: -------------------------------------------------------------------------------- 1 | # Delete the gpt-rag-ingestion folder from .azure if it exists 2 | if (Test-Path -Path ".\.azure\gpt-rag-ingestion") { 3 | Remove-Item -Path ".\.azure\gpt-rag-ingestion" -Recurse -Force 4 | } 5 | 6 | # Delete the gpt-rag-orchestrator folder from .azure if it exists 7 | if (Test-Path -Path ".\.azure\gpt-rag-orchestrator") { 8 | Remove-Item -Path ".\.azure\gpt-rag-orchestrator" -Recurse -Force 9 | } 10 | 11 | # Delete the gpt-rag-frontend folder from .azure if it exists 12 | if (Test-Path -Path ".\.azure\gpt-rag-frontend") { 13 | Remove-Item -Path ".\.azure\gpt-rag-frontend" -Recurse -Force 14 | } 15 | -------------------------------------------------------------------------------- /scripts/cleanComponents.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Delete the gpt-rag-ingestion folder from .azure if it exists 4 | if [ -d ./.azure/gpt-rag-ingestion ]; then 5 | rm -rf ./.azure/gpt-rag-ingestion 6 | fi 7 | 8 | # Delete the gpt-rag-orchestrator folder from .azure if it exists 9 | if [ -d ./.azure/gpt-rag-orchestrator ]; then 10 | rm -rf ./.azure/gpt-rag-orchestrator 11 | fi 12 | 13 | # Delete the gpt-rag-frontend folder from .azure if it exists 14 | if [ -d ./.azure/gpt-rag-frontend ]; then 15 | rm -rf ./.azure/gpt-rag-frontend 16 | fi 17 | -------------------------------------------------------------------------------- /scripts/fetchComponents.ps1: -------------------------------------------------------------------------------- 1 | # Delete the gpt-rag-ingestion folder from .azure if it exists 2 | if (Test-Path -Path ".\.azure\gpt-rag-ingestion") { 3 | Remove-Item -Path ".\.azure\gpt-rag-ingestion" -Recurse -Force 4 | } 5 | 6 | # Clone the repository into the .azure folder 7 | git clone https://github.com/Azure/gpt-rag-ingestion .\.azure\gpt-rag-ingestion 8 | 9 | # Delete the gpt-rag-orchestrator folder from .azure if it exists 10 | if (Test-Path -Path ".\.azure\gpt-rag-orchestrator") { 11 | Remove-Item -Path ".\.azure\gpt-rag-orchestrator" -Recurse -Force 12 | } 13 | 14 | # Clone the repository into the .azure folder 15 | git clone https://github.com/Azure/gpt-rag-orchestrator .\.azure\gpt-rag-orchestrator 16 | 17 | # Delete the gpt-rag-frontend folder from .azure if it exists 18 | if (Test-Path -Path ".\.azure\gpt-rag-frontend") { 19 | Remove-Item -Path ".\.azure\gpt-rag-frontend" -Recurse -Force 20 | } 21 | 22 | # Clone the repository into the .azure folder 23 | git clone https://github.com/Azure/gpt-rag-frontend .\.azure\gpt-rag-frontend 24 | -------------------------------------------------------------------------------- /scripts/fetchComponents.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Delete the gpt-rag-ingestion folder from .azure if it exists 4 | if [ -d ./.azure/gpt-rag-ingestion ]; then 5 | rm -rf ./.azure/gpt-rag-ingestion 6 | fi 7 | 8 | # Clone the repository into the .azure folder 9 | git clone https://github.com/Azure/gpt-rag-ingestion ./.azure/gpt-rag-ingestion 10 | 11 | # Delete the gpt-rag-orchestrator folder from .azure if it exists 12 | if [ -d ./.azure/gpt-rag-orchestrator ]; then 13 | rm -rf ./.azure/gpt-rag-orchestrator 14 | fi 15 | 16 | # Clone the repository into the .azure folder 17 | git clone https://github.com/Azure/gpt-rag-orchestrator ./.azure/gpt-rag-orchestrator 18 | 19 | # Delete the gpt-rag-frontend folder from .azure if it exists 20 | if [ -d ./.azure/gpt-rag-frontend ]; then 21 | rm -rf ./.azure/gpt-rag-frontend 22 | fi 23 | 24 | # Clone the repository into the .azure folder 25 | git clone https://github.com/Azure/gpt-rag-frontend ./.azure/gpt-rag-frontend 26 | -------------------------------------------------------------------------------- /scripts/postprovision.ps1: -------------------------------------------------------------------------------- 1 | $YELLOW = [ConsoleColor]::Yellow 2 | $BLUE = [ConsoleColor]::Blue 3 | $NC = [ConsoleColor]::White 4 | 5 | $resourceGroupName = $env:AZURE_RESOURCE_GROUP_NAME 6 | $subscriptionId = $env:AZURE_SUBSCRIPTION_ID 7 | $tenantId = $env:AZURE_TENANT_ID 8 | 9 | # Creating a new RAI policy and attaching to deployed OpenAI model. 10 | $aoaiResourceName = $env:AZURE_OPENAI_SERVICE_NAME 11 | $aoaiModelName = $env:AZURE_CHAT_GPT_DEPLOYMENT_NAME 12 | 13 | # Check conditions 14 | # RAI script: AOAI content filters 15 | $RAIscript = Join-Path -Path $PSScriptRoot -ChildPath 'rai\raipolicies.ps1' 16 | & $RAIscript -Tenant $tenantId -Subscription $subscriptionId -ResourceGroup $resourceGroupName -AoaiResourceName $aoaiResourceName -AoaiModelName $aoaiModelName -RaiPolicyName 'MainRAIpolicy' -RaiBlocklistName 'MainBlockListPolicy' 17 | 18 | if ($env:AZURE_ZERO_TRUST -eq "FALSE") { 19 | exit 0 20 | } 21 | 22 | Write-Host "For accessing the Zero Trust infrastructure, from the Azure Portal:" 23 | Write-Host "Virtual Machine: $($env:AZURE_VM_NAME)" 24 | Write-Host "Select connect using Bastion with:" 25 | Write-Host " username: $($env:AZURE_VM_USER_NAME)" 26 | Write-Host " Key Vault/Secret: $($env:AZURE_BASTION_KV_NAME)/$($env:AZURE_VM_KV_SEC_NAME)" -------------------------------------------------------------------------------- /scripts/postprovision.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ## Provides a head's up to user for AZURE_NETWORK_ISOLATION 4 | 5 | YELLOW='\033[0;33m' 6 | BLUE='\033[0;34m' 7 | NC='\033[0m' # No Color 8 | 9 | resourceGroupName="$AZURE_RESOURCE_GROUP_NAME" 10 | subscriptionId="$AZURE_SUBSCRIPTION_ID" 11 | tenantId="$AZURE_TENANT_ID" 12 | 13 | # Creating a new RAI policy and attaching to deployed OpenAI model. 14 | aoaiResourceName="$AZURE_OPENAI_SERVICE_NAME" 15 | aoaiModelName="$AZURE_CHAT_GPT_DEPLOYMENT_NAME" 16 | 17 | # Extract values without jq 18 | deployDataIngestion=$(echo $AZURE_COMPONENT_CONFIG | grep -o '"deployDataIngestion":"[^"]*' | grep -o '[^"]*$') 19 | deployOrchestrator=$(echo $AZURE_COMPONENT_CONFIG | grep -o '"deployOrchestrator":"[^"]*' | grep -o '[^"]*$') 20 | 21 | # RAI script: AOAI content filters 22 | cd $PWD/scripts/rai 23 | ./raipolicies.sh $tenantId $subscriptionId $resourceGroupName $aoaiResourceName $aoaiModelName "MainRAIpolicy" "MainBlockListPolicy" 24 | 25 | if [ "$AZURE_ZERO_TRUST" = "FALSE" ]; then 26 | exit 0 27 | fi 28 | 29 | echo "For accessing the ${YELLOW}Zero Trust infrastructure${NC}, from the Azure Portal:" 30 | echo "Virtual Machine: ${BLUE}$AZURE_VM_NAME${NC}" 31 | echo "Select connect using Bastion with:" 32 | echo " username: $AZURE_VM_USER_NAME" 33 | echo " Key Vault/Secret: ${BLUE}$AZURE_BASTION_KV_NAME${NC}/${BLUE}$AZURE_VM_KV_SEC_NAME${NC}" 34 | -------------------------------------------------------------------------------- /scripts/preDeploy.ps1: -------------------------------------------------------------------------------- 1 | if ($env:AZURE_ZERO_TRUST -eq "TRUE") { 2 | # Prompt for user confirmation 3 | $confirmation = Read-Host -Prompt "Zero Trust Infrastructure enabled. Confirm you are using a connection where resources are reachable (like VM+Bastion)? [Y/n]" 4 | 5 | # Check if the confirmation is positive 6 | if ($confirmation -ne "Y" -and $confirmation -ne "y" -and $confirmation) { 7 | exit 1 8 | } 9 | exit 0 10 | } 11 | -------------------------------------------------------------------------------- /scripts/preDeploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "$AZURE_ZERO_TRUST" = "TRUE" ]; then 4 | # Prompt for user confirmation 5 | echo -n "Zero Trust Infrastructe enabled. Confirm you are using a connection where resources are reachable (like VM+Bastion)? [Y/n]: " 6 | read confirmation 7 | 8 | # Check if the confirmation is positive 9 | if [ "$confirmation" != "Y" ] && [ "$confirmation" != "y" ] && [ -n "$confirmation" ]; then 10 | exit 1 11 | fi 12 | exit 0 13 | fi 14 | -------------------------------------------------------------------------------- /scripts/preprovision.ps1: -------------------------------------------------------------------------------- 1 | ## Provides a head's up to user for AZURE_NETWORK_ISOLATION 2 | 3 | # Check if AZURE_NETWORK_ISOLATION environment variable is defined 4 | if (-not $env:AZURE_NETWORK_ISOLATION) { 5 | exit 0 6 | } 7 | 8 | # Check if AZURE_NETWORK_ISOLATION environment variable is set to a positive value 9 | if ($env:AZURE_NETWORK_ISOLATION -match '^[1-9][0-9]*$' -or $env:AZURE_NETWORK_ISOLATION -match '^[Tt][Rr][Uu][Ee]$' -or $env:AZURE_NETWORK_ISOLATION -match '^[Tt]$') { 10 | 11 | # Display a heads up warning 12 | Write-Host "Heads up! AZURE_NETWORK_ISOLATION is set to a positive value." 13 | 14 | # Prompt for user confirmation 15 | $confirmation = Read-Host "Continue with the script? [Y/n]: " 16 | 17 | # Check if the confirmation is positive 18 | if ($confirmation -ne "Y" -and $confirmation -ne "y" -and $confirmation) { 19 | exit 1 20 | } 21 | } 22 | 23 | exit 0 24 | -------------------------------------------------------------------------------- /scripts/preprovision.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ## Provides a head's up to user for AZURE_NETWORK_ISOLATION 4 | 5 | YELLOW='\033[0;33m' 6 | BLUE='\033[0;34m' 7 | GREEN='\033[0;32m' 8 | NC='\033[0m' # No Color 9 | 10 | # Check if AZURE_NETWORK_ISOLATION environment variable is defined 11 | if [ -z "$AZURE_NETWORK_ISOLATION" ]; then 12 | exit 0 13 | fi 14 | 15 | # AZURE_SKIP_NETWORK_ISOLATION_WARNING explicit no-warning requested 16 | if [ "$AZURE_SKIP_NETWORK_ISOLATION_WARNING" -ge 1 ] 2>/dev/null || [ "$AZURE_SKIP_NETWORK_ISOLATION_WARNING" = "true" ] || [ "$AZURE_SKIP_NETWORK_ISOLATION_WARNING" = "t" ]; then 17 | exit 0 18 | fi 19 | 20 | # Check if AZURE_NETWORK_ISOLATION environment variable is set to a positive value 21 | if [ "$AZURE_NETWORK_ISOLATION" -ge 1 ] 2>/dev/null || [ "$AZURE_NETWORK_ISOLATION" = "true" ] || [ "$AZURE_NETWORK_ISOLATION" = "t" ]; then 22 | 23 | # Display a heads up warning 24 | echo "${YELLOW}Warning!${NC} AZURE_NETWORK_ISOLATION is set." 25 | echo " - After provisioning, you need to switch to the ${GREEN}VirtualMachine & Bastion${NC} to continue deploying components." 26 | echo " - Infrastucture will be only reachable from within the Bastion host." 27 | 28 | # Prompt for user confirmation 29 | echo -n "${BLUE}?${NC} Continue with Zero Trust provisioning? [Y/n]: " 30 | read confirmation 31 | 32 | # Check if the confirmation is positive 33 | if [ "$confirmation" != "Y" ] && [ "$confirmation" != "y" ] && [ -n "$confirmation" ]; then 34 | exit 1 35 | fi 36 | fi 37 | 38 | exit 0 -------------------------------------------------------------------------------- /scripts/rai/raiblocklist.json: -------------------------------------------------------------------------------- 1 | { 2 | "blocklistname": "{{BlocklistName}}", 3 | "blocklistItems": [ 4 | { 5 | "pattern": "", 6 | "isRegex": false 7 | } 8 | ] 9 | } -------------------------------------------------------------------------------- /scripts/rai/raipolicies.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "{{PolicyName}}", 3 | "properties": { 4 | "basePolicyName": "Microsoft.Default", 5 | "type": "UserManaged", 6 | "contentFilters": [ 7 | { 8 | "name": "hate", 9 | "blocking": true, 10 | "enabled": true, 11 | "allowedContentLevel": "medium", 12 | "source": "prompt" 13 | }, 14 | { 15 | "name": "sexual", 16 | "blocking": true, 17 | "enabled": true, 18 | "allowedContentLevel": "medium", 19 | "source": "prompt" 20 | }, 21 | { 22 | "name": "selfharm", 23 | "blocking": true, 24 | "enabled": true, 25 | "allowedContentLevel": "medium", 26 | "source": "prompt" 27 | }, 28 | { 29 | "name": "violence", 30 | "blocking": true, 31 | "enabled": true, 32 | "allowedContentLevel": "medium", 33 | "source": "prompt" 34 | }, 35 | { 36 | "name": "hate", 37 | "blocking": true, 38 | "enabled": true, 39 | "allowedContentLevel": "medium", 40 | "source": "completion" 41 | }, 42 | { 43 | "name": "sexual", 44 | "blocking": true, 45 | "enabled": true, 46 | "allowedContentLevel": "medium", 47 | "source": "completion" 48 | }, 49 | { 50 | "name": "selfharm", 51 | "blocking": true, 52 | "enabled": true, 53 | "allowedContentLevel": "medium", 54 | "source": "completion" 55 | }, 56 | { 57 | "name": "violence", 58 | "blocking": true, 59 | "enabled": true, 60 | "allowedContentLevel": "medium", 61 | "source": "completion" 62 | }, 63 | { 64 | "name": "jailbreak", 65 | "blocking": false, 66 | "source": "prompt", 67 | "enabled": false 68 | }, 69 | { 70 | "name": "protected_material_text", 71 | "blocking": false, 72 | "source": "completion", 73 | "enabled": false 74 | }, 75 | { 76 | "name": "protected_material_code", 77 | "blocking": false, 78 | "source": "completion", 79 | "enabled": false 80 | } 81 | ], 82 | "promptBlocklists" : [ 83 | { 84 | "blocking": true, 85 | "blocklistName": "{{BlocklistName}}" 86 | } 87 | ], 88 | "completionBlocklists" : [ 89 | { 90 | "blocking": true, 91 | "blocklistName": "{{BlocklistName}}" 92 | } 93 | ], 94 | "mode": "default" 95 | } 96 | } -------------------------------------------------------------------------------- /scripts/rai/raipolicies.ps1: -------------------------------------------------------------------------------- 1 | param ( 2 | [string]$Tenant, 3 | [string]$Subscription, 4 | [string]$ResourceGroup, 5 | [string]$AoaiResourceName, 6 | [string]$AoaiModelName, 7 | [string]$RaiPolicyName, 8 | [string]$RaiBlocklistName 9 | ) 10 | 11 | Write-Host "RAI Script: Setting up AOAI content filters & blocklist" 12 | 13 | $token = az account get-access-token --tenant "$Tenant" --query accessToken --output tsv 14 | 15 | if ([string]::IsNullOrWhiteSpace($token)) { 16 | Write-Host "Failed to get access token. Please manually sign-in to Azure account" 17 | az login --use-device-code 18 | $token = az account get-access-token --tenant "$Tenant" --query accessToken --output tsv 19 | } 20 | 21 | $headers = @{ 22 | Authorization = "Bearer $token" 23 | "Content-Type" = "application/json" 24 | } 25 | 26 | $baseURI = "https://management.azure.com/subscriptions/$Subscription/resourceGroups/$ResourceGroup/providers/Microsoft.CognitiveServices/accounts/$AoaiResourceName" 27 | 28 | # Creating a blocklist for AOAI account 29 | $filePath = Join-Path -Path $PSScriptRoot -ChildPath 'raiblocklist.json' 30 | $blocklistJson = (Get-Content -Path $filePath -Raw).Replace("{{BlocklistName}}", $RaiBlocklistName) | ConvertFrom-Json 31 | 32 | $blocklistName = $blocklistJson.blocklistname 33 | $blocklistItems = $blocklistJson.blocklistItems 34 | 35 | $blocklistBody = [PSCustomObject]@{ 36 | properties = [PSCustomObject]@{ 37 | description = "$($blocklistName) blocklist policy" 38 | } 39 | } 40 | 41 | $blocklistURI = $baseURI + "/raiBlocklists/$($blocklistName)?api-version=2023-10-01-preview" 42 | Invoke-RestMethod -Uri $blocklistURI -Method Put -Body ($blocklistBody | ConvertTo-Json) -Headers $headers | Out-Null 43 | 44 | $blocklistItemsURI = $baseURI + "/raiBlocklists/$($blocklistName)/raiBlocklistItems/$($blocklistName)Items?api-version=2023-10-01-preview" 45 | 46 | # Remove previous items from blocklist 47 | # - This covers scenario where blocklist items get updated in existing deployment 48 | do { 49 | Try { 50 | Invoke-RestMethod -Uri $blocklistItemsURI -Method Delete -Headers $headers | Out-Null 51 | } Catch { 52 | break 53 | } 54 | } while ($true) 55 | 56 | # Add items into blocklist 57 | foreach ($item in $blocklistItems) { 58 | if ($item.pattern) { 59 | $blocklistItemsBody = [PSCustomObject]@{ 60 | properties = [PSCustomObject]@{ 61 | pattern = $item.pattern 62 | isRegex = $item.isRegex 63 | } 64 | } 65 | 66 | Invoke-RestMethod -Uri $blocklistItemsURI -Method Put -Body ($blocklistItemsBody | ConvertTo-Json) -Headers $headers | Out-Null 67 | } 68 | } 69 | 70 | # Creating a content filter policy for AOAI account 71 | $filePath = Join-Path -Path $PSScriptRoot -ChildPath 'raipolicies.json' 72 | $policyBody = (Get-Content -Path $filePath -Raw).Replace("{{PolicyName}}", $RaiPolicyName).Replace("{{BlocklistName}}", $blocklistName) 73 | 74 | $policyURI = $baseURI + "/raiPolicies/$($RaiPolicyName)?api-version=2023-10-01-preview" 75 | Invoke-RestMethod -Uri $policyURI -Method Put -Body $policyBody -Headers $headers | Out-Null 76 | 77 | # Getting deployed AOAI model profile 78 | $modelURI = $baseURI + "/deployments/$($AoaiModelName)?api-version=2023-10-01-preview" 79 | $modelDeployments = Invoke-RestMethod -Uri $modelURI -Method Get -Headers $headers 80 | $model = $modelDeployments | Where-Object name -eq $AoaiModelName | Select-Object -First 1 81 | 82 | # Assign created policy to model profile 83 | $updatedModel = [PSCustomObject]@{ 84 | displayName = $ModelName 85 | sku = $model.sku 86 | properties = [PSCustomObject]@{ 87 | model = $model.properties.model 88 | versionUpgradeOption = $model.properties.versionUpgradeOption 89 | raiPolicyName = $RaiPolicyName 90 | } 91 | } 92 | Invoke-RestMethod -Uri $modelURI -Method Put -Body ($updatedModel | ConvertTo-Json) -Headers $headers | Out-Null 93 | -------------------------------------------------------------------------------- /scripts/rai/raipolicies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Parameters 4 | Tenant="$1" 5 | Subscription="$2" 6 | ResourceGroup="$3" 7 | AoaiResourceName="$4" 8 | AoaiModelName="$5" 9 | RaiPolicyName="$6" 10 | RaiBlocklistName="$7" 11 | 12 | echo "RAI Script: Setting up AOAI content filters & blocklist" 13 | 14 | # Get access token 15 | token=$(az account get-access-token --tenant "$Tenant" --query accessToken --output tsv) 16 | if [ -z "$token" ]; then 17 | echo "No access token found. Please follow the instructon below to log in to your Azure account." 18 | az login --use-device-code 19 | fi 20 | 21 | # Set headers 22 | headers=( 23 | "Authorization: Bearer $token" 24 | "Content-Type: application/json" 25 | ) 26 | 27 | baseURI="https://management.azure.com/subscriptions/$Subscription/resourceGroups/$ResourceGroup/providers/Microsoft.CognitiveServices/accounts/$AoaiResourceName" 28 | 29 | # Creating a blocklist for AOAI account 30 | filePath="$PWD/raiblocklist.json" 31 | blocklistJson=$(cat "$filePath" | sed "s/{{BlocklistName}}/$RaiBlocklistName/g") 32 | blocklistName=$(echo "$blocklistJson" | awk -F'"' '/blocklistname/ {print $4}') 33 | 34 | blocklistDescription="$blocklistName blocklist policy" 35 | blocklistBody="{\"properties\": {\"description\": \"$blocklistDescription\"}}" 36 | blocklistURI="$baseURI/raiBlocklists/$blocklistName?api-version=2023-10-01-preview" 37 | curl -s -X PUT -H "${headers[0]}" -H "${headers[1]}" -o /dev/null -d "$blocklistBody" "$blocklistURI" 38 | 39 | blocklistItemsURI="$baseURI/raiBlocklists/$blocklistName/raiBlocklistItems/${blocklistName}Items?api-version=2023-10-01-preview" 40 | 41 | # Remove previous items from blocklist 42 | # - This covers scenario where blocklist items get updated in existing deployment 43 | while true; do 44 | response=$(curl -s -X DELETE -H "${headers[0]}" -H "${headers[1]}" -o /dev/null -w "%{http_code}" "$blocklistItemsURI") 45 | if [[ "$response" != 2* ]]; then 46 | break 47 | fi 48 | done 49 | 50 | # Extract blocklistItems content using awk and sed 51 | blocklistItems=$(echo "$blocklistJson" | awk '/"blocklistItems": \[/,/\]/' | sed '1d;$d') 52 | 53 | # Extract individual patterns and isRegex values 54 | patterns=$(echo "$blocklistItems" | grep '"pattern":' | sed 's/.*"pattern": "\(.*\)".*/\1/') 55 | isRegexes=$(echo "$blocklistItems" | grep '"isRegex":' | sed 's/.*"isRegex": \(.*\)/\1/') 56 | 57 | # Convert strings to arrays 58 | IFS=$'\n' patternsArray=($patterns) 59 | IFS=$'\n' isRegexesArray=($isRegexes) 60 | 61 | # Loop through each item and add it to blocklist 62 | for i in "${!patternsArray[@]}"; do 63 | pattern=${patternsArray[$i]} 64 | isRegex=${isRegexesArray[$i]} 65 | 66 | blocklistItemsBody="{\"properties\": {\"pattern\": \"$pattern\", \"isRegex\": $isRegex}}" 67 | curl -s -X PUT -H "${headers[0]}" -H "${headers[1]}" -o /dev/null -d "$blocklistItemsBody" "$blocklistItemsURI" 68 | done 69 | 70 | # Create content filter policy for AOAI account 71 | filePath="$PWD/raipolicies.json" 72 | policyBody=$(cat "$filePath" | sed "s/{{PolicyName}}/$RaiPolicyName/" | sed "s/{{BlocklistName}}/$RaiBlocklistName/") 73 | policyURI="$baseURI/raiPolicies/$RaiPolicyName?api-version=2023-10-01-preview" 74 | curl -s -X PUT -H "${headers[0]}" -H "${headers[1]}" -d "$policyBody" -o /dev/null "$policyURI" 75 | 76 | # Get deployed AOAI model profile 77 | modelURI="$baseURI/deployments/$AoaiModelName?api-version=2023-10-01-preview" 78 | modelDeployments=$(curl -s -H "${headers[0]}" "$modelURI") 79 | 80 | # Extract the model object 81 | while read -r line; do 82 | if [[ "$line" == *"$AoaiModelName"* ]]; then 83 | model="$line" 84 | break 85 | fi 86 | done <<< "$modelDeployments" 87 | 88 | modelSkuName=$(echo "$model" | sed -En 's/.*"sku":\{"name":"([^"]*).*/\1/p') 89 | modelSkuCapacity=$(echo "$model" | sed -En 's/.*"sku":\{"name":"[^"]*","capacity":([0-9]*).*/\1/p') 90 | modelFormat=$(echo "$model" | sed -En 's/.*"model":\{"format":"([^"]*).*/\1/p') 91 | modelName=$(echo "$model" | sed -En 's/.*"model":\{"format":"[^"]*","name":"([^"]*).*/\1/p') 92 | modelVersion=$(echo "$model" | sed -En 's/.*"model":\{"format":"[^"]*","name":"[^"]*","version":"([^"]*).*/\1/p') 93 | modelVUpgOps=$(echo "$model" | sed -En 's/.*"versionUpgradeOption":"([^"]*).*/\1/p') 94 | 95 | updatedModel=$(printf '{ 96 | "displayName": "%s", 97 | "sku": { 98 | "name": "%s", 99 | "capacity": "%s" 100 | }, 101 | "properties": { 102 | "model": { 103 | "format": "%s", 104 | "name": "%s", 105 | "version": "%s" 106 | }, 107 | "versionUpgradeOption": "%s", 108 | "raiPolicyName": "%s" 109 | } 110 | }' "$AoaiModelName" "$modelSkuName" "$modelSkuCapacity" "$modelFormat" "$modelName" "$modelVersion" "$modelVUpgOps" "$RaiPolicyName") 111 | 112 | curl -s -X PUT -H "${headers[0]}" -H "${headers[1]}" -o /dev/null -d "$updatedModel" "$modelURI" --------------------------------------------------------------------------------