diff --git a/adding-goals-and-tools.md b/adding-goals-and-tools.md
index 0ff5aa8..0993c9c 100644
--- a/adding-goals-and-tools.md
+++ b/adding-goals-and-tools.md
@@ -41,6 +41,7 @@ description="Help the user gather args for these tools in order: "
- The file name and function name will be the same as each other and should also be the same as the name of the tool, without "tool" - so future_pto_tool would be future_pto.py with a function named future_pto within it.
- The function should have `args: dict` as the input and also return a `dict`
- The return dict should match the output format you specified in the goal's `example_conversation_history`
+- tools are where the user input+model output becomes deterministic. Add validation here to make sure what the system is doing is valid and acceptable
#### Add to `tools/__init__.py`
- In `tools/__init__.py`, add an import statement for each new tool as well as an applicable return statement in `get_handler`. The tool name here should match the tool name as described in the goal's `description` field.
diff --git a/architecture.md b/architecture.md
index f1a5d7b..a97c02d 100644
--- a/architecture.md
+++ b/architecture.md
@@ -8,5 +8,7 @@ talk through the pieces
explain elements
+tools do determinism
+
# Adding features
link to how to LLM interactions/how to change
\ No newline at end of file
diff --git a/scripts/run_worker.py b/scripts/run_worker.py
index 7b9549e..c5b280e 100644
--- a/scripts/run_worker.py
+++ b/scripts/run_worker.py
@@ -2,6 +2,7 @@ import asyncio
import concurrent.futures
import os
from dotenv import load_dotenv
+import logging
from temporalio.worker import Worker
@@ -48,6 +49,9 @@ async def main():
print("===========================================================\n")
print("Worker ready to process tasks!")
+ logging.basicConfig(level=logging.WARN)
+
+
# Run the worker
with concurrent.futures.ThreadPoolExecutor(max_workers=100) as activity_executor:
diff --git a/todo.md b/todo.md
index 624805e..87fd312 100644
--- a/todo.md
+++ b/todo.md
@@ -16,6 +16,7 @@
[ ] how to add more scenarios, tools
[ ] create tests
+[ ] fix logging statements not to be all warn, maybe set logging level to info
[ ] create people management scenarios
[x] 1. Schedule PTO goal
diff --git a/workflows/agent_goal_workflow.py b/workflows/agent_goal_workflow.py
index 3f73866..d52e9ab 100644
--- a/workflows/agent_goal_workflow.py
+++ b/workflows/agent_goal_workflow.py
@@ -77,55 +77,32 @@ class AgentGoalWorkflow:
# This is the main interactive loop. Main responsibilities:
# - Selecting and changing goals as directed by the user
# - reacting to user input (from signals)
- # - calling activities to determine next steps and prompts
- # - executing the selected tools
+ # - validating user input to make sure it makes sense with the current goal and tools
+ # - calling the LLM through activities to determine next steps and prompts
+ # - executing the selected tools via activities
while True:
# wait indefinitely for input from signals - user_prompt, end_chat, or confirm as defined below
await workflow.wait_condition(
lambda: bool(self.prompt_queue) or self.chat_ended or self.confirm
)
- # handle chat-end signal
- if self.chat_ended:
- workflow.logger.warning(f"workflow step: chat-end signal received, ending")
- workflow.logger.info("Chat ended.")
+ # handle chat should end. When chat ends, push conversation history to workflow results.
+ if self.chat_should_end():
return f"{self.conversation_history}"
# Execute the tool
- if self.confirm and waiting_for_confirm and current_tool and self.tool_data:
- workflow.logger.warning(f"workflow step: user has confirmed, executing the tool {current_tool}")
- self.confirm = False
- waiting_for_confirm = False
-
- confirmed_tool_data = self.tool_data.copy()
- confirmed_tool_data["next"] = "user_confirmed_tool_run"
- self.add_message("user_confirmed_tool_run", confirmed_tool_data)
-
- # execute the tool by key as defined in tools/__init__.py
- await helpers.handle_tool_execution(
- current_tool,
- self.tool_data,
- self.tool_results,
- self.add_message,
- self.prompt_queue
- )
-
- #set new goal if we should
- if len(self.tool_results) > 0:
- if "ChangeGoal" in self.tool_results[-1].values() and "new_goal" in self.tool_results[-1].keys():
- new_goal = self.tool_results[-1].get("new_goal")
- workflow.logger.warning(f"Booya new goal!: {new_goal}")
- self.change_goal(new_goal)
- elif "ListAgents" in self.tool_results[-1].values() and self.goal.id != "goal_choose_agent_type":
- workflow.logger.warning("setting goal to goal_choose_agent_type")
- self.change_goal("goal_choose_agent_type")
+ if self.ready_for_tool_execution(waiting_for_confirm, current_tool):
+ waiting_for_confirm = await self.execute_tool(current_tool)
continue
- # if we've received messages to be processed on the prompt queue...
+ # process forward on the prompt queue if any
if self.prompt_queue:
+ # get most recent prompt
prompt = self.prompt_queue.popleft()
- workflow.logger.warning(f"workflow step: processing message on the prompt queue, message is {prompt}")
- if not prompt.startswith("###"): #if the message isn't from the LLM but is instead from the user
+ workflow.logger.info(f"workflow step: processing message on the prompt queue, message is {prompt}")
+
+ # Validate user-provided prompts
+ if self.is_user_prompt(prompt):
self.add_message("user", prompt)
# Validate the prompt before proceeding
@@ -144,7 +121,7 @@ class AgentGoalWorkflow:
),
)
- #If validation fails, provide that feedback to the user - i.e., "your words make no sense, puny human" end this iteration of processing
+ # If validation fails, provide that feedback to the user - i.e., "your words make no sense, puny human" end this iteration of processing
if not validation_result.validationResult:
workflow.logger.warning(f"Prompt validation failed: {validation_result.validationFailedReason}")
self.add_message("agent", validation_result.validationFailedReason)
@@ -171,7 +148,8 @@ class AgentGoalWorkflow:
next_step = tool_data.get("next")
current_tool = tool_data.get("tool")
- workflow.logger.warning(f"next_step: {next_step}, current tool is {current_tool}")
+ workflow.logger.info(f"next_step: {next_step}, current tool is {current_tool}")
+
#if the next step is to confirm...
if next_step == "confirm" and current_tool:
args = tool_data.get("args", {})
@@ -212,9 +190,9 @@ class AgentGoalWorkflow:
@workflow.signal
async def user_prompt(self, prompt: str) -> None:
"""Signal handler for receiving user prompts."""
- workflow.logger.warning(f"signal received: user_prompt, prompt is {prompt}")
+ workflow.logger.info(f"signal received: user_prompt, prompt is {prompt}")
if self.chat_ended:
- workflow.logger.warning(f"Message dropped due to chat closed: {prompt}")
+ workflow.logger.info(f"Message dropped due to chat closed: {prompt}")
return
self.prompt_queue.append(prompt)
@@ -222,15 +200,14 @@ class AgentGoalWorkflow:
@workflow.signal
async def confirm(self) -> None:
"""Signal handler for user confirmation of tool execution."""
- workflow.logger.info("Received user confirmation")
- workflow.logger.warning(f"signal recieved: confirm")
+ workflow.logger.info("Received user signal: confirmation")
self.confirm = True
#Signal that comes from api/main.py via a post to /end-chat
@workflow.signal
async def end_chat(self) -> None:
"""Signal handler for ending the chat session."""
- workflow.logger.warning("signal received: end_chat")
+ workflow.logger.info("signal received: end_chat")
self.chat_ended = True
@workflow.query
@@ -283,5 +260,61 @@ class AgentGoalWorkflow:
if listed_goal.id == goal:
self.goal = listed_goal
# self.goal = goals.get(goal)
- workflow.logger.warning("Changed goal to " + goal)
+ workflow.logger.info("Changed goal to " + goal)
#todo reset goal or tools if this doesn't work or whatever
+
+ # workflow function that defines if chat should end
+ def chat_should_end(self) -> bool:
+ if self.chat_ended:
+ workflow.logger.info("Chat-end signal received. Chat ending.")
+ return True
+ else:
+ return False
+
+ # define if we're ready for tool execution
+ def ready_for_tool_execution(self, waiting_for_confirm: bool, current_tool: Any) -> bool:
+ if self.confirm and waiting_for_confirm and current_tool and self.tool_data:
+ return True
+ else:
+ return False
+
+ # LLM-tagged prompts start with "###"
+ # all others are from the user
+ def is_user_prompt(self, prompt) -> bool:
+ if prompt.startswith("###"):
+ return False
+ else:
+ return True
+
+ # execute the tool - return False if we're not waiting for confirm anymore (always the case if it works successfully)
+ #
+ async def execute_tool(self, current_tool: str)->bool:
+ workflow.logger.info(f"workflow step: user has confirmed, executing the tool {current_tool}")
+ self.confirm = False
+ waiting_for_confirm = False
+ confirmed_tool_data = self.tool_data.copy()
+ confirmed_tool_data["next"] = "user_confirmed_tool_run"
+ self.add_message("user_confirmed_tool_run", confirmed_tool_data)
+
+ # execute the tool by key as defined in tools/__init__.py
+ await helpers.handle_tool_execution(
+ current_tool,
+ self.tool_data,
+ self.tool_results,
+ self.add_message,
+ self.prompt_queue
+ )
+
+ #set new goal if we should
+ if len(self.tool_results) > 0:
+ if "ChangeGoal" in self.tool_results[-1].values() and "new_goal" in self.tool_results[-1].keys():
+ new_goal = self.tool_results[-1].get("new_goal")
+ workflow.logger.info(f"Booya new goal!: {new_goal}")
+ self.change_goal(new_goal)
+ elif "ListAgents" in self.tool_results[-1].values() and self.goal.id != "goal_choose_agent_type":
+ workflow.logger.info("setting goal to goal_choose_agent_type")
+ self.change_goal("goal_choose_agent_type")
+ return waiting_for_confirm
+
+
+