File size: 5,827 Bytes
087ce88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
from typing import Dict, List, Optional
import logging
from datetime import datetime
from .model_manager import ModelManager
from .config import Config

logger = logging.getLogger(__name__)

class CodeReview:
    def __init__(self, code: str, language: str, review_id: str):
        self.code = code
        self.language = language
        self.review_id = review_id
        self.timestamp = datetime.now()
        self.suggestions: List[Dict] = []
        self.metrics: Dict = {}

class CodeReviewer:
    def __init__(self, model_manager: ModelManager):
        self.model_manager = model_manager
        self.review_history: List[CodeReview] = []
        
    def _create_review_prompt(self, code: str, language: str) -> str:
        """Create a structured prompt for code review."""
        return f"""As a code reviewer, analyze the following {language} code and provide specific suggestions in exactly these sections:
- Issues: (list critical problems)
- Improvements: (list suggested enhancements)
- Best Practices: (list recommendations)
- Security: (list security concerns)

Code to review:
```{language}
{code}
```

Provide your review in exactly these sections: Issues, Improvements, Best Practices, Security.
Each section should contain a list of specific points.
"""

    def review_code(self, code: str, language: str, review_id: str) -> CodeReview:
        """Perform code review using the LLM."""
        try:
            start_time = datetime.now()
            
            # Create review instance
            review = CodeReview(code, language, review_id)
            
            # Generate review prompt
            prompt = self._create_review_prompt(code, language)
            
            # Get model response
            response = self.model_manager.generate_text(
                prompt,
                max_new_tokens=Config.MAX_OUTPUT_LENGTH
            )
            
            # Parse and structure the response
            sections = self._parse_review_response(response)
            
            # Store suggestions
            review.suggestions = sections
            
            # Calculate metrics
            end_time = datetime.now()
            review.metrics = {
                'response_time': (end_time - start_time).total_seconds(),
                'code_length': len(code),
                'suggestion_count': sum(len(section['items']) for section in sections)
            }
            
            # Store review in history
            self._add_to_history(review)
            
            return review
            
        except Exception as e:
            logger.error(f"Error during code review: {str(e)}")
            raise

    def _parse_review_response(self, response: str) -> List[Dict]:
        """Parse the LLM response into structured sections."""
        sections = []
        current_section = None
        
        # Split response into lines and process each line
        lines = response.split('\n')
        for line in lines:
            line = line.strip()
            if not line:
                continue
            
            # Check for section headers
            if line.startswith('- ') and ':' in line:
                section_type = line[2:].split(':', 1)[0].strip()
                current_section = {
                    'type': section_type,
                    'items': []
                }
                sections.append(current_section)
                # Add any content after the colon as first item
                content = line.split(':', 1)[1].strip()
                if content:
                    current_section['items'].append(content)
            # Add items to current section
            elif current_section and line.strip('-* '):
                item = line.strip('-* ')
                if item:  # Only add non-empty items
                    current_section['items'].append(item)
        
        # Ensure all required sections exist
        required_sections = ['Issues', 'Improvements', 'Best Practices', 'Security']
        result = []
        for section_type in required_sections:
            found_section = next((s for s in sections if s['type'] == section_type), None)
            if found_section:
                result.append(found_section)
            else:
                result.append({
                    'type': section_type,
                    'items': []
                })
        
        return result

    def _add_to_history(self, review: CodeReview):
        """Add review to history and maintain size limit."""
        self.review_history.append(review)
        if len(self.review_history) > Config.MAX_HISTORY_ITEMS:
            self.review_history.pop(0)

    def get_review_metrics(self) -> Dict:
        """Calculate aggregate metrics from review history."""
        if not self.review_history:
            return {
                'total_reviews': 0,
                'avg_response_time': 0.0,
                'avg_suggestions': 0.0,
                'reviews_today': 0
            }
            
        total_reviews = len(self.review_history)
        avg_response_time = sum(r.metrics['response_time'] for r in self.review_history) / total_reviews
        avg_suggestions = sum(r.metrics['suggestion_count'] for r in self.review_history) / total_reviews
        
        return {
            'total_reviews': total_reviews,
            'avg_response_time': avg_response_time,
            'avg_suggestions': avg_suggestions,
            'reviews_today': sum(1 for r in self.review_history if r.timestamp.date() == datetime.now().date())
        }

    def get_review_history(self, limit: Optional[int] = None) -> List[CodeReview]:
        """Get review history with optional limit."""
        if limit:
            return self.review_history[-limit:]
        return self.review_history