Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minimal Docker Sandbox with GPT-3.5 Execution Example #48

Merged
merged 22 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
dd0ff16
minimal docker sandbox
xingyaoww Mar 18, 2024
b41efe1
make container_image as an argument (fall back to ubuntu);
xingyaoww Mar 18, 2024
79d1c1d
add a minimal working (imperfect) example
xingyaoww Mar 18, 2024
4f2eb53
fix typo
xingyaoww Mar 18, 2024
1dcb0b4
change default container name
xingyaoww Mar 18, 2024
415efea
attempt to fix "Bad file descriptor" error
xingyaoww Mar 18, 2024
652af30
handle ctrl+D
xingyaoww Mar 18, 2024
10f02a6
add Python gitignore
xingyaoww Mar 20, 2024
1cf3540
Merge commit '10f02a660e3c5c17bba685522d17a353974c049f' into sandbox
xingyaoww Mar 20, 2024
7754e37
push sandbox to shared dockerhub for ease of use
xingyaoww Mar 20, 2024
1747269
move codeact example into research folder
xingyaoww Mar 20, 2024
386abe3
add README for opendevin
xingyaoww Mar 20, 2024
43d4927
change container image name to opendevin dockerhub
xingyaoww Mar 20, 2024
b1551a0
Merge commit '0380070e98e8d59efa411fc74dd95aa49f0ea752' into sandbox
xingyaoww Mar 21, 2024
cea4b4b
move folder; change example to a more general agent
xingyaoww Mar 21, 2024
135f3ee
update Message and Role
xingyaoww Mar 21, 2024
f65c0b7
update docker sandbox to support mounting folder and switch to user w…
xingyaoww Mar 21, 2024
e2b4b90
make network as host
xingyaoww Mar 21, 2024
c10a2d9
handle erorrs when attrs are not set yet
xingyaoww Mar 21, 2024
45e4c6d
convert codeact agent into a compatible agent
xingyaoww Mar 21, 2024
6ebffca
add workspace to gitignore
xingyaoww Mar 21, 2024
8815aa9
make sure the agent interface adjustment works for langchain_agent
xingyaoww Mar 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
convert codeact agent into a compatible agent
  • Loading branch information
xingyaoww committed Mar 21, 2024
commit 45e4c6dd760af0de3ec1c33a9a023ea7c9dfd2a2
4 changes: 3 additions & 1 deletion agenthub/codeact_agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ This folder implements the [CodeAct idea](https://arxiv.org/abs/2402.13463) that
A minimalistic exmaple can be found at [research/codeact/examples/run_flask_server_with_bash.py](./examples/run_flask_server_with_bash.py):

```bash
python3 examples/run_flask_server_with_bash.py
mkdir workspace
PYTHONPATH=`pwd`:$PYTHONPATH python3 opendevin/main.py -d ./workspace -c CodeActAgent -t "Please write a flask app that returns 'Hello, World\!' at the root URL, then start the app on port 5000. python3 has already been installed for you."
```


Example: prompts `gpt-3.5-turbo-0125` to write a flask server, install `flask` library, and start the server.

<img width="951" alt="image" src="https://github.com/OpenDevin/OpenDevin/assets/38853559/325c3115-a343-4cc5-a92b-f1e5d552a077">
Expand Down
29 changes: 17 additions & 12 deletions agenthub/codeact_agent/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from termcolor import colored
from typing import List, Dict

from opendevin.agent import Agent, Message
from opendevin.agent import Agent, Message, Role
from opendevin.sandbox.docker import DockerInteractive

assert (
Expand Down Expand Up @@ -50,20 +50,25 @@ def parse_response(response) -> str:


class CodeActAgent(Agent):
def __init__(self, instruction: str, max_steps: int = 100) -> None:
def __init__(
self,
instruction: str,
workspace_dir: str,
model_name: str,
max_steps: int = 100
) -> None:
"""
Initializes a new instance of the CodeActAgent class.

Parameters:
- instruction (str): The instruction for the agent to execute.
- max_steps (int): The maximum number of steps to run the agent.
"""
super().__init__(instruction, max_steps)
self._history = [Message(Agent.SYSTEM, SYSTEM_MESSAGE)]
self._history.append(Message(Agent.USER, instruction))
self.env = DockerInteractive("opendevin/sandbox:latest")

self.model_name = "gpt-3.5-turbo-0125" # TODO: hard-coded here, will need to accept this as an argument in future PR
super().__init__(instruction, workspace_dir, model_name, max_steps)
self._history = [Message(Role.SYSTEM, SYSTEM_MESSAGE)]
self._history.append(Message(Role.USER, instruction))
self.env = DockerInteractive(workspace_dir=workspace_dir)
print(colored("===USER:===\n" + instruction, "green"))

def _history_to_messages(self) -> List[Dict]:
return [message.to_dict() for message in self._history]
Expand All @@ -73,7 +78,7 @@ def run(self) -> None:
Starts the execution of the assigned instruction. This method should
be implemented by subclasses to define the specific execution logic.
"""
for _ in range(self.max_turns):
for _ in range(self.max_steps):
response = completion(
messages=self._history_to_messages(),
model=self.model_name,
Expand All @@ -82,7 +87,7 @@ def run(self) -> None:
seed=42,
)
action = parse_response(response)
self._history.append(Message(Agent.ASSISTANT, action))
self._history.append(Message(Role.ASSISTANT, action))
print(colored("===ASSISTANT:===\n" + action, "yellow"))

command = re.search(r"<execute>(.*)</execute>", action, re.DOTALL)
Expand All @@ -94,13 +99,13 @@ def run(self) -> None:
break
# execute the code
observation = self.env.execute(command)
self._history.append(Message(Agent.ASSISTANT, observation))
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(Agent.ASSISTANT, observation))
self._history.append(Message(Role.ASSISTANT, observation))
print(colored("===ENV OBSERVATION:===\n" + observation, "blue"))

self.env.close()
Expand Down
21 changes: 14 additions & 7 deletions opendevin/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,25 @@ class Agent(ABC):
executing a specific instruction and allowing human interaction with the
agent during execution.
It tracks the execution status and maintains a history of interactions.

:param instruction: The instruction for the agent to execute.
:param workspace_dir: The working directory for the agent.
:param model_name: The litellm name of the model to use for the agent.
:param max_steps: The maximum number of steps to run the agent.
"""

_registry: Dict[str, Type['Agent']] = {}

def __init__(
self,
instruction: str,
workspace_dir: str,
model_name: str,
max_steps: int = 100
):
self.instruction = instruction
self.workspace_dir = workspace_dir
self.model_name = model_name
self.max_steps = max_steps

self._complete = False
Expand Down Expand Up @@ -119,18 +128,16 @@ def register(cls, name: str, agent_cls: Type['Agent']):
cls._registry[name] = agent_cls

@classmethod
def create_instance(cls, name: str, instruction: str) -> 'Agent':
def get_cls(cls, name: str) -> Type['Agent']:
"""
Creates an instance of a registered agent class based on the given name.
Retrieves an agent class from the registry.

Parameters:
- name (str): The name of the agent class to instantiate.
- instruction (str): The instruction for the new agent instance.
- name (str): The name of the class to retrieve

Returns:
- An instance of the specified agent class.
- agent_cls (Type['Agent']): The class registered under the specified name.
"""
if name not in cls._registry:
raise ValueError(f"No agent class registered under '{name}'.")
agent_cls = cls._registry[name]
return agent_cls(instruction)
return cls._registry[name]
11 changes: 7 additions & 4 deletions opendevin/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
parser.add_argument("-d", "--directory", required=True, type=str, help="The working directory for the agent")
parser.add_argument("-t", "--task", required=True, type=str, help="The task for the agent to perform")
parser.add_argument("-c", "--agent-cls", default="LangchainsAgent", type=str, help="The agent class to use")
parser.add_argument("-m", "--model-name", default="gpt-3.5-turbo-0125", type=str, help="The (litellm) model name to use")
args = parser.parse_args()

print("Working in directory:", args.directory)
os.chdir(args.directory)

agent = Agent.create_instance(args.agent_cls, args.task)
AgentCls: Agent = Agent.get_cls(args.agent_cls)
agent = AgentCls(
instruction=args.task,
workspace_dir=args.directory,
model_name=args.model_name
)
agent.run()