| | |
| |
|
| | from typing import Any, Dict, List, Optional, Union |
| | import logging |
| | import time |
| | from abc import ABC, abstractmethod |
| |
|
| | class ModelInterface(ABC): |
| | """ |
| | Base interface for models that can be evaluated using Recursive-SWE-bench. |
| | |
| | This abstract class defines the core functionality required for a model to |
| | be evaluated using the recursive evaluation framework. Concrete implementations |
| | must provide the actual model-specific logic. |
| | """ |
| | |
| | def __init__(self, model_identifier: str, config: Optional[Dict[str, Any]] = None): |
| | """ |
| | Initialize the model interface. |
| | |
| | Args: |
| | model_identifier: Identifier for the model |
| | config: Configuration options |
| | """ |
| | self.model_identifier = model_identifier |
| | self.config = config or {} |
| | self.logger = self._setup_logger() |
| | |
| | def _setup_logger(self) -> logging.Logger: |
| | """Set up logging for the model.""" |
| | logger = logging.getLogger(f"Model.{self.model_identifier}") |
| | handler = logging.StreamHandler() |
| | formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') |
| | handler.setFormatter(formatter) |
| | logger.addHandler(handler) |
| | logger.setLevel(self.config.get("log_level", logging.INFO)) |
| | return logger |
| | |
| | @abstractmethod |
| | def solve(self, problem: Dict[str, Any], history: Optional[List[Dict[str, Any]]] = None) -> str: |
| | """ |
| | Generate a solution for the given problem. |
| | |
| | Args: |
| | problem: The problem to solve |
| | history: Optional history of previous solution attempts |
| | |
| | Returns: |
| | The generated solution |
| | """ |
| | pass |
| | |
| | @abstractmethod |
| | def get_meta_information(self) -> Dict[str, Any]: |
| | """ |
| | Get meta information about the model. |
| | |
| | Returns: |
| | Dictionary containing model information |
| | """ |
| | pass |
| |
|
| |
|
| | |
| |
|
| | import openai |
| | import json |
| | import backoff |
| | from typing import Any, Dict, List, Optional, Union |
| |
|
| | from recursive_swe_bench.models.base_model import ModelInterface |
| |
|
| | class OpenAIModel(ModelInterface): |
| | """ |
| | Integration with OpenAI models (GPT-3.5, GPT-4, etc.). |
| | |
| | This class provides integration with OpenAI's API for evaluating |
| | models like GPT-3.5 and GPT-4 with Recursive-SWE-bench. |
| | """ |
| | |
| | def __init__( |
| | self, |
| | model_identifier: str, |
| | api_key: Optional[str] = None, |
| | config: Optional[Dict[str, Any]] = None |
| | ): |
| | """ |
| | Initialize the OpenAI model interface. |
| | |
| | Args: |
| | model_identifier: OpenAI model identifier (e.g., "gpt-4", "gpt-3.5-turbo") |
| | api_key: OpenAI API key (optional if set in environment) |
| | config: Additional configuration options |
| | """ |
| | super().__init__(model_identifier, config) |
| | |
| | |
| | if api_key: |
| | openai.api_key = api_key |
| | |
| | |
| | self.prompts = self.config.get("prompts", { |
| | "system": "You are an expert programmer tasked with fixing bugs in code. Fix the code based on the description and tests.", |
| | "user_template": "# Bug Fixing Task\n\n{description}\n\n# Code\n```python\n{code}\n```\n\n{tests_description}\n\n# Your task\nFix the bugs in the code above. Provide only the corrected code without any explanations.", |
| | }) |
| | |
| | |
| | self.api_params = self.config.get("api_params", { |
| | "temperature": 0.2, |
| | "max_tokens": 2000, |
| | "top_p": 0.95, |
| | "frequency_penalty": 0, |
| | "presence_penalty": 0, |
| | }) |
| | |
| | self.logger.info(f"Initialized OpenAI model: {model_identifier}") |
| | |
| | @backoff.on_exception( |
| | backoff.expo, |
| | (openai.error.RateLimitError, openai.error.ServiceUnavailableError, openai.error.APIError), |
| | max_tries=5 |
| | ) |
| | def solve( |
| | self, |
| | problem: Dict[str, Any], |
| | history: Optional[List[Dict[str, Any]]] = None |
| | ) -> str: |
| | """ |
| | Generate a solution using the OpenAI model. |
| | |
| | Args: |
| | problem: The problem to solve |
| | history: Optional history of previous solution attempts |
| | |
| | Returns: |
| | The generated solution |
| | """ |
| | self.logger.info(f"Solving problem with OpenAI model: {self.model_identifier}") |
| | start_time = time.time() |
| | |
| | |
| | messages = self._format_messages(problem, history) |
| | |
| | |
| | response = openai.ChatCompletion.create( |
| | model=self.model_identifier, |
| | messages=messages, |
| | **self.api_params |
| | ) |
| | |
| | |
| | solution = response.choices[0].message.content.strip() |
| | |
| | end_time = time.time() |
| | self.logger.info(f"Solution generated in {end_time - start_time:.2f} seconds") |
| | |
| | return self._extract_code(solution) |
| | |
| | def _format_messages( |
| | self, |
| | problem: Dict[str, Any], |
| | history: Optional[List[Dict[str, Any]]] = None |
| | ) -> List[Dict[str, str]]: |
| | """ |
| | Format the problem and history into messages for the OpenAI API. |
| | |
| | Args: |
| | problem: The problem to solve |
| | history: Optional history of previous solution attempts |
| | |
| | Returns: |
| | List of formatted messages |
| | """ |
| | messages = [ |
| | {"role": "system", "content": self.prompts["system"]} |
| | ] |
| | |
| | |
| | code = problem["code_context"]["code"] |
| | |
| | |
| | tests_description = "# Tests\n" |
| | if "tests" in problem["code_context"]: |
| | tests_description += "The code must pass the following tests:\n\n" |
| | for i, test in enumerate(problem["code_context"]["tests"]): |
| | tests_description += f"## Test {i+1}: {test['name']}\n```python\n{test['content']}\n```\n\n" |
| | else: |
| | tests_description += "The code must work correctly according to its intended functionality." |
| | |
| | |
| | user_content = self.prompts["user_template"].format( |
| | description=problem["description"], |
| | code=code, |
| | tests_description=tests_description |
| | ) |
| | |
| | messages.append({"role": "user", "content": user_content}) |
| | |
| | |
| | if history and self.config.get("include_history", True): |
| | for entry in history: |
| | |
| | messages.append({ |
| | "role": "assistant", |
| | "content": entry["solution"] |
| | }) |
| | |
| | |
| | feedback_content = f"Your solution has the following issues:\n" |
| | for issue in entry["feedback"]["issues"]: |
| | feedback_content += f"- {issue['message']}\n" |
| | |
| | feedback_content += "\nPlease try again with these improvements:\n" |
| | for suggestion in entry["feedback"]["suggestions"]: |
| | feedback_content += f"- {suggestion['message']}\n" |
| | |
| | messages.append({ |
| | "role": "user", |
| | "content": feedback_content |
| | }) |
| | |
| | return messages |
| | |
| | def _extract_code(self, text: str) -> str: |
| | """ |
| | Extract code from the model's response. |
| | |
| | Args: |
| | text: The model's response |
| | |
| | Returns: |
| | Extracted code |
| | """ |
| | |
| | import re |
| | code_blocks = re.findall(r'```(?:python)?\s*(.*?)\s*```', text, re.DOTALL) |
| | |
| | if code_blocks: |
| | return code_blocks[0].strip() |
| | |
| | |
| | return text.strip() |
| | |
| | def get_meta_information(self) -> Dict[str, Any]: |
| | """ |
| | Get meta information about the model. |
| | |
| | Returns: |
| | Dictionary containing model information |
| | """ |
| | return { |
| | "model_name": self.model_identifier, |
| | "provider": "OpenAI", |
| | "type": "API", |
| | "parameters": self.api_params, |
| | "system_prompt": self.prompts["system"] |
| | } |
| |
|
| |
|
| |
|