-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun_self_eval.py
More file actions
142 lines (111 loc) · 5.26 KB
/
Copy pathrun_self_eval.py
File metadata and controls
142 lines (111 loc) · 5.26 KB
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
from StarCoder import build_model, generate_code, execute
import json
import os
from datasets import load_dataset
def generate_self_evaluation(model, tokenizer, failed_result):
"""Generate analysis of failed code"""
# More specific and detailed prompt for better analysis
eval_prompt = f"""Analyze this Python code implementation that failed testing:
FUNCTION DESCRIPTION:
{failed_result.get('prompt', 'No description available')}
GENERATED CODE:
{failed_result['generated_code']}
TEST FAILURE:
{failed_result['output']}
Provide a detailed analysis of:
1. Logic errors found
2. Implementation issues (be specific about what's wrong)
3. Edge cases missed
4. Specific code fixes needed with corrected implementation
Focus on substantive issues rather than style. Be concise and specific.
"""
return generate_code(model, tokenizer, eval_prompt)
def preprocess_improved_code(code, task_id, problem):
"""Preprocess the improved code for better test success"""
# Add imports for typing if needed
if any(typ in code for typ in ["List", "Optional", "Tuple", "Any"]):
if "from typing import" not in code:
code = "from typing import List, Optional, Tuple, Any\n\n" + code
# Extract function name from problem if possible
if problem and 'prompt' in problem:
import re
func_match = re.search(r'def\s+([a-zA-Z_][a-zA-Z0-9_]*)', problem['prompt'])
if func_match:
func_name = func_match.group(1)
# Ensure the function name is correct in the generated code
if func_name in code and not code.strip().startswith(f"def {func_name}"):
code_parts = code.split(f"def {func_name}")
if len(code_parts) > 1:
code = f"def {func_name}" + code_parts[1]
# Clean up code structure
code_lines = [line for line in code.split('\n')
if not line.strip().startswith(('assert', '>>>'))]
return '\n'.join(code_lines)
def improve_with_self_eval(baseline_results_path='results/baseline_results.json'):
"""Improve code generation using self-evaluation"""
model, tokenizer, _ = build_model()
# Load baseline results
with open(baseline_results_path) as f:
baseline_results = json.load(f)
# Load HumanEval dataset to get test cases
dataset = load_dataset("openai_humaneval")
problems = {p['task_id']: p for p in dataset['test']}
improved_results = []
for result in baseline_results:
task_id = result['task_id']
problem = problems.get(task_id)
if not result['execution_success'] and problem:
print(f"\nProcessing failed task: {task_id}")
# Generate evaluation
evaluation = generate_self_evaluation(model, tokenizer, result)
print("Generated self-evaluation")
# Try again with evaluation feedback - improved prompt
improved_prompt = f"""
Complete the following Python function. Fix the issues identified below:
ORIGINAL PROMPT:
{problem['prompt']}
PREVIOUS IMPLEMENTATION ISSUES:
{evaluation}
Write a complete, correct implementation that fixes these issues.
Make sure your solution has proper error handling and handles all edge cases.
"""
improved_code = generate_code(model, tokenizer, improved_prompt)
print("Generated improved code")
# Process and clean the improved code
improved_code = preprocess_improved_code(improved_code, task_id, problem)
# Test improved version with actual test cases
test_code = problem['test'] # Get test cases from HumanEval dataset
success, output = execute(improved_code, test_code)
improved_results.append({
**result,
'self_evaluation': evaluation,
'improved_code': improved_code,
'improved_success': success,
'improved_output': output,
'test_cases': test_code
})
print(f"Execution success: {success}")
else:
improved_results.append(result)
# Save results
os.makedirs('results', exist_ok=True)
save_path = 'results/self_eval_results.json'
with open(save_path, 'w') as f:
json.dump(improved_results, f, indent=2)
# Print summary
initial_success = sum(1 for r in baseline_results if r['execution_success'])
# Fixed success calculation
improved_success = 0
for r in improved_results:
if r.get('improved_success', False) == True: # New successes
improved_success += 1
elif r.get('execution_success', False) == True: # Original successes
improved_success += 1
total = len(baseline_results)
print(f"\nResults Summary:")
print(f"Initial success rate: {initial_success}/{total} ({initial_success/total*100:.2f}%)")
print(f"Improved success rate: {improved_success}/{total} ({improved_success/total*100:.2f}%)")
print(f"Results saved to {save_path}")
return improved_results
if __name__ == "__main__":
improve_with_self_eval()