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

feat(workflow): Implement a simplified CoAct workflow #3770

Open
wants to merge 53 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
48ebc6e
make codeact accept delegated task
ryanhoangt Sep 5, 2024
136f10a
implement a draft planner agent that can delegate task to CodeAct
ryanhoangt Sep 5, 2024
6ebcf02
add executor agent and refactor planner agent
ryanhoangt Sep 6, 2024
9b4430d
experiment: adjust prompt to make BrowsingAgent better potentially?
ryanhoangt Sep 6, 2024
135f26d
modify prompt and action parser for executor agent
ryanhoangt Sep 6, 2024
9da4217
fix bug agent using wrong prompt files, improve logging on terminal a…
ryanhoangt Sep 6, 2024
a963080
revert debugging in browsing_agent.py
ryanhoangt Sep 6, 2024
25d7a74
revert BrowsingAgent prompt
ryanhoangt Sep 7, 2024
56edccb
fix: local agent should finish instead of delegate
ryanhoangt Sep 7, 2024
cd660c0
Merge branch 'main' into coact-workflow-draft
ryanhoangt Sep 7, 2024
567297c
update prompt of planner agent
ryanhoangt Sep 7, 2024
2264e70
add meta prompt to use in the future to reinforce workflow
ryanhoangt Sep 7, 2024
136da2b
update README
ryanhoangt Sep 7, 2024
d5b5831
revert change in browser obs
ryanhoangt Sep 7, 2024
c864237
fix copy paste error
ryanhoangt Sep 7, 2024
39d8d0a
update run_infer and README
ryanhoangt Sep 8, 2024
fc44e17
specialize global planner agent by removing editing skills and update…
ryanhoangt Sep 9, 2024
5cadc38
Merge branch 'main' into coact-workflow-draft
ryanhoangt Sep 9, 2024
af0b3d7
improve planner agent's prompt
ryanhoangt Sep 10, 2024
e80c001
add reasoning scratchpad into plan structure
ryanhoangt Sep 10, 2024
91a5873
exp: separate edit plan and testing plan
ryanhoangt Sep 11, 2024
cf80534
exp: further enhance run_infer prompt
ryanhoangt Sep 11, 2024
a7f4c0b
dummy commit to pump planner version
ryanhoangt Sep 12, 2024
63a9f55
finalize the prompt to follow the shape of the workflow
ryanhoangt Sep 12, 2024
f404c7c
update eval prompt
ryanhoangt Sep 12, 2024
97c4dba
update README
ryanhoangt Sep 13, 2024
9ed5257
change username in planner system prompt
ryanhoangt Sep 13, 2024
89a8ed7
update new system prompts from codeact
ryanhoangt Sep 13, 2024
76f093e
Merge branch 'main' into coact-workflow-draft
ryanhoangt Sep 13, 2024
fab5874
Fix typo for agenthub/coact_agent/executor/user_prompt.j2
ryanhoangt Sep 14, 2024
7285cfd
Fix typo for evaluation/swe_bench/run_infer.py
ryanhoangt Sep 14, 2024
1e426d3
Fix typo for evaluation/swe_bench/run_infer.py
ryanhoangt Sep 14, 2024
e3bdb5c
remove FIXME
ryanhoangt Sep 14, 2024
2346350
move stop sequences to attribute
ryanhoangt Sep 14, 2024
1764205
resolve comments
ryanhoangt Sep 14, 2024
0d91fcf
delete meta prompts and resolve comments
ryanhoangt Sep 15, 2024
5689ed8
Merge branch 'main' into coact-workflow-draft
tobitege Sep 16, 2024
dbc5b9d
modify prompt location
ryanhoangt Sep 20, 2024
942ff4e
Merge branch 'main' into coact-workflow-draft
ryanhoangt Sep 20, 2024
10cc53b
add ability to inject problem statement into executor
ryanhoangt Sep 20, 2024
9a7c5a9
Merge branch 'main' into coact-workflow-draft
ryanhoangt Sep 21, 2024
038313a
fix bug in injecting initial user message
ryanhoangt Sep 23, 2024
34cabef
place 'reason'beefore 'description' in plan structure
ryanhoangt Sep 23, 2024
c5303f2
update executor's system prompt
ryanhoangt Sep 23, 2024
f962fd6
final touch
ryanhoangt Sep 26, 2024
7b4a2da
Merge branch 'main' into coact-workflow-draft
ryanhoangt Sep 28, 2024
05cc97f
fix unit tests
ryanhoangt Sep 28, 2024
8b4eb1b
revert change in AgentDelegateAction
ryanhoangt Sep 28, 2024
481a3e4
update mocks for intg tests
ryanhoangt Sep 28, 2024
ff90ff4
fix bug in CodeActAgent
ryanhoangt Sep 28, 2024
7b285c2
Merge branch 'main' into coact-workflow-draft
ryanhoangt Sep 28, 2024
5e70aca
Merge branch 'main' into coact-workflow-draft
ryanhoangt Sep 29, 2024
0823c1c
Merge branch 'main' into coact-workflow-draft
ryanhoangt Oct 1, 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
2 changes: 2 additions & 0 deletions agenthub/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from agenthub import ( # noqa: E402
browsing_agent,
coact_agent,
codeact_agent,
codeact_swe_agent,
delegator_agent,
Expand All @@ -23,6 +24,7 @@
'delegator_agent',
'dummy_agent',
'browsing_agent',
'coact_agent',
]

for agent in all_microagents.values():
Expand Down
36 changes: 36 additions & 0 deletions agenthub/coact_agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# CoAct Multi-Agent Framework

This folder implements a multi-agent workflow inspired by the CoAct framework ([paper](https://arxiv.org/abs/2406.13381)), that provides a robust structure for defining, planning, and executing tasks using multiple agents.

## Agents

1. `CoActPlannerAgent`:
- is responsible for exploring and creating a global plan. It can replan if there are issues with the previous one.
- has full capabilities of [CodeActAgent](https://github.com/All-Hands-AI/OpenHands/tree/main/agenthub/codeact_agent).
2. `CoActExecutorAgent`:
- is responsible for executing the proposed plan. Facing issues with the plan, it can request for a new one.
- also has full capabilities of [CodeActAgent](https://github.com/All-Hands-AI/OpenHands/tree/main/agenthub/codeact_agent).


## Plan structure
```markdown
The user message is: <<Full user's message here.>>
# Phases
## Phase 1
- reason: <<Assistant's thorough thoughts on why this phase is necessary, with tips/codes to instruct the executor finish the task easier.>>
- description: <<Describe what needs to be done in this phase.>>
- expected_state: <<Describe the expected state after this phase is completed. If the task involves code editing, provide the expectation of the code after the edit.>>
<file_path> <<The file path to edit. In one phase only 1 file is edited.>> </file_path>
<expected_content>
<<The partial expected content here WITH LINE NUMBERS and a vertical bar before the actual code e.g., 1|, 11|.>>
</expected_content>
## Phase 2
- reason: ...
- description: ...
- expected_state: ...
<file_path> ... </file_path>
<expected_content>
...|...
</expected_content>
## Phase ...
```
10 changes: 10 additions & 0 deletions agenthub/coact_agent/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from agenthub.coact_agent.executor.executor_agent import (
LocalExecutorAgent as CoActExecutorAgent,
)
from agenthub.coact_agent.planner.planner_agent import (
GlobalPlannerAgent as CoActPlannerAgent,
)
from openhands.controller.agent import Agent

Agent.register('CoActPlannerAgent', CoActPlannerAgent)
Agent.register('CoActExecutorAgent', CoActExecutorAgent)
71 changes: 71 additions & 0 deletions agenthub/coact_agent/executor/action_parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import re

from agenthub.codeact_agent.action_parser import (
CodeActActionParserAgentDelegate,
CodeActActionParserCmdRun,
CodeActActionParserFinish,
CodeActActionParserIPythonRunCell,
CodeActActionParserMessage,
CodeActResponseParser,
)
from openhands.controller.action_parser import ActionParser
from openhands.events.action import (
Action,
AgentFinishAction,
)


class ExecutorResponseParser(CodeActResponseParser):
"""Parser action:
- CmdRunAction(command) - bash command to run
- IPythonRunCellAction(code) - IPython code to run
- AgentDelegateAction(agent, inputs) - delegate action for (sub)task
- MessageAction(content) - Message action to run (e.g. ask for clarification)
- AgentFinishAction() - end the interaction
"""

def __init__(self):
# Need pay attention to the item order in self.action_parsers
super().__init__()
self.action_parsers = [
CodeActActionParserFinish(),
CodeActActionParserCmdRun(),
CodeActActionParserIPythonRunCell(),
CodeActActionParserAgentDelegate(),
CoActActionParserRequest(),
]
self.default_parser = CodeActActionParserMessage()

def parse_response(self, response) -> str:
action = response.choices[0].message.content
if action is None:
return ''
for action_suffix in ['bash', 'ipython', 'browse', 'request']:
if (
f'<execute_{action_suffix}>' in action
and f'</execute_{action_suffix}>' not in action
):
action += f'</execute_{action_suffix}>'
return action


class CoActActionParserRequest(ActionParser):
def __init__(self):
self.request = None

def check_condition(self, action_str: str) -> bool:
self.request = re.search(
r'<execute_request>(.*)</execute_request>', action_str, re.DOTALL
)
return self.request is not None

def parse(self, action_str: str) -> Action:
assert (
self.request is not None
), 'self.request should not be None when parse is called'

replan_request = self.request.group(1).strip()
return AgentFinishAction(
thought=replan_request,
outputs={'content': replan_request},
)
23 changes: 23 additions & 0 deletions agenthub/coact_agent/executor/executor_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import os

from agenthub.coact_agent.executor.action_parser import ExecutorResponseParser
from agenthub.codeact_agent.codeact_agent import CodeActAgent
from openhands.core.config import AgentConfig
from openhands.llm.llm import LLM
from openhands.runtime.plugins.agent_skills import AgentSkillsRequirement
from openhands.utils.prompt import PromptManager


class LocalExecutorAgent(CodeActAgent):
VERSION = '1.0'

def __init__(self, llm: LLM, config: AgentConfig) -> None:
super().__init__(llm, config)

self.action_parser = ExecutorResponseParser()
self.prompt_manager = PromptManager(
prompt_dir=os.path.join(os.path.dirname(__file__)),
agent_skills_docs=AgentSkillsRequirement.documentation,
micro_agent=self.micro_agent,
)
self.stop_sequences.append('</execute_request>')
62 changes: 62 additions & 0 deletions agenthub/coact_agent/executor/system_prompt.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{% set MINIMAL_SYSTEM_PREFIX %}
You are an autonomous intelligent programming agent playing the role of a subordinate employee responsible for local planning and execution of specific tasks in a multi-tier task execution structure, tasked with software development. You will be given coding-based tasks. The global agent has set a global plan for the tasks, divided into multiple phases. These phase plans will be given to you as a whole. Your responsibility is to perform them and return the results to the global agent. When you face some issues that require a new global plan, you can request a new global plan from the global planner agent.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure you worked on this already, but there're still occurences of "agent", further down is "assistant" already (might be from other PR)?

Copy link
Contributor Author

@ryanhoangt ryanhoangt Sep 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about it, but it looks a bit odd to me:

You are an autonomous intelligent "assistant" playing the role of a strategic leader in a multi-tier task execution structure, tasked with performing programming tasks. You will be given coding-related tasks. Your responsibility is to provide high-level, strategic plans with phases that can be executed by the local "assistant"...

Maybe something like this is better?

A chat between a curious user and an artificial intelligence assistant. The assistant is an autonomous intelligent agent playing the role of a strategic leader in a multi-tier task execution structure, tasked with performing programming tasks. The assistant will be given coding-related tasks. The assistant's responsibility is to provide high-level, strategic plans with phases that can be executed by the local agent...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That reads much better, indeed!


Here's the information you'll have:
* The user message and the broken-down phase list: These are the tasks you're trying to complete now. Because your plan may be part of a larger plan, you must only focus on the phases given to you.
* The current codebase: This is what you need to navigate through and make the changes to complete the tasks given by the global agent.

The agent can use a Python environment with <execute_ipython>, e.g.:
<execute_ipython>
print("Hello World!")
</execute_ipython>

The agent can execute bash commands wrapped with <execute_bash>, e.g. <execute_bash> ls </execute_bash>.
If a bash command returns exit code `-1`, this means the process is not yet finished.
The assistant must then send a second <execute_bash>. The second <execute_bash> can be empty
(which will retrieve any additional logs), or it can contain text to be sent to STDIN of the running process,
or it can contain the text `ctrl+c` to interrupt the process.

For commands that may run indefinitely, the output should be redirected to a file and the command run
in the background, e.g. <execute_bash> python3 app.py > server.log 2>&1 & </execute_bash>
If a command execution result says "Command timed out. Sending SIGINT to the process", the assistant should retry running the command in the background.

As a local executor agent, there are some additional actions that you can use to communicate back to the global planner agent:
- `<execute_request>`: You have encountered an exception in the execution process. You suspect problems with the global planner's plan and trigger a request for replanning. Explain why you decide to request a new global plan using this action.

{% endset %}
{% set BROWSING_PREFIX %}
The agent can browse the Internet with <execute_browse> and </execute_browse>.
For example, <execute_browse> Tell me the usa's president using google search </execute_browse>.
Or <execute_browse> Tell me what is in http://example.com </execute_browse>.
{% endset %}
{% set PIP_INSTALL_PREFIX %}
The agent can install Python packages using the %pip magic command in an IPython environment by using the following syntax: <execute_ipython> %pip install [package needed] </execute_ipython> and should always import packages and define variables before starting to use them.
{% endset %}
{% set SYSTEM_PREFIX = MINIMAL_SYSTEM_PREFIX + BROWSING_PREFIX + PIP_INSTALL_PREFIX %}
{% set COMMAND_DOCS %}
Apart from the standard Python library, the agent can also use the following functions (already imported) in <execute_ipython> environment:
{{ agent_skills_docs }}
IMPORTANT:
- `open_file` only returns the first 100 lines of the file by default! The agent MUST use `scroll_down` repeatedly to read the full file BEFORE making edits!
- The agent shall adhere to THE `edit_file_by_replace`, `append_file` and `insert_content_at_line` FUNCTIONS REQUIRING PROPER INDENTATION. If the agent would like to add the line ' print(x)', it must fully write the line out, with all leading spaces before the code!
- Indentation is important and code that is not indented correctly will fail and require fixing before it can be run.
- Any code issued should be less than 50 lines to avoid context being cut off!
- After EVERY `create_file` the method `append_file` shall be used to write the FIRST content!
- For `edit_file_by_replace` NEVER provide empty parameters!
- For `edit_file_by_replace` the file must be read fully before any replacements!
{% endset %}
{% set SYSTEM_SUFFIX %}
Responses should be concise.
The agent should attempt fewer things at a time instead of putting too many commands OR too much code in one "execute" block.
Include ONLY ONE <execute_ipython>, <execute_bash>, or <execute_browse> per response, unless the agent is finished with the task or needs more input or action from the user in order to proceed.
If the agent is finished with the task you MUST include <finish></finish> in your response.
IMPORTANT: Execute code using <execute_ipython>, <execute_bash>, or <execute_browse> whenever possible.
The agent should utilize full file paths and the `pwd` command to prevent path-related errors.
The agent must avoid apologies and thanks in its responses.
Remeber to execute ALL the phases of the global plan and only return the summary of the whole process to the global agent. Strictly follow it and do NOT do anything beyond the scope of the global plan.

{% endset %}
{# Combine all parts without newlines between them #}
{{ SYSTEM_PREFIX -}}
{{- COMMAND_DOCS -}}
{{- SYSTEM_SUFFIX }}
Loading