From 0217cf262b8329ba21c8cc278df8c5d83056c9db Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 1 Mar 2024 07:50:15 -0800 Subject: [PATCH] updates to sample --- Services/ChatService.cs | 3 +- Services/OpenAiService.cs | 23 +++++----- azuredeploy-no-aoai.bicep | 64 ++++++++++++++++---------- azuredeploy-no-aoai.json | 89 ++++++++++++++++++++++--------------- azuredeploy.bicep | 54 +++++++++++----------- azuredeploy.json | 81 +++++++++++++++++---------------- azuredeploy.parameters.json | 27 ----------- cosmoschatgpt.csproj | 4 +- readme.md | 15 +++---- 9 files changed, 184 insertions(+), 176 deletions(-) delete mode 100644 azuredeploy.parameters.json diff --git a/Services/ChatService.cs b/Services/ChatService.cs index d28e5af..15b9872 100644 --- a/Services/ChatService.cs +++ b/Services/ChatService.cs @@ -1,6 +1,5 @@ using Cosmos.Chat.GPT.Constants; using Cosmos.Chat.GPT.Models; -using Microsoft.AspNetCore.SignalR.Protocol; using SharpToken; namespace Cosmos.Chat.GPT.Services; @@ -107,7 +106,7 @@ public async Task DeleteChatSessionAsync(string? sessionId) } /// - /// Get a completion from _openAiService + /// Get a completion from Azure OpenAi Service /// public async Task GetChatCompletionAsync(string? sessionId, string promptText) { diff --git a/Services/OpenAiService.cs b/Services/OpenAiService.cs index a9e48ec..59b8789 100644 --- a/Services/OpenAiService.cs +++ b/Services/OpenAiService.cs @@ -51,31 +51,31 @@ public OpenAiService(string endpoint, string key, string modelName) /// Sends a prompt to the deployed OpenAI LLM model and returns the response. /// /// Chat session identifier for the current conversation. - /// Prompt message to send to the deployment. + /// Prompt message and chat history to send to the model. /// Response from the OpenAI model along with tokens for the prompt and response. public async Task<(string completionText, int completionTokens)> GetChatCompletionAsync(string sessionId, string userPrompt) { - ChatMessage systemMessage = new(ChatRole.System, _systemPrompt); - ChatMessage userMessage = new(ChatRole.User, userPrompt); + ChatRequestSystemMessage systemMessage = new(_systemPrompt); + ChatRequestUserMessage userMessage = new(userPrompt); ChatCompletionsOptions options = new() { - + DeploymentName = _modelName, Messages = { systemMessage, userMessage }, User = sessionId, - MaxTokens = 2000, - Temperature = 0.3f, - NucleusSamplingFactor = 0.5f, + MaxTokens = 1000, + Temperature = 0.2f, + NucleusSamplingFactor = 0.7f, FrequencyPenalty = 0, PresencePenalty = 0 }; - Response completionsResponse = await _client.GetChatCompletionsAsync(_modelName, options); + Response completionsResponse = await _client.GetChatCompletionsAsync(options); ChatCompletions completions = completionsResponse.Value; @@ -94,11 +94,12 @@ public OpenAiService(string endpoint, string key, string modelName) public async Task SummarizeAsync(string sessionId, string conversationText) { - ChatMessage systemMessage = new(ChatRole.System, _summarizePrompt); - ChatMessage userMessage = new(ChatRole.User, conversationText); + ChatRequestSystemMessage systemMessage = new(_summarizePrompt); + ChatRequestUserMessage userMessage = new(conversationText); ChatCompletionsOptions options = new() { + DeploymentName = _modelName, Messages = { systemMessage, userMessage @@ -111,7 +112,7 @@ public async Task SummarizeAsync(string sessionId, string conversationTe PresencePenalty = 0 }; - Response completionsResponse = await _client.GetChatCompletionsAsync(_modelName, options); + Response completionsResponse = await _client.GetChatCompletionsAsync(options); ChatCompletions completions = completionsResponse.Value; diff --git a/azuredeploy-no-aoai.bicep b/azuredeploy-no-aoai.bicep index d6143c6..51fb544 100644 --- a/azuredeploy-no-aoai.bicep +++ b/azuredeploy-no-aoai.bicep @@ -1,15 +1,28 @@ -@description('Location where all resources will be deployed. This value defaults to the **East US** region.') +@description('Location where all resources are deployed. Is limited by the regions with Azure OpenAI availability. Defaults to **East US** region.') @allowed([ 'Australia East' + 'Brazil South' + 'Canada Central' 'Canada East' 'East US' 'East US 2' 'France Central' + 'Germany West Central' 'Japan East' + 'Korea Central' 'North Central US' + 'Norway East' + 'Poland Central' + 'South Africa North' + 'South Central US' + 'South India' + 'Sweden Central' 'Switzerland North' + 'UAE North' 'UK South' 'West Europe' + 'West US' + 'West US 3' ]) param location string = 'East US' @@ -21,9 +34,6 @@ The name defaults to a unique string generated from the resource group identifie ''') param name string = uniqueString(resourceGroup().id) -@description('Boolean indicating whether Azure Cosmos DB free tier should be used for the account. This defaults to **true**.') -param cosmosDbEnableFreeTier bool = true - @description('Specifies the SKU for the Azure App Service plan. Defaults to **F1** Free Tier') @allowed([ 'F1' @@ -37,10 +47,10 @@ param openAiAccountName string = '' @description('Specifies the key for Azure OpenAI account.') @secure() -param openAiKey string = '' +param openAiAccountKey string = '' -@description('Specifies the deployed model name for your Azure OpenAI account completions API.') -param openAiModelName string = '' +@description('Specifies the deployed model name for your Azure OpenAI account GPT model.') +param openAiGptModelName string = '' @description('Git repository URL for the chat application. This defaults to the [`azure-samples/cosmosdb-chatgpt`](https://github.com/azure-samples/cosmosdb-chatgpt) repository.') param appGitRepository string = 'https://github.com/azure-samples/cosmosdb-chatgpt.git' @@ -48,17 +58,26 @@ param appGitRepository string = 'https://github.com/azure-samples/cosmosdb-chatg @description('Git repository branch for the chat application. This defaults to the [**main** branch of the `azure-samples/cosmosdb-chatgpt`](https://github.com/azure-samples/cosmosdb-chatgpt/tree/main) repository.') param appGetRepositoryBranch string = 'main' -var openAiEndpoint = 'https://${openAiAccountName}.openai.azure.com' +var openAiSettings = { + name: openAiAccountName + endpoint: 'https://${openAiAccountName}.openai.azure.com' + key: openAiAccountKey + sku: 'S0' + maxConversationTokens: '2000' + model: { + deployment: { + name: openAiGptModelName + } + } +} var cosmosDbSettings = { name: '${name}-cosmos-nosql' - enableFreeTier: cosmosDbEnableFreeTier database: { name: 'chatdatabase' } container: { name: 'chatcontainer' - throughput: 400 } } @@ -76,7 +95,7 @@ var appServiceSettings = { sku: appServiceSku } -resource cosmosDbAccount 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' = { +resource cosmosDbAccount 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' = { name: cosmosDbSettings.name location: location kind: 'GlobalDocumentDB' @@ -85,7 +104,7 @@ resource cosmosDbAccount 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' = { defaultConsistencyLevel: 'Session' } databaseAccountOfferType: 'Standard' - enableFreeTier: cosmosDbSettings.enableFreeTier + capabilities: [ { name: 'EnableServerless' } ] locations: [ { failoverPriority: 0 @@ -96,7 +115,7 @@ resource cosmosDbAccount 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' = { } } -resource cosmosDbDatabase 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2022-08-15' = { +resource cosmosDbDatabase 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2023-04-15' = { parent: cosmosDbAccount name: cosmosDbSettings.database.name properties: { @@ -106,7 +125,7 @@ resource cosmosDbDatabase 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@20 } } -resource cosmosDbContainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2022-08-15' = { +resource cosmosDbContainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2023-04-15' = { parent: cosmosDbDatabase name: cosmosDbSettings.container.name properties: { @@ -138,12 +157,11 @@ resource cosmosDbContainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/c } } options: { - throughput: cosmosDbSettings.container.throughput } } } -resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = { +resource appServicePlan 'Microsoft.Web/serverfarms@2022-09-01' = { name: appServiceSettings.plan.name location: location sku: { @@ -151,7 +169,7 @@ resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = { } } -resource appServiceWeb 'Microsoft.Web/sites@2022-03-01' = { +resource appServiceWeb 'Microsoft.Web/sites@2022-09-01' = { name: appServiceSettings.web.name location: location properties: { @@ -160,7 +178,7 @@ resource appServiceWeb 'Microsoft.Web/sites@2022-03-01' = { } } -resource appServiceWebSettings 'Microsoft.Web/sites/config@2022-03-01' = { +resource appServiceWebSettings 'Microsoft.Web/sites/config@2022-09-01' = { parent: appServiceWeb name: 'appsettings' kind: 'string' @@ -169,14 +187,14 @@ resource appServiceWebSettings 'Microsoft.Web/sites/config@2022-03-01' = { COSMOSDB__KEY: cosmosDbAccount.listKeys().primaryMasterKey COSMOSDB__DATABASE: cosmosDbDatabase.name COSMOSDB__CONTAINER: cosmosDbContainer.name - OPENAI__ENDPOINT: openAiEndpoint - OPENAI__KEY: openAiKey - OPENAI__MODELNAME: openAiModelName - OPENAI__MAXCONVERSATIONTOKENS: '2000' + OPENAI__ENDPOINT: openAiSettings.endpoint + OPENAI__KEY: openAiSettings.key + OPENAI__MODELNAME: openAiSettings.model.deployment.name + OPENAI__MAXCONVERSATIONTOKENS: openAiSettings.maxConversationTokens } } -resource appServiceWebDeployment 'Microsoft.Web/sites/sourcecontrols@2021-03-01' = { +resource appServiceWebDeployment 'Microsoft.Web/sites/sourcecontrols@2022-09-01' = { parent: appServiceWeb name: 'web' properties: { diff --git a/azuredeploy-no-aoai.json b/azuredeploy-no-aoai.json index 7540f4b..f3def12 100644 --- a/azuredeploy-no-aoai.json +++ b/azuredeploy-no-aoai.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.20.4.51522", - "templateHash": "12310353177236113213" + "version": "0.25.53.49325", + "templateHash": "8421590683852965200" } }, "parameters": { @@ -14,18 +14,31 @@ "defaultValue": "East US", "allowedValues": [ "Australia East", + "Brazil South", + "Canada Central", "Canada East", "East US", "East US 2", "France Central", + "Germany West Central", "Japan East", + "Korea Central", "North Central US", + "Norway East", + "Poland Central", + "South Africa North", + "South Central US", + "South India", + "Sweden Central", "Switzerland North", + "UAE North", "UK South", - "West Europe" + "West Europe", + "West US", + "West US 3" ], "metadata": { - "description": "Location where all resources will be deployed. This value defaults to the **East US** region." + "description": "Location where all resources are deployed. Is limited by the regions with Azure OpenAI availability. Defaults to **East US** region." } }, "name": { @@ -35,13 +48,6 @@ "description": "Unique name for the chat application. The name is required to be unique as it will be used as a prefix for the names of these resources:\r\n- Azure Cosmos DB\r\n- Azure App Service\r\nThe name defaults to a unique string generated from the resource group identifier.\r\n" } }, - "cosmosDbEnableFreeTier": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Boolean indicating whether Azure Cosmos DB free tier should be used for the account. This defaults to **true**." - } - }, "appServiceSku": { "type": "string", "defaultValue": "F1", @@ -61,18 +67,18 @@ "description": "Specifies the Azure OpenAI account name." } }, - "openAiKey": { + "openAiAccountKey": { "type": "securestring", "defaultValue": "", "metadata": { "description": "Specifies the key for Azure OpenAI account." } }, - "openAiModelName": { + "openAiGptModelName": { "type": "string", "defaultValue": "", "metadata": { - "description": "Specifies the deployed model name for your Azure OpenAI account completions API." + "description": "Specifies the deployed model name for your Azure OpenAI account GPT model." } }, "appGitRepository": { @@ -91,16 +97,25 @@ } }, "variables": { - "openAiEndpoint": "[format('https://{0}.openai.azure.com', parameters('openAiAccountName'))]", + "openAiSettings": { + "name": "[parameters('openAiAccountName')]", + "endpoint": "[format('https://{0}.openai.azure.com', parameters('openAiAccountName'))]", + "key": "[parameters('openAiAccountKey')]", + "sku": "S0", + "maxConversationTokens": "2000", + "model": { + "deployment": { + "name": "[parameters('openAiGptModelName')]" + } + } + }, "cosmosDbSettings": { "name": "[format('{0}-cosmos-nosql', parameters('name'))]", - "enableFreeTier": "[parameters('cosmosDbEnableFreeTier')]", "database": { "name": "chatdatabase" }, "container": { - "name": "chatcontainer", - "throughput": 400 + "name": "chatcontainer" } }, "appServiceSettings": { @@ -120,7 +135,7 @@ "resources": [ { "type": "Microsoft.DocumentDB/databaseAccounts", - "apiVersion": "2022-08-15", + "apiVersion": "2023-04-15", "name": "[variables('cosmosDbSettings').name]", "location": "[parameters('location')]", "kind": "GlobalDocumentDB", @@ -129,7 +144,11 @@ "defaultConsistencyLevel": "Session" }, "databaseAccountOfferType": "Standard", - "enableFreeTier": "[variables('cosmosDbSettings').enableFreeTier]", + "capabilities": [ + { + "name": "EnableServerless" + } + ], "locations": [ { "failoverPriority": 0, @@ -141,7 +160,7 @@ }, { "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases", - "apiVersion": "2022-08-15", + "apiVersion": "2023-04-15", "name": "[format('{0}/{1}', variables('cosmosDbSettings').name, variables('cosmosDbSettings').database.name)]", "properties": { "resource": { @@ -154,7 +173,7 @@ }, { "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers", - "apiVersion": "2022-08-15", + "apiVersion": "2023-04-15", "name": "[format('{0}/{1}/{2}', variables('cosmosDbSettings').name, variables('cosmosDbSettings').database.name, variables('cosmosDbSettings').container.name)]", "properties": { "resource": { @@ -184,9 +203,7 @@ ] } }, - "options": { - "throughput": "[variables('cosmosDbSettings').container.throughput]" - } + "options": {} }, "dependsOn": [ "[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', variables('cosmosDbSettings').name, variables('cosmosDbSettings').database.name)]" @@ -194,7 +211,7 @@ }, { "type": "Microsoft.Web/serverfarms", - "apiVersion": "2022-03-01", + "apiVersion": "2022-09-01", "name": "[variables('appServiceSettings').plan.name]", "location": "[parameters('location')]", "sku": { @@ -203,7 +220,7 @@ }, { "type": "Microsoft.Web/sites", - "apiVersion": "2022-03-01", + "apiVersion": "2022-09-01", "name": "[variables('appServiceSettings').web.name]", "location": "[parameters('location')]", "properties": { @@ -216,18 +233,18 @@ }, { "type": "Microsoft.Web/sites/config", - "apiVersion": "2022-03-01", + "apiVersion": "2022-09-01", "name": "[format('{0}/{1}', variables('appServiceSettings').web.name, 'appsettings')]", "kind": "string", "properties": { - "COSMOSDB__ENDPOINT": "[reference(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbSettings').name), '2022-08-15').documentEndpoint]", - "COSMOSDB__KEY": "[listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbSettings').name), '2022-08-15').primaryMasterKey]", + "COSMOSDB__ENDPOINT": "[reference(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbSettings').name), '2023-04-15').documentEndpoint]", + "COSMOSDB__KEY": "[listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbSettings').name), '2023-04-15').primaryMasterKey]", "COSMOSDB__DATABASE": "[variables('cosmosDbSettings').database.name]", "COSMOSDB__CONTAINER": "[variables('cosmosDbSettings').container.name]", - "OPENAI__ENDPOINT": "[variables('openAiEndpoint')]", - "OPENAI__KEY": "[parameters('openAiKey')]", - "OPENAI__MODELNAME": "[parameters('openAiModelName')]", - "OPENAI__MAXCONVERSATIONTOKENS": "2000" + "OPENAI__ENDPOINT": "[variables('openAiSettings').endpoint]", + "OPENAI__KEY": "[variables('openAiSettings').key]", + "OPENAI__MODELNAME": "[variables('openAiSettings').model.deployment.name]", + "OPENAI__MAXCONVERSATIONTOKENS": "[variables('openAiSettings').maxConversationTokens]" }, "dependsOn": [ "[resourceId('Microsoft.Web/sites', variables('appServiceSettings').web.name)]", @@ -238,7 +255,7 @@ }, { "type": "Microsoft.Web/sites/sourcecontrols", - "apiVersion": "2021-03-01", + "apiVersion": "2022-09-01", "name": "[format('{0}/{1}', variables('appServiceSettings').web.name, 'web')]", "properties": { "repoUrl": "[variables('appServiceSettings').web.git.repo]", @@ -253,7 +270,7 @@ "outputs": { "deployedUrl": { "type": "string", - "value": "[reference(resourceId('Microsoft.Web/sites', variables('appServiceSettings').web.name), '2022-03-01').defaultHostName]" + "value": "[reference(resourceId('Microsoft.Web/sites', variables('appServiceSettings').web.name), '2022-09-01').defaultHostName]" } } } \ No newline at end of file diff --git a/azuredeploy.bicep b/azuredeploy.bicep index e8fb8f7..06e957d 100644 --- a/azuredeploy.bicep +++ b/azuredeploy.bicep @@ -1,15 +1,28 @@ -@description('Location where all resources will be deployed. This value defaults to the **East US** region.') +@description('Location where all resources are deployed. Is limited by the regions with Azure OpenAI availability. Defaults to **East US** region.') @allowed([ 'Australia East' + 'Brazil South' + 'Canada Central' 'Canada East' 'East US' 'East US 2' 'France Central' + 'Germany West Central' 'Japan East' + 'Korea Central' 'North Central US' + 'Norway East' + 'Poland Central' + 'South Africa North' + 'South Central US' + 'South India' + 'Sweden Central' 'Switzerland North' + 'UAE North' 'UK South' 'West Europe' + 'West US' + 'West US 3' ]) param location string = 'East US' @@ -22,9 +35,6 @@ The name defaults to a unique string generated from the resource group identifie ''') param name string = uniqueString(resourceGroup().id) -@description('Boolean indicating whether Azure Cosmos DB free tier should be used for the account. This defaults to **true**.') -param cosmosDbEnableFreeTier bool = true - @description('Specifies the SKU for the Azure App Service plan. Defaults to **F1**') @allowed([ 'F1' @@ -33,12 +43,6 @@ param cosmosDbEnableFreeTier bool = true ]) param appServiceSku string = 'F1' -@description('Specifies the SKU for the Azure OpenAI resource. Defaults to **S0**') -@allowed([ - 'S0' -]) -param openAiSku string = 'S0' - @description('Git repository URL for the chat application. This defaults to the [`azure-samples/cosmosdb-chatgpt`](https://github.com/azure-samples/cosmosdb-chatgpt) repository.') param appGitRepository string = 'https://github.com/azure-samples/cosmosdb-chatgpt.git' @@ -50,26 +54,24 @@ param deployOpenAi bool = true var openAiSettings = { name: '${name}-openai' - sku: openAiSku + sku: 'S0' maxConversationTokens: '2000' model: { - name: 'gpt-35-turbo' - version: '0301' + name: 'gpt-4' + version: '0613' deployment: { - name: 'chatmodel' + name: 'gpt4-chat-sample' } } } var cosmosDbSettings = { name: '${name}-cosmos-nosql' - enableFreeTier: cosmosDbEnableFreeTier database: { name: 'chatdatabase' } container: { name: 'chatcontainer' - throughput: 400 } } @@ -87,16 +89,16 @@ var appServiceSettings = { sku: appServiceSku } -resource cosmosDbAccount 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' = { +resource cosmosDbAccount 'Microsoft.DocumentDB/databaseAccounts@2023-04-15' = { name: cosmosDbSettings.name location: location kind: 'GlobalDocumentDB' properties: { + capabilities: [ { name: 'EnableServerless' } ] consistencyPolicy: { defaultConsistencyLevel: 'Session' } databaseAccountOfferType: 'Standard' - enableFreeTier: cosmosDbSettings.enableFreeTier locations: [ { failoverPriority: 0 @@ -107,7 +109,7 @@ resource cosmosDbAccount 'Microsoft.DocumentDB/databaseAccounts@2022-08-15' = { } } -resource cosmosDbDatabase 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2022-08-15' = { +resource cosmosDbDatabase 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@2023-04-15' = { parent: cosmosDbAccount name: cosmosDbSettings.database.name properties: { @@ -117,7 +119,7 @@ resource cosmosDbDatabase 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases@20 } } -resource cosmosDbContainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2022-08-15' = { +resource cosmosDbContainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2023-04-15' = { parent: cosmosDbDatabase name: cosmosDbSettings.container.name properties: { @@ -149,7 +151,6 @@ resource cosmosDbContainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/c } } options: { - throughput: cosmosDbSettings.container.throughput } } } @@ -178,7 +179,7 @@ resource openAiModelDeployment 'Microsoft.CognitiveServices/accounts/deployments model: { format: 'OpenAI' name: openAiSettings.model.name - version: openAiSettings.model.version + version: 'S0' } } } @@ -222,7 +223,7 @@ resource appServiceWebSettingsApplication 'Microsoft.Web/sites/config@2022-09-01 parent: appServiceWeb name: 'appsettings' kind: 'string' - properties: deployOpenAi ? { + properties: { COSMOSDB__ENDPOINT: cosmosDbAccount.properties.documentEndpoint COSMOSDB__KEY: cosmosDbAccount.listKeys().primaryMasterKey COSMOSDB__DATABASE: cosmosDbDatabase.name @@ -231,15 +232,10 @@ resource appServiceWebSettingsApplication 'Microsoft.Web/sites/config@2022-09-01 OPENAI__KEY: openAiAccount.listKeys().key1 OPENAI__MODELNAME: openAiModelDeployment.name OPENAI__MAXCONVERSATIONTOKENS: openAiSettings.maxConversationTokens - } : { - COSMOSDB__ENDPOINT: cosmosDbAccount.properties.documentEndpoint - COSMOSDB__KEY: cosmosDbAccount.listKeys().primaryMasterKey - COSMOSDB__DATABASE: cosmosDbDatabase.name - COSMOSDB__CONTAINER: cosmosDbContainer.name } } -resource appServiceWebDeployment 'Microsoft.Web/sites/sourcecontrols@2021-03-01' = { +resource appServiceWebDeployment 'Microsoft.Web/sites/sourcecontrols@2022-09-01' = { parent: appServiceWeb name: 'web' properties: { diff --git a/azuredeploy.json b/azuredeploy.json index 35e0282..9916f75 100644 --- a/azuredeploy.json +++ b/azuredeploy.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.22.6.54827", - "templateHash": "2702760770067258847" + "version": "0.25.53.49325", + "templateHash": "6955649851012380135" } }, "parameters": { @@ -14,18 +14,31 @@ "defaultValue": "East US", "allowedValues": [ "Australia East", + "Brazil South", + "Canada Central", "Canada East", "East US", "East US 2", "France Central", + "Germany West Central", "Japan East", + "Korea Central", "North Central US", + "Norway East", + "Poland Central", + "South Africa North", + "South Central US", + "South India", + "Sweden Central", "Switzerland North", + "UAE North", "UK South", - "West Europe" + "West Europe", + "West US", + "West US 3" ], "metadata": { - "description": "Location where all resources will be deployed. This value defaults to the **East US** region." + "description": "Location where all resources are deployed. Is limited by the regions with Azure OpenAI availability. Defaults to **East US** region." } }, "name": { @@ -35,13 +48,6 @@ "description": "Unique name for the chat application. The name is required to be unique as it will be used as a prefix for the names of these resources:\r\n- Azure Cosmos DB\r\n- Azure App Service\r\n- Azure OpenAI\r\nThe name defaults to a unique string generated from the resource group identifier.\r\n" } }, - "cosmosDbEnableFreeTier": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Boolean indicating whether Azure Cosmos DB free tier should be used for the account. This defaults to **true**." - } - }, "appServiceSku": { "type": "string", "defaultValue": "F1", @@ -54,16 +60,6 @@ "description": "Specifies the SKU for the Azure App Service plan. Defaults to **F1**" } }, - "openAiSku": { - "type": "string", - "defaultValue": "S0", - "allowedValues": [ - "S0" - ], - "metadata": { - "description": "Specifies the SKU for the Azure OpenAI resource. Defaults to **S0**" - } - }, "appGitRepository": { "type": "string", "defaultValue": "https://github.com/azure-samples/cosmosdb-chatgpt.git", @@ -89,25 +85,23 @@ "variables": { "openAiSettings": { "name": "[format('{0}-openai', parameters('name'))]", - "sku": "[parameters('openAiSku')]", + "sku": "S0", "maxConversationTokens": "2000", "model": { - "name": "gpt-35-turbo", - "version": "0301", + "name": "gpt-4", + "version": "0613", "deployment": { - "name": "chatmodel" + "name": "gpt4" } } }, "cosmosDbSettings": { "name": "[format('{0}-cosmos-nosql', parameters('name'))]", - "enableFreeTier": "[parameters('cosmosDbEnableFreeTier')]", "database": { "name": "chatdatabase" }, "container": { - "name": "chatcontainer", - "throughput": 400 + "name": "chatcontainer" } }, "appServiceSettings": { @@ -127,16 +121,20 @@ "resources": [ { "type": "Microsoft.DocumentDB/databaseAccounts", - "apiVersion": "2022-08-15", + "apiVersion": "2023-04-15", "name": "[variables('cosmosDbSettings').name]", "location": "[parameters('location')]", "kind": "GlobalDocumentDB", "properties": { + "capabilities": [ + { + "name": "EnableServerless" + } + ], "consistencyPolicy": { "defaultConsistencyLevel": "Session" }, "databaseAccountOfferType": "Standard", - "enableFreeTier": "[variables('cosmosDbSettings').enableFreeTier]", "locations": [ { "failoverPriority": 0, @@ -148,7 +146,7 @@ }, { "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases", - "apiVersion": "2022-08-15", + "apiVersion": "2023-04-15", "name": "[format('{0}/{1}', variables('cosmosDbSettings').name, variables('cosmosDbSettings').database.name)]", "properties": { "resource": { @@ -161,7 +159,7 @@ }, { "type": "Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers", - "apiVersion": "2022-08-15", + "apiVersion": "2023-04-15", "name": "[format('{0}/{1}/{2}', variables('cosmosDbSettings').name, variables('cosmosDbSettings').database.name, variables('cosmosDbSettings').container.name)]", "properties": { "resource": { @@ -191,9 +189,7 @@ ] } }, - "options": { - "throughput": "[variables('cosmosDbSettings').container.throughput]" - } + "options": {} }, "dependsOn": [ "[resourceId('Microsoft.DocumentDB/databaseAccounts/sqlDatabases', variables('cosmosDbSettings').name, variables('cosmosDbSettings').database.name)]" @@ -227,7 +223,7 @@ "model": { "format": "OpenAI", "name": "[variables('openAiSettings').model.name]", - "version": "[variables('openAiSettings').model.version]" + "version": "S0" } }, "dependsOn": [ @@ -285,7 +281,16 @@ "apiVersion": "2022-09-01", "name": "[format('{0}/{1}', variables('appServiceSettings').web.name, 'appsettings')]", "kind": "string", - "properties": "[if(parameters('deployOpenAi'), createObject('COSMOSDB__ENDPOINT', reference(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbSettings').name), '2022-08-15').documentEndpoint, 'COSMOSDB__KEY', listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbSettings').name), '2022-08-15').primaryMasterKey, 'COSMOSDB__DATABASE', variables('cosmosDbSettings').database.name, 'COSMOSDB__CONTAINER', variables('cosmosDbSettings').container.name, 'OPENAI__ENDPOINT', reference(resourceId('Microsoft.CognitiveServices/accounts', variables('openAiSettings').name), '2023-05-01').endpoint, 'OPENAI__KEY', listKeys(resourceId('Microsoft.CognitiveServices/accounts', variables('openAiSettings').name), '2023-05-01').key1, 'OPENAI__MODELNAME', variables('openAiSettings').model.deployment.name, 'OPENAI__MAXCONVERSATIONTOKENS', variables('openAiSettings').maxConversationTokens), createObject('COSMOSDB__ENDPOINT', reference(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbSettings').name), '2022-08-15').documentEndpoint, 'COSMOSDB__KEY', listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbSettings').name), '2022-08-15').primaryMasterKey, 'COSMOSDB__DATABASE', variables('cosmosDbSettings').database.name, 'COSMOSDB__CONTAINER', variables('cosmosDbSettings').container.name))]", + "properties": { + "COSMOSDB__ENDPOINT": "[reference(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbSettings').name), '2023-04-15').documentEndpoint]", + "COSMOSDB__KEY": "[listKeys(resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbSettings').name), '2023-04-15').primaryMasterKey]", + "COSMOSDB__DATABASE": "[variables('cosmosDbSettings').database.name]", + "COSMOSDB__CONTAINER": "[variables('cosmosDbSettings').container.name]", + "OPENAI__ENDPOINT": "[reference(resourceId('Microsoft.CognitiveServices/accounts', variables('openAiSettings').name), '2023-05-01').endpoint]", + "OPENAI__KEY": "[listKeys(resourceId('Microsoft.CognitiveServices/accounts', variables('openAiSettings').name), '2023-05-01').key1]", + "OPENAI__MODELNAME": "[variables('openAiSettings').model.deployment.name]", + "OPENAI__MAXCONVERSATIONTOKENS": "[variables('openAiSettings').maxConversationTokens]" + }, "dependsOn": [ "[resourceId('Microsoft.Web/sites', variables('appServiceSettings').web.name)]", "[resourceId('Microsoft.DocumentDB/databaseAccounts', variables('cosmosDbSettings').name)]", @@ -297,7 +302,7 @@ }, { "type": "Microsoft.Web/sites/sourcecontrols", - "apiVersion": "2021-03-01", + "apiVersion": "2022-09-01", "name": "[format('{0}/{1}', variables('appServiceSettings').web.name, 'web')]", "properties": { "repoUrl": "[variables('appServiceSettings').web.git.repo]", diff --git a/azuredeploy.parameters.json b/azuredeploy.parameters.json deleted file mode 100644 index 7f9d86d..0000000 --- a/azuredeploy.parameters.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "location": { - "value": "East US" - }, - "cosmosDbEnableFreeTier": { - "value": false - }, - "appServiceSku": { - "value": "D1" - }, - "openAiSku": { - "value": "S0" - }, - "appGitRepository": { - "value": "https://github.com/azure-samples/cosmosdb-chatgpt.git" - }, - "appGetRepositoryBranch": { - "value": "main" - }, - "deployOpenAi": { - "value": true - } - } -} \ No newline at end of file diff --git a/cosmoschatgpt.csproj b/cosmoschatgpt.csproj index 2252719..642de53 100644 --- a/cosmoschatgpt.csproj +++ b/cosmoschatgpt.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/readme.md b/readme.md index 84ecf3f..55a61aa 100644 --- a/readme.md +++ b/readme.md @@ -7,13 +7,13 @@ products: - azure-openai name: Sample chat app using Azure Cosmos DB for NoSQL and Azure OpenAI Service urlFragment: chat-app -description: Sample application that implements multiple chat threads using the Azure OpenAI "gpt-35-turbo" model and Azure Cosmos DB for NoSQL for storage. +description: Sample application that implements multiple chat threads using the Azure OpenAI "gpt-4" and Azure Cosmos DB for NoSQL for storage. azureDeploy: https://raw.githubusercontent.com/azure-samples/cosmosdb-chatgpt/main/azuredeploy.json --- # Azure Cosmos DB + Azure OpenAI Service ChatGPT -This sample application combines Azure Cosmos DB with Azure OpenAI Service to build a simple AI-enabled Chat Application. The application is written in C# on .NET 8 with a Blazor Server front-end and is hosted on Azure Web Apps. +This sample application combines Azure Cosmos DB with Azure OpenAI Service to build a simple AI-enabled Chat Application. The purpose of this application is to provide a simple demonstration of how to design a service to generate completions from user prompts and store the chat history prompts and completions from a generative AI application. The application is written in C# on .NET 8 with a Blazor Server front-end and is hosted on Azure Web Apps. ![Cosmos DB + ChatGPT user interface](screenshot.png) @@ -23,27 +23,27 @@ Individual chat sessions (or conversations) are displayed and can be selected in When a new prompt is sent to the Azure OpenAI Service, some or all of the conversation history is sent with it. This provides context allowing ChatGPT to respond as though it is having a conversation. The length of this conversation history can be configured from appsettings.json with the `OpenAiMaxTokens` value. When a user prompt is entered, the application will cycle from the most recent to the oldest prompts and completions, counting the tokens used for each. When it gets to the `OpenAiMaxTokens` it stops and returns the conversational history as far back as the token limit allows. -The "gpt-35-turbo" model used by this sample has a maximum of 4096 tokens. Token are used in both the request and reponse from the service. Overriding the maxConversationLength to values approaching maximum token value could result in completions that contain little to no text if all of it has been used in the request. +The "gpt-4" model used by this sample has a maximum of 4096 tokens. Token are used in both the request and reponse from the service. Overriding the maxConversationLength to values approaching maximum token value could result in completions that contain little to no text if all of it has been used in the request. The history for all prompts and completions is stored in Azure Cosmos DB. Deleting a chat session in the UI will delete it's corresponding user prompts and completions. The application summarizes the name of the chat session by asking ChatGPT to provide a one or two word summary of the first user prompt and completion. This allows you to easily identity different chat sessions. -Please note this is a sample application. It is intended to demonstrate how to use Azure Cosmos DB and Azure OpenAI Service ChatGPT together. It demonstrates how system prompts are used to define behavior for generation completions in a Generative AI scenario. It also provides an example of how to model data for a chat-based application. +Please note this is a sample application. It is intended to demonstrate how to use Azure Cosmos DB and Azure OpenAI Service ChatGPT together and capture user prompts and completions with an example of how to model data for a chat-based application. It also demonstrates how system prompts are used to define behavior for generation completions in a Generative AI scenario. ## Getting Started ### Prerequisites - Azure Subscription -- Subscription access to Azure OpenAI service. Start here to [Request Acces to Azure OpenAI Service](https://customervoice.microsoft.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR7en2Ais5pxKtso_Pz4b1_xUOFA5Qk1UWDRBMjg0WFhPMkIzTzhKQ1dWNyQlQCN0PWcu) +- Subscription access to Azure OpenAI service. Start here to [Request Access to Azure OpenAI Service](https://customervoice.microsoft.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR7en2Ais5pxKtso_Pz4b1_xUNTZBNzRKNlVQSFhZMU9aV09EVzYxWFdORCQlQCN0PWcu) - Visual Studio, VS Code, or some editor if you want to edit or view the source for this sample. ### Installation from this repository If you do not expect to modify this solution and deploy merged changes, you can install using this step below. -1. Click ***Deploy to Azure*** below and follow the prompts in Azure Portal to deploy this solution. +1. Click one of the ***Deploy to Azure*** buttons belows and follow the prompts in Azure Portal to deploy this solution. There is one that deploys a new Azure OpenAI account and a second that allows you to use an existing Azure OpenAI account. ### Installation from forked repository @@ -58,7 +58,7 @@ The provided ARM or Bicep Template will provision the following resources: 1. **Azure Cosmos DB** account with database and container at 400 RU/s. This can optionally be configured to run on the Cosmos DB free tier if available for your subscription. 1. **Azure App service** configured for CI/CD to your forked GitHub repository. This service can also be configured to run on App Service free tier. -1. **Azure OpenAI** You must also specify a name for the deployment of the "gpt-35-turbo" model which is used by this application. +1. **Azure OpenAI** You must also specify a name for the deployment of the "gpt-4" model which is used by this application. **Note:** You must have access to Azure Open AI service from your subscription before attempting to deploy this application. @@ -85,7 +85,6 @@ To remove all the resources used by this sample, you must first manually delete ## Resources - [Azure Cosmos DB + Azure OpenAI ChatGPT Blog Post Announcement](https://devblogs.microsoft.com/cosmosdb/chatgpt-azure-cosmos-db/) -- [Azure Cosmos DB Free Trial](https://aka.ms/TryCosmos) - [Azure OpenAI Service documentation](https://learn.microsoft.com/azure/cognitive-services/openai/) - [Azure App Service documentation](https://learn.microsoft.com/azure/app-service/) - [ASP.NET Core Blazor documentation](https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor)