Merge branch 'development' of https://github.com/joshmsmith/temporal-ai-agent into development

This commit is contained in:
Joshua Smith
2025-03-11 14:02:22 -04:00
8 changed files with 28 additions and 57 deletions

View File

@@ -194,7 +194,6 @@ async def end_chat():
@app.post("/start-workflow") @app.post("/start-workflow")
async def start_workflow(): async def start_workflow():
# Get the initial goal as set in shared/config or env or just...always should be "pick a goal?"
initial_agent_goal = get_initial_agent_goal() initial_agent_goal = get_initial_agent_goal()
# Create combined input # Create combined input

View File

@@ -81,9 +81,8 @@ 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='done' and tool=null.\n" "3) If no more tools are needed (user_confirmed_tool_run has been run for all), set next='confirm' and tool='ListAgents'.\n"
"4) response should be short and user-friendly.\n" "4) response should be short and user-friendly.\n"
"5) Don't set next='done' until the final tool has returned user_confirmed_tool_run.\n"
) )
# Validation Task (If raw_json is provided) # Validation Task (If raw_json is provided)
@@ -126,9 +125,7 @@ def generate_tool_completion_prompt(current_tool: str, dynamic_result: dict) ->
"You will need to use the tool_results to auto-fill arguments for subsequent tools and also to figure out if all tools have been run." "You will need to use the tool_results to auto-fill arguments for subsequent tools and also to figure out if all tools have been run."
'{"next": "<question|confirm|done>", "tool": "<tool_name or null>", "args": {"<arg1>": "<value1 or null>", "<arg2>": "<value2 or null>}, "response": "<plain text (can include \\n line breaks)>"}' '{"next": "<question|confirm|done>", "tool": "<tool_name or null>", "args": {"<arg1>": "<value1 or null>", "<arg2>": "<value2 or null>}, "response": "<plain text (can include \\n line breaks)>"}'
"ONLY return those json keys (next, tool, args, response), nothing else." "ONLY return those json keys (next, tool, args, response), nothing else."
'Next should only be "done" if all tools have been run (use the system prompt to figure that out).' 'Next should be "question".'
'Next should be "question" if the tool is not the last one in the sequence.'
'Next should NOT be "confirm" at this point.'
) )
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:

View File

@@ -4,7 +4,7 @@ from .search_trains import search_trains
from .search_trains import book_trains from .search_trains import book_trains
from .create_invoice import create_invoice from .create_invoice import create_invoice
from .find_events import find_events from .find_events import find_events
from .choose_agent import choose_agent from .list_agents import list_agents
from .change_goal import change_goal from .change_goal import change_goal
from .transfer_control import transfer_control from .transfer_control import transfer_control
@@ -22,8 +22,8 @@ def get_handler(tool_name: str):
return create_invoice return create_invoice
if tool_name == "FindEvents": if tool_name == "FindEvents":
return find_events return find_events
if tool_name == "ChooseAgent": if tool_name == "ListAgents":
return choose_agent return list_agents
if tool_name == "ChangeGoal": if tool_name == "ChangeGoal":
return change_goal return change_goal
if tool_name == "TransferControl": if tool_name == "TransferControl":

View File

@@ -13,8 +13,7 @@ import shared.config
def change_goal(args: dict) -> dict: def change_goal(args: dict) -> dict:
new_goal = args.get("goalID") new_goal = args.get("goalID")
shared.config.AGENT_GOAL = new_goal
return { return {
"new_goal": shared.config.AGENT_GOAL, "new_goal": new_goal,
} }

View File

@@ -7,39 +7,32 @@ from tools.tool_registry import (
create_invoice_tool, create_invoice_tool,
find_events_tool, find_events_tool,
change_goal_tool, change_goal_tool,
choose_agent_tool, list_agents_tool
transfer_control_tool
) )
starter_prompt_generic = "Welcome me, give me a description of what you can do, then ask me for the details you need to do your job" starter_prompt_generic = "Welcome me, give me a description of what you can do, then ask me for the details you need to do your job"
goal_choose_agent_type = AgentGoal( goal_choose_agent_type = AgentGoal(
tools=[ tools=[
choose_agent_tool, list_agents_tool,
change_goal_tool, change_goal_tool
transfer_control_tool
], ],
description="The user wants to choose which type of agent they will interact with. " description="The user wants to choose which type of agent they will interact with. "
"Help the user gather args for these tools, in order: " "Help the user gather args for these tools, in order: "
"1. ChooseAgent: Choose which agent to interact with " "1. ListAgents: List agents available to interact with "
"2. ChangeGoal: Change goal of agent " "2. ChangeGoal: Change goal of agent "
"3. TransferControl: Transfer control to new 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, starter_prompt=starter_prompt_generic,
example_conversation_history="\n ".join( example_conversation_history="\n ".join(
[ [
"user: I'd like to choose an agent", "user: I'd like to choose an agent",
"agent: Sure! Would you like me to list the available agents?", "agent: Sure! Would you like me to list the available agents?",
"user_confirmed_tool_run: <user clicks confirm on ChooseAgent 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. Which agent would you like to speak to?", "agent: The available agents are: 1. Event Flight Finder. Which agent would you like to speak to?",
"user: 1", "user: 1",
"user_confirmed_tool_run: <user clicks confirm on ChangeGoal tool>", "user_confirmed_tool_run: <user clicks confirm on ChangeGoal tool>",
# bot changes goal here and hopefully just...switches??
# could also end 1 workflow and start another with new goal
"tool_result: { 'new_goal': 'goal_event_flight_invoice' }", "tool_result: { 'new_goal': 'goal_event_flight_invoice' }",
"agent: Would you like to transfer control to the new agent now?",
"user: yes",
] ]
), ),
) )

View File

@@ -1,7 +1,7 @@
from pathlib import Path from pathlib import Path
import json import json
def choose_agent(args: dict) -> dict: def list_agents(args: dict) -> dict:
# file_path = Path(__file__).resolve().parent / "goal_regsitry.py" # file_path = Path(__file__).resolve().parent / "goal_regsitry.py"
#if not file_path.exists(): #if not file_path.exists():

View File

@@ -1,21 +1,7 @@
from models.tool_definitions import ToolDefinition, ToolArgument from models.tool_definitions import ToolDefinition, ToolArgument
#This also doesn't help... list_agents_tool = ToolDefinition(
transfer_control_tool = ToolDefinition( name="ListAgents",
name="TransferControl",
description="Do one extra input from user to apply the new goal to the workflow (Hacky, hopefully temp). ",
arguments=[
ToolArgument(
name="userConfirmation",
type="string",
description="dummy variable to make thing work",
),
],
)
choose_agent_tool = ToolDefinition(
name="ChooseAgent",
description="List available agents to interact with, pulled from goal_registry. ", description="List available agents to interact with, pulled from goal_registry. ",
arguments=[ arguments=[
ToolArgument( ToolArgument(

View File

@@ -12,9 +12,6 @@ from workflows.workflow_helpers import LLM_ACTIVITY_START_TO_CLOSE_TIMEOUT, \
LLM_ACTIVITY_SCHEDULE_TO_CLOSE_TIMEOUT LLM_ACTIVITY_SCHEDULE_TO_CLOSE_TIMEOUT
from workflows import workflow_helpers as helpers from workflows import workflow_helpers as helpers
#importlib.reload(my_module)
with workflow.unsafe.imports_passed_through(): with workflow.unsafe.imports_passed_through():
from activities.tool_activities import ToolActivities from activities.tool_activities import ToolActivities
from prompts.agent_prompt_generators import ( from prompts.agent_prompt_generators import (
@@ -24,9 +21,6 @@ with workflow.unsafe.imports_passed_through():
CombinedInput, CombinedInput,
ToolPromptInput, ToolPromptInput,
) )
import shared.config
importlib.reload(shared.config)
#from shared.config import AGENT_GOAL
from tools.goal_registry import goal_match_train_invoice, goal_event_flight_invoice, goal_choose_agent_type from tools.goal_registry import goal_match_train_invoice, goal_event_flight_invoice, goal_choose_agent_type
# Constants # Constants
@@ -50,7 +44,6 @@ class AgentGoalWorkflow:
self.tool_data: Optional[ToolData] = None self.tool_data: Optional[ToolData] = None
self.confirm: bool = False self.confirm: bool = False
self.tool_results: List[Dict[str, Any]] = [] self.tool_results: List[Dict[str, Any]] = []
#set initial goal of "pick an agent" here??
self.goal: AgentGoal = {"tools": []} self.goal: AgentGoal = {"tools": []}
# 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
@@ -111,16 +104,8 @@ class AgentGoalWorkflow:
if len(self.tool_results) > 0 and "new_goal" in self.tool_results[-1].keys() and "ChangeGoal" in self.tool_results[-1].values(): if len(self.tool_results) > 0 and "new_goal" in self.tool_results[-1].keys() and "ChangeGoal" in self.tool_results[-1].values():
new_goal = self.tool_results[-1].get("new_goal") new_goal = self.tool_results[-1].get("new_goal")
workflow.logger.info(f"Booya new goal!: {new_goal}") workflow.logger.warning(f"Booya new goal!: {new_goal}")
goals = { self.change_goal(new_goal)
"goal_match_train_invoice": goal_match_train_invoice,
"goal_event_flight_invoice": goal_event_flight_invoice,
"goal_choose_agent_type": goal_choose_agent_type,
}
if new_goal is not None:
self.goal = goals.get(new_goal)
#todo reset goal or tools if this doesn't work or whatever
continue continue
# push messages to UI if there are any # push messages to UI if there are any
@@ -264,3 +249,15 @@ class AgentGoalWorkflow:
self.conversation_history["messages"].append( self.conversation_history["messages"].append(
{"actor": actor, "response": response} {"actor": actor, "response": response}
) )
def change_goal(self, goal: str) -> None:
goals = {
"goal_match_train_invoice": goal_match_train_invoice,
"goal_event_flight_invoice": goal_event_flight_invoice,
"goal_choose_agent_type": goal_choose_agent_type,
}
if goal is not None:
self.goal = goals.get(goal)
workflow.logger.warning("Changed goal to " + goal)
#todo reset goal or tools if this doesn't work or whatever