Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Configurable System Prompts for function app & Deploy azure function by using bicep file #194

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 41 additions & 32 deletions ClientAdvisor/AzureFunction/function_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,28 +79,33 @@ def get_SQL_Response(
)
deployment = os.environ.get("AZURE_OPEN_AI_DEPLOYMENT_MODEL")

sql_prompt = f'''A valid T-SQL query to find {query} for tables and columns provided below:
1. Table: Clients
Columns: ClientId,Client,Email,Occupation,MaritalStatus,Dependents
2. Table: InvestmentGoals
Columns: ClientId,InvestmentGoal
3. Table: Assets
Columns: ClientId,AssetDate,Investment,ROI,Revenue,AssetType
4. Table: ClientSummaries
Columns: ClientId,ClientSummary
5. Table: InvestmentGoalsDetails
Columns: ClientId,InvestmentGoal,TargetAmount,Contribution
6. Table: Retirement
Columns: ClientId,StatusDate,RetirementGoalProgress,EducationGoalProgress
7.Table: ClientMeetings
Columns: ClientId,ConversationId,Title,StartTime,EndTime,Advisor,ClientEmail
Use Investement column from Assets table as value always.
Assets table has snapshots of values by date. Do not add numbers across different dates for total values.
Do not use client name in filter.
Do not include assets values unless asked for.
Always use ClientId = {clientid} in the query filter.
Always return client name in the query.
Only return the generated sql query. do not return anything else'''
sql_prompt = os.environ.get("AZURE_SQL_SYSTEM_PROMPT")
if sql_prompt:
sql_prompt = sql_prompt.replace("{query}", query)
sql_prompt = sql_prompt.replace("{clientid}", clientid)
else:
sql_prompt = f'''A valid T-SQL query to find {query} for tables and columns provided below:
1. Table: Clients
Columns: ClientId,Client,Email,Occupation,MaritalStatus,Dependents
2. Table: InvestmentGoals
Columns: ClientId,InvestmentGoal
3. Table: Assets
Columns: ClientId,AssetDate,Investment,ROI,Revenue,AssetType
4. Table: ClientSummaries
Columns: ClientId,ClientSummary
5. Table: InvestmentGoalsDetails
Columns: ClientId,InvestmentGoal,TargetAmount,Contribution
6. Table: Retirement
Columns: ClientId,StatusDate,RetirementGoalProgress,EducationGoalProgress
7.Table: ClientMeetings
Columns: ClientId,ConversationId,Title,StartTime,EndTime,Advisor,ClientEmail
Use Investement column from Assets table as value always.
Assets table has snapshots of values by date. Do not add numbers across different dates for total values.
Do not use client name in filter.
Do not include assets values unless asked for.
Always use ClientId = {clientid} in the query filter.
Always return client name in the query.
Only return the generated sql query. do not return anything else'''
try:

completion = client.chat.completions.create(
Expand Down Expand Up @@ -156,9 +161,11 @@ def get_answers_from_calltranscripts(
)

query = question
system_message = '''You are an assistant who provides wealth advisors with helpful information to prepare for client meetings.
You have access to the client’s meeting call transcripts.
You can use this information to answer questions about the clients'''
system_message = os.environ.get("AZURE_CALL_TRANSCRIPT_SYSTEM_PROMPT")
if not system_message:
system_message = '''You are an assistant who provides wealth advisors with helpful information to prepare for client meetings.
You have access to the client’s meeting call transcripts.
You can use this information to answer questions about the clients'''

completion = client.chat.completions.create(
model = deployment,
Expand Down Expand Up @@ -259,13 +266,15 @@ async def stream_openai_text(req: Request) -> StreamingResponse:
settings.max_tokens = 800
settings.temperature = 0

system_message = '''you are a helpful assistant to a wealth advisor.
Do not answer any questions not related to wealth advisors queries.
If the client name and client id do not match, only return - Please only ask questions about the selected client or select another client to inquire about their details. do not return any other information.
Only use the client name returned from database in the response.
If you cannot answer the question, always return - I cannot answer this question from the data available. Please rephrase or add more details.
** Remove any client identifiers or ids or numbers or ClientId in the final response.
'''
system_message = os.environ.get("AZURE_OPENAI_STREAM_TEXT_SYSTEM_PROMPT")
if not system_message:
system_message = '''you are a helpful assistant to a wealth advisor.
Do not answer any questions not related to wealth advisors queries.
If the client name and client id do not match, only return - Please only ask questions about the selected client or select another client to inquire about their details. do not return any other information.
Only use the client name returned from database in the response.
If you cannot answer the question, always return - I cannot answer this question from the data available. Please rephrase or add more details.
** Remove any client identifiers or ids or numbers or ClientId in the final response.
'''

user_query = query.replace('?',' ')

Expand Down
167 changes: 167 additions & 0 deletions ClientAdvisor/Deployment/bicep/deploy_azure_function.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
@description('Specifies the location for resources.')
param solutionName string
param solutionLocation string
@secure()
param azureOpenAIApiKey string
param azureOpenAIApiVersion string
param azureOpenAIEndpoint string
@secure()
param azureSearchAdminKey string
param azureSearchServiceEndpoint string
param azureSearchIndex string
param sqlServerName string
param sqlDbName string
param sqlDbUser string
@secure()
param sqlDbPwd string
param functionAppVersion string
@description('Azure Function App SQL System Prompt')
param sqlSystemPrompt string
@description('Azure Function App CallTranscript System Prompt')
param callTranscriptSystemPrompt string
@description('Azure Function App Stream Text System Prompt')
param streamTextSystemPrompt string

var functionAppName = '${solutionName}fn'
var azureOpenAIDeploymentModel = 'gpt-4'
var azureOpenAIEmbeddingDeployment = 'text-embedding-ada-002'
var valueOne = '1'

resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' = {
name: '${solutionName}fnstorage'
location: solutionLocation
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
properties: {
allowSharedKeyAccess: false
}
}

resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
name: 'workspace-${solutionName}'
location: solutionLocation
}

resource ApplicationInsights 'Microsoft.Insights/components@2020-02-02' = {
name: functionAppName
location: solutionLocation
kind: 'web'
properties: {
Application_Type: 'web'
publicNetworkAccessForIngestion: 'Enabled'
publicNetworkAccessForQuery: 'Enabled'
WorkspaceResourceId: logAnalyticsWorkspace.id
}
}

resource containerAppEnv 'Microsoft.App/managedEnvironments@2022-06-01-preview' = {
name: '${solutionName}env'
location: solutionLocation
sku: {
name: 'Consumption'
}
properties: {
appLogsConfiguration: {
destination: 'log-analytics'
logAnalyticsConfiguration: {
customerId: logAnalyticsWorkspace.properties.customerId
sharedKey: logAnalyticsWorkspace.listKeys().primarySharedKey
}
}
}
}

resource functionApp 'Microsoft.Web/sites@2024-04-01' = {
name: functionAppName
location: solutionLocation
kind: 'functionapp'
identity: {
type: 'SystemAssigned'
}
properties: {
managedEnvironmentId: containerAppEnv.id
siteConfig: {
linuxFxVersion: 'DOCKER|bycwacontainerreg.azurecr.io/byc-wa-fn:${functionAppVersion}'
appSettings: [
{
name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
value: reference(ApplicationInsights.id, '2015-05-01').InstrumentationKey
}
{
name: 'AZURE_OPEN_AI_API_KEY'
value: azureOpenAIApiKey
}
{
name: 'AZURE_OPEN_AI_DEPLOYMENT_MODEL'
value: azureOpenAIDeploymentModel
}
{
name: 'AZURE_OPEN_AI_ENDPOINT'
value: azureOpenAIEndpoint
}
{
name: 'AZURE_OPENAI_EMBEDDING_DEPLOYMENT'
value: azureOpenAIEmbeddingDeployment
}
{
name: 'OPENAI_API_VERSION'
value: azureOpenAIApiVersion
}
{
name: 'AZURE_AI_SEARCH_API_KEY'
value: azureSearchAdminKey
}
{
name: 'AZURE_AI_SEARCH_ENDPOINT'
value: azureSearchServiceEndpoint
}
{
name: 'AZURE_SEARCH_INDEX'
value: azureSearchIndex
}
{
name: 'PYTHON_ENABLE_INIT_INDEXING'
value: valueOne
}
{
name: 'PYTHON_ISOLATE_WORKER_DEPENDENCIES'
value: valueOne
}
{
name: 'SQLDB_CONNECTION_STRING'
value: 'TBD'
}
{
name: 'SQLDB_SERVER'
value: sqlServerName
}
{
name: 'SQLDB_DATABASE'
value: sqlDbName
}
{
name: 'SQLDB_USERNAME'
value: sqlDbUser
}
{
name: 'SQLDB_PASSWORD'
value: sqlDbPwd
}
{
name: 'AZURE_SQL_SYSTEM_PROMPT'
value: sqlSystemPrompt
}
{
name: 'AZURE_CALL_TRANSCRIPT_SYSTEM_PROMPT'
value: callTranscriptSystemPrompt
}
{
name: 'AZURE_OPENAI_STREAM_TEXT_SYSTEM_PROMPT'
value: streamTextSystemPrompt
}
]
}
}
}

This file was deleted.

45 changes: 39 additions & 6 deletions ClientAdvisor/Deployment/bicep/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,46 @@ param cosmosLocation string
// param fabricWorkspaceId string

var resourceGroupLocation = resourceGroup().location
var resourceGroupName = resourceGroup().name
// var subscriptionId = subscription().subscriptionId

var solutionLocation = resourceGroupLocation
var baseUrl = 'https://raw.githubusercontent.com/microsoft/Build-your-own-copilot-Solution-Accelerator/main/ClientAdvisor/'
var appversion = 'latest'

var functionAppSqlPrompt = '''A valid T-SQL query to find {query} for tables and columns provided below:
1. Table: Clients
Columns: ClientId,Client,Email,Occupation,MaritalStatus,Dependents
2. Table: InvestmentGoals
Columns: ClientId,InvestmentGoal
3. Table: Assets
Columns: ClientId,AssetDate,Investment,ROI,Revenue,AssetType
4. Table: ClientSummaries
Columns: ClientId,ClientSummary
5. Table: InvestmentGoalsDetails
Columns: ClientId,InvestmentGoal,TargetAmount,Contribution
6. Table: Retirement
Columns: ClientId,StatusDate,RetirementGoalProgress,EducationGoalProgress
7.Table: ClientMeetings
Columns: ClientId,ConversationId,Title,StartTime,EndTime,Advisor,ClientEmail
Use Investement column from Assets table as value always.
Assets table has snapshots of values by date. Do not add numbers across different dates for total values.
Do not use client name in filter.
Do not include assets values unless asked for.
Always use ClientId = {clientid} in the query filter.
Always return client name in the query.
Only return the generated sql query. do not return anything else'''

var functionAppCallTranscriptSystemPrompt = '''You are an assistant who provides wealth advisors with helpful information to prepare for client meetings.
You have access to the client’s meeting call transcripts.
You can use this information to answer questions about the clients'''

var functionAppStreamTextSystemPrompt = '''You are a helpful assistant to a wealth advisor.
Do not answer any questions not related to wealth advisors queries.
If the client name and client id do not match, only return - Please only ask questions about the selected client or select another client to inquire about their details. do not return any other information.
Only use the client name returned from database in the response.
If you cannot answer the question, always return - I cannot answer this question from the data available. Please rephrase or add more details.
** Remove any client identifiers or ids or numbers or ClientId in the final response.'''

// ========== Managed Identity ========== //
module managedIdentityModule 'deploy_managed_identity.bicep' = {
name: 'deploy_managed_identity'
Expand Down Expand Up @@ -101,12 +134,11 @@ module uploadFiles 'deploy_upload_files_script.bicep' = {
dependsOn:[storageAccountModule]
}

module azureFunctions 'deploy_azure_function_script.bicep' = {
name : 'deploy_azure_function_script'
module azureFunctions 'deploy_azure_function.bicep' = {
name : 'deploy_azure_function'
params:{
solutionName: solutionPrefix
solutionLocation: solutionLocation
resourceGroupName:resourceGroupName
azureOpenAIApiKey:azOpenAI.outputs.openAIOutput.openAPIKey
azureOpenAIApiVersion:'2024-02-15-preview'
azureOpenAIEndpoint:azOpenAI.outputs.openAIOutput.openAPIEndpoint
Expand All @@ -117,9 +149,10 @@ module azureFunctions 'deploy_azure_function_script.bicep' = {
sqlDbName:sqlDBModule.outputs.sqlDbOutput.sqlDbName
sqlDbUser:sqlDBModule.outputs.sqlDbOutput.sqlDbUser
sqlDbPwd:sqlDBModule.outputs.sqlDbOutput.sqlDbPwd
identity:managedIdentityModule.outputs.managedIdentityOutput.id
baseUrl:baseUrl
functionAppVersion: appversion
sqlSystemPrompt: functionAppSqlPrompt
callTranscriptSystemPrompt: functionAppCallTranscriptSystemPrompt
streamTextSystemPrompt: functionAppStreamTextSystemPrompt
}
dependsOn:[storageAccountModule]
}
Expand Down
Loading
Loading