Print with color in controller (#176)

* and color-coded printing action abd obs

* fix langchains agent's observation

* remove color printing from codeact agent

* fix mypy

* fix ruff

* resolve conflict

* fix ruff
This commit is contained in:
Xingyao Wang 2024-04-02 13:13:19 +08:00 committed by GitHub
parent 6d715c2ac7
commit fe736013cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 31 additions and 23 deletions

View File

@ -1,7 +1,6 @@
import re
from typing import List, Mapping
from termcolor import colored
from opendevin.agent import Agent
from opendevin.state import State
@ -75,19 +74,16 @@ class CodeActAgent(Agent):
{"role": "system", "content": SYSTEM_MESSAGE},
{"role": "user", "content": state.plan.main_goal},
]
print(colored("===USER:===\n" + state.plan.main_goal, "green"))
updated_info = state.updated_info
if updated_info:
for prev_action, obs in updated_info:
assert isinstance(prev_action, (CmdRunAction, AgentEchoAction)), "Expecting CmdRunAction or AgentEchoAction for Action"
if isinstance(obs, AgentMessageObservation): # warning message from itself
self.messages.append({"role": "user", "content": obs.content})
print(colored("===USER:===\n" + obs.content, "green"))
elif isinstance(obs, CmdOutputObservation):
content = "OBSERVATION:\n" + obs.content
content += f"\n[Command {obs.command_id} finished with exit code {obs.exit_code}]]"
self.messages.append({"role": "user", "content": content})
print(colored("===ENV OBSERVATION:===\n" + content, "blue"))
else:
raise NotImplementedError(f"Unknown observation type: {obs.__class__}")
response = self.llm.completion(
@ -98,27 +94,23 @@ class CodeActAgent(Agent):
)
action_str: str = parse_response(response)
self.messages.append({"role": "assistant", "content": action_str})
print(colored("===ASSISTANT:===\n" + action_str, "yellow"))
command = re.search(r"<execute>(.*)</execute>", action_str, re.DOTALL)
if command is not None:
# a command was found
command_group = command.group(1)
if command_group.strip() == "exit":
print(colored("Exit received. Exiting...", "red"))
return AgentFinishAction()
return CmdRunAction(command = command_group)
# # execute the code
# # TODO: does exit_code get loaded into Message?
# exit_code, observation = self.env.execute(command_group)
# self._history.append(Message(Role.ASSISTANT, observation))
# print(colored("===ENV OBSERVATION:===\n" + observation, "blue"))
else:
# we could provide a error message for the model to continue similar to
# https://github.com/xingyaoww/mint-bench/blob/main/mint/envs/general_env.py#L18-L23
# observation = INVALID_INPUT_MESSAGE
# self._history.append(Message(Role.ASSISTANT, observation))
# print(colored("===ENV OBSERVATION:===\n" + observation, "blue"))
return AgentEchoAction(content=INVALID_INPUT_MESSAGE) # warning message to itself

View File

@ -1,7 +1,7 @@
import json
from typing import List, Tuple, Dict, Type
from opendevin.controller.agent_controller import print_with_indent
from opendevin.controller.agent_controller import print_with_color
from opendevin.plan import Plan
from opendevin.action import Action, action_from_dict
from opendevin.observation import Observation
@ -178,7 +178,7 @@ def get_prompt(plan: Plan, history: List[Tuple[Action, Observation]]):
elif latest_action_id == "finish":
hint = ""
print_with_indent("HINT:\n" + hint)
print_with_color("HINT:\n" + hint, "INFO")
return prompt % {
'task': plan.main_goal,
'plan': plan_str,

View File

@ -1,7 +1,8 @@
import asyncio
from typing import List, Callable
import traceback
from typing import List, Callable, Literal, Mapping, Any
from termcolor import colored
from opendevin.plan import Plan
from opendevin.state import State
@ -21,8 +22,24 @@ from opendevin.observation import (
from .command_manager import CommandManager
def print_with_indent(text: str):
print("\t"+text.replace("\n","\n\t"), flush=True)
ColorType = Literal['red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'light_grey', 'dark_grey', 'light_red', 'light_green', 'light_yellow', 'light_blue', 'light_magenta', 'light_cyan', 'white']
def print_with_color(text: Any, print_type: str = "INFO"):
TYPE_TO_COLOR: Mapping[str, ColorType] = {
"BACKGROUND LOG": "blue",
"ACTION": "green",
"OBSERVATION": "yellow",
"INFO": "cyan",
"ERROR": "red",
"PLAN": "light_magenta",
}
color = TYPE_TO_COLOR.get(print_type.upper(), TYPE_TO_COLOR["INFO"])
print(
colored(f"\n{print_type.upper()}:\n", color, attrs=["bold"])
+ colored(str(text), color),
flush=True,
)
class AgentController:
def __init__(
@ -72,14 +89,13 @@ class AgentController:
async def step(self, i: int):
print("\n\n==============", flush=True)
print("STEP", i, flush=True)
print_with_indent("\nPLAN:\n")
print_with_indent(self.state.plan.__str__())
print_with_color(self.state.plan.main_goal, "PLAN")
log_obs = self.command_manager.get_background_obs()
for obs in log_obs:
self.add_history(NullAction(), obs)
await self._run_callbacks(obs)
print_with_indent("\nBACKGROUND LOG:\n%s" % obs)
print_with_color(obs, "BACKGROUND LOG")
self.update_state_for_step(i)
action: Action = NullAction()
@ -88,10 +104,10 @@ class AgentController:
action = self.agent.step(self.state)
if action is None:
raise ValueError("Agent must return an action")
print_with_indent("\nACTION:\n%s" % action)
print_with_color(action, "ACTION")
except Exception as e:
observation = AgentErrorObservation(str(e))
print_with_indent("\nAGENT ERROR:\n%s" % observation)
print_with_color(observation, "ERROR")
traceback.print_exc()
# TODO Change to more robust error handling
if "The api_key client option must be set" in observation.content:
@ -102,7 +118,7 @@ class AgentController:
finished = isinstance(action, AgentFinishAction)
if finished:
print_with_indent("\nFINISHED")
print_with_color(action, "INFO")
return True
if isinstance(action, AddTaskAction):
@ -110,14 +126,14 @@ class AgentController:
self.state.plan.add_subtask(action.parent, action.goal, action.subtasks)
except Exception as e:
observation = AgentErrorObservation(str(e))
print_with_indent("\nADD TASK ERROR:\n%s" % observation)
print_with_color(observation, "ERROR")
traceback.print_exc()
elif isinstance(action, ModifyTaskAction):
try:
self.state.plan.set_subtask_state(action.id, action.state)
except Exception as e:
observation = AgentErrorObservation(str(e))
print_with_indent("\nMODIFY TASK ERROR:\n%s" % observation)
print_with_color(observation, "ERROR")
traceback.print_exc()
if action.executable:
@ -125,11 +141,11 @@ class AgentController:
observation = action.run(self)
except Exception as e:
observation = AgentErrorObservation(str(e))
print_with_indent("\nACTION RUN ERROR:\n%s" % observation)
print_with_color(observation, "ERROR")
traceback.print_exc()
if not isinstance(observation, NullObservation):
print_with_indent("\nOBSERVATION:\n%s" % observation)
print_with_color(observation, "OBSERVATION")
self.add_history(action, observation)
await self._run_callbacks(observation)