Skip to content

Commit

Permalink
Streamline code agent creation
Browse files Browse the repository at this point in the history
  • Loading branch information
aorwall committed Jan 25, 2025
1 parent fd8590a commit c1d85b9
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 22 deletions.
107 changes: 93 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,38 +191,100 @@ poetry run python -m moatless.benchmark.run_evaluation \
--instance-ids "django__django-16527"
```

# Code Example
# Code Examples

Basic setup using the `AgenticLoop` to solve a SWE-Bench instance.

## Example 1: Using Claude 3.5 Sonnet
```python
from moatless.actions.string_replace import StringReplace
from moatless.agent.code_agent import CodingAgent
from moatless.benchmark.swebench import create_repository
from moatless.benchmark.utils import get_moatless_instance
from moatless.completion.base import BaseCompletionModel, LLMResponseFormat
from moatless.completion.tool_call import ToolCallCompletionModel
from moatless.file_context import FileContext
from moatless.agent.code_agent import CodingAgent
from moatless.index import CodeIndex
from moatless.loop import AgenticLoop
from moatless.file_context import FileContext
from moatless.completion.base import LLMResponseFormat
from moatless.schema import MessageHistoryType

index_store_dir = "/tmp/index_store"
repo_base_dir = "/tmp/repos"
index_store_dir = os.getenv("INDEX_STORE_DIR", "/tmp/index_store")
repo_base_dir = os.getenv("REPO_DIR", "/tmp/repos")
persist_path = "trajectory.json"

instance = get_moatless_instance("django__django-16379")
repository = create_repository(instance)
code_index = CodeIndex.from_index_name(
instance["instance_id"],
index_store_dir=index_store_dir,
file_repo=repository
)
file_context = FileContext(repo=repository)

completion_model = BaseCompletionModel.create(response_format=LLMResponseFormat.TOOLS, model="claude-3-5-sonnet-20240620", temperature=0.0)
# Create agent using Claude 3.5 Sonnet with explicit config
agent = CodingAgent.create(
repository=repository, # Repository instance with codebase
code_index=code_index, # Code index for semantic search

model="claude-3-5-sonnet-20241022",
temperature=0.0,
max_tokens=4000,
few_shot_examples=False, # We don't need few-shot examples for this model

response_format=LLMResponseFormat.TOOLS,
message_history_type=MessageHistoryType.MESSAGES, # We must show the full message history to make us of claude's prompt cache
)

repository = create_repository(instance)
loop = AgenticLoop.create(
message=instance["problem_statement"],
agent=agent,
file_context=file_context,
repository=repository,
persist_path=persist_path,
max_iterations=50,
max_cost=2.0
)

final_node = loop.run()
if final_node:
print(final_node.observation.message)
```

## Example 2: Using Deepseek V3
```python
from moatless.benchmark.swebench import create_repository
from moatless.benchmark.utils import get_moatless_instance
from moatless.agent.code_agent import CodingAgent
from moatless.index import CodeIndex
from moatless.loop import AgenticLoop
from moatless.file_context import FileContext
from moatless.completion.base import LLMResponseFormat
from moatless.schema import MessageHistoryType

index_store_dir = os.getenv("INDEX_STORE_DIR", "/tmp/index_store")
repo_base_dir = os.getenv("REPO_DIR", "/tmp/repos")
persist_path = "trajectory.json"

instance = get_moatless_instance("django__django-16379")
repository = create_repository(instance)
code_index = CodeIndex.from_index_name(
instance["instance_id"], index_store_dir=index_store_dir, file_repo=repository
instance["instance_id"],
index_store_dir=index_store_dir,
file_repo=repository
)

file_context = FileContext(repo=repository)
agent = CodingAgent.create(completion_model=completion_model, code_index=code_index, repository=repository, message_history_type=MessageHistoryType.MESSAGES)

# Create agent using Deepseek Chat with explicit config
agent = CodingAgent.create(
repository=repository,
code_index=code_index,

model="deepseek/deepseek-chat",
temperature=0.0,
max_tokens=4000,
few_shot_examples=True,

response_format=LLMResponseFormat.REACT,
message_history_type=MessageHistoryType.REACT
)

loop = AgenticLoop.create(
message=instance["problem_statement"],
Expand All @@ -231,10 +293,27 @@ loop = AgenticLoop.create(
repository=repository,
persist_path=persist_path,
max_iterations=50,
max_cost=2.0 # Optional: Set maximum cost in dollars
max_cost=2.0
)

final_node = loop.run()
if final_node:
print(final_node.observation.message)
```

## CodingAgent Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `model` | str | Required | Model identifier from supported models table (e.g., "claude-3-5-sonnet-20241022") |
| `repository` | Repository | Required | Repository instance containing the codebase |
| `code_index` | CodeIndex | None | Code index for semantic search functionality |
| `runtime` | RuntimeEnvironment | None | Environment for running tests |
| `message_history_type` | MessageHistoryType | From config | How to format the message history in the prompt ('messages', 'react', etc.) |
| `thoughts_in_action` | bool | From config | Whether to include thoughts in action responses, used when the LLM can't provide the reasoning in the message content |
| `disable_thoughts` | bool | From config | Whether to completely disable thought generation, used for reasoning models like o1 and Deepseek R1 |
| `few_shot_examples` | bool | From config | Whether to use few-shot examples in prompts |
| `temperature` | float | From config | Temperature for model sampling (0.0 = deterministic) |
| `max_tokens` | int | From config | Maximum tokens per model completion |

The default values for optional parameters are taken from the model's configuration in `model_config.py`. See the Verified Models table above for model-specific defaults.
49 changes: 41 additions & 8 deletions moatless/agent/code_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
)
from moatless.index import CodeIndex
from moatless.message_history import MessageHistoryGenerator
from moatless.model_config import get_model_config
from moatless.repository.repository import Repository
from moatless.runtime.runtime import RuntimeEnvironment
from moatless.schema import MessageHistoryType
Expand All @@ -47,25 +48,58 @@ class CodingAgent(ActionAgent):
def create(
cls,
repository: Repository,
completion_model: BaseCompletionModel,
completion_model: BaseCompletionModel | None = None,
model: str | None = None,
code_index: CodeIndex | None = None,
runtime: RuntimeEnvironment | None = None,
edit_completion_model: BaseCompletionModel | None = None,
message_history_type: MessageHistoryType | None = None,
thoughts_in_action: bool = False,
disable_thoughts: bool = False,
few_shot_examples: bool = False,
thoughts_in_action: bool | None = None,
disable_thoughts: bool | None = None,
few_shot_examples: bool | None = None,
**kwargs,
):
# Clone the completion model to ensure we have our own instance
completion_model = completion_model.clone()
if completion_model is None:
if model is None:
raise ValueError("Either completion_model or model name must be provided")

# Get default config for the model from model_config
model_config = get_model_config(model)

# Set instance variables from model config if not explicitly provided
if thoughts_in_action is None:
thoughts_in_action = model_config.get('thoughts_in_action', False)
if disable_thoughts is None:
disable_thoughts = model_config.get('disable_thoughts', False)
if few_shot_examples is None:
few_shot_examples = model_config.get('few_shot_examples', True)

# Override with any provided kwargs
model_config.update(kwargs)

# Create completion model
completion_model = BaseCompletionModel.create(**model_config)
else:
# Clone the completion model to ensure we have our own instance
completion_model = completion_model.clone()

# Set instance variables from completion model if not explicitly provided
if thoughts_in_action is None:
thoughts_in_action = completion_model.thoughts_in_action
if disable_thoughts is None:
disable_thoughts = completion_model.disable_thoughts

if message_history_type is None:
if completion_model.response_format == LLMResponseFormat.TOOLS:
message_history_type = MessageHistoryType.MESSAGES

if few_shot_examples is None:
few_shot_examples = False
else:
message_history_type = MessageHistoryType.REACT

if few_shot_examples is None:
few_shot_examples = True

action_completion_format = completion_model.response_format
if action_completion_format != LLMResponseFormat.TOOLS:
logger.info("Default to JSON as Response format for action completion model")
Expand Down Expand Up @@ -133,7 +167,6 @@ def create(
"completion_model": completion_model.__class__.__name__,
"code_index_enabled": code_index is not None,
"runtime_enabled": runtime is not None,
"edit_completion_model": edit_completion_model.__class__.__name__ if edit_completion_model else None,
"action_type": action_type,
"actions": [a.__class__.__name__ for a in actions],
"message_history_type": message_history_type.value,
Expand Down
59 changes: 59 additions & 0 deletions scripts/run_deepseek.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@

import logging
import os

from dotenv import load_dotenv
from moatless.benchmark.swebench import create_repository
from moatless.benchmark.utils import get_moatless_instance
from moatless.agent.code_agent import CodingAgent
from moatless.index import CodeIndex
from moatless.loop import AgenticLoop
from moatless.file_context import FileContext
from moatless.completion.base import LLMResponseFormat
from moatless.schema import MessageHistoryType

load_dotenv()

index_store_dir = os.getenv("INDEX_STORE_DIR", "/tmp/index_store")
repo_base_dir = os.getenv("REPO_DIR", "/tmp/repos")

persist_path = "trajectory.json"

logging.basicConfig(level=logging.INFO)

instance = get_moatless_instance("django__django-16379")
repository = create_repository(instance)
code_index = CodeIndex.from_index_name(
instance["instance_id"],
index_store_dir=index_store_dir,
file_repo=repository
)
file_context = FileContext(repo=repository)

# Create agent using Deepseek Chat with explicit config
agent = CodingAgent.create(
repository=repository,
code_index=code_index,

model="deepseek/deepseek-chat",
temperature=0.0,
max_tokens=4000,
few_shot_examples=True,

response_format=LLMResponseFormat.REACT,
message_history_type=MessageHistoryType.REACT
)

loop = AgenticLoop.create(
message=instance["problem_statement"],
agent=agent,
file_context=file_context,
repository=repository,
persist_path=persist_path,
max_iterations=50,
max_cost=2.0
)

final_node = loop.run()
if final_node:
print(final_node.observation.message)

0 comments on commit c1d85b9

Please sign in to comment.