mirror of
https://github.com/temporal-community/temporal-ai-agent.git
synced 2026-03-15 14:08:08 +01:00
- dynamic agent prompt based on multi goal or not
- made choose_agent_goal be dynamically included - made tool selection not be required in all toolchains - changes to get env vars easier in workflow - Updated docs/guides, todo based on aboe
This commit is contained in:
@@ -35,12 +35,13 @@ OPENAI_API_KEY=sk-proj-...
|
|||||||
# Uncomment if using API key (not needed for local dev server)
|
# Uncomment if using API key (not needed for local dev server)
|
||||||
# TEMPORAL_API_KEY=abcdef1234567890
|
# TEMPORAL_API_KEY=abcdef1234567890
|
||||||
|
|
||||||
# Set starting goal of agent - if unset default is all
|
# Set starting goal of agent - if unset default is goal_choose_agent_type
|
||||||
AGENT_GOAL=goal_choose_agent_type # default for multi-goal start
|
AGENT_GOAL=goal_choose_agent_type # for multi-goal start
|
||||||
#AGENT_GOAL=goal_event_flight_invoice # for original goal
|
#AGENT_GOAL=goal_event_flight_invoice # for original goal
|
||||||
#AGENT_GOAL=goal_match_train_invoice # for replay goal
|
#AGENT_GOAL=goal_match_train_invoice # for replay goal
|
||||||
|
|
||||||
#Choose which category(ies) of goals you want to be listed by the Agent - options are system (always included), hr, travel, or all.
|
#Choose which category(ies) of goals you want to be listed by the Agent Goal picker if enabled above
|
||||||
|
# - options are system (always included), hr, travel, or all.
|
||||||
GOAL_CATEGORIES=hr,travel-flights,travel-trains,fin # default is all
|
GOAL_CATEGORIES=hr,travel-flights,travel-trains,fin # default is all
|
||||||
#GOAL_CATEGORIES=travel-flights
|
#GOAL_CATEGORIES=travel-flights
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import google.generativeai as genai
|
|||||||
import anthropic
|
import anthropic
|
||||||
import deepseek
|
import deepseek
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from models.data_types import ValidationInput, ValidationResult, ToolPromptInput, EnvLookupInput
|
from models.data_types import EnvLookupOutput, ValidationInput, ValidationResult, ToolPromptInput, EnvLookupInput
|
||||||
|
|
||||||
load_dotenv(override=True)
|
load_dotenv(override=True)
|
||||||
print(
|
print(
|
||||||
@@ -370,7 +370,8 @@ class ToolActivities:
|
|||||||
print("Initialized Anthropic client on demand")
|
print("Initialized Anthropic client on demand")
|
||||||
|
|
||||||
response = self.anthropic_client.messages.create(
|
response = self.anthropic_client.messages.create(
|
||||||
model="claude-3-5-sonnet-20241022", # todo try claude-3-7-sonnet-20250219
|
#model="claude-3-5-sonnet-20241022", # todo try claude-3-7-sonnet-20250219
|
||||||
|
model="claude-3-7-sonnet-20250219", # todo try claude-3-7-sonnet-20250219
|
||||||
max_tokens=1024,
|
max_tokens=1024,
|
||||||
system=input.context_instructions
|
system=input.context_instructions
|
||||||
+ ". The current date is "
|
+ ". The current date is "
|
||||||
@@ -473,17 +474,29 @@ class ToolActivities:
|
|||||||
|
|
||||||
# get env vars for workflow
|
# get env vars for workflow
|
||||||
@activity.defn
|
@activity.defn
|
||||||
async def get_env_bool(self, input: EnvLookupInput) -> bool:
|
async def get_wf_env_vars(self, input: EnvLookupInput) -> EnvLookupOutput:
|
||||||
""" gets boolean env vars for workflow as an activity result so it's deterministic
|
""" gets env vars for workflow as an activity result so it's deterministic
|
||||||
handles default/None
|
handles default/None
|
||||||
"""
|
"""
|
||||||
value = os.getenv(input.env_var_name)
|
output: EnvLookupOutput = EnvLookupOutput(show_confirm=input.show_confirm_default,
|
||||||
if value is None:
|
multi_goal_mode=True)
|
||||||
return input.default
|
show_confirm_value = os.getenv(input.show_confirm_env_var_name)
|
||||||
if value is not None and value.lower() == "false":
|
if show_confirm_value is None:
|
||||||
return False
|
output.show_confirm = input.show_confirm_default
|
||||||
|
elif show_confirm_value is not None and show_confirm_value.lower() == "false":
|
||||||
|
output.show_confirm = False
|
||||||
else:
|
else:
|
||||||
return True
|
output.show_confirm = True
|
||||||
|
|
||||||
|
first_goal_value = os.getenv("AGENT_GOAL")
|
||||||
|
if first_goal_value is None:
|
||||||
|
output.multi_goal_mode = True # default if unset
|
||||||
|
elif first_goal_value is not None and first_goal_value.lower() != "goal_choose_agent_type":
|
||||||
|
output.multi_goal_mode = False
|
||||||
|
else:
|
||||||
|
output.multi_goal_mode = True
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
def get_current_date_human_readable():
|
def get_current_date_human_readable():
|
||||||
|
|||||||
@@ -19,14 +19,13 @@ Goal Categories lets you pick which groups of goals to show. Set via an .env set
|
|||||||
- `category_tag`: category for the goal
|
- `category_tag`: category for the goal
|
||||||
- `agent_friendly_description`: user-facing description of what the agent/chatbot does
|
- `agent_friendly_description`: user-facing description of what the agent/chatbot does
|
||||||
- `tools`: the list of tools the goal will walk the user through. These will be defined in the [tools/tool_registry.py](tools/tool_registry.py) and should be defined in list form as tool_registry.[name of tool]
|
- `tools`: the list of tools the goal will walk the user through. These will be defined in the [tools/tool_registry.py](tools/tool_registry.py) and should be defined in list form as tool_registry.[name of tool]
|
||||||
- Important! If you want to prompt the user with options for another goal, the last tool listed must be `list_agents_tool`. This allows the chatbot to guide the user back to choosing from the list of available goals once a goal is complete. This is recommended for multi-goal behavior. The `goal_choose_agent_type` is the exception as it handles the changing of goals. <br />
|
|
||||||
Example:
|
Example:
|
||||||
```
|
```
|
||||||
tools=[
|
tools=[
|
||||||
tool_registry.current_pto_tool,
|
tool_registry.current_pto_tool,
|
||||||
tool_registry.future_pto_calc_tool,
|
tool_registry.future_pto_calc_tool,
|
||||||
tool_registry.book_pto_tool,
|
tool_registry.book_pto_tool,
|
||||||
tool_registry.list_agents_tool,
|
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
- `description`: LLM-facing description of the goal that lists the tools by name and purpose.
|
- `description`: LLM-facing description of the goal that lists the tools by name and purpose.
|
||||||
|
|||||||
@@ -45,5 +45,10 @@ class ValidationResult:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class EnvLookupInput:
|
class EnvLookupInput:
|
||||||
env_var_name: str
|
show_confirm_env_var_name: str
|
||||||
default: bool
|
show_confirm_default: bool
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class EnvLookupOutput:
|
||||||
|
show_confirm: bool
|
||||||
|
multi_goal_mode: bool
|
||||||
@@ -2,15 +2,17 @@ from models.tool_definitions import AgentGoal
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
MULTI_GOAL_MODE:bool = None
|
||||||
|
|
||||||
def generate_genai_prompt(
|
def generate_genai_prompt(
|
||||||
agent_goal: AgentGoal, conversation_history: str, raw_json: Optional[str] = None
|
agent_goal: AgentGoal, conversation_history: str, multi_goal_mode:bool, raw_json: Optional[str] = None
|
||||||
) -> str:
|
) -> str:
|
||||||
"""
|
"""
|
||||||
Generates a concise prompt for producing or validating JSON instructions
|
Generates a concise prompt for producing or validating JSON instructions
|
||||||
with the provided tools and conversation history.
|
with the provided tools and conversation history.
|
||||||
"""
|
"""
|
||||||
prompt_lines = []
|
prompt_lines = []
|
||||||
|
set_multi_goal_mode_if_unset(multi_goal_mode)
|
||||||
|
|
||||||
# Intro / Role
|
# Intro / Role
|
||||||
prompt_lines.append(
|
prompt_lines.append(
|
||||||
@@ -81,7 +83,7 @@ def generate_genai_prompt(
|
|||||||
"1) If any required argument is missing, set next='question' and ask the user.\n"
|
"1) If any required argument is missing, set next='question' and ask the user.\n"
|
||||||
"2) If all required arguments are known, set next='confirm' and specify the tool.\n"
|
"2) If all required arguments are known, set next='confirm' and specify the tool.\n"
|
||||||
" The user will confirm before the tool is run.\n"
|
" The user will confirm before the tool is run.\n"
|
||||||
"3) If no more tools are needed (user_confirmed_tool_run has been run for all), set next='confirm' and tool='ListAgents'.\n"
|
f"3) {generate_toolchain_complete_guidance()}\n"
|
||||||
"4) response should be short and user-friendly.\n"
|
"4) response should be short and user-friendly.\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -127,8 +129,7 @@ def generate_tool_completion_prompt(current_tool: str, dynamic_result: dict) ->
|
|||||||
"ONLY return those json keys (next, tool, args, response), nothing else. "
|
"ONLY return those json keys (next, tool, args, response), nothing else. "
|
||||||
'Next should be "question" if the tool is not the last one in the sequence. '
|
'Next should be "question" if the tool is not the last one in the sequence. '
|
||||||
'Next should be "done" if the user is asking to be done with the chat. '
|
'Next should be "done" if the user is asking to be done with the chat. '
|
||||||
'Next should only be "pick-new-goal" if all tools have been run (use the system prompt to figure that out).'
|
f"{generate_pick_new_goal_guidance()}"
|
||||||
#'If all tools have been run (use the system prompt to figure that out) then clear tool history.' todo maybe fix this
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def generate_missing_args_prompt(current_tool: str, tool_data: dict, missing_args: list[str]) -> str:
|
def generate_missing_args_prompt(current_tool: str, tool_data: dict, missing_args: list[str]) -> str:
|
||||||
@@ -148,3 +149,59 @@ def generate_missing_args_prompt(current_tool: str, tool_data: dict, missing_arg
|
|||||||
f"and following missing arguments for tool {current_tool}: {missing_args}. "
|
f"and following missing arguments for tool {current_tool}: {missing_args}. "
|
||||||
"Only provide a valid JSON response without any comments or metadata."
|
"Only provide a valid JSON response without any comments or metadata."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def set_multi_goal_mode_if_unset(mode:bool)->None:
|
||||||
|
"""
|
||||||
|
Set multi-mode (used to pass workflow)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if in multi-goal mode, false if not
|
||||||
|
"""
|
||||||
|
global MULTI_GOAL_MODE
|
||||||
|
if MULTI_GOAL_MODE is None:
|
||||||
|
MULTI_GOAL_MODE = mode
|
||||||
|
|
||||||
|
def is_multi_goal_mode()-> bool:
|
||||||
|
"""
|
||||||
|
Centralized logic for if we're in multi-goal mode.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if in multi-goal mode, false if not
|
||||||
|
"""
|
||||||
|
return MULTI_GOAL_MODE
|
||||||
|
|
||||||
|
def generate_pick_new_goal_guidance()-> str:
|
||||||
|
"""
|
||||||
|
Generates a prompt for guiding the LLM to pick a new goal or be done depending on multi-goal mode.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: A prompt string prompting the LLM to when to go to pick-new-goal
|
||||||
|
"""
|
||||||
|
if is_multi_goal_mode():
|
||||||
|
return 'Next should only be "pick-new-goal" if all tools have been run (use the system prompt to figure that out) or the user explicitly requested to pick a new goal.'
|
||||||
|
else:
|
||||||
|
return 'Next should never be "pick-new-goal".'
|
||||||
|
|
||||||
|
def generate_toolchain_complete_guidance() -> str:
|
||||||
|
"""
|
||||||
|
Generates a prompt for guiding the LLM to handle the end of the toolchain.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: A prompt string prompting the LLM to prompt for a new goal, or be done
|
||||||
|
"""
|
||||||
|
if is_multi_goal_mode():
|
||||||
|
return "If no more tools are needed (user_confirmed_tool_run has been run for all), set next='confirm' and tool='ListAgents'."
|
||||||
|
else :
|
||||||
|
return "If no more tools are needed (user_confirmed_tool_run has been run for all), set next='done' and tool=''."
|
||||||
@@ -62,7 +62,7 @@ async def main():
|
|||||||
activities=[
|
activities=[
|
||||||
activities.agent_validatePrompt,
|
activities.agent_validatePrompt,
|
||||||
activities.agent_toolPlanner,
|
activities.agent_toolPlanner,
|
||||||
activities.get_env_bool,
|
activities.get_wf_env_vars,
|
||||||
dynamic_tool_activity,
|
dynamic_tool_activity,
|
||||||
],
|
],
|
||||||
activity_executor=activity_executor,
|
activity_executor=activity_executor,
|
||||||
|
|||||||
7
setup.md
7
setup.md
@@ -16,9 +16,12 @@ SHOW_CONFIRM=True
|
|||||||
|
|
||||||
### Agent Goal Configuration
|
### Agent Goal Configuration
|
||||||
|
|
||||||
The agent can be configured to pursue different goals using the `AGENT_GOAL` environment variable in your `.env` file.
|
The agent can be configured to pursue different goals using the `AGENT_GOAL` environment variable in your `.env` file. If unset, default is `goal_choose_agent_type`.
|
||||||
|
|
||||||
The agent can support multiple goals using goal categories using `GOAL_CATEGORIES` in your .env file. If unset, default is all.
|
If the first goal is `goal_choose_agent_type` the agent will support multiple goals using goal categories defined by `GOAL_CATEGORIES` in your .env file. If unset, default is all.
|
||||||
|
```bash
|
||||||
|
GOAL_CATEGORIES=hr,travel-flights,travel-trains,fin
|
||||||
|
```
|
||||||
|
|
||||||
See the section Goal-Specific Tool Configuration below for tool configuration for specific goals.
|
See the section Goal-Specific Tool Configuration below for tool configuration for specific goals.
|
||||||
|
|
||||||
|
|||||||
12
todo.md
12
todo.md
@@ -1,11 +1,15 @@
|
|||||||
# todo list
|
# todo list
|
||||||
[ ] goal change management tweaks <br />
|
[ ] goal change management tweaks <br />
|
||||||
- [ ] maybe make the choose_Agent_goal tag not be system/not always included? <br />
|
- [x] maybe make the choose_Agent_goal tag not be system/not always included? <br />
|
||||||
- [ ] try taking out list-agents as a tool because agent_prompt_generators may do it for you <br />
|
- [x] try taking out list-agents as a tool because agent_prompt_generators may do it for you <br />
|
||||||
- [ ] make goal selection not be a system tool but be an option in .env, see how that works, includes taking it out of the goal/toolset for all goals <br />
|
- [x] make goal selection not be a system tool but be an option in .env, see how that works, includes taking it out of the goal/toolset for all goals <br />
|
||||||
|
- [x] test single-goal <br />
|
||||||
|
- [x] test claude and grok<br />
|
||||||
|
- [x] document in sample env and docs how to control <br />
|
||||||
|
|
||||||
[ ] expand [tests](./tests/agent_goal_workflow_test.py)<br />
|
[ ] expand [tests](./tests/agent_goal_workflow_test.py)<br />
|
||||||
[ ] try claude-3-7-sonnet-20250219, see [tool_activities.py](./activities/tool_activities.py) <br />
|
[x] try claude-3-7-sonnet-20250219, see [tool_activities.py](./activities/tool_activities.py) <br />
|
||||||
|
[x] test Grok with changes
|
||||||
|
|
||||||
[ ] adding fintech goals <br />
|
[ ] adding fintech goals <br />
|
||||||
- Fraud Detection and Prevention - The AI monitors transactions across accounts, flagging suspicious activities (e.g., unusual spending patterns or login attempts) and autonomously freezing accounts or notifying customers and compliance teams.<br />
|
- Fraud Detection and Prevention - The AI monitors transactions across accounts, flagging suspicious activities (e.g., unusual spending patterns or login attempts) and autonomously freezing accounts or notifying customers and compliance teams.<br />
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ starter_prompt_generic = silly_prompt + "Welcome me, give me a description of wh
|
|||||||
|
|
||||||
goal_choose_agent_type = AgentGoal(
|
goal_choose_agent_type = AgentGoal(
|
||||||
id = "goal_choose_agent_type",
|
id = "goal_choose_agent_type",
|
||||||
category_tag="system",
|
category_tag="agent_selection",
|
||||||
agent_name="Choose Agent",
|
agent_name="Choose Agent",
|
||||||
agent_friendly_description="Choose the type of agent to assist you today.",
|
agent_friendly_description="Choose the type of agent to assist you today.",
|
||||||
tools=[
|
tools=[
|
||||||
@@ -33,13 +33,13 @@ goal_choose_agent_type = AgentGoal(
|
|||||||
"1. ListAgents: List agents available to interact with. Do not ask for user confirmation for this tool. "
|
"1. ListAgents: List agents available to interact with. Do not ask for user confirmation for this tool. "
|
||||||
"2. ChangeGoal: Change goal of agent "
|
"2. ChangeGoal: Change goal of agent "
|
||||||
"After these tools are complete, change your goal to the new goal as chosen by the user. ",
|
"After these tools are complete, change your goal to the new goal as chosen by the user. ",
|
||||||
starter_prompt=starter_prompt_generic + "Begin by listing all details of all agents as provided by the output of the first tool included in this goal. ",
|
starter_prompt=starter_prompt_generic + " Begin by listing all details of all agents as provided by the output of the first tool included in this goal. ",
|
||||||
example_conversation_history="\n ".join(
|
example_conversation_history="\n ".join(
|
||||||
[
|
[
|
||||||
"agent: Here are the currently available agents.",
|
"agent: Here are the currently available agents.",
|
||||||
"user_confirmed_tool_run: <user clicks confirm on ListAgents tool>",
|
"user_confirmed_tool_run: <user clicks confirm on ListAgents tool>",
|
||||||
"tool_result: { 'agent_name': 'Event Flight Finder', 'goal_id': 'goal_event_flight_invoice', 'agent_description': 'Helps users find interesting events and arrange travel to them' }",
|
"tool_result: { 'agent_name': 'Event Flight Finder', 'goal_id': 'goal_event_flight_invoice', 'agent_description': 'Helps users find interesting events and arrange travel to them' }",
|
||||||
"agent: The available agents are: 1. Event Flight Finder. \n Which agent would you like to speak to (?",
|
"agent: The available agents are: 1. Event Flight Finder. \n Which agent would you like to speak to? (You can respond with name or number.)",
|
||||||
"user: 1, Event Flight Finder",
|
"user: 1, Event Flight Finder",
|
||||||
"user_confirmed_tool_run: <user clicks confirm on ChangeGoal tool>",
|
"user_confirmed_tool_run: <user clicks confirm on ChangeGoal tool>",
|
||||||
"tool_result: { 'new_goal': 'goal_event_flight_invoice' }",
|
"tool_result: { 'new_goal': 'goal_event_flight_invoice' }",
|
||||||
@@ -61,7 +61,6 @@ goal_pirate_treasure = AgentGoal(
|
|||||||
tools=[
|
tools=[
|
||||||
tool_registry.give_hint_tool,
|
tool_registry.give_hint_tool,
|
||||||
tool_registry.guess_location_tool,
|
tool_registry.guess_location_tool,
|
||||||
tool_registry.list_agents_tool,
|
|
||||||
],
|
],
|
||||||
description="The user wants to find a pirate treasure. "
|
description="The user wants to find a pirate treasure. "
|
||||||
"Help the user gather args for these tools, in a loop, until treasure_found is True or the user requests to be done: "
|
"Help the user gather args for these tools, in a loop, until treasure_found is True or the user requests to be done: "
|
||||||
@@ -106,7 +105,6 @@ goal_match_train_invoice = AgentGoal(
|
|||||||
tool_registry.search_trains_tool,
|
tool_registry.search_trains_tool,
|
||||||
tool_registry.book_trains_tool,
|
tool_registry.book_trains_tool,
|
||||||
tool_registry.create_invoice_tool,
|
tool_registry.create_invoice_tool,
|
||||||
tool_registry.list_agents_tool, #last tool must be list_agents to fasciliate changing back to picking an agent again at the end
|
|
||||||
],
|
],
|
||||||
description="The user wants to book a trip to a city in the UK around the dates of a premier league match. "
|
description="The user wants to book a trip to a city in the UK around the dates of a premier league match. "
|
||||||
"Help the user find a premier league match to attend, search and book trains for that match and offers to invoice them for the cost of train tickets. "
|
"Help the user find a premier league match to attend, search and book trains for that match and offers to invoice them for the cost of train tickets. "
|
||||||
@@ -153,7 +151,6 @@ goal_event_flight_invoice = AgentGoal(
|
|||||||
tool_registry.find_events_tool,
|
tool_registry.find_events_tool,
|
||||||
tool_registry.search_flights_tool,
|
tool_registry.search_flights_tool,
|
||||||
tool_registry.create_invoice_tool,
|
tool_registry.create_invoice_tool,
|
||||||
#tool_registry.list_agents_tool, #last tool must be list_agents to faciliate changing back to picking an agent again at the end
|
|
||||||
],
|
],
|
||||||
description="Help the user gather args for these tools in order: "
|
description="Help the user gather args for these tools in order: "
|
||||||
"1. FindEvents: Find an event to travel to "
|
"1. FindEvents: Find an event to travel to "
|
||||||
@@ -193,7 +190,6 @@ goal_hr_schedule_pto = AgentGoal(
|
|||||||
tool_registry.current_pto_tool,
|
tool_registry.current_pto_tool,
|
||||||
tool_registry.future_pto_calc_tool,
|
tool_registry.future_pto_calc_tool,
|
||||||
tool_registry.book_pto_tool,
|
tool_registry.book_pto_tool,
|
||||||
tool_registry.list_agents_tool, #last tool must be list_agents to fasciliate changing back to picking an agent again at the end
|
|
||||||
],
|
],
|
||||||
description="The user wants to schedule paid time off (PTO) after today's date. To assist with that goal, help the user gather args for these tools in order: "
|
description="The user wants to schedule paid time off (PTO) after today's date. To assist with that goal, help the user gather args for these tools in order: "
|
||||||
"1. CurrentPTO: Tell the user how much PTO they currently have "
|
"1. CurrentPTO: Tell the user how much PTO they currently have "
|
||||||
@@ -230,7 +226,6 @@ goal_hr_check_pto = AgentGoal(
|
|||||||
agent_friendly_description="Check your available PTO.",
|
agent_friendly_description="Check your available PTO.",
|
||||||
tools=[
|
tools=[
|
||||||
tool_registry.current_pto_tool,
|
tool_registry.current_pto_tool,
|
||||||
tool_registry.list_agents_tool, #last tool must be list_agents to fasciliate changing back to picking an agent again at the end
|
|
||||||
],
|
],
|
||||||
description="The user wants to check their paid time off (PTO) after today's date. To assist with that goal, help the user gather args for these tools in order: "
|
description="The user wants to check their paid time off (PTO) after today's date. To assist with that goal, help the user gather args for these tools in order: "
|
||||||
"1. CurrentPTO: Tell the user how much PTO they currently have ",
|
"1. CurrentPTO: Tell the user how much PTO they currently have ",
|
||||||
@@ -252,11 +247,10 @@ goal_hr_check_pto = AgentGoal(
|
|||||||
goal_hr_check_paycheck_bank_integration_status = AgentGoal(
|
goal_hr_check_paycheck_bank_integration_status = AgentGoal(
|
||||||
id = "goal_hr_check_paycheck_bank_integration_status",
|
id = "goal_hr_check_paycheck_bank_integration_status",
|
||||||
category_tag="hr",
|
category_tag="hr",
|
||||||
agent_name="Check paycheck bank integration status",
|
agent_name="Check paycheck deposit status",
|
||||||
agent_friendly_description="Check your integration between paycheck payer and your financial institution.",
|
agent_friendly_description="Check your integration between your employer and your financial institution.",
|
||||||
tools=[
|
tools=[
|
||||||
tool_registry.paycheck_bank_integration_status_check,
|
tool_registry.paycheck_bank_integration_status_check,
|
||||||
tool_registry.list_agents_tool, #last tool must be list_agents to fasciliate changing back to picking an agent again at the end
|
|
||||||
],
|
],
|
||||||
description="The user wants to check their bank integration used to deposit their paycheck. To assist with that goal, help the user gather args for these tools in order: "
|
description="The user wants to check their bank integration used to deposit their paycheck. To assist with that goal, help the user gather args for these tools in order: "
|
||||||
"1. CheckPayBankStatus: Tell the user the status of their paycheck bank integration ",
|
"1. CheckPayBankStatus: Tell the user the status of their paycheck bank integration ",
|
||||||
@@ -283,7 +277,6 @@ goal_fin_check_account_balances = AgentGoal(
|
|||||||
tools=[
|
tools=[
|
||||||
tool_registry.financial_check_account_is_valid,
|
tool_registry.financial_check_account_is_valid,
|
||||||
tool_registry.financial_get_account_balances,
|
tool_registry.financial_get_account_balances,
|
||||||
tool_registry.list_agents_tool, #last tool must be list_agents to fasciliate changing back to picking an agent again at the end
|
|
||||||
],
|
],
|
||||||
description="The user wants to check their account balances at the bank or financial institution. To assist with that goal, help the user gather args for these tools in order: "
|
description="The user wants to check their account balances at the bank or financial institution. To assist with that goal, help the user gather args for these tools in order: "
|
||||||
"1. FinCheckAccountIsValid: validate the user's account is valid"
|
"1. FinCheckAccountIsValid: validate the user's account is valid"
|
||||||
@@ -318,7 +311,6 @@ goal_fin_move_money = AgentGoal(
|
|||||||
tool_registry.financial_check_account_is_valid,
|
tool_registry.financial_check_account_is_valid,
|
||||||
tool_registry.financial_get_account_balances,
|
tool_registry.financial_get_account_balances,
|
||||||
tool_registry.financial_move_money,
|
tool_registry.financial_move_money,
|
||||||
tool_registry.list_agents_tool, #last tool must be list_agents to fasciliate changing back to picking an agent again at the end
|
|
||||||
],
|
],
|
||||||
description="The user wants to transfer money in their account at the bank or financial institution. To assist with that goal, help the user gather args for these tools in order: "
|
description="The user wants to transfer money in their account at the bank or financial institution. To assist with that goal, help the user gather args for these tools in order: "
|
||||||
"1. FinCheckAccountIsValid: validate the user's account is valid"
|
"1. FinCheckAccountIsValid: validate the user's account is valid"
|
||||||
@@ -333,7 +325,7 @@ goal_fin_move_money = AgentGoal(
|
|||||||
"user_confirmed_tool_run: <user clicks confirm on FincheckAccountIsValid tool>",
|
"user_confirmed_tool_run: <user clicks confirm on FincheckAccountIsValid tool>",
|
||||||
"tool_result: { 'status': account valid }",
|
"tool_result: { 'status': account valid }",
|
||||||
"agent: Great! Here are your account balances:",
|
"agent: Great! Here are your account balances:",
|
||||||
"user_confirmed_tool_run: <user clicks confirm on FinCheckAccountBalance tool>", #todo is this needed?
|
"user_confirmed_tool_run: <user clicks confirm on FinCheckAccountBalance tool>",
|
||||||
"tool_result: { 'name': Matt Murdock, 'email': matt.murdock@nelsonmurdock.com, 'account_id': 11235, 'checking_balance': 875.40, 'savings_balance': 3200.15, 'bitcoin_balance': 0.1378, 'account_creation_date': 2014-03-10 }",
|
"tool_result: { 'name': Matt Murdock, 'email': matt.murdock@nelsonmurdock.com, 'account_id': 11235, 'checking_balance': 875.40, 'savings_balance': 3200.15, 'bitcoin_balance': 0.1378, 'account_creation_date': 2014-03-10 }",
|
||||||
"agent: Your account balances are as follows: \n "
|
"agent: Your account balances are as follows: \n "
|
||||||
"Checking: $875.40. \n "
|
"Checking: $875.40. \n "
|
||||||
@@ -348,7 +340,6 @@ goal_fin_move_money = AgentGoal(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
#todo add money movement, fraud check (update with start)
|
|
||||||
#Add the goals to a list for more generic processing, like listing available agents
|
#Add the goals to a list for more generic processing, like listing available agents
|
||||||
goal_list: List[AgentGoal] = []
|
goal_list: List[AgentGoal] = []
|
||||||
goal_list.append(goal_choose_agent_type)
|
goal_list.append(goal_choose_agent_type)
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ def list_agents(args: dict) -> dict:
|
|||||||
goal_categories_start.strip().lower() # handle extra spaces or non-lowercase
|
goal_categories_start.strip().lower() # handle extra spaces or non-lowercase
|
||||||
goal_categories = goal_categories_start.split(",")
|
goal_categories = goal_categories_start.split(",")
|
||||||
|
|
||||||
|
# if multi-goal-mode, add agent_selection as a goal (defaults to True)
|
||||||
|
if "agent_selection" not in goal_categories :
|
||||||
|
first_goal_value = os.getenv("AGENT_GOAL")
|
||||||
|
if first_goal_value is None or first_goal_value.lower() == "goal_choose_agent_type":
|
||||||
|
goal_categories.append("agent_selection")
|
||||||
|
|
||||||
# always show goals labeled as "system," like the goal chooser
|
# always show goals labeled as "system," like the goal chooser
|
||||||
if "system" not in goal_categories:
|
if "system" not in goal_categories:
|
||||||
goal_categories.append("system")
|
goal_categories.append("system")
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
from collections import deque
|
from collections import deque
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import os
|
|
||||||
from typing import Dict, Any, Union, List, Optional, Deque, TypedDict
|
from typing import Dict, Any, Union, List, Optional, Deque, TypedDict
|
||||||
|
|
||||||
from temporalio.common import RetryPolicy
|
from temporalio.common import RetryPolicy
|
||||||
from temporalio import workflow
|
from temporalio import workflow
|
||||||
|
|
||||||
from models.data_types import ConversationHistory, NextStep, ValidationInput, EnvLookupInput
|
from models.data_types import ConversationHistory, EnvLookupOutput, NextStep, ValidationInput, EnvLookupInput
|
||||||
from models.tool_definitions import AgentGoal
|
from models.tool_definitions import AgentGoal
|
||||||
from workflows.workflow_helpers import LLM_ACTIVITY_START_TO_CLOSE_TIMEOUT, \
|
from workflows.workflow_helpers import LLM_ACTIVITY_START_TO_CLOSE_TIMEOUT, \
|
||||||
LLM_ACTIVITY_SCHEDULE_TO_CLOSE_TIMEOUT
|
LLM_ACTIVITY_SCHEDULE_TO_CLOSE_TIMEOUT
|
||||||
@@ -47,7 +46,8 @@ class AgentGoalWorkflow:
|
|||||||
self.confirmed: bool = False # indicates that we have confirmation to proceed to run tool
|
self.confirmed: bool = False # indicates that we have confirmation to proceed to run tool
|
||||||
self.tool_results: List[Dict[str, Any]] = []
|
self.tool_results: List[Dict[str, Any]] = []
|
||||||
self.goal: AgentGoal = {"tools": []}
|
self.goal: AgentGoal = {"tools": []}
|
||||||
self.show_tool_args_confirmation: bool = True
|
self.show_tool_args_confirmation: bool = True # set from env file in activity lookup_wf_env_settings
|
||||||
|
self.multi_goal_mode: bool = False # set from env file in activity lookup_wf_env_settings
|
||||||
|
|
||||||
# see ../api/main.py#temporal_client.start_workflow() for how the input parameters are set
|
# see ../api/main.py#temporal_client.start_workflow() for how the input parameters are set
|
||||||
@workflow.run
|
@workflow.run
|
||||||
@@ -125,7 +125,12 @@ class AgentGoalWorkflow:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# If valid, proceed with generating the context and prompt
|
# If valid, proceed with generating the context and prompt
|
||||||
context_instructions = generate_genai_prompt(self.goal, self.conversation_history, self.tool_data)
|
context_instructions = generate_genai_prompt(
|
||||||
|
agent_goal=self.goal,
|
||||||
|
conversation_history = self.conversation_history,
|
||||||
|
multi_goal_mode=self.multi_goal_mode,
|
||||||
|
raw_json=self.tool_data)
|
||||||
|
|
||||||
prompt_input = ToolPromptInput(prompt=prompt, context_instructions=context_instructions)
|
prompt_input = ToolPromptInput(prompt=prompt, context_instructions=context_instructions)
|
||||||
|
|
||||||
# connect to LLM and execute to get next steps
|
# connect to LLM and execute to get next steps
|
||||||
@@ -165,17 +170,21 @@ class AgentGoalWorkflow:
|
|||||||
else:
|
else:
|
||||||
self.confirmed = True
|
self.confirmed = True
|
||||||
|
|
||||||
# else if the next step is to pick a new goal...
|
# else if the next step is to pick a new goal, set the goal and tool to do it
|
||||||
elif next_step == "pick-new-goal":
|
elif next_step == "pick-new-goal":
|
||||||
workflow.logger.info("All steps completed. Resetting goal.")
|
workflow.logger.info("All steps completed. Resetting goal.")
|
||||||
self.change_goal("goal_choose_agent_type")
|
self.change_goal("goal_choose_agent_type")
|
||||||
|
next_step = tool_data["next"] = "confirm"
|
||||||
|
current_tool = tool_data["tool"] = "ListAgents"
|
||||||
|
waiting_for_confirm = True
|
||||||
|
self.confirmed = True
|
||||||
|
|
||||||
# else if the next step is to be done with the conversation such as if the user requests it via asking to "end conversation"
|
# else if the next step is to be done with the conversation such as if the user requests it via asking to "end conversation"
|
||||||
elif next_step == "done":
|
elif next_step == "done":
|
||||||
|
|
||||||
self.add_message("agent", tool_data)
|
self.add_message("agent", tool_data)
|
||||||
|
|
||||||
#todo send conversation to AI for analysis
|
#here we could send conversation to AI for analysis
|
||||||
|
|
||||||
# end the workflow
|
# end the workflow
|
||||||
return str(self.conversation_history)
|
return str(self.conversation_history)
|
||||||
@@ -266,12 +275,11 @@ class AgentGoalWorkflow:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def change_goal(self, goal: str) -> None:
|
def change_goal(self, goal: str) -> None:
|
||||||
'''goalsLocal = {
|
""" Change the goal (usually on request of the user).
|
||||||
"goal_match_train_invoice": goal_match_train_invoice,
|
|
||||||
"goal_event_flight_invoice": goal_event_flight_invoice,
|
|
||||||
"goal_choose_agent_type": goal_choose_agent_type,
|
|
||||||
}'''
|
|
||||||
|
|
||||||
|
Args:
|
||||||
|
goal: goal to change to)
|
||||||
|
"""
|
||||||
if goal is not None:
|
if goal is not None:
|
||||||
for listed_goal in goal_list:
|
for listed_goal in goal_list:
|
||||||
if listed_goal.id == goal:
|
if listed_goal.id == goal:
|
||||||
@@ -304,17 +312,21 @@ class AgentGoalWorkflow:
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# look up env settings as needed in activities so they're part of history
|
# look up env settings in an activity so they're part of history
|
||||||
async def lookup_wf_env_settings(self, combined_input: CombinedInput)->None:
|
async def lookup_wf_env_settings(self, combined_input: CombinedInput)->None:
|
||||||
env_lookup_input = EnvLookupInput(env_var_name = "SHOW_CONFIRM", default = True)
|
env_lookup_input = EnvLookupInput(
|
||||||
self.show_tool_args_confirmation = await workflow.execute_activity(
|
show_confirm_env_var_name = "SHOW_CONFIRM",
|
||||||
ToolActivities.get_env_bool,
|
show_confirm_default = True)
|
||||||
|
env_output:EnvLookupOutput = await workflow.execute_activity(
|
||||||
|
ToolActivities.get_wf_env_vars,
|
||||||
env_lookup_input,
|
env_lookup_input,
|
||||||
start_to_close_timeout=LLM_ACTIVITY_START_TO_CLOSE_TIMEOUT,
|
start_to_close_timeout=LLM_ACTIVITY_START_TO_CLOSE_TIMEOUT,
|
||||||
retry_policy=RetryPolicy(
|
retry_policy=RetryPolicy(
|
||||||
initial_interval=timedelta(seconds=5), backoff_coefficient=1
|
initial_interval=timedelta(seconds=5), backoff_coefficient=1
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
self.show_tool_args_confirmation = env_output.show_confirm
|
||||||
|
self.multi_goal_mode = env_output.multi_goal_mode
|
||||||
|
|
||||||
# execute the tool - return False if we're not waiting for confirm anymore (always the case if it works successfully)
|
# execute the tool - return False if we're not waiting for confirm anymore (always the case if it works successfully)
|
||||||
#
|
#
|
||||||
|
|||||||
Reference in New Issue
Block a user