Skip to content

Commit f18b921

Browse files
committed
add new chain of code approach
1 parent 45cbb23 commit f18b921

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed

optillm.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,10 @@ def proxy():
395395
model = data.get('model', server_config['model'])
396396

397397
optillm_approach = data.get('optillm_approach', server_config['approach'])
398+
logger.debug(data)
399+
server_config['mcts_depth'] = data.get('mcts_depth', server_config['mcts_depth'])
400+
server_config['mcts_exploration' ] = data.get('mcts_exploration', server_config['mcts_exploration'])
401+
server_config['mcts_simulations'] = data.get('mcts_simulations', server_config['mcts_simulations'])
398402

399403
system_prompt, initial_query, message_optillm_approach = parse_conversation(messages)
400404

optillm/plugins/coc_plugin.py

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import re
2+
import logging
3+
from typing import Tuple, Dict, Any, List
4+
import ast
5+
import traceback
6+
7+
logger = logging.getLogger(__name__)
8+
9+
# Plugin identifier
10+
SLUG = "coc"
11+
12+
# Prompts
13+
CHAIN_OF_CODE_PROMPT = '''
14+
You are an AI assistant that uses Chain of Code (CoC) approach to solve problems. Follow these steps:
15+
16+
1. Write Python code that breaks down the problem into clear steps
17+
2. Each step should either be:
18+
- Executable Python code that performs computations
19+
- Pseudocode that you will simulate with natural language understanding
20+
3. Track program state after each line execution
21+
4. Return the final answer within the <output> tags
22+
23+
Format your response using:
24+
```python
25+
[Your code here]
26+
```
27+
28+
And track state after each line with:
29+
delta_state: {...}
30+
31+
Finally provide output as:
32+
<output>
33+
[Your final answer]
34+
</output>
35+
'''
36+
37+
STATE_SIMULATION_PROMPT = '''You are simulating the execution of Python code.
38+
Given the current program state and a line of code, return ONLY a Python dictionary representing the new state variables.
39+
Do not include any other text, code blocks, or formatting - just the Python dict.
40+
41+
For example:
42+
state = {'x': 5}
43+
code = "y = x + 3"
44+
You should return:
45+
{'y': 8}
46+
'''
47+
48+
def extract_code_blocks(text: str) -> List[str]:
49+
"""Extract Python code blocks from text."""
50+
pattern = r'```python\s*(.*?)\s*```'
51+
matches = re.findall(pattern, text, re.DOTALL)
52+
return [m.strip() for m in matches]
53+
54+
def extract_output(text: str) -> str:
55+
"""Extract content from output tags."""
56+
pattern = r'<output>(.*?)</output>'
57+
match = re.search(pattern, text, re.DOTALL)
58+
return match.group(1).strip() if match else text.strip()
59+
60+
def extract_state_updates(text: str) -> List[Dict[str, Any]]:
61+
"""Extract state updates from delta_state markers."""
62+
pattern = r'delta_state:\s*({.*?})'
63+
matches = re.findall(pattern, text, re.DOTALL)
64+
states = []
65+
for m in matches:
66+
try:
67+
# Clean up the state string before evaluation
68+
cleaned = re.sub(r'```python\s*|\s*```', '', m)
69+
state = ast.literal_eval(cleaned)
70+
states.append(state)
71+
except:
72+
logger.warning(f"Could not parse state update: {m}")
73+
return states
74+
75+
def clean_state_response(response: str) -> str:
76+
"""Clean up LM state response to get just the dictionary."""
77+
# Remove any code blocks
78+
response = re.sub(r'```python\s*|\s*```', '', response)
79+
# Remove any natural language before or after the dict
80+
response = re.sub(r'^[^{]*', '', response)
81+
response = re.sub(r'[^}]*$', '', response)
82+
return response.strip()
83+
84+
def execute_line(line: str, state: Dict[str, Any], client, model: str) -> Tuple[Any, Dict[str, Any]]:
85+
"""Execute a single line of code, either with Python or LM simulation."""
86+
try:
87+
# Try executing with Python
88+
# Create a copy of state for local execution
89+
local_state = state.copy()
90+
exec(line, globals(), local_state)
91+
# Extract any new/modified variables
92+
new_state = {k:v for k,v in local_state.items()
93+
if k not in state or state[k] != v}
94+
return None, new_state
95+
except Exception as e:
96+
# If Python execution fails, simulate with LM
97+
context = f"Current program state: {state}\nExecute line: {line}"
98+
response = client.chat.completions.create(
99+
model=model,
100+
messages=[
101+
{"role": "system", "content": STATE_SIMULATION_PROMPT},
102+
{"role": "user", "content": context}
103+
],
104+
temperature=0.2
105+
)
106+
try:
107+
# Clean and parse LM response
108+
cleaned_response = clean_state_response(response.choices[0].message.content)
109+
new_state = ast.literal_eval(cleaned_response)
110+
return response.usage.completion_tokens, new_state
111+
except Exception as e:
112+
logger.error(f"Could not parse LM state response: {response.choices[0].message.content}")
113+
logger.error(f"Error: {str(e)}")
114+
logger.error(f"Cleaned response: {cleaned_response}")
115+
return response.usage.completion_tokens, {}
116+
117+
def run(system_prompt: str, initial_query: str, client, model: str) -> Tuple[str, int]:
118+
"""Main Chain of Code execution function."""
119+
# Generate initial code solution
120+
messages = [
121+
{"role": "system", "content": system_prompt + "\n" + CHAIN_OF_CODE_PROMPT},
122+
{"role": "user", "content": initial_query}
123+
]
124+
125+
response = client.chat.completions.create(
126+
model=model,
127+
messages=messages,
128+
temperature=0.7
129+
)
130+
initial_response = response.choices[0].message.content
131+
total_tokens = response.usage.completion_tokens
132+
133+
# Extract code blocks
134+
code_blocks = extract_code_blocks(initial_response)
135+
if not code_blocks:
136+
logger.warning("No code blocks found in response")
137+
return initial_response, total_tokens
138+
139+
# Execute code blocks line by line
140+
final_state = {}
141+
code = code_blocks[0] # Take first code block
142+
143+
# Split into lines and filter empty lines
144+
lines = [line.strip() for line in code.split('\n') if line.strip()]
145+
146+
for line in lines:
147+
if not line or line.startswith('#'):
148+
continue
149+
150+
tokens, new_state = execute_line(line, final_state, client, model)
151+
if tokens:
152+
total_tokens += tokens
153+
final_state.update(new_state)
154+
logger.debug(f"Executed line: {line}")
155+
logger.debug(f"New state: {new_state}")
156+
157+
# Extract output tags from the initial response, or use answer from state
158+
final_answer = extract_output(initial_response)
159+
if not final_answer and 'answer' in final_state:
160+
final_answer = str(final_state['answer'])
161+
162+
return final_answer, total_tokens

0 commit comments

Comments
 (0)