diff --git a/infra/deploy_app_service.bicep b/infra/deploy_app_service.bicep index 648fbf16f..fb6892ca1 100644 --- a/infra/deploy_app_service.bicep +++ b/infra/deploy_app_service.bicep @@ -128,6 +128,8 @@ param azureSearchServiceEndpoint string @description('Azure Function App SQL System Prompt') param sqlSystemPrompt string +@description('Azure Function App SQL Agent System Prompt') +param sqlAgentFallbackSystemPrompt string @description('Azure Function App CallTranscript System Prompt') param callTranscriptSystemPrompt string @description('Azure Function App Stream Text System Prompt') @@ -339,6 +341,10 @@ resource Website 'Microsoft.Web/sites@2020-06-01' = { name: 'AZURE_SQL_SYSTEM_PROMPT' value: sqlSystemPrompt } + { + name: 'SQL_AGENT_FALLBACK_PROMPT' + value: sqlAgentFallbackSystemPrompt + } { name: 'AZURE_CALL_TRANSCRIPT_SYSTEM_PROMPT' value: callTranscriptSystemPrompt diff --git a/infra/main.bicep b/infra/main.bicep index 7c225c1f8..da53335da 100644 --- a/infra/main.bicep +++ b/infra/main.bicep @@ -110,6 +110,24 @@ var functionAppSqlPrompt = '''Generate a valid T-SQL query to find {query} for t When answering scheduling or time-based meeting questions, always use the StartTime column from ClientMeetings table. Use correct logic to return the most recent past meeting (last/previous) or the nearest future meeting (next/upcoming), and ensure only StartTime column is used for meeting timing comparisons. Only return the generated SQL query. Do not return anything else.''' +var sqlagentFallbackSystemPrompt = '''You are an expert assistant in generating T-SQL queries based on user questions. + Always use the following schema: + 1. Table: Clients (ClientId, Client, Email, Occupation, MaritalStatus, Dependents) + 2. Table: InvestmentGoals (ClientId, InvestmentGoal) + 3. Table: Assets (ClientId, AssetDate, Investment, ROI, Revenue, AssetType) + 4. Table: ClientSummaries (ClientId, ClientSummary) + 5. Table: InvestmentGoalsDetails (ClientId, InvestmentGoal, TargetAmount, Contribution) + 6. Table: Retirement (ClientId, StatusDate, RetirementGoalProgress, EducationGoalProgress) + 7. Table: ClientMeetings (ClientId, ConversationId, Title, StartTime, EndTime, Advisor, ClientEmail) + + Rules: + - Always filter by ClientId = + - Do not use client name for filtering + - Assets table contains snapshots by date; do not sum values across dates + - Use StartTime for time-based filtering (meetings) + - Only return the raw T-SQL query. No explanations or comments. + ''' + var functionAppCallTranscriptSystemPrompt = '''You are an assistant who supports wealth advisors in preparing for client meetings. You have access to the client’s past meeting call transcripts. When answering questions, especially summary requests, provide a detailed and structured response that includes key topics, concerns, decisions, and trends. @@ -261,6 +279,7 @@ module appserviceModule 'deploy_app_service.bicep' = { applicationInsightsId: aifoundry.outputs.applicationInsightsId azureSearchServiceEndpoint: aifoundry.outputs.aiSearchTarget sqlSystemPrompt: functionAppSqlPrompt + sqlAgentFallbackSystemPrompt: sqlagentFallbackSystemPrompt callTranscriptSystemPrompt: functionAppCallTranscriptSystemPrompt streamTextSystemPrompt: functionAppStreamTextSystemPrompt //aiFoundryProjectName:aifoundry.outputs.aiFoundryProjectName diff --git a/src/App/.env.sample b/src/App/.env.sample index 0f69d5442..4d5d58717 100644 --- a/src/App/.env.sample +++ b/src/App/.env.sample @@ -63,7 +63,24 @@ AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME= AZURE_CALL_TRANSCRIPT_SYSTEM_PROMPT="You are an assistant who supports wealth advisors in preparing for client meetings. \n You have access to the client’s past meeting call transcripts. \n When answering questions, especially summary requests, provide a detailed and structured response that includes key topics, concerns, decisions, and trends. \n If no data is available, state 'No relevant data found for previous meetings." AZURE_OPENAI_STREAM_TEXT_SYSTEM_PROMPT="You are a helpful assistant to a Wealth Advisor. \n The currently selected client's name is '{SelectedClientName}', and any case-insensitive or partial mention should be understood as referring to this client.\n If no name is provided, assume the question is about '{SelectedClientName}'.\n If the query references a different client or includes comparative terms like 'compare' or 'other client', please respond with: 'Please only ask questions about the selected client or select another client.'\n Otherwise, provide thorough answers using only data from SQL or call transcripts. \n If no data is found, please respond with 'No data found for that client.' Remove any client identifiers from the final response." AZURE_SQL_SYSTEM_PROMPT="Generate a valid T-SQL query to find {query} for tables and columns provided below:\n 1. Table: Clients\n Columns: ClientId, Client, Email, Occupation, MaritalStatus, Dependents\n 2. Table: InvestmentGoals\n Columns: ClientId, InvestmentGoal\n 3. Table: Assets\n Columns: ClientId, AssetDate, Investment, ROI, Revenue, AssetType\n 4. Table: ClientSummaries\n Columns: ClientId, ClientSummary\n 5. Table: InvestmentGoalsDetails\n Columns: ClientId, InvestmentGoal, TargetAmount, Contribution\n 6. Table: Retirement\n Columns: ClientId, StatusDate, RetirementGoalProgress, EducationGoalProgress\n 7. Table: ClientMeetings\n Columns: ClientId, ConversationId, Title, StartTime, EndTime, Advisor, ClientEmail\n Always use the Investment column from the Assets table as the value.\n Assets table has snapshots of values by date. Do not add numbers across different dates for total values.\n Do not use client name in filters.\n Do not include assets values unless asked for.\n ALWAYS use ClientId = {clientid} in the query filter.\n ALWAYS select Client Name (Column: Client) in the query.\n Query filters are IMPORTANT. Add filters like AssetType, AssetDate, etc. if needed.\n Only return the generated SQL query. Do not return anything else." +SQL_AGENT_FALLBACK_PROMPT=""" + You are an expert assistant in generating T-SQL queries based on user questions. + Always use the following schema: + 1. Table: Clients (ClientId, Client, Email, Occupation, MaritalStatus, Dependents) + 2. Table: InvestmentGoals (ClientId, InvestmentGoal) + 3. Table: Assets (ClientId, AssetDate, Investment, ROI, Revenue, AssetType) + 4. Table: ClientSummaries (ClientId, ClientSummary) + 5. Table: InvestmentGoalsDetails (ClientId, InvestmentGoal, TargetAmount, Contribution) + 6. Table: Retirement (ClientId, StatusDate, RetirementGoalProgress, EducationGoalProgress) + 7. Table: ClientMeetings (ClientId, ConversationId, Title, StartTime, EndTime, Advisor, ClientEmail) + Rules: + - Always filter by ClientId = + - Do not use client name for filtering + - Assets table contains snapshots by date; do not sum values across dates + - Use StartTime for time-based filtering (meetings) + - Only return the raw T-SQL query. No explanations or comments. + """ # Misc APPINSIGHTS_INSTRUMENTATIONKEY= AUTH_ENABLED="false" diff --git a/src/App/backend/agents/agent_factory.py b/src/App/backend/agents/agent_factory.py index df81a2caf..1ce003f74 100644 --- a/src/App/backend/agents/agent_factory.py +++ b/src/App/backend/agents/agent_factory.py @@ -116,24 +116,7 @@ async def get_sql_agent(cls) -> dict: async with cls._lock: if not hasattr(cls, "_sql_agent") or cls._sql_agent is None: - agent_instructions = config.SQL_SYSTEM_PROMPT or """ - You are an expert assistant in generating T-SQL queries based on user questions. - Always use the following schema: - 1. Table: Clients (ClientId, Client, Email, Occupation, MaritalStatus, Dependents) - 2. Table: InvestmentGoals (ClientId, InvestmentGoal) - 3. Table: Assets (ClientId, AssetDate, Investment, ROI, Revenue, AssetType) - 4. Table: ClientSummaries (ClientId, ClientSummary) - 5. Table: InvestmentGoalsDetails (ClientId, InvestmentGoal, TargetAmount, Contribution) - 6. Table: Retirement (ClientId, StatusDate, RetirementGoalProgress, EducationGoalProgress) - 7. Table: ClientMeetings (ClientId, ConversationId, Title, StartTime, EndTime, Advisor, ClientEmail) - - Rules: - - Always filter by ClientId = - - Do not use client name for filtering - - Assets table contains snapshots by date; do not sum values across dates - - Use StartTime for time-based filtering (meetings) - - Only return the raw T-SQL query. No explanations or comments. - """ + agent_instructions = config.SQL_SYSTEM_PROMPT or config.SQL_AGENT_FALLBACK_PROMPT project_client = AIProjectClient( endpoint=config.AI_PROJECT_ENDPOINT, diff --git a/src/App/backend/common/config.py b/src/App/backend/common/config.py index 06073a427..facc79860 100644 --- a/src/App/backend/common/config.py +++ b/src/App/backend/common/config.py @@ -146,6 +146,7 @@ def __init__(self): # System Prompts self.SQL_SYSTEM_PROMPT = os.environ.get("AZURE_SQL_SYSTEM_PROMPT") + self.SQL_AGENT_FALLBACK_PROMPT=os.environ.get('SQL_AGENT_FALLBACK_PROMPT') self.CALL_TRANSCRIPT_SYSTEM_PROMPT = os.environ.get( "AZURE_CALL_TRANSCRIPT_SYSTEM_PROMPT" )