Skip to content

Commit 7276138

Browse files
committed
Update coc_plugin.py
1 parent 2107637 commit 7276138

File tree

1 file changed

+182
-83
lines changed

1 file changed

+182
-83
lines changed

optillm/plugins/coc_plugin.py

Lines changed: 182 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,70 @@
1212
# Plugin identifier
1313
SLUG = "coc"
1414

15+
# Maximum attempts to fix code
16+
MAX_FIX_ATTEMPTS = 3
17+
1518
# List of allowed modules for execution
1619
ALLOWED_MODULES = {
1720
'math': math,
1821
}
1922

20-
# Prompts
23+
# Initial code generation prompt
2124
CHAIN_OF_CODE_PROMPT = '''
22-
You are an AI assistant that uses Chain of Code (CoC) approach to solve problems. Follow these steps:
23-
24-
1. Write Python code that breaks down the problem into clear steps
25-
2. Each step should either be:
26-
- Executable Python code that performs computations
27-
- Pseudocode that you will simulate with natural language understanding
28-
3. Track final result in an 'answer' variable
29-
4. Return the final answer within the <output> tags
25+
Write Python code to solve this problem. The code should:
26+
1. Break down the problem into clear computational steps
27+
2. Use standard Python features and math operations
28+
3. Store the final result in a variable named 'answer'
29+
4. Include error handling where appropriate
30+
5. Be complete and executable
3031
3132
Format your response using:
3233
```python
3334
[Your complete Python program here]
3435
```
36+
'''
37+
38+
# Code fix prompt
39+
CODE_FIX_PROMPT = '''
40+
The following Python code failed to execute. Fix the code to make it work.
41+
Original code:
42+
```python
43+
{code}
44+
```
3545
36-
Finally provide output as:
37-
<output>
38-
[Your final answer]
39-
</output>
46+
Error encountered:
47+
{error}
48+
49+
Please provide a complete, fixed version of the code that:
50+
1. Addresses the error message
51+
2. Maintains the same logic and approach
52+
3. Stores the final result in 'answer'
53+
4. Is complete and executable
54+
55+
Return only the fixed code in a code block:
56+
```python
57+
[Your fixed code here]
58+
```
4059
'''
4160

42-
STATE_SIMULATION_PROMPT = '''You are simulating the execution of a Python program.
43-
Given the code below, simulate its execution and return the final value that would be in the 'answer' variable.
44-
Return ONLY the final value, no explanations or additional text.
61+
# Simulation prompt
62+
SIMULATION_PROMPT = '''
63+
The following Python code could not be executed after several attempts.
64+
Please simulate its execution and determine the final value that would be in the 'answer' variable.
4565
4666
Code to simulate:
67+
```python
4768
{code}
69+
```
70+
71+
Last error encountered:
72+
{error}
73+
74+
Important:
75+
1. Follow the logic of the code exactly
76+
2. Perform all calculations carefully
77+
3. Return ONLY the final numeric or string value, no explanations
78+
4. If the code contains semantic functions (like text analysis), use your judgment to simulate them
4879
'''
4980

5081
def extract_code_blocks(text: str) -> List[str]:
@@ -57,100 +88,168 @@ def extract_code_blocks(text: str) -> List[str]:
5788
logger.info(f"Code block {i+1}:\n{block}")
5889
return blocks
5990

60-
def extract_output(text: str) -> str:
61-
"""Extract content from output tags."""
62-
pattern = r'<output>(.*?)</output>'
63-
match = re.search(pattern, text, re.DOTALL)
64-
result = match.group(1).strip() if match else text.strip()
65-
logger.info(f"Extracted output: {result}")
66-
return result
67-
68-
def execute_code(code: str, client, model: str) -> Tuple[Any, int]:
69-
"""Execute full code block either with Python or LM simulation."""
70-
logger.info("Attempting to execute complete code block")
91+
def sanitize_code(code: str) -> str:
92+
"""Prepare code for execution by adding necessary imports and safety checks."""
93+
# Add standard imports
94+
imports = "\n".join(f"import {mod}" for mod in ALLOWED_MODULES)
95+
96+
# Add safety wrapper
97+
wrapper = f"""
98+
{imports}
99+
100+
def safe_execute():
101+
{code.replace('\n', '\n ')}
102+
return answer if 'answer' in locals() else None
103+
104+
result = safe_execute()
105+
answer = result
106+
"""
107+
return wrapper
108+
109+
def execute_code(code: str) -> Tuple[Any, str]:
110+
"""Attempt to execute the code and return result or error."""
111+
logger.info("Attempting to execute code")
71112
logger.info(f"Code:\n{code}")
72113

73-
# Add imports
74114
execution_env = {}
75-
for mod_name, mod in ALLOWED_MODULES.items():
76-
execution_env[mod_name] = mod
77-
78115
try:
79-
# Try executing the complete code block with Python
80-
logger.info("Attempting Python execution")
81-
exec(code, execution_env)
116+
sanitized_code = sanitize_code(code)
117+
exec(sanitized_code, execution_env)
82118
answer = execution_env.get('answer')
83-
logger.info(f"Python execution successful. Answer: {answer}")
84-
return answer, 0
85119

120+
if answer is not None:
121+
logger.info(f"Execution successful. Answer: {answer}")
122+
return answer, None
123+
else:
124+
error = "Code executed but did not produce an answer"
125+
logger.warning(error)
126+
return None, error
127+
86128
except Exception as e:
87-
logger.info(f"Python execution failed: {str(e)}")
88-
logger.info("Falling back to LM simulation")
89-
90-
# If Python execution fails, simulate with LM
91-
response = client.chat.completions.create(
92-
model=model,
93-
messages=[
94-
{"role": "system", "content": STATE_SIMULATION_PROMPT.format(code=code)},
95-
{"role": "user", "content": "Simulate this code and return the final value of 'answer'."}
96-
],
97-
temperature=0.2
98-
)
99-
129+
error = f"{type(e).__name__}: {str(e)}\n{traceback.format_exc()}"
130+
logger.error(f"Execution failed: {error}")
131+
return None, error
132+
133+
def generate_fixed_code(original_code: str, error: str, client, model: str) -> Tuple[str, int]:
134+
"""Ask LLM to fix the broken code."""
135+
logger.info("Requesting code fix from LLM")
136+
logger.info(f"Original error: {error}")
137+
138+
response = client.chat.completions.create(
139+
model=model,
140+
messages=[
141+
{"role": "system", "content": CODE_FIX_PROMPT.format(
142+
code=original_code, error=error)},
143+
{"role": "user", "content": "Fix the code to make it work."}
144+
],
145+
temperature=0.2
146+
)
147+
148+
fixed_code = response.choices[0].message.content
149+
code_blocks = extract_code_blocks(fixed_code)
150+
151+
if code_blocks:
152+
logger.info("Received fixed code from LLM")
153+
return code_blocks[0], response.usage.completion_tokens
154+
else:
155+
logger.warning("No code block found in LLM response")
156+
return None, response.usage.completion_tokens
157+
158+
def simulate_execution(code: str, error: str, client, model: str) -> Tuple[Any, int]:
159+
"""Ask LLM to simulate code execution."""
160+
logger.info("Attempting code simulation with LLM")
161+
162+
response = client.chat.completions.create(
163+
model=model,
164+
messages=[
165+
{"role": "system", "content": SIMULATION_PROMPT.format(
166+
code=code, error=error)},
167+
{"role": "user", "content": "Simulate this code and return the final answer value."}
168+
],
169+
temperature=0.2
170+
)
171+
172+
try:
173+
result = response.choices[0].message.content.strip()
174+
# Try to convert to appropriate type
100175
try:
101-
answer = response.choices[0].message.content.strip()
102-
logger.info(f"LM simulation successful. Answer: {answer}")
103-
104-
# Try to convert to number if possible
105-
try:
106-
answer = ast.literal_eval(answer)
107-
except:
108-
pass
109-
110-
return answer, response.usage.completion_tokens
111-
112-
except Exception as e:
113-
logger.error(f"Could not parse LM simulation response: {str(e)}")
114-
return None, response.usage.completion_tokens
176+
answer = ast.literal_eval(result)
177+
except:
178+
answer = result
179+
logger.info(f"Simulation successful. Result: {answer}")
180+
return answer, response.usage.completion_tokens
181+
except Exception as e:
182+
logger.error(f"Failed to parse simulation result: {str(e)}")
183+
return None, response.usage.completion_tokens
115184

116185
def run(system_prompt: str, initial_query: str, client, model: str) -> Tuple[str, int]:
117186
"""Main Chain of Code execution function."""
118187
logger.info("Starting Chain of Code execution")
119188
logger.info(f"Query: {initial_query}")
120189

190+
# Initial code generation
121191
messages = [
122192
{"role": "system", "content": system_prompt + "\n" + CHAIN_OF_CODE_PROMPT},
123193
{"role": "user", "content": initial_query}
124194
]
125195

126-
logger.info("Generating code solution")
127196
response = client.chat.completions.create(
128197
model=model,
129198
messages=messages,
130199
temperature=0.7
131200
)
132-
initial_response = response.choices[0].message.content
133201
total_tokens = response.usage.completion_tokens
134202

135-
logger.info("Initial response from LM:")
136-
logger.info(initial_response)
137-
138-
code_blocks = extract_code_blocks(initial_response)
203+
# Extract initial code
204+
code_blocks = extract_code_blocks(response.choices[0].message.content)
139205
if not code_blocks:
140206
logger.warning("No code blocks found in response")
141-
return initial_response, total_tokens
142-
143-
# Execute the complete code block
144-
code = code_blocks[0]
145-
answer, execution_tokens = execute_code(code, client, model)
146-
total_tokens += execution_tokens
207+
return response.choices[0].message.content, total_tokens
147208

148-
# If we got an answer from code execution, use it
149-
if answer is not None:
150-
final_answer = str(answer)
151-
else:
152-
# Fall back to output tags if code execution failed
153-
final_answer = extract_output(initial_response)
209+
current_code = code_blocks[0]
210+
fix_attempts = 0
211+
last_error = None
212+
213+
# Strategy 1: Direct execution and fix attempts
214+
while fix_attempts < MAX_FIX_ATTEMPTS:
215+
fix_attempts += 1
216+
logger.info(f"Execution attempt {fix_attempts}/{MAX_FIX_ATTEMPTS}")
217+
218+
# Try to execute current code
219+
answer, error = execute_code(current_code)
220+
221+
# If successful, return the answer
222+
if error is None:
223+
logger.info(f"Successful execution on attempt {fix_attempts}")
224+
return str(answer), total_tokens
154225

155-
logger.info(f"Chain of Code execution completed. Final answer: {final_answer}")
156-
return final_answer, total_tokens
226+
last_error = error
227+
228+
# If we hit max attempts, break to try simulation
229+
if fix_attempts >= MAX_FIX_ATTEMPTS:
230+
logger.warning(f"Failed after {fix_attempts} fix attempts")
231+
break
232+
233+
# Otherwise, try to get fixed code from LLM
234+
logger.info(f"Requesting code fix, attempt {fix_attempts}")
235+
fixed_code, fix_tokens = generate_fixed_code(current_code, error, client, model)
236+
total_tokens += fix_tokens
237+
238+
if fixed_code:
239+
current_code = fixed_code
240+
else:
241+
logger.error("Failed to get fixed code from LLM")
242+
break
243+
244+
# Strategy 2: If all execution attempts failed, try simulation
245+
logger.info("All execution attempts failed, trying simulation")
246+
simulated_answer, sim_tokens = simulate_execution(current_code, last_error, client, model)
247+
total_tokens += sim_tokens
248+
249+
if simulated_answer is not None:
250+
logger.info("Successfully got answer from simulation")
251+
return str(simulated_answer), total_tokens
252+
253+
# If we get here, everything failed
254+
logger.warning("All strategies failed")
255+
return f"Error: Could not solve problem after all attempts. Last error: {last_error}", total_tokens

0 commit comments

Comments
 (0)