diff --git a/.gitignore b/.gitignore index 0bd4239ca..83208207f 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ yarn-error.log* # local env files .env*.local +.env # typescript *.tsbuildinfo diff --git a/README.md b/README.md index dad35ef84..7f6f9914e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Unleash the Power of Azure Open AI +# Unleash the Power of Azure OpenAI 1. [Introduction](#introduction) 1. [Solution Overview](/docs/1-introduction.md) @@ -14,11 +14,11 @@ # Introduction -_Azure Chat Solution Accelerator powered by Azure Open AI Service_ +_Azure Chat Solution Accelerator powered by Azure OpenAI Service_ ![](/docs/images/intro.png) -_Azure Chat Solution Accelerator powered by Azure Open AI Service_ is a solution accelerator that allows organisations to deploy a private chat tenant in their Azure Subscription, with a familiar user experience and the added capabilities of chatting over your data and files. +_Azure Chat Solution Accelerator powered by Azure OpenAI Service_ is a solution accelerator that allows organisations to deploy a private chat tenant in their Azure Subscription, with a familiar user experience and the added capabilities of chatting over your data and files. Benefits are: diff --git a/docs/8-extensions.md b/docs/8-extensions.md index 992a287cd..1b50fcecb 100644 --- a/docs/8-extensions.md +++ b/docs/8-extensions.md @@ -47,6 +47,9 @@ As an example you can create an extension that calls Bing Search API to search f In the example below only the `query` is required as Bing does not require a body parameter. +> [!NOTE] +> As header values specified for an extension often contain secrets (e.g. API keys) Azure Chat stores those values securely in Azure Key Vault. If you are deploying the solution to Azure using azd or the bicep templates the required Key Vault role assignment is automatically created. If you are running the solution locally you will need to manually add the "Key Vault Secrets Officer" role to identy that is running the solution (wh8ch will typically be the user logged into the Azure CLI) + # Bing Search Extension 1. **Name**: `Bing Search` diff --git a/docs/migration.md b/docs/migration.md index 3e71e7d2d..82de9c1db 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -1,4 +1,8 @@ -# Migration +# Migration 2.1 + +The new changes merges GPT-4 and GPT-4 Vision models into a single GPT-4o model. This allows multi-modal inputs and generates text as an output. The new model is available within the following [regions](https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/models#gpt-4-and-gpt-4-turbo-preview-model-availability). + +# Migration 2.0 The following changes and services are required to migrate from the old version to the new version. @@ -6,10 +10,10 @@ Refer the `.env.example` file for the latest environment variable changes. If you previously had Azure Chat running and have pulled the v2 version you will need at minimum to make the following changes: -* Change the "OPENAI_API_KEY" environment setting to "AZURE_OPENAI_API_KEY" -* Add an additional container to your Cosmos DB database called "config" with a partition key of "/userId" -* Add the "AZURE_KEY_VAULT_NAME" environment setting with the name of your Azure Key Vault -* Add the "New Azure Services" settings below if you wish to use these features +- Change the "OPENAI_API_KEY" environment setting to "AZURE_OPENAI_API_KEY" +- Add an additional container to your Cosmos DB database called "config" with a partition key of "/userId" +- Add the "AZURE_KEY_VAULT_NAME" environment setting with the name of your Azure Key Vault +- Add the "New Azure Services" settings below if you wish to use these features ## New Azure Services diff --git a/infra/main.bicep b/infra/main.bicep index c6e2f3ad7..f15740ad5 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -9,9 +9,9 @@ param name string @description('Primary location for all resources') param location string -// azure open ai -- only regions supporting gpt-35-turbo v1106 +// azure open ai -- regions currently support gpt-4o global-standard @description('Location for the OpenAI resource group') -@allowed(['australiaeast', 'canadaeast', 'francecentral', 'southindia', 'uksouth', 'swedencentral', 'westus']) +@allowed(['australiaeast', 'brazilsouth', 'canadaeast', 'eastus', 'eastus2', 'francecentral', 'germanywestcentral', 'japaneast', 'koreacentral', 'northcentralus', 'norwayeast', 'polandcentral', 'spaincentral', 'southafricanorth', 'southcentralus', 'southindia', 'swedencentral', 'switzerlandnorth', 'uksouth', 'westeurope', 'westus', 'westus3']) @metadata({ azd: { type: 'location' @@ -20,19 +20,19 @@ param location string param openAILocation string param openAISku string = 'S0' -param openAIApiVersion string = '2023-12-01-preview' +param openAIApiVersion string ='2024-08-01-preview' -param chatGptDeploymentCapacity int = 120 -param chatGptDeploymentName string = 'chat-gpt-35-turbo' -param chatGptModelName string = 'gpt-35-turbo' -param chatGptModelVersion string = '1106' +param chatGptDeploymentCapacity int = 30 +param chatGptDeploymentName string = 'gpt-4o' +param chatGptModelName string = 'gpt-4o' +param chatGptModelVersion string = '2024-05-13' param embeddingDeploymentName string = 'embedding' param embeddingDeploymentCapacity int = 120 param embeddingModelName string = 'text-embedding-ada-002' -// DALL-E v3 only supported in Sweden Central for now +// DALL-E v3 only supported in limited regions for now @description('Location for the OpenAI DALL-E 3 instance resource group') -@allowed(['swedencentral']) +@allowed(['swedencentral', 'eastus', 'australiaeast']) param dalleLocation string param dalleDeploymentCapacity int = 1 @@ -40,17 +40,6 @@ param dalleDeploymentName string = 'dall-e-3' param dalleModelName string = 'dall-e-3' param dalleApiVersion string = '2023-12-01-preview' -// DALL-E v3 only supported in Sweden Central for now -@description('Location for the GPT vision instance resource') -@allowed(['swedencentral','westus',]) -param gptvisionLocation string - -param gptvisionDeploymentCapacity int = 1 -param gptvisionDeploymentName string = 'gpt-4-vision' -param gptvisionModelName string = 'gpt-4' -param gptvisionApiVersion string = '2023-12-01-preview' -param gptvisionModelVersion string = 'vision-preview' - param formRecognizerSkuName string = 'S0' param searchServiceIndexName string = 'azure-chat' param searchServiceSkuName string = 'standard' @@ -93,12 +82,6 @@ module resources 'resources.bicep' = { dalleDeploymentName: dalleDeploymentName dalleModelName: dalleModelName dalleApiVersion: dalleApiVersion - gptvisionLocation: gptvisionLocation - gptvisionApiVersion: gptvisionApiVersion - gptvisionDeploymentCapacity: gptvisionDeploymentCapacity - gptvisionDeploymentName: gptvisionDeploymentName - gptvisionModelName: gptvisionModelName - gptvisionModelVersion: gptvisionModelVersion formRecognizerSkuName: formRecognizerSkuName searchServiceIndexName: searchServiceIndexName searchServiceSkuName: searchServiceSkuName diff --git a/infra/main.json b/infra/main.json index 25d7ee091..397308da6 100644 --- a/infra/main.json +++ b/infra/main.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "16779160080190232837" + "version": "0.29.47.4906", + "templateHash": "18214004695586675733" } }, "parameters": { @@ -48,23 +48,23 @@ }, "openAIApiVersion": { "type": "string", - "defaultValue": "2023-12-01-preview" + "defaultValue": "2024-05-13" }, "chatGptDeploymentCapacity": { "type": "int", - "defaultValue": 120 + "defaultValue": 30 }, "chatGptDeploymentName": { "type": "string", - "defaultValue": "chat-gpt-35-turbo" + "defaultValue": "gpt-4o" }, "chatGptModelName": { "type": "string", - "defaultValue": "gpt-35-turbo" + "defaultValue": "gpt-4o" }, "chatGptModelVersion": { "type": "string", - "defaultValue": "1106" + "defaultValue": "2024-05-13" }, "embeddingDeploymentName": { "type": "string", @@ -103,36 +103,6 @@ "type": "string", "defaultValue": "2023-12-01-preview" }, - "gptvisionLocation": { - "type": "string", - "allowedValues": [ - "swedencentral", - "westus" - ], - "metadata": { - "description": "Location for the GPT vision instance resource" - } - }, - "gptvisionDeploymentCapacity": { - "type": "int", - "defaultValue": 1 - }, - "gptvisionDeploymentName": { - "type": "string", - "defaultValue": "gpt-4-vision" - }, - "gptvisionModelName": { - "type": "string", - "defaultValue": "gpt-4" - }, - "gptvisionApiVersion": { - "type": "string", - "defaultValue": "2023-12-01-preview" - }, - "gptvisionModelVersion": { - "type": "string", - "defaultValue": "vision-preview" - }, "formRecognizerSkuName": { "type": "string", "defaultValue": "S0" @@ -239,24 +209,6 @@ "dalleApiVersion": { "value": "[parameters('dalleApiVersion')]" }, - "gptvisionLocation": { - "value": "[parameters('gptvisionLocation')]" - }, - "gptvisionApiVersion": { - "value": "[parameters('gptvisionApiVersion')]" - }, - "gptvisionDeploymentCapacity": { - "value": "[parameters('gptvisionDeploymentCapacity')]" - }, - "gptvisionDeploymentName": { - "value": "[parameters('gptvisionDeploymentName')]" - }, - "gptvisionModelName": { - "value": "[parameters('gptvisionModelName')]" - }, - "gptvisionModelVersion": { - "value": "[parameters('gptvisionModelVersion')]" - }, "formRecognizerSkuName": { "value": "[parameters('formRecognizerSkuName')]" }, @@ -282,8 +234,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.24.24.22086", - "templateHash": "14077555141603956691" + "version": "0.29.47.4906", + "templateHash": "18109441359842852578" } }, "parameters": { @@ -301,36 +253,28 @@ "type": "string" }, "openAiSkuName": { - "type": "string", - "defaultValue": "S0" + "type": "string" }, "chatGptDeploymentCapacity": { - "type": "int", - "defaultValue": 30 + "type": "int" }, "chatGptDeploymentName": { - "type": "string", - "defaultValue": "chat-gpt-35-turbo" + "type": "string" }, "chatGptModelName": { - "type": "string", - "defaultValue": "chat-gpt-35-turbo" + "type": "string" }, "chatGptModelVersion": { - "type": "string", - "defaultValue": "1106" + "type": "string" }, "embeddingDeploymentName": { - "type": "string", - "defaultValue": "text-embedding-ada-002" + "type": "string" }, "embeddingDeploymentCapacity": { - "type": "int", - "defaultValue": 10 + "type": "int" }, "embeddingModelName": { - "type": "string", - "defaultValue": "text-embedding-ada-002" + "type": "string" }, "dalleLocation": { "type": "string" @@ -347,29 +291,6 @@ "dalleApiVersion": { "type": "string" }, - "gptvisionLocation": { - "type": "string" - }, - "gptvisionDeploymentCapacity": { - "type": "int", - "defaultValue": 30 - }, - "gptvisionDeploymentName": { - "type": "string", - "defaultValue": "gpt-4-vision" - }, - "gptvisionModelName": { - "type": "string", - "defaultValue": "gpt-4" - }, - "gptvisionApiVersion": { - "type": "string", - "defaultValue": "2023-12-01-preview" - }, - "gptvisionModelVersion": { - "type": "string", - "defaultValue": "vision-preview" - }, "speechServiceSkuName": { "type": "string", "defaultValue": "S0" @@ -408,7 +329,6 @@ "variables": { "openai_name": "[toLower(format('{0}-aillm-{1}', parameters('name'), parameters('resourceToken')))]", "openai_dalle_name": "[toLower(format('{0}-aidalle-{1}', parameters('name'), parameters('resourceToken')))]", - "openai_gpt_vision_name": "[toLower(format('{0}-aivision-{1}', parameters('name'), parameters('resourceToken')))]", "form_recognizer_name": "[toLower(format('{0}-form-{1}', parameters('name'), parameters('resourceToken')))]", "speech_service_name": "[toLower(format('{0}-speech-{1}', parameters('name'), parameters('resourceToken')))]", "cosmos_name": "[toLower(format('{0}-cosmos-{1}', parameters('name'), parameters('resourceToken')))]", @@ -435,7 +355,7 @@ "version": "[parameters('chatGptModelVersion')]" }, "sku": { - "name": "Standard", + "name": "GlobalStandard", "capacity": "[parameters('chatGptDeploymentCapacity')]" } }, @@ -479,19 +399,6 @@ "[resourceId('Microsoft.Web/sites', variables('webapp_name'))]" ] }, - { - "type": "Microsoft.KeyVault/vaults/secrets", - "apiVersion": "2021-06-01-preview", - "name": "[format('{0}/{1}', variables('keyVaultName'), 'AZURE-OPENAI-VISION-API-KEY')]", - "properties": { - "contentType": "text/plain", - "value": "[listKeys(resourceId('Microsoft.CognitiveServices/accounts', variables('openai_gpt_vision_name')), '2023-05-01').key1]" - }, - "dependsOn": [ - "[resourceId('Microsoft.CognitiveServices/accounts', variables('openai_gpt_vision_name'))]", - "[resourceId('Microsoft.KeyVault/vaults', variables('keyVaultName'))]" - ] - }, { "type": "Microsoft.KeyVault/vaults/secrets", "apiVersion": "2021-06-01-preview", @@ -613,25 +520,6 @@ "[resourceId('Microsoft.CognitiveServices/accounts', variables('openai_dalle_name'))]" ] }, - { - "type": "Microsoft.CognitiveServices/accounts/deployments", - "apiVersion": "2023-05-01", - "name": "[format('{0}/{1}', variables('openai_gpt_vision_name'), parameters('gptvisionDeploymentName'))]", - "properties": { - "model": { - "format": "OpenAI", - "name": "[parameters('gptvisionModelName')]", - "version": "[parameters('gptvisionModelVersion')]" - } - }, - "sku": { - "name": "Standard", - "capacity": "[parameters('gptvisionDeploymentCapacity')]" - }, - "dependsOn": [ - "[resourceId('Microsoft.CognitiveServices/accounts', variables('openai_gpt_vision_name'))]" - ] - }, { "type": "Microsoft.Storage/storageAccounts/blobServices/containers", "apiVersion": "2022-05-01", @@ -693,22 +581,6 @@ "name": "SCM_DO_BUILD_DURING_DEPLOYMENT", "value": "true" }, - { - "name": "AZURE_OPENAI_VISION_API_KEY", - "value": "[format('@Microsoft.KeyVault(VaultName={0};SecretName={1})', variables('keyVaultName'), 'AZURE-OPENAI-VISION-API-KEY')]" - }, - { - "name": "AZURE_OPENAI_VISION_API_INSTANCE_NAME", - "value": "[variables('openai_gpt_vision_name')]" - }, - { - "name": "AZURE_OPENAI_VISION_API_DEPLOYMENT_NAME", - "value": "[parameters('gptvisionDeploymentName')]" - }, - { - "name": "AZURE_OPENAI_VISION_API_VERSION", - "value": "[parameters('gptvisionApiVersion')]" - }, { "name": "AZURE_OPENAI_API_KEY", "value": "[format('@Microsoft.KeyVault(VaultName={0};SecretName={1})', variables('keyVaultName'), 'AZURE-OPENAI-API-KEY')]" @@ -809,7 +681,6 @@ "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'AZURE-DOCUMENT-INTELLIGENCE-KEY')]", "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'AZURE-OPENAI-API-KEY')]", "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'AZURE-OPENAI-DALLE-API-KEY')]", - "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'AZURE-OPENAI-VISION-API-KEY')]", "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'AZURE-SEARCH-API-KEY')]", "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'AZURE-SPEECH-KEY')]", "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'AZURE-STORAGE-ACCOUNT-KEY')]", @@ -1024,21 +895,6 @@ "name": "[parameters('openAiSkuName')]" } }, - { - "type": "Microsoft.CognitiveServices/accounts", - "apiVersion": "2023-05-01", - "name": "[variables('openai_gpt_vision_name')]", - "location": "[parameters('gptvisionLocation')]", - "tags": "[parameters('tags')]", - "kind": "OpenAI", - "properties": { - "customSubDomainName": "[variables('openai_gpt_vision_name')]", - "publicNetworkAccess": "Enabled" - }, - "sku": { - "name": "[parameters('openAiSkuName')]" - } - }, { "type": "Microsoft.CognitiveServices/accounts", "apiVersion": "2023-05-01", diff --git a/infra/resources.bicep b/infra/resources.bicep index 110672927..1240bfc17 100644 --- a/infra/resources.bicep +++ b/infra/resources.bicep @@ -4,14 +4,14 @@ param resourceToken string param openai_api_version string param openAiLocation string -param openAiSkuName string = 'S0' -param chatGptDeploymentCapacity int = 30 -param chatGptDeploymentName string = 'chat-gpt-35-turbo' -param chatGptModelName string = 'chat-gpt-35-turbo' -param chatGptModelVersion string = '1106' -param embeddingDeploymentName string = 'text-embedding-ada-002' -param embeddingDeploymentCapacity int = 10 -param embeddingModelName string = 'text-embedding-ada-002' +param openAiSkuName string +param chatGptDeploymentCapacity int +param chatGptDeploymentName string +param chatGptModelName string +param chatGptModelVersion string +param embeddingDeploymentName string +param embeddingDeploymentCapacity int +param embeddingModelName string param dalleLocation string param dalleDeploymentCapacity int @@ -19,13 +19,6 @@ param dalleDeploymentName string param dalleModelName string param dalleApiVersion string -param gptvisionLocation string -param gptvisionDeploymentCapacity int = 30 -param gptvisionDeploymentName string = 'gpt-4-vision' -param gptvisionModelName string = 'gpt-4' -param gptvisionApiVersion string = '2023-12-01-preview' -param gptvisionModelVersion string = 'vision-preview' - param speechServiceSkuName string = 'S0' param formRecognizerSkuName string = 'S0' @@ -45,7 +38,6 @@ param tags object = {} var openai_name = toLower('${name}-aillm-${resourceToken}') var openai_dalle_name = toLower('${name}-aidalle-${resourceToken}') -var openai_gpt_vision_name = toLower('${name}-aivision-${resourceToken}') var form_recognizer_name = toLower('${name}-form-${resourceToken}') var speech_service_name = toLower('${name}-speech-${resourceToken}') @@ -53,8 +45,9 @@ var cosmos_name = toLower('${name}-cosmos-${resourceToken}') var search_name = toLower('${name}search${resourceToken}') var webapp_name = toLower('${name}-webapp-${resourceToken}') var appservice_name = toLower('${name}-app-${resourceToken}') -// storage name must be less than 24 chars, alphanumeric only - token is 13 -var storage_prefix = take(name, 8) +// storage name must be < 24 chars, alphanumeric only. 'sto' is 3 and resourceToken is 13 +var clean_name = replace(replace(name, '-', ''), '_', '') +var storage_prefix = take(clean_name, 8) var storage_name = toLower('${storage_prefix}sto${resourceToken}') // keyvault name must be less than 24 chars - token is 13 var kv_prefix = take(name, 7) @@ -79,7 +72,7 @@ var llmDeployments = [ version: chatGptModelVersion } sku: { - name: 'Standard' + name: 'GlobalStandard' capacity: chatGptDeploymentCapacity } } @@ -121,7 +114,7 @@ resource webApp 'Microsoft.Web/sites@2020-06-01' = { siteConfig: { linuxFxVersion: 'node|18-lts' alwaysOn: true - appCommandLine: 'next start' + appCommandLine: 'node .next/standalone/server.js' ftpsState: 'Disabled' minTlsVersion: '1.2' appSettings: [ @@ -133,22 +126,6 @@ resource webApp 'Microsoft.Web/sites@2020-06-01' = { name: 'SCM_DO_BUILD_DURING_DEPLOYMENT' value: 'true' } - { - name: 'AZURE_OPENAI_VISION_API_KEY' - value: '@Microsoft.KeyVault(VaultName=${kv.name};SecretName=${kv::AZURE_OPENAI_VISION_API_KEY.name})' - } - { - name: 'AZURE_OPENAI_VISION_API_INSTANCE_NAME' - value: openai_gpt_vision_name - } - { - name: 'AZURE_OPENAI_VISION_API_DEPLOYMENT_NAME' - value: gptvisionDeploymentName - } - { - name: 'AZURE_OPENAI_VISION_API_VERSION' - value: gptvisionApiVersion - } { name: 'AZURE_OPENAI_API_KEY' value: '@Microsoft.KeyVault(VaultName=${kv.name};SecretName=${kv::AZURE_OPENAI_API_KEY.name})' @@ -298,14 +275,6 @@ resource kv 'Microsoft.KeyVault/vaults@2021-06-01-preview' = { enabledForTemplateDeployment: false } - resource AZURE_OPENAI_VISION_API_KEY 'secrets' = { - name: 'AZURE-OPENAI-VISION-API-KEY' - properties: { - contentType: 'text/plain' - value: azureopenaivision.listKeys().key1 - } - } - resource AZURE_OPENAI_API_KEY 'secrets' = { name: 'AZURE-OPENAI-API-KEY' properties: { @@ -516,35 +485,6 @@ resource azureopenaidalle 'Microsoft.CognitiveServices/accounts@2023-05-01' = { -resource azureopenaivision 'Microsoft.CognitiveServices/accounts@2023-05-01' = { - name: openai_gpt_vision_name - location: gptvisionLocation - tags: tags - kind: 'OpenAI' - properties: { - customSubDomainName: openai_gpt_vision_name - publicNetworkAccess: 'Enabled' - } - sku: { - name: openAiSkuName - } - - resource dalleDeployment 'deployments' = { - name: gptvisionDeploymentName - properties: { - model: { - format: 'OpenAI' - name: gptvisionModelName - version:gptvisionModelVersion - } - } - sku: { - name: 'Standard' - capacity: gptvisionDeploymentCapacity - } - } -} - resource speechService 'Microsoft.CognitiveServices/accounts@2023-05-01' = { name: speech_service_name location: location diff --git a/src/.env.example b/src/.env.example index 915f905e7..83999adfe 100644 --- a/src/.env.example +++ b/src/.env.example @@ -18,12 +18,6 @@ AZURE_OPENAI_DALLE_API_INSTANCE_NAME=azurechat-dall-e AZURE_OPENAI_DALLE_API_DEPLOYMENT_NAME=dall-e AZURE_OPENAI_DALLE_API_VERSION=2023-12-01-preview -# GPT4 V OpenaAI details -AZURE_OPENAI_VISION_API_KEY=333333 -AZURE_OPENAI_VISION_API_INSTANCE_NAME=azurechat-vision -AZURE_OPENAI_VISION_API_DEPLOYMENT_NAME=gpt-4-vision -AZURE_OPENAI_VISION_API_VERSION=2023-12-01-preview - # Update your admin email addresses - comma separated ADMIN_EMAIL_ADDRESS=you@email.com,you2@email.com @@ -55,7 +49,7 @@ AZURE_SEARCH_NAME= AZURE_SEARCH_INDEX_NAME= # Azure AI Document Intelligence to extract content from your data -AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT=https://NAME.api.cognitive.microsoft.com/ +AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT=https://NAME.cognitiveservices.azure.com/ AZURE_DOCUMENT_INTELLIGENCE_KEY= # max upload document size in bytes @@ -70,4 +64,10 @@ AZURE_STORAGE_ACCOUNT_NAME=azurechat AZURE_STORAGE_ACCOUNT_KEY=123456 # Azure Key Vault to store secrets -AZURE_KEY_VAULT_NAME= \ No newline at end of file +AZURE_KEY_VAULT_NAME= + +# optional - endpoint suffix overrides - typically used for Azure Government Clouds, China Clouds, etc. Only use if required. +# AZURE_OPENAI_API_ENDPOINT_SUFFIX= +# AZURE_SEARCH_ENDPOINT_SUFFIX= +# AZURE_STORAGE_ENDPOINT_SUFFIX= +# AZURE_KEY_VAULT_ENDPOINT_SUFFIX= \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx index 91616adfd..41000a6d9 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -5,7 +5,11 @@ export default async function Home() { await redirectIfAuthenticated(); return (
- +
); } diff --git a/src/features/auth-page/login.tsx b/src/features/auth-page/login.tsx index 6e4f14820..339569fb0 100644 --- a/src/features/auth-page/login.tsx +++ b/src/features/auth-page/login.tsx @@ -14,6 +14,8 @@ import { interface LoginProps { isDevMode: boolean; + githubEnabled: boolean; + entraIdEnabled: boolean; } export const LogIn: FC = (props) => { @@ -34,7 +36,19 @@ export const LogIn: FC = (props) => { Signing in with your Microsoft account - Signing in... + + {props.githubEnabled && ( + + )} + {props.entraIdEnabled && ( + + )} + {props.isDevMode && ( + + )} + ); }; diff --git a/src/features/chat-page/chat-services/azure-ai-search/azure-ai-search.ts b/src/features/chat-page/chat-services/azure-ai-search/azure-ai-search.ts index d2b3c6398..b6d26679f 100644 --- a/src/features/chat-page/chat-services/azure-ai-search/azure-ai-search.ts +++ b/src/features/chat-page/chat-services/azure-ai-search/azure-ai-search.ts @@ -129,8 +129,9 @@ export const ExtensionSimilaritySearch = async (props: { input: searchText, model: "", }); + const endpointSuffix = process.env.AZURE_SEARCH_ENDPOINT_SUFFIX || "search.windows.net"; - const endpoint = `https://${searchName}.search.windows.net`; + const endpoint = `https://${searchName}.${endpointSuffix}`; const searchClient = new SearchClient( endpoint, diff --git a/src/features/chat-page/chat-services/chat-api/chat-api-multimodal.tsx b/src/features/chat-page/chat-services/chat-api/chat-api-multimodal.tsx index c47d1f0da..45630514e 100644 --- a/src/features/chat-page/chat-services/chat-api/chat-api-multimodal.tsx +++ b/src/features/chat-page/chat-services/chat-api/chat-api-multimodal.tsx @@ -1,7 +1,7 @@ "use server"; import "server-only"; -import { OpenAIVisionInstance } from "@/features/common/services/openai"; +import { OpenAIInstance } from "@/features/common/services/openai"; import { ChatCompletionStreamingRunner } from "openai/resources/beta/chat/completions"; import { ChatThreadModel } from "../models"; export const ChatApiMultimodal = (props: { @@ -12,7 +12,7 @@ export const ChatApiMultimodal = (props: { }): ChatCompletionStreamingRunner => { const { chatThread, userMessage, signal, file } = props; - const openAI = OpenAIVisionInstance(); + const openAI = OpenAIInstance(); return openAI.beta.chat.completions.stream( { diff --git a/src/features/chat-page/chat-services/chat-api/chat-api.ts b/src/features/chat-page/chat-services/chat-api/chat-api.ts index deec3ac11..f176587a0 100644 --- a/src/features/chat-page/chat-services/chat-api/chat-api.ts +++ b/src/features/chat-page/chat-services/chat-api/chat-api.ts @@ -102,6 +102,7 @@ export const ChatAPIEntry = async (props: UserPrompt, signal: AbortSignal) => { headers: { "Cache-Control": "no-cache", Connection: "keep-alive", + "Content-Type": "text/event-stream" }, }); }; diff --git a/src/features/common/services/ai-search.ts b/src/features/common/services/ai-search.ts index 187cac299..86b669e04 100644 --- a/src/features/common/services/ai-search.ts +++ b/src/features/common/services/ai-search.ts @@ -15,8 +15,9 @@ export const AzureAISearchCredentials = () => { "One or more Azure AI Search environment variables are not set" ); } + const endpointSuffix = process.env.AZURE_SEARCH_ENDPOINT_SUFFIX || "search.windows.net"; - const endpoint = `https://${searchName}.search.windows.net`; + const endpoint = `https://${searchName}.${endpointSuffix}`; return { apiKey, endpoint, diff --git a/src/features/common/services/azure-storage.ts b/src/features/common/services/azure-storage.ts index 0cc026426..42e0eaffe 100644 --- a/src/features/common/services/azure-storage.ts +++ b/src/features/common/services/azure-storage.ts @@ -10,8 +10,9 @@ const InitBlobServiceClient = () => { throw new Error( "Azure Storage Account not configured correctly, check environment variables." ); + const endpointSuffix = process.env.AZURE_STORAGE_ENDPOINT_SUFFIX || "core.windows.net"; - const connectionString = `DefaultEndpointsProtocol=https;AccountName=${acc};AccountKey=${key};EndpointSuffix=core.windows.net`; + const connectionString = `DefaultEndpointsProtocol=https;AccountName=${acc};AccountKey=${key};EndpointSuffix=${endpointSuffix}`; const blobServiceClient = BlobServiceClient.fromConnectionString(connectionString); diff --git a/src/features/common/services/key-vault.ts b/src/features/common/services/key-vault.ts index 0a0b09580..7f821b642 100644 --- a/src/features/common/services/key-vault.ts +++ b/src/features/common/services/key-vault.ts @@ -10,7 +10,8 @@ export const AzureKeyVaultInstance = () => { "Azure Key vault is not configured correctly, check environment variables." ); } - const url = `https://${keyVaultName}.vault.azure.net`; + const endpointSuffix = process.env.AZURE_KEY_VAULT_ENDPOINT_SUFFIX || "vault.azure.net"; + const url = `https://${keyVaultName}.${endpointSuffix}`; return new SecretClient(url, credential); }; diff --git a/src/features/common/services/openai.ts b/src/features/common/services/openai.ts index 41c9ed0d6..0e44a4523 100644 --- a/src/features/common/services/openai.ts +++ b/src/features/common/services/openai.ts @@ -1,9 +1,10 @@ import { OpenAI } from "openai"; export const OpenAIInstance = () => { + const endpointSuffix = process.env.AZURE_OPENAI_API_ENDPOINT_SUFFIX || "openai.azure.com"; const openai = new OpenAI({ apiKey: process.env.AZURE_OPENAI_API_KEY, - baseURL: `https://${process.env.AZURE_OPENAI_API_INSTANCE_NAME}.openai.azure.com/openai/deployments/${process.env.AZURE_OPENAI_API_DEPLOYMENT_NAME}`, + baseURL: `https://${process.env.AZURE_OPENAI_API_INSTANCE_NAME}.${endpointSuffix}/openai/deployments/${process.env.AZURE_OPENAI_API_DEPLOYMENT_NAME}`, defaultQuery: { "api-version": process.env.AZURE_OPENAI_API_VERSION }, defaultHeaders: { "api-key": process.env.AZURE_OPENAI_API_KEY }, }); @@ -20,10 +21,11 @@ export const OpenAIEmbeddingInstance = () => { "Azure OpenAI Embeddings endpoint config is not set, check environment variables." ); } + const endpointSuffix = process.env.AZURE_OPENAI_API_ENDPOINT_SUFFIX || "openai.azure.com"; const openai = new OpenAI({ apiKey: process.env.AZURE_OPENAI_API_KEY, - baseURL: `https://${process.env.AZURE_OPENAI_API_INSTANCE_NAME}.openai.azure.com/openai/deployments/${process.env.AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME}`, + baseURL: `https://${process.env.AZURE_OPENAI_API_INSTANCE_NAME}.${endpointSuffix}/openai/deployments/${process.env.AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME}`, defaultQuery: { "api-version": process.env.AZURE_OPENAI_API_VERSION }, defaultHeaders: { "api-key": process.env.AZURE_OPENAI_API_KEY }, }); @@ -41,10 +43,11 @@ export const OpenAIDALLEInstance = () => { "Azure OpenAI DALLE endpoint config is not set, check environment variables." ); } + const endpointSuffix = process.env.AZURE_OPENAI_API_ENDPOINT_SUFFIX || "openai.azure.com"; const openai = new OpenAI({ apiKey: process.env.AZURE_OPENAI_DALLE_API_KEY, - baseURL: `https://${process.env.AZURE_OPENAI_DALLE_API_INSTANCE_NAME}.openai.azure.com/openai/deployments/${process.env.AZURE_OPENAI_DALLE_API_DEPLOYMENT_NAME}`, + baseURL: `https://${process.env.AZURE_OPENAI_DALLE_API_INSTANCE_NAME}.${endpointSuffix}/openai/deployments/${process.env.AZURE_OPENAI_DALLE_API_DEPLOYMENT_NAME}`, defaultQuery: { "api-version": process.env.AZURE_OPENAI_DALLE_API_VERSION || "2023-12-01-preview", @@ -55,26 +58,3 @@ export const OpenAIDALLEInstance = () => { }); return openai; }; - -export const OpenAIVisionInstance = () => { - if ( - !process.env.AZURE_OPENAI_VISION_API_KEY || - !process.env.AZURE_OPENAI_VISION_API_DEPLOYMENT_NAME || - !process.env.AZURE_OPENAI_VISION_API_INSTANCE_NAME || - !process.env.AZURE_OPENAI_VISION_API_VERSION - ) { - throw new Error( - "Azure OpenAI Vision environment config is not set, check environment variables." - ); - } - - const openai = new OpenAI({ - apiKey: process.env.AZURE_OPENAI_VISION_API_KEY, - baseURL: `https://${process.env.AZURE_OPENAI_VISION_API_INSTANCE_NAME}.openai.azure.com/openai/deployments/${process.env.AZURE_OPENAI_VISION_API_DEPLOYMENT_NAME}`, - defaultQuery: { - "api-version": process.env.AZURE_OPENAI_VISION_API_VERSION, - }, - defaultHeaders: { "api-key": process.env.AZURE_OPENAI_VISION_API_KEY }, - }); - return openai; -}; diff --git a/src/features/extensions-page/extension-services/extension-service.ts b/src/features/extensions-page/extension-services/extension-service.ts index 59d08ff7d..e73b1ee6c 100644 --- a/src/features/extensions-page/extension-services/extension-service.ts +++ b/src/features/extensions-page/extension-services/extension-service.ts @@ -123,7 +123,7 @@ export const CreateExtension = async ( status: "ERROR", errors: [ { - message: `Error adding Extension: ${resource}`, + message: `Unable to add Extension: ${resource}`, }, ], }; diff --git a/src/features/prompt-page/prompt-service.ts b/src/features/prompt-page/prompt-service.ts index f50feaba6..52e9d3bc3 100644 --- a/src/features/prompt-page/prompt-service.ts +++ b/src/features/prompt-page/prompt-service.ts @@ -25,7 +25,7 @@ export const CreatePrompt = async ( status: "UNAUTHORIZED", errors: [ { - message: `Unable to create prompt`, + message: `Unable to create prompt - admin role required.`, }, ], };