ReproAgent / agents /debugger.py
Yusufarsh's picture
Upload 13 files
c8d0576 verified
"""
Debugging agent - analyzes and fixes code errors.
"""
import re
from typing import Dict, Any, List, Optional, Tuple
from reproagent.models import LLMClient
class Debugger:
"""
Debugging agent that:
1. Analyzes error messages
2. Searches for solutions
3. Proposes fixes
4. Applies patches
"""
def __init__(self, llm_client: LLMClient):
"""
Args:
llm_client: LLM for error analysis
"""
self.llm = llm_client
# Common error patterns
self.error_patterns = {
'ImportError': r'ImportError: No module named [\'"](.+)[\'"]',
'ModuleNotFoundError': r'ModuleNotFoundError: No module named [\'"](.+)[\'"]',
'FileNotFoundError': r'FileNotFoundError: \[Errno 2\] No such file or directory: [\'"](.+)[\'"]',
'RuntimeError': r'RuntimeError: (.+)',
'ValueError': r'ValueError: (.+)',
'TypeError': r'TypeError: (.+)',
'AttributeError': r'AttributeError: (.+)',
}
def analyze_error(self, error_message: str, code_context: Optional[str] = None) -> Dict[str, Any]:
"""
Analyze error and determine cause.
Args:
error_message: Full error message/traceback
code_context: Relevant code snippet (optional)
Returns:
Analysis dict with error type, cause, and suggested fixes
"""
print(f"🔍 Analyzing error...")
# Classify error type
error_type = self._classify_error(error_message)
# Extract error details
error_details = self._extract_error_details(error_message, error_type)
# Get LLM analysis
llm_analysis = self._llm_analyze_error(error_message, code_context)
analysis = {
'error_type': error_type,
'error_details': error_details,
'root_cause': llm_analysis.get('root_cause', 'Unknown'),
'suggested_fixes': llm_analysis.get('fixes', []),
'confidence': llm_analysis.get('confidence', 0.5)
}
print(f"✅ Error analyzed: {error_type}")
print(f" Cause: {analysis['root_cause']}")
return analysis
def _classify_error(self, error_message: str) -> str:
"""Classify error type."""
for error_type, pattern in self.error_patterns.items():
if re.search(pattern, error_message):
return error_type
# Check for common error types in message
if 'import' in error_message.lower():
return 'ImportError'
elif 'file' in error_message.lower() and 'not found' in error_message.lower():
return 'FileNotFoundError'
elif 'cuda' in error_message.lower() or 'gpu' in error_message.lower():
return 'CUDAError'
elif 'memory' in error_message.lower():
return 'MemoryError'
return 'UnknownError'
def _extract_error_details(self, error_message: str, error_type: str) -> Dict[str, str]:
"""Extract specific details from error."""
details = {}
if error_type in self.error_patterns:
pattern = self.error_patterns[error_type]
match = re.search(pattern, error_message)
if match:
details['detail'] = match.group(1)
# Extract file and line number
file_pattern = r'File "(.+)", line (\d+)'
file_match = re.search(file_pattern, error_message)
if file_match:
details['file'] = file_match.group(1)
details['line'] = file_match.group(2)
return details
def _llm_analyze_error(self, error_message: str, code_context: Optional[str]) -> Dict[str, Any]:
"""Use LLM to analyze error."""
prompt = f"""
Analyze this Python error and provide solutions.
Error:
{error_message[:1000]}
"""
if code_context:
prompt += f"\n\nRelevant code:\n{code_context[:500]}"
prompt += """
Respond with JSON:
{
"root_cause": "explanation of what caused the error",
"fixes": ["fix 1", "fix 2", "fix 3"],
"confidence": 0.9
}
"""
try:
result = self.llm.generate_structured(prompt)
return result
except:
return self._fallback_analysis(error_message)
def _fallback_analysis(self, error_message: str) -> Dict[str, Any]:
"""Fallback analysis without LLM."""
# Common fixes for common errors
fixes = []
if 'ModuleNotFoundError' in error_message or 'ImportError' in error_message:
match = re.search(r"module named ['\"](.+)['\"]", error_message)
if match:
module = match.group(1)
fixes = [
f"Install missing package: pip install {module}",
f"Check if {module} is in requirements.txt",
"Activate correct virtual environment"
]
elif 'FileNotFoundError' in error_message:
fixes = [
"Check if file path is correct",
"Ensure data is downloaded",
"Check working directory"
]
elif 'CUDA' in error_message or 'GPU' in error_message:
fixes = [
"Check CUDA installation",
"Verify GPU availability",
"Try running on CPU: device='cpu'"
]
elif 'memory' in error_message.lower():
fixes = [
"Reduce batch size",
"Use gradient accumulation",
"Clear GPU cache: torch.cuda.empty_cache()"
]
return {
'root_cause': 'Error detected',
'fixes': fixes or ['Debug manually'],
'confidence': 0.6
}
def generate_fix(self, error_analysis: Dict[str, Any]) -> str:
"""
Generate code fix based on error analysis.
Args:
error_analysis: Output from analyze_error()
Returns:
Fix as code or command
"""
error_type = error_analysis['error_type']
details = error_analysis['error_details']
# Generate specific fix based on error type
if error_type in ['ImportError', 'ModuleNotFoundError']:
module = details.get('detail', '')
return f"pip install {module}"
elif error_type == 'FileNotFoundError':
file_path = details.get('detail', '')
return f"# Check if {file_path} exists or download it"
elif error_type == 'CUDAError':
return "# Try: model.to('cpu') or install CUDA"
elif error_type == 'MemoryError':
return "# Reduce batch_size or use gradient accumulation"
# Use LLM for complex fixes
return self._llm_generate_fix(error_analysis)
def _llm_generate_fix(self, error_analysis: Dict[str, Any]) -> str:
"""Use LLM to generate code fix."""
prompt = f"""
Generate a code fix for this error:
Error Type: {error_analysis['error_type']}
Root Cause: {error_analysis['root_cause']}
Provide the fix as Python code or shell command.
"""
try:
fix = self.llm.generate(prompt, max_tokens=200)
return fix.strip()
except:
return "# Manual fix required"
def search_solution(self, error_message: str) -> List[str]:
"""
Search for solutions to error.
Simulates searching StackOverflow, documentation, etc.
Args:
error_message: Error message
Returns:
List of solution suggestions
"""
# In full implementation, would search:
# - StackOverflow API
# - GitHub Issues
# - Documentation
# For now, use LLM to generate solutions
prompt = f"""
This error occurred: {error_message[:500]}
List 3 common solutions to this error.
Respond with JSON:
{{
"solutions": ["solution 1", "solution 2", "solution 3"]
}}
"""
try:
result = self.llm.generate_structured(prompt)
return result.get('solutions', [])
except:
return ["Check dependencies", "Review code", "Search documentation"]
# Test
if __name__ == "__main__":
from reproagent.models import LLMClient
llm = LLMClient()
debugger = Debugger(llm)
# Test error
error = """
Traceback (most recent call last):
File "train.py", line 10, in <module>
import torch
ModuleNotFoundError: No module named 'torch'
"""
analysis = debugger.analyze_error(error)
print(analysis)
fix = debugger.generate_fix(analysis)
print(f"\nFix: {fix}")