text2model 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- text2model/__init__.py +1 -0
- text2model/grammar.mzn +277 -0
- text2model/knowledge_graphs/CSPLib_12.ttl +41 -0
- text2model/knowledge_graphs/CSPLib_14.ttl +51 -0
- text2model/knowledge_graphs/CSPLib_2.ttl +59 -0
- text2model/knowledge_graphs/CSPLib_22.ttl +62 -0
- text2model/knowledge_graphs/CSPLib_28.ttl +28 -0
- text2model/knowledge_graphs/CSPLib_30.ttl +72 -0
- text2model/knowledge_graphs/CSPLib_34.ttl +52 -0
- text2model/knowledge_graphs/CSPLib_39.ttl +51 -0
- text2model/knowledge_graphs/CSPLib_54.ttl +50 -0
- text2model/knowledge_graphs/CSPLib_6.ttl +36 -0
- text2model/knowledge_graphs/CSPLib_8.ttl +53 -0
- text2model/knowledge_graphs/LPWP_128.ttl +79 -0
- text2model/knowledge_graphs/LPWP_232.ttl +95 -0
- text2model/knowledge_graphs/LPWP_53.ttl +58 -0
- text2model/knowledge_graphs/LPWP_66.ttl +52 -0
- text2model/knowledge_graphs/LPWP_85.ttl +95 -0
- text2model/knowledge_graphs/OR_LP_IP_Scheduling_problem_1.ttl +34 -0
- text2model/knowledge_graphs/OR_LP_IP_Scheduling_problem_18.ttl +59 -0
- text2model/knowledge_graphs/OR_LP_IP_Scheduling_problem_2.ttl +43 -0
- text2model/knowledge_graphs/OR_LP_IP_Scheduling_problem_28.ttl +42 -0
- text2model/knowledge_graphs/OR_LP_IP_Scheduling_problem_31.ttl +44 -0
- text2model/knowledge_graphs/OR_LP_IP_Scheduling_problem_4.ttl +48 -0
- text2model/knowledge_graphs/OR_LP_IP_Scheduling_problem_5.ttl +40 -0
- text2model/knowledge_graphs/OR_LP_IP_Scheduling_problem_6.ttl +61 -0
- text2model/knowledge_graphs/OR_LP_IP_Scheduling_problem_8.ttl +54 -0
- text2model/knowledge_graphs/combinatorial_problem_1.ttl +48 -0
- text2model/knowledge_graphs/combinatorial_problem_31.ttl +43 -0
- text2model/knowledge_graphs/combinatorial_problem_32.ttl +39 -0
- text2model/knowledge_graphs/combinatorial_problem_7.ttl +52 -0
- text2model/knowledge_graphs/complexor_AircraftAssignment.ttl +73 -0
- text2model/knowledge_graphs/complexor_AircraftLanding.ttl +53 -0
- text2model/knowledge_graphs/complexor_CFLP.ttl +43 -0
- text2model/knowledge_graphs/complexor_CapacitatedWarehouseLocation.ttl +59 -0
- text2model/knowledge_graphs/complexor_CarSelection.ttl +30 -0
- text2model/knowledge_graphs/complexor_TSP.ttl +52 -0
- text2model/knowledge_graphs/complexor_VRPTW.ttl +67 -0
- text2model/knowledge_graphs/nlp4lp_1.ttl +56 -0
- text2model/knowledge_graphs/nlp4lp_10.ttl +46 -0
- text2model/knowledge_graphs/nlp4lp_11.ttl +57 -0
- text2model/knowledge_graphs/nlp4lp_12.ttl +48 -0
- text2model/knowledge_graphs/nlp4lp_13.ttl +48 -0
- text2model/knowledge_graphs/nlp4lp_14.ttl +82 -0
- text2model/knowledge_graphs/nlp4lp_15.ttl +60 -0
- text2model/knowledge_graphs/nlp4lp_16.ttl +64 -0
- text2model/knowledge_graphs/nlp4lp_17.ttl +72 -0
- text2model/knowledge_graphs/nlp4lp_18.ttl +64 -0
- text2model/knowledge_graphs/nlp4lp_19.ttl +98 -0
- text2model/knowledge_graphs/nlp4lp_2.ttl +103 -0
- text2model/knowledge_graphs/nlp4lp_20.ttl +129 -0
- text2model/knowledge_graphs/nlp4lp_21.ttl +65 -0
- text2model/knowledge_graphs/nlp4lp_22.ttl +72 -0
- text2model/knowledge_graphs/nlp4lp_23.ttl +63 -0
- text2model/knowledge_graphs/nlp4lp_24.ttl +99 -0
- text2model/knowledge_graphs/nlp4lp_25.ttl +77 -0
- text2model/knowledge_graphs/nlp4lp_27.ttl +75 -0
- text2model/knowledge_graphs/nlp4lp_28.ttl +50 -0
- text2model/knowledge_graphs/nlp4lp_29.ttl +63 -0
- text2model/knowledge_graphs/nlp4lp_3.ttl +49 -0
- text2model/knowledge_graphs/nlp4lp_30.ttl +49 -0
- text2model/knowledge_graphs/nlp4lp_31.ttl +35 -0
- text2model/knowledge_graphs/nlp4lp_32.ttl +33 -0
- text2model/knowledge_graphs/nlp4lp_33.ttl +49 -0
- text2model/knowledge_graphs/nlp4lp_34.ttl +67 -0
- text2model/knowledge_graphs/nlp4lp_35.ttl +75 -0
- text2model/knowledge_graphs/nlp4lp_36.ttl +56 -0
- text2model/knowledge_graphs/nlp4lp_37.ttl +52 -0
- text2model/knowledge_graphs/nlp4lp_38.ttl +55 -0
- text2model/knowledge_graphs/nlp4lp_39.ttl +58 -0
- text2model/knowledge_graphs/nlp4lp_4.ttl +64 -0
- text2model/knowledge_graphs/nlp4lp_40.ttl +49 -0
- text2model/knowledge_graphs/nlp4lp_41.ttl +62 -0
- text2model/knowledge_graphs/nlp4lp_42.ttl +49 -0
- text2model/knowledge_graphs/nlp4lp_43.ttl +98 -0
- text2model/knowledge_graphs/nlp4lp_44.ttl +41 -0
- text2model/knowledge_graphs/nlp4lp_45.ttl +56 -0
- text2model/knowledge_graphs/nlp4lp_46.ttl +35 -0
- text2model/knowledge_graphs/nlp4lp_47.ttl +68 -0
- text2model/knowledge_graphs/nlp4lp_48.ttl +74 -0
- text2model/knowledge_graphs/nlp4lp_49.ttl +66 -0
- text2model/knowledge_graphs/nlp4lp_5.ttl +69 -0
- text2model/knowledge_graphs/nlp4lp_50.ttl +51 -0
- text2model/knowledge_graphs/nlp4lp_51.ttl +53 -0
- text2model/knowledge_graphs/nlp4lp_52.ttl +51 -0
- text2model/knowledge_graphs/nlp4lp_53.ttl +55 -0
- text2model/knowledge_graphs/nlp4lp_54.ttl +74 -0
- text2model/knowledge_graphs/nlp4lp_55.ttl +50 -0
- text2model/knowledge_graphs/nlp4lp_56.ttl +67 -0
- text2model/knowledge_graphs/nlp4lp_57.ttl +59 -0
- text2model/knowledge_graphs/nlp4lp_58.ttl +65 -0
- text2model/knowledge_graphs/nlp4lp_6.ttl +63 -0
- text2model/knowledge_graphs/nlp4lp_60.ttl +36 -0
- text2model/knowledge_graphs/nlp4lp_61.ttl +83 -0
- text2model/knowledge_graphs/nlp4lp_62.ttl +44 -0
- text2model/knowledge_graphs/nlp4lp_63.ttl +49 -0
- text2model/knowledge_graphs/nlp4lp_64.ttl +41 -0
- text2model/knowledge_graphs/nlp4lp_65.ttl +78 -0
- text2model/knowledge_graphs/nlp4lp_66.ttl +51 -0
- text2model/knowledge_graphs/nlp4lp_67.ttl +40 -0
- text2model/knowledge_graphs/nlp4lp_7.ttl +53 -0
- text2model/knowledge_graphs/nlp4lp_8.ttl +51 -0
- text2model/knowledge_graphs/nlp4lp_9.ttl +58 -0
- text2model/knowledge_graphs/non_linear_problem_10.ttl +57 -0
- text2model/knowledge_graphs/non_linear_problem_15.ttl +55 -0
- text2model/knowledge_graphs/non_linear_problem_23.ttl +42 -0
- text2model/knowledge_graphs/non_linear_problem_9.ttl +61 -0
- text2model/knowledge_graphs/puzzles_problem_1.ttl +64 -0
- text2model/knowledge_graphs/puzzles_problem_11.ttl +65 -0
- text2model/knowledge_graphs/puzzles_problem_12.ttl +79 -0
- text2model/knowledge_graphs/puzzles_problem_13.ttl +50 -0
- text2model/knowledge_graphs/puzzles_problem_31.ttl +62 -0
- text2model/main.py +771 -0
- text2model/prompts/assembler_prompt.txt +104 -0
- text2model/prompts/code_stitching_prompt.txt +49 -0
- text2model/prompts/code_validation_prompt.txt +36 -0
- text2model/prompts/constraint_generation_prompt.txt +35 -0
- text2model/prompts/cot_prompt.txt +45 -0
- text2model/prompts/global_constraint_prompts/all_different_prompt.txt +67 -0
- text2model/prompts/global_constraint_prompts/count_prompt.txt +75 -0
- text2model/prompts/global_constraint_prompts/cumulative_prompt.txt +88 -0
- text2model/prompts/global_constraint_prompts/global_cardinality_prompt.txt +76 -0
- text2model/prompts/global_constraint_prompts/increasing_prompt.txt +81 -0
- text2model/prompts/global_constraint_prompts/lex_less_prompt.txt +68 -0
- text2model/prompts/grammar_validation_prompt.txt +18 -0
- text2model/prompts/kg_code_generation_prompt.txt +20 -0
- text2model/prompts/kg_generation_prompt.txt +40 -0
- text2model/prompts/objective_generation_prompt.txt +34 -0
- text2model/prompts/parameter_and_variable_generation_prompt.txt +35 -0
- text2model/utils.py +350 -0
- text2model-0.1.0.dist-info/METADATA +221 -0
- text2model-0.1.0.dist-info/RECORD +135 -0
- text2model-0.1.0.dist-info/WHEEL +5 -0
- text2model-0.1.0.dist-info/entry_points.txt +2 -0
- text2model-0.1.0.dist-info/top_level.txt +1 -0
text2model/main.py
ADDED
|
@@ -0,0 +1,771 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import ast
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
import tempfile
|
|
7
|
+
import time
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
import openai
|
|
11
|
+
from datasets import DatasetDict, load_dataset
|
|
12
|
+
from langchain_ollama import ChatOllama
|
|
13
|
+
from tqdm import tqdm
|
|
14
|
+
|
|
15
|
+
from text2model import utils
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
###########################################################
|
|
19
|
+
# Single-call Strategy
|
|
20
|
+
###########################################################
|
|
21
|
+
def run_baseline_strategy(client, model, problem, problem_identifier, output_dir):
|
|
22
|
+
"""Run the baseline single-prompt strategy"""
|
|
23
|
+
try:
|
|
24
|
+
prompt = utils.create_baseline_prompt(problem)
|
|
25
|
+
solution = utils.call_api(client, model, prompt)
|
|
26
|
+
|
|
27
|
+
if solution:
|
|
28
|
+
utils.save_solution(output_dir, problem_identifier, solution)
|
|
29
|
+
return True
|
|
30
|
+
return False
|
|
31
|
+
except Exception as e:
|
|
32
|
+
print(f"Error in baseline strategy for problem {problem_identifier}: {e}")
|
|
33
|
+
return False
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
###########################################################
|
|
37
|
+
# Two-call Strategies
|
|
38
|
+
###########################################################
|
|
39
|
+
def run_knowledge_graph_strategy(client, model, problem, problem_identifier, output_dir):
|
|
40
|
+
"""Run the strategy using knowledge graphs"""
|
|
41
|
+
try:
|
|
42
|
+
kg_path = utils._resolve_path(f"knowledge_graphs/{problem_identifier}.ttl")
|
|
43
|
+
if not kg_path.exists():
|
|
44
|
+
print(f"Knowledge graph not found for problem {problem_identifier}")
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
problem_data = utils.prepare_problem_data(problem)
|
|
48
|
+
effective_input_data = utils.get_effective_input_data(problem_data)
|
|
49
|
+
knowledge_graph = utils.load_file(str(kg_path))
|
|
50
|
+
|
|
51
|
+
kg_prompt = utils.load_file('prompts/kg_code_generation_prompt.txt')
|
|
52
|
+
prompt = kg_prompt.format(
|
|
53
|
+
problem_description=problem_data['description'],
|
|
54
|
+
knowledge_graph=knowledge_graph,
|
|
55
|
+
input_data=effective_input_data
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
solution = utils.call_api(client, model, prompt)
|
|
59
|
+
|
|
60
|
+
if solution:
|
|
61
|
+
utils.save_solution(output_dir, problem_identifier, solution)
|
|
62
|
+
return True
|
|
63
|
+
return False
|
|
64
|
+
|
|
65
|
+
except Exception as e:
|
|
66
|
+
print(f"Error in knowledge graph strategy for problem {problem_identifier}: {e}")
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def run_cot_with_code_validation_strategy(client, model, problem, problem_identifier, output_dir):
|
|
71
|
+
"""Run the cot strategy with conditional code validation (only if compilation fails)"""
|
|
72
|
+
try:
|
|
73
|
+
problem_data = utils.prepare_problem_data(problem)
|
|
74
|
+
effective_input_data = utils.get_effective_input_data(problem_data)
|
|
75
|
+
|
|
76
|
+
cot_prompt = utils.load_file('prompts/cot_prompt.txt')
|
|
77
|
+
initial_code = utils.call_api(
|
|
78
|
+
client,
|
|
79
|
+
model,
|
|
80
|
+
cot_prompt.format(
|
|
81
|
+
problem_description=problem_data['description'],
|
|
82
|
+
input_data=effective_input_data
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
if not initial_code:
|
|
87
|
+
return False
|
|
88
|
+
|
|
89
|
+
current_code = initial_code
|
|
90
|
+
|
|
91
|
+
dzn_data = problem.get('data.dzn') or ""
|
|
92
|
+
syntax_error_message = utils.check_syntax(initial_code, dzn_data)
|
|
93
|
+
|
|
94
|
+
if syntax_error_message:
|
|
95
|
+
time.sleep(2)
|
|
96
|
+
|
|
97
|
+
validation_prompt = utils.load_file('prompts/code_validation_prompt.txt')
|
|
98
|
+
validated_code = utils.call_api(
|
|
99
|
+
client,
|
|
100
|
+
model,
|
|
101
|
+
validation_prompt.format(
|
|
102
|
+
problem_description=problem_data['description'],
|
|
103
|
+
input_data=effective_input_data,
|
|
104
|
+
objective_type=problem_data['objective_type'],
|
|
105
|
+
final_code=initial_code,
|
|
106
|
+
syntax_error_message=syntax_error_message
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
if validated_code:
|
|
111
|
+
current_code = validated_code
|
|
112
|
+
|
|
113
|
+
utils.save_solution(output_dir, problem_identifier, current_code)
|
|
114
|
+
return True
|
|
115
|
+
|
|
116
|
+
except Exception as e:
|
|
117
|
+
print(f"Error in two-stage strategy for problem {problem_identifier}: {e}")
|
|
118
|
+
return False
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def run_cot_strategy(client, model, problem, problem_identifier, output_dir):
|
|
122
|
+
"""Run the Chain of Thought strategy (single-stage)"""
|
|
123
|
+
try:
|
|
124
|
+
problem_data = utils.prepare_problem_data(problem)
|
|
125
|
+
effective_input_data = utils.get_effective_input_data(problem_data)
|
|
126
|
+
|
|
127
|
+
cot_prompt = utils.load_file('prompts/cot_prompt.txt')
|
|
128
|
+
code = utils.call_api(
|
|
129
|
+
client,
|
|
130
|
+
model,
|
|
131
|
+
cot_prompt.format(
|
|
132
|
+
problem_description=problem_data['description'],
|
|
133
|
+
input_data=effective_input_data
|
|
134
|
+
)
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
if not code:
|
|
138
|
+
return False
|
|
139
|
+
|
|
140
|
+
utils.save_solution(output_dir, problem_identifier, code)
|
|
141
|
+
return True
|
|
142
|
+
|
|
143
|
+
except Exception as e:
|
|
144
|
+
print(f"Error in CoT strategy for problem {problem_identifier}: {e}")
|
|
145
|
+
return False
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def run_cot_with_grammar_validation_strategy(client, model, problem, problem_identifier, output_dir):
|
|
149
|
+
"""Run the CoT + Grammar Validation strategy (2-stage)"""
|
|
150
|
+
try:
|
|
151
|
+
problem_data = utils.prepare_problem_data(problem)
|
|
152
|
+
effective_input_data = utils.get_effective_input_data(problem_data)
|
|
153
|
+
|
|
154
|
+
cot_prompt = utils.load_file('prompts/cot_prompt.txt')
|
|
155
|
+
initial_code = utils.call_api(
|
|
156
|
+
client,
|
|
157
|
+
model,
|
|
158
|
+
cot_prompt.format(
|
|
159
|
+
problem_description=problem_data['description'],
|
|
160
|
+
input_data=effective_input_data
|
|
161
|
+
)
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
if not initial_code:
|
|
165
|
+
return False
|
|
166
|
+
|
|
167
|
+
time.sleep(2)
|
|
168
|
+
|
|
169
|
+
current_code = initial_code
|
|
170
|
+
|
|
171
|
+
dzn_data = problem.get('data.dzn') or ""
|
|
172
|
+
syntax_error_message = utils.check_syntax(initial_code, dzn_data)
|
|
173
|
+
|
|
174
|
+
if syntax_error_message:
|
|
175
|
+
grammar_prompt = utils.load_file('prompts/grammar_validation_prompt.txt')
|
|
176
|
+
minizinc_grammar = utils.load_file('grammar.mzn')
|
|
177
|
+
|
|
178
|
+
grammar_corrected_code = utils.call_api(
|
|
179
|
+
client,
|
|
180
|
+
model,
|
|
181
|
+
grammar_prompt.format(
|
|
182
|
+
problem_description=problem_data['description'],
|
|
183
|
+
input_data=effective_input_data,
|
|
184
|
+
current_code=current_code,
|
|
185
|
+
syntax_error_message=syntax_error_message,
|
|
186
|
+
minizinc_grammar=minizinc_grammar
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
if grammar_corrected_code:
|
|
191
|
+
current_code = grammar_corrected_code
|
|
192
|
+
|
|
193
|
+
utils.save_solution(output_dir, problem_identifier, current_code)
|
|
194
|
+
return True
|
|
195
|
+
|
|
196
|
+
except Exception as e:
|
|
197
|
+
print(f"Error in CoT + Grammar Check strategy for problem {problem_identifier}: {e}")
|
|
198
|
+
return False
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
###########################################################
|
|
202
|
+
# Three-call Strategies
|
|
203
|
+
###########################################################
|
|
204
|
+
def run_cot_with_code_and_grammar_validation_strategy(client, model, problem, problem_identifier, output_dir):
|
|
205
|
+
"""Run the CoT + Code Validation + Grammar Validation strategy (3-stage)"""
|
|
206
|
+
try:
|
|
207
|
+
problem_data = utils.prepare_problem_data(problem)
|
|
208
|
+
effective_input_data = utils.get_effective_input_data(problem_data)
|
|
209
|
+
|
|
210
|
+
cot_prompt = utils.load_file('prompts/cot_prompt.txt')
|
|
211
|
+
initial_code = utils.call_api(
|
|
212
|
+
client,
|
|
213
|
+
model,
|
|
214
|
+
cot_prompt.format(
|
|
215
|
+
problem_description=problem_data['description'],
|
|
216
|
+
input_data=effective_input_data
|
|
217
|
+
)
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
if not initial_code:
|
|
221
|
+
return False
|
|
222
|
+
|
|
223
|
+
time.sleep(2)
|
|
224
|
+
|
|
225
|
+
current_code = initial_code
|
|
226
|
+
|
|
227
|
+
dzn_data = problem.get('data.dzn') or ""
|
|
228
|
+
syntax_error_message = utils.check_syntax(initial_code, dzn_data)
|
|
229
|
+
|
|
230
|
+
if syntax_error_message:
|
|
231
|
+
validation_prompt = utils.load_file('prompts/code_validation_prompt.txt')
|
|
232
|
+
validated_code = utils.call_api(
|
|
233
|
+
client,
|
|
234
|
+
model,
|
|
235
|
+
validation_prompt.format(
|
|
236
|
+
problem_description=problem_data['description'],
|
|
237
|
+
input_data=effective_input_data,
|
|
238
|
+
objective_type=problem_data['objective_type'],
|
|
239
|
+
final_code=initial_code,
|
|
240
|
+
syntax_error_message=syntax_error_message
|
|
241
|
+
)
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
if validated_code:
|
|
245
|
+
current_code = validated_code
|
|
246
|
+
dzn_data2 = problem.get('data.dzn') or ""
|
|
247
|
+
syntax_error_message = utils.check_syntax(validated_code, dzn_data2)
|
|
248
|
+
|
|
249
|
+
time.sleep(2)
|
|
250
|
+
|
|
251
|
+
if syntax_error_message:
|
|
252
|
+
grammar_prompt = utils.load_file('prompts/grammar_validation_prompt.txt')
|
|
253
|
+
minizinc_grammar = utils.load_file('grammar.mzn')
|
|
254
|
+
|
|
255
|
+
grammar_corrected_code = utils.call_api(
|
|
256
|
+
client,
|
|
257
|
+
model,
|
|
258
|
+
grammar_prompt.format(
|
|
259
|
+
problem_description=problem_data['description'],
|
|
260
|
+
input_data=effective_input_data,
|
|
261
|
+
current_code=current_code,
|
|
262
|
+
syntax_error_message=syntax_error_message,
|
|
263
|
+
minizinc_grammar=minizinc_grammar
|
|
264
|
+
)
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
if grammar_corrected_code:
|
|
268
|
+
current_code = grammar_corrected_code
|
|
269
|
+
|
|
270
|
+
utils.save_solution(output_dir, problem_identifier, current_code)
|
|
271
|
+
return True
|
|
272
|
+
|
|
273
|
+
except Exception as e:
|
|
274
|
+
print(f"Error in CoT + Validation + Grammar Check strategy for problem {problem_identifier}: {e}")
|
|
275
|
+
return False
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
###########################################################
|
|
279
|
+
# Four and Five-call Strategies
|
|
280
|
+
###########################################################
|
|
281
|
+
def run_agents_strategy(client, model, problem, problem_identifier, output_dir, validate=True):
|
|
282
|
+
"""Run the agents strategy"""
|
|
283
|
+
try:
|
|
284
|
+
problem_data = utils.prepare_problem_data(problem)
|
|
285
|
+
effective_input_data = utils.get_effective_input_data(problem_data)
|
|
286
|
+
|
|
287
|
+
param_prompt = utils.load_file('prompts/parameter_and_variable_generation_prompt.txt')
|
|
288
|
+
params_vars = utils.call_api(
|
|
289
|
+
client,
|
|
290
|
+
model,
|
|
291
|
+
param_prompt.format(
|
|
292
|
+
problem_description=problem_data['description'],
|
|
293
|
+
input_data=effective_input_data
|
|
294
|
+
)
|
|
295
|
+
)
|
|
296
|
+
if not params_vars:
|
|
297
|
+
return False
|
|
298
|
+
time.sleep(2)
|
|
299
|
+
|
|
300
|
+
constraint_prompt = utils.load_file('prompts/constraint_generation_prompt.txt')
|
|
301
|
+
constraints = utils.call_api(
|
|
302
|
+
client,
|
|
303
|
+
model,
|
|
304
|
+
constraint_prompt.format(
|
|
305
|
+
problem_description=problem_data['description'],
|
|
306
|
+
input_data=effective_input_data,
|
|
307
|
+
parameters_and_variables=params_vars
|
|
308
|
+
)
|
|
309
|
+
)
|
|
310
|
+
if not constraints:
|
|
311
|
+
return False
|
|
312
|
+
time.sleep(2)
|
|
313
|
+
|
|
314
|
+
objective_prompt = utils.load_file('prompts/objective_generation_prompt.txt')
|
|
315
|
+
objective = utils.call_api(
|
|
316
|
+
client,
|
|
317
|
+
model,
|
|
318
|
+
objective_prompt.format(
|
|
319
|
+
problem_description=problem_data['description'],
|
|
320
|
+
input_data=effective_input_data,
|
|
321
|
+
parameters_and_variables=params_vars,
|
|
322
|
+
constraints=constraints
|
|
323
|
+
)
|
|
324
|
+
)
|
|
325
|
+
if not objective:
|
|
326
|
+
return False
|
|
327
|
+
time.sleep(2)
|
|
328
|
+
|
|
329
|
+
code_prompt = utils.load_file('prompts/code_stitching_prompt.txt')
|
|
330
|
+
final_code = utils.call_api(
|
|
331
|
+
client,
|
|
332
|
+
model,
|
|
333
|
+
code_prompt.format(
|
|
334
|
+
problem_description=problem_data['description'],
|
|
335
|
+
input_data=effective_input_data,
|
|
336
|
+
parameters_and_variables=params_vars,
|
|
337
|
+
constraints=constraints,
|
|
338
|
+
objective=objective
|
|
339
|
+
)
|
|
340
|
+
)
|
|
341
|
+
if not final_code:
|
|
342
|
+
return False
|
|
343
|
+
|
|
344
|
+
dzn_data = problem.get('data.dzn') or ""
|
|
345
|
+
syntax_error_message = utils.check_syntax(final_code, dzn_data)
|
|
346
|
+
|
|
347
|
+
if syntax_error_message and validate:
|
|
348
|
+
time.sleep(2)
|
|
349
|
+
validation_prompt = utils.load_file('prompts/code_validation_prompt.txt')
|
|
350
|
+
validated_code = utils.call_api(
|
|
351
|
+
client,
|
|
352
|
+
model,
|
|
353
|
+
validation_prompt.format(
|
|
354
|
+
problem_description=problem_data['description'],
|
|
355
|
+
input_data=effective_input_data,
|
|
356
|
+
objective_type=problem_data['objective_type'],
|
|
357
|
+
final_code=final_code,
|
|
358
|
+
syntax_error_message=syntax_error_message
|
|
359
|
+
)
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
if validated_code:
|
|
363
|
+
utils.save_solution(output_dir, problem_identifier, validated_code)
|
|
364
|
+
return True
|
|
365
|
+
return False
|
|
366
|
+
else:
|
|
367
|
+
utils.save_solution(output_dir, problem_identifier, final_code)
|
|
368
|
+
return True
|
|
369
|
+
|
|
370
|
+
except Exception as e:
|
|
371
|
+
print(f"Error in agents strategy for problem {problem_identifier}: {e}")
|
|
372
|
+
return False
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
###########################################################
|
|
376
|
+
# Global Agentic (GALA) Strategies
|
|
377
|
+
###########################################################
|
|
378
|
+
def run_gala_strategy(client, model, problem, problem_identifier, output_dir):
|
|
379
|
+
"""Run the gala strategy (workers -> assembler)"""
|
|
380
|
+
try:
|
|
381
|
+
problem_data = utils.prepare_problem_data(problem)
|
|
382
|
+
effective_input_data = utils.get_effective_input_data(problem_data)
|
|
383
|
+
|
|
384
|
+
hints = ""
|
|
385
|
+
|
|
386
|
+
prompt_dir = utils._resolve_path("prompts/global_constraint_prompts")
|
|
387
|
+
for prompt in prompt_dir.glob("*.txt"):
|
|
388
|
+
ind_prompt = utils.load_file(str(prompt))
|
|
389
|
+
ind_prompt = ind_prompt + f"""
|
|
390
|
+
**Problem description**:
|
|
391
|
+
{problem_data['description']}
|
|
392
|
+
|
|
393
|
+
**Input data**:
|
|
394
|
+
{effective_input_data}
|
|
395
|
+
"""
|
|
396
|
+
|
|
397
|
+
code = utils.call_api(client, model, ind_prompt)
|
|
398
|
+
code = utils.extract_global_constraint(ind_prompt) + ": \n" + code + "\n"
|
|
399
|
+
if "FALSE" not in code:
|
|
400
|
+
hints += code
|
|
401
|
+
|
|
402
|
+
assembler_prompt = utils.load_file('prompts/assembler_prompt.txt')
|
|
403
|
+
assembler_prompt = assembler_prompt + f"""
|
|
404
|
+
**Problem description**:
|
|
405
|
+
{problem_data['description']}
|
|
406
|
+
|
|
407
|
+
**Input data**:
|
|
408
|
+
{effective_input_data}
|
|
409
|
+
|
|
410
|
+
**Hints**:
|
|
411
|
+
{hints}
|
|
412
|
+
"""
|
|
413
|
+
|
|
414
|
+
code = utils.call_api(client, model, assembler_prompt)
|
|
415
|
+
|
|
416
|
+
if not code:
|
|
417
|
+
return False
|
|
418
|
+
|
|
419
|
+
utils.save_solution(output_dir, problem_identifier, code)
|
|
420
|
+
return True
|
|
421
|
+
|
|
422
|
+
except Exception as e:
|
|
423
|
+
print(f"Error in gala strategy for problem {problem_identifier}: {e}")
|
|
424
|
+
return False
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
###########################################################
|
|
428
|
+
# Helpers
|
|
429
|
+
###########################################################
|
|
430
|
+
def check_already_processed(output_dir, problem_identifier):
|
|
431
|
+
"""Check if a problem has already been successfully processed"""
|
|
432
|
+
solution_path = os.path.join(output_dir, f"{problem_identifier}.mzn")
|
|
433
|
+
return os.path.exists(solution_path) and os.path.getsize(solution_path) > 0
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
_STRATEGY_MAP = {
|
|
437
|
+
'baseline': run_baseline_strategy,
|
|
438
|
+
'cot': run_cot_strategy,
|
|
439
|
+
'knowledge_graph': run_knowledge_graph_strategy,
|
|
440
|
+
'cot_with_code_validation': run_cot_with_code_validation_strategy,
|
|
441
|
+
'cot_with_grammar_validation': run_cot_with_grammar_validation_strategy,
|
|
442
|
+
'cot_with_code_and_grammar_validation': run_cot_with_code_and_grammar_validation_strategy,
|
|
443
|
+
'agents': lambda c, m, p, i, o: run_agents_strategy(c, m, p, i, o, validate=False),
|
|
444
|
+
'agents_with_code_validation': run_agents_strategy,
|
|
445
|
+
'gala': run_gala_strategy,
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def _init_client(args):
|
|
450
|
+
"""Create and configure the LLM client from parsed args."""
|
|
451
|
+
if args.model in ["gpt-4", "gpt-4o", "gpt-5.2"]:
|
|
452
|
+
if not args.api_key:
|
|
453
|
+
raise ValueError(
|
|
454
|
+
"OpenAI API key not provided. "
|
|
455
|
+
"Set OPENAI_API_KEY environment variable or use --api-key"
|
|
456
|
+
)
|
|
457
|
+
client = openai.OpenAI(api_key=args.api_key)
|
|
458
|
+
utils.API_CONFIG['temperature'] = args.temperature
|
|
459
|
+
utils.API_CONFIG['max_tokens'] = args.max_tokens
|
|
460
|
+
utils.API_CONFIG['sleep_time'] = args.sleep_time
|
|
461
|
+
utils.API_CONFIG['model'] = args.model
|
|
462
|
+
else:
|
|
463
|
+
client = ChatOllama(
|
|
464
|
+
model=args.model,
|
|
465
|
+
temperature=args.temperature,
|
|
466
|
+
num_predict=args.max_tokens,
|
|
467
|
+
)
|
|
468
|
+
return client
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def _run_problem_mode(args, client):
|
|
472
|
+
"""Handle --problem mode: generate MiniZinc from a single problem description."""
|
|
473
|
+
# Accept a file path or a literal description string
|
|
474
|
+
problem_text = args.problem
|
|
475
|
+
if os.path.isfile(problem_text):
|
|
476
|
+
with open(problem_text, 'r') as f:
|
|
477
|
+
problem_text = f.read()
|
|
478
|
+
|
|
479
|
+
problem = utils.create_problem_from_text(problem_text)
|
|
480
|
+
|
|
481
|
+
# Use the first requested strategy; default to 'cot'
|
|
482
|
+
strategy = (args.strategies or ['cot'])[0]
|
|
483
|
+
|
|
484
|
+
if strategy == 'knowledge_graph':
|
|
485
|
+
print(
|
|
486
|
+
"Warning: 'knowledge_graph' strategy requires pre-built TTL files. "
|
|
487
|
+
"Falling back to 'cot'.",
|
|
488
|
+
file=sys.stderr,
|
|
489
|
+
)
|
|
490
|
+
strategy = 'cot'
|
|
491
|
+
|
|
492
|
+
strategy_fn = _STRATEGY_MAP[strategy]
|
|
493
|
+
|
|
494
|
+
print(f"Generating MiniZinc model using strategy '{strategy}' with model '{args.model}'...",
|
|
495
|
+
file=sys.stderr)
|
|
496
|
+
|
|
497
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
498
|
+
success = strategy_fn(client, args.model, problem, 'output', tmpdir)
|
|
499
|
+
if success:
|
|
500
|
+
output_path = os.path.join(tmpdir, 'output.mzn')
|
|
501
|
+
with open(output_path) as f:
|
|
502
|
+
code = f.read()
|
|
503
|
+
print(code)
|
|
504
|
+
else:
|
|
505
|
+
print("Failed to generate MiniZinc code.", file=sys.stderr)
|
|
506
|
+
sys.exit(1)
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
###########################################################
|
|
510
|
+
# Entry point
|
|
511
|
+
###########################################################
|
|
512
|
+
def main():
|
|
513
|
+
parser = argparse.ArgumentParser(
|
|
514
|
+
prog='text2model',
|
|
515
|
+
description=(
|
|
516
|
+
'text2model: turn a natural-language optimization problem description '
|
|
517
|
+
'into a MiniZinc constraint model using an LLM.\n\n'
|
|
518
|
+
'Two modes:\n'
|
|
519
|
+
' 1) Single problem - pass --problem to translate one description and\n'
|
|
520
|
+
' print the generated .mzn code to stdout.\n'
|
|
521
|
+
' 2) Batch - omit --problem to run one or more prompting\n'
|
|
522
|
+
' strategies over the skadio/text2zinc benchmark dataset.'
|
|
523
|
+
),
|
|
524
|
+
epilog=(
|
|
525
|
+
'Examples:\n'
|
|
526
|
+
' # Translate a problem description given directly on the command line\n'
|
|
527
|
+
' text2model --problem "Pack items of given weights into the fewest bins "\\\n'
|
|
528
|
+
' "of capacity 10." --model gpt-4o --api-key sk-...\n\n'
|
|
529
|
+
' # Translate a problem description stored in a file\n'
|
|
530
|
+
' text2model --problem problem.txt --model gpt-4o\n\n'
|
|
531
|
+
' # List the sources available in the benchmark dataset\n'
|
|
532
|
+
' text2model --list-sources\n\n'
|
|
533
|
+
' # Batch-run the chain-of-thought strategy over one source\n'
|
|
534
|
+
' text2model --strategies cot --source "csplib" --output-dir results/\n\n'
|
|
535
|
+
'The OpenAI API key can also be set via the OPENAI_API_KEY environment '
|
|
536
|
+
'variable. Local models (e.g. phi4) are served through Ollama and need '
|
|
537
|
+
'no API key.'
|
|
538
|
+
),
|
|
539
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
# ── Simple single-problem mode ──────────────────────────────────────────
|
|
543
|
+
parser.add_argument(
|
|
544
|
+
'--problem', type=str, default=None,
|
|
545
|
+
help='Problem description string, or path to a .txt file containing the description. '
|
|
546
|
+
'When provided, generates MiniZinc code and prints it to stdout.'
|
|
547
|
+
)
|
|
548
|
+
|
|
549
|
+
# ── Model / API ─────────────────────────────────────────────────────────
|
|
550
|
+
parser.add_argument('--model', default='gpt-4',
|
|
551
|
+
choices=['gpt-4', 'gpt-4o', 'gpt-5.2', 'phi4'],
|
|
552
|
+
help='LLM model to use')
|
|
553
|
+
parser.add_argument('--api-key', default=os.getenv('OPENAI_API_KEY'),
|
|
554
|
+
help='OpenAI API key')
|
|
555
|
+
parser.add_argument('--temperature', type=float, default=0,
|
|
556
|
+
help='Temperature for API calls')
|
|
557
|
+
parser.add_argument('--max-tokens', type=int, default=4096,
|
|
558
|
+
help='Max tokens for API calls')
|
|
559
|
+
parser.add_argument('--sleep-time', type=float, default=3,
|
|
560
|
+
help='Sleep time between API calls')
|
|
561
|
+
|
|
562
|
+
# ── Strategy ────────────────────────────────────────────────────────────
|
|
563
|
+
parser.add_argument(
|
|
564
|
+
'--strategies', nargs='+',
|
|
565
|
+
default=['cot'],
|
|
566
|
+
choices=[
|
|
567
|
+
'baseline', 'cot', 'knowledge_graph',
|
|
568
|
+
'cot_with_code_validation', 'cot_with_grammar_validation',
|
|
569
|
+
'cot_with_code_and_grammar_validation',
|
|
570
|
+
'agents', 'agents_with_code_validation', 'gala', 'all',
|
|
571
|
+
],
|
|
572
|
+
help='Strategy (or strategies for batch mode). '
|
|
573
|
+
'In --problem mode only the first strategy is used; default is cot.'
|
|
574
|
+
)
|
|
575
|
+
|
|
576
|
+
# ── Batch-mode dataset arguments ────────────────────────────────────────
|
|
577
|
+
parser.add_argument('--problem-ids', nargs='+', type=int,
|
|
578
|
+
help='Specific problem IDs to process (batch mode)')
|
|
579
|
+
parser.add_argument('--source', type=str, nargs='*', default=None,
|
|
580
|
+
help='Filter problems by source (batch mode). Supports partial matching.')
|
|
581
|
+
parser.add_argument('--list-sources', action='store_true',
|
|
582
|
+
help='List all available sources in the dataset and exit')
|
|
583
|
+
parser.add_argument('--include-unverified', action='store_true',
|
|
584
|
+
help='Include unverified problems (batch mode)')
|
|
585
|
+
parser.add_argument('--all-sources', action='store_true',
|
|
586
|
+
help='Run on all sources (batch mode)')
|
|
587
|
+
parser.add_argument('--output-dir', default=None,
|
|
588
|
+
help='Base output directory for batch mode (must not already exist)')
|
|
589
|
+
|
|
590
|
+
args = parser.parse_args()
|
|
591
|
+
|
|
592
|
+
# ── --problem mode: skip dataset loading ────────────────────────────────
|
|
593
|
+
if args.problem:
|
|
594
|
+
client = _init_client(args)
|
|
595
|
+
_run_problem_mode(args, client)
|
|
596
|
+
return
|
|
597
|
+
|
|
598
|
+
# ── Batch mode ───────────────────────────────────────────────────────────
|
|
599
|
+
print("Loading dataset...")
|
|
600
|
+
dataset = load_dataset("skadio/text2zinc")
|
|
601
|
+
|
|
602
|
+
if args.include_unverified:
|
|
603
|
+
print("Including ALL problems (verified and unverified)")
|
|
604
|
+
filtered_train = dataset["train"]
|
|
605
|
+
else:
|
|
606
|
+
print("Including only VERIFIED problems (use --include-unverified to include all)")
|
|
607
|
+
filtered_train = dataset["train"].filter(lambda x: x["is_verified"])
|
|
608
|
+
|
|
609
|
+
dataset = DatasetDict({"train": filtered_train})
|
|
610
|
+
print(f"Loaded dataset with {len(dataset['train'])} examples")
|
|
611
|
+
|
|
612
|
+
if args.list_sources:
|
|
613
|
+
print("\nAvailable sources in the dataset:")
|
|
614
|
+
sources = utils.get_available_sources(dataset['train'])
|
|
615
|
+
for source in sources:
|
|
616
|
+
count = sum(1 for p in dataset['train'] if utils.get_problem_source(p) == source)
|
|
617
|
+
print(f" - {source}: {count} instances")
|
|
618
|
+
return
|
|
619
|
+
|
|
620
|
+
if not args.output_dir:
|
|
621
|
+
parser.error("--output-dir is required in batch mode (not needed with --problem)")
|
|
622
|
+
|
|
623
|
+
while os.path.exists(args.output_dir):
|
|
624
|
+
print(f"Output directory '{args.output_dir}' already exists. Please choose a different name.")
|
|
625
|
+
new_dir = input("Enter a new output directory name: ").strip()
|
|
626
|
+
if new_dir:
|
|
627
|
+
args.output_dir = new_dir
|
|
628
|
+
|
|
629
|
+
if args.source:
|
|
630
|
+
print(f"\nFiltering dataset by sources: {args.source}")
|
|
631
|
+
|
|
632
|
+
def matches_any_source(problem):
|
|
633
|
+
source = utils.get_problem_source(problem)
|
|
634
|
+
if source is None:
|
|
635
|
+
return False
|
|
636
|
+
return any(s.lower() in source.lower() for s in args.source)
|
|
637
|
+
|
|
638
|
+
filtered_train = dataset['train'].filter(matches_any_source)
|
|
639
|
+
dataset = DatasetDict({"train": filtered_train})
|
|
640
|
+
print(f"Filtered dataset contains {len(dataset['train'])} instances matching sources")
|
|
641
|
+
|
|
642
|
+
if len(dataset['train']) == 0:
|
|
643
|
+
print("\nNo instances found matching the specified source.")
|
|
644
|
+
print("Use --list-sources to see available sources.")
|
|
645
|
+
return
|
|
646
|
+
|
|
647
|
+
client = _init_client(args)
|
|
648
|
+
|
|
649
|
+
if 'all' in args.strategies:
|
|
650
|
+
strategies = [
|
|
651
|
+
'baseline', 'cot', 'knowledge_graph',
|
|
652
|
+
'cot_with_code_validation', 'cot_with_grammar_validation',
|
|
653
|
+
'cot_with_code_and_grammar_validation',
|
|
654
|
+
'agents', 'agents_with_code_validation', 'gala',
|
|
655
|
+
]
|
|
656
|
+
else:
|
|
657
|
+
strategies = args.strategies
|
|
658
|
+
|
|
659
|
+
if args.problem_ids:
|
|
660
|
+
problems_to_process = [
|
|
661
|
+
(idx, dataset['train'][idx])
|
|
662
|
+
for idx in args.problem_ids
|
|
663
|
+
if idx < len(dataset['train'])
|
|
664
|
+
]
|
|
665
|
+
else:
|
|
666
|
+
problems_to_process = list(enumerate(dataset['train']))
|
|
667
|
+
|
|
668
|
+
print(f"\n{'='*50}")
|
|
669
|
+
print("RUN CONFIGURATION SUMMARY")
|
|
670
|
+
print(f"{'='*50}")
|
|
671
|
+
print(f"Model: {args.model}")
|
|
672
|
+
print(f"Strategies: {', '.join(strategies)}")
|
|
673
|
+
print(f"Source filter: {args.source if args.source else 'None (all sources)'}")
|
|
674
|
+
print(f"Include unverified: {args.include_unverified}")
|
|
675
|
+
print(f"Number of instances to process: {len(problems_to_process)}")
|
|
676
|
+
print(f"Output directory: {args.output_dir}")
|
|
677
|
+
print(f"{'='*50}\n")
|
|
678
|
+
|
|
679
|
+
results = {}
|
|
680
|
+
for strategy in strategies:
|
|
681
|
+
print(f"\nRunning {strategy} strategy with {args.model}...")
|
|
682
|
+
|
|
683
|
+
results[strategy] = {'success': 0, 'failed': 0, 'errors': []}
|
|
684
|
+
|
|
685
|
+
for idx, problem in tqdm(problems_to_process, desc=f"{strategy} progress"):
|
|
686
|
+
try:
|
|
687
|
+
problem_identifier = utils.get_problem_identifier(problem, idx)
|
|
688
|
+
|
|
689
|
+
cardinal_subfolder = utils.get_cardinal_ops_subfolder(problem)
|
|
690
|
+
if cardinal_subfolder:
|
|
691
|
+
output_dir = os.path.join(
|
|
692
|
+
args.output_dir, args.model, f"{strategy}_{cardinal_subfolder}"
|
|
693
|
+
)
|
|
694
|
+
else:
|
|
695
|
+
output_dir = os.path.join(args.output_dir, args.model, strategy)
|
|
696
|
+
|
|
697
|
+
if check_already_processed(output_dir, problem_identifier):
|
|
698
|
+
continue
|
|
699
|
+
|
|
700
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
701
|
+
|
|
702
|
+
success = _STRATEGY_MAP[strategy](client, args.model, problem, problem_identifier, output_dir)
|
|
703
|
+
|
|
704
|
+
if success:
|
|
705
|
+
results[strategy]['success'] += 1
|
|
706
|
+
else:
|
|
707
|
+
results[strategy]['failed'] += 1
|
|
708
|
+
results[strategy]['errors'].append({
|
|
709
|
+
'idx': idx,
|
|
710
|
+
'identifier': problem_identifier,
|
|
711
|
+
'error': 'Strategy returned False'
|
|
712
|
+
})
|
|
713
|
+
|
|
714
|
+
except Exception as e:
|
|
715
|
+
print(f"\nUnexpected error processing problem at index {idx}: {e}")
|
|
716
|
+
results[strategy]['failed'] += 1
|
|
717
|
+
problem_identifier = utils.get_problem_identifier(problem, idx)
|
|
718
|
+
results[strategy]['errors'].append({
|
|
719
|
+
'idx': idx,
|
|
720
|
+
'identifier': problem_identifier,
|
|
721
|
+
'error': str(e)
|
|
722
|
+
})
|
|
723
|
+
continue
|
|
724
|
+
|
|
725
|
+
time.sleep(args.sleep_time)
|
|
726
|
+
|
|
727
|
+
print("\n" + "="*50)
|
|
728
|
+
print("SUMMARY")
|
|
729
|
+
print("="*50)
|
|
730
|
+
for strategy, result in results.items():
|
|
731
|
+
total = result['success'] + result['failed']
|
|
732
|
+
success_rate = (result['success'] / total * 100) if total > 0 else 0
|
|
733
|
+
print(f"{strategy}: {result['success']}/{total} successful ({success_rate:.1f}%)")
|
|
734
|
+
if result['errors']:
|
|
735
|
+
print(" Failed instances:")
|
|
736
|
+
for err in result['errors'][:5]:
|
|
737
|
+
print(f" - {err['identifier']}: {err['error'][:50]}...")
|
|
738
|
+
if len(result['errors']) > 5:
|
|
739
|
+
print(f" ... and {len(result['errors']) - 5} more errors")
|
|
740
|
+
|
|
741
|
+
results_for_json = {
|
|
742
|
+
strategy: {
|
|
743
|
+
'success': result['success'],
|
|
744
|
+
'failed': result['failed'],
|
|
745
|
+
'total': result['success'] + result['failed'],
|
|
746
|
+
'success_rate': (
|
|
747
|
+
result['success'] / (result['success'] + result['failed']) * 100
|
|
748
|
+
if (result['success'] + result['failed']) > 0 else 0
|
|
749
|
+
),
|
|
750
|
+
'failed_identifiers': [err['identifier'] for err in result['errors']]
|
|
751
|
+
}
|
|
752
|
+
for strategy, result in results.items()
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
results_for_json['_metadata'] = {
|
|
756
|
+
'model': args.model,
|
|
757
|
+
'source_filter': args.source,
|
|
758
|
+
'include_unverified': args.include_unverified,
|
|
759
|
+
'num_instances': len(problems_to_process),
|
|
760
|
+
'strategies': strategies,
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
summary_path = os.path.join(args.output_dir, args.model, 'summary.json')
|
|
764
|
+
os.makedirs(os.path.dirname(summary_path), exist_ok=True)
|
|
765
|
+
with open(summary_path, 'w') as f:
|
|
766
|
+
json.dump(results_for_json, f, indent=2)
|
|
767
|
+
print(f"\nResults saved to {summary_path}")
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
if __name__ == "__main__":
|
|
771
|
+
main()
|