CoderAgent: Render summary prompt conditionally (#1461)

* CoderAgent: Render repo summary conditionally

* Add unittests

---------

Co-authored-by: Robert Brennan <accounts@rbren.io>
This commit is contained in:
Boxuan Li 2024-05-01 08:40:20 -07:00 committed by GitHub
parent c50319138e
commit c7dd443fa2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 90 additions and 0 deletions

14
agenthub/micro/README.md Normal file
View File

@ -0,0 +1,14 @@
## Introduction
This package contains definitions of micro-agents. A micro-agent is defined
in the following structure:
```
[AgentName]
├── agent.yaml
└── prompt.md
```
Note that `prompt.md` could use jinja2 template syntax. During runtime, `prompt.md`
is loaded and rendered, and used together with `agent.yaml` to initialize a
micro-agent.

View File

@ -4,9 +4,11 @@ need to modify to complete this task:
{{ state.plan.main_goal }}
{% if state.inputs.summary %}
Here's a summary of the codebase, as it relates to this task:
{{ state.inputs.summary }}
{% endif %}
## Available Actions
{{ instructions.actions.run }}

View File

@ -0,0 +1,74 @@
import json
import os
from unittest.mock import MagicMock
import yaml
from agenthub.micro.registry import all_microagents
from opendevin.agent import Agent
from opendevin.plan import Plan
from opendevin.state import State
def test_all_agents_are_loaded():
full_path = os.path.join('agenthub', 'micro')
agent_names = set()
for root, _, files in os.walk(full_path):
for file in files:
if file == 'agent.yaml':
file_path = os.path.join(root, file)
with open(file_path, 'r') as yaml_file:
data = yaml.safe_load(yaml_file)
agent_names.add(data['name'])
assert agent_names == set(all_microagents.keys())
def test_coder_agent_with_summary():
"""
Coder agent should render code summary as part of prompt
"""
mock_llm = MagicMock()
content = json.dumps({'action': 'finish', 'args': {}})
mock_llm.completion.return_value = {
'choices': [{'message': {'content': content}}]
}
coder_agent = Agent.get_cls('CoderAgent')(llm=mock_llm)
assert coder_agent is not None
task = 'This is a dummy task'
plan = Plan(task)
summary = 'This is a dummy summary about this repo'
state = State(plan, inputs={'summary': summary})
coder_agent.step(state)
mock_llm.completion.assert_called_once()
_, kwargs = mock_llm.completion.call_args
prompt = kwargs['messages'][0]['content']
assert task in prompt
assert "Here's a summary of the codebase, as it relates to this task" in prompt
assert summary in prompt
def test_coder_agent_without_summary():
"""
When there's no codebase_summary available, there shouldn't be any prompt
about 'code summary'
"""
mock_llm = MagicMock()
content = json.dumps({'action': 'finish', 'args': {}})
mock_llm.completion.return_value = {
'choices': [{'message': {'content': content}}]
}
coder_agent = Agent.get_cls('CoderAgent')(llm=mock_llm)
assert coder_agent is not None
task = 'This is a dummy task'
plan = Plan(task)
state = State(plan)
coder_agent.step(state)
mock_llm.completion.assert_called_once()
_, kwargs = mock_llm.completion.call_args
prompt = kwargs['messages'][0]['content']
assert task in prompt
assert "Here's a summary of the codebase, as it relates to this task" not in prompt