Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- inference.py +17 -24
- server/compiler_env_environment.py +100 -8
inference.py
CHANGED
|
@@ -86,10 +86,8 @@ SYSTEM_PROMPT = textwrap.dedent(
|
|
| 86 |
Each turn you must reply with exactly ONE tool call. Available tools:
|
| 87 |
- add_pass(pass_name): Try adding a pass. Auto-compiled and evaluated.
|
| 88 |
- remove_pass(pass_name): Remove a previously kept pass (-0.05 penalty).
|
|
|
|
| 89 |
- finalize(): End the episode. You receive a final bonus based on baselines.
|
| 90 |
-
- get_program_info(): Get program name and baseline execution times
|
| 91 |
-
- list_passes(): List all 19 valid LLVM optimization passes
|
| 92 |
-
- get_current_sequence(): Get kept passes and current best time
|
| 93 |
|
| 94 |
Available 19 passes (use exact names):
|
| 95 |
MEMORY:
|
|
@@ -169,32 +167,25 @@ TOOLS = [
|
|
| 169 |
{
|
| 170 |
"type": "function",
|
| 171 |
"function": {
|
| 172 |
-
"name": "
|
| 173 |
-
"description": "
|
| 174 |
-
"parameters": {
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
},
|
| 185 |
-
{
|
| 186 |
-
"type": "function",
|
| 187 |
-
"function": {
|
| 188 |
-
"name": "list_passes",
|
| 189 |
-
"description": "List all valid LLVM optimization passes.",
|
| 190 |
-
"parameters": {"type": "object", "properties": {}},
|
| 191 |
},
|
| 192 |
},
|
| 193 |
{
|
| 194 |
"type": "function",
|
| 195 |
"function": {
|
| 196 |
-
"name": "
|
| 197 |
-
"description": "
|
| 198 |
"parameters": {"type": "object", "properties": {}},
|
| 199 |
},
|
| 200 |
},
|
|
@@ -322,6 +313,8 @@ def tool_call_to_action(tool_name: str, tool_args: dict) -> str:
|
|
| 322 |
return f"add_pass:{tool_args.get('pass_name', '')}"
|
| 323 |
if tool_name == "remove_pass":
|
| 324 |
return f"remove_pass:{tool_args.get('pass_name', '')}"
|
|
|
|
|
|
|
| 325 |
return tool_name
|
| 326 |
|
| 327 |
|
|
|
|
| 86 |
Each turn you must reply with exactly ONE tool call. Available tools:
|
| 87 |
- add_pass(pass_name): Try adding a pass. Auto-compiled and evaluated.
|
| 88 |
- remove_pass(pass_name): Remove a previously kept pass (-0.05 penalty).
|
| 89 |
+
- reorder_sequence(new_order): Reorder passes. +0.1 if improves, -0.05 if not (reverts).
|
| 90 |
- finalize(): End the episode. You receive a final bonus based on baselines.
|
|
|
|
|
|
|
|
|
|
| 91 |
|
| 92 |
Available 19 passes (use exact names):
|
| 93 |
MEMORY:
|
|
|
|
| 167 |
{
|
| 168 |
"type": "function",
|
| 169 |
"function": {
|
| 170 |
+
"name": "reorder_sequence",
|
| 171 |
+
"description": "Reorder the current pass sequence. Provide the same passes in a new order. Auto-compiles: +0.1 if time improves (keeps new order), -0.05 if not (reverts).",
|
| 172 |
+
"parameters": {
|
| 173 |
+
"type": "object",
|
| 174 |
+
"properties": {
|
| 175 |
+
"new_order": {
|
| 176 |
+
"type": "string",
|
| 177 |
+
"description": "Comma-separated pass names in the desired new order, e.g. 'gvn,mem2reg,simplifycfg'",
|
| 178 |
+
}
|
| 179 |
+
},
|
| 180 |
+
"required": ["new_order"],
|
| 181 |
+
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 182 |
},
|
| 183 |
},
|
| 184 |
{
|
| 185 |
"type": "function",
|
| 186 |
"function": {
|
| 187 |
+
"name": "finalize",
|
| 188 |
+
"description": "End the episode. Computes final bonus based on how your best time compares to O0/O1/O2/O3 baselines. Call this when you are satisfied with your pass sequence.",
|
| 189 |
"parameters": {"type": "object", "properties": {}},
|
| 190 |
},
|
| 191 |
},
|
|
|
|
| 313 |
return f"add_pass:{tool_args.get('pass_name', '')}"
|
| 314 |
if tool_name == "remove_pass":
|
| 315 |
return f"remove_pass:{tool_args.get('pass_name', '')}"
|
| 316 |
+
if tool_name == "reorder_sequence":
|
| 317 |
+
return f"reorder_sequence:{tool_args.get('new_order', '')}"
|
| 318 |
return tool_name
|
| 319 |
|
| 320 |
|
server/compiler_env_environment.py
CHANGED
|
@@ -99,8 +99,7 @@ class CompilerEnvironment(Environment):
|
|
| 99 |
|
| 100 |
self.max_steps = 30
|
| 101 |
self.action_space = [
|
| 102 |
-
"add_pass", "remove_pass", "
|
| 103 |
-
"list_passes", "get_current_sequence",
|
| 104 |
]
|
| 105 |
self.current_sequence = []
|
| 106 |
self.valid_passes = ALL_PASSES
|
|
@@ -239,14 +238,10 @@ class CompilerEnvironment(Environment):
|
|
| 239 |
obs_data, status, message = self._add_pass(action_arg)
|
| 240 |
elif action_name == "remove_pass":
|
| 241 |
obs_data, status, message = self._remove_pass(action_arg)
|
|
|
|
|
|
|
| 242 |
elif action_name == "finalize":
|
| 243 |
obs_data, status, message = self._finalize()
|
| 244 |
-
elif action_name == "get_program_info":
|
| 245 |
-
obs_data, status, message = self._get_program_info()
|
| 246 |
-
elif action_name == "list_passes":
|
| 247 |
-
obs_data, status, message = self._list_passes()
|
| 248 |
-
elif action_name == "get_current_sequence":
|
| 249 |
-
obs_data, status, message = self._get_current_sequence()
|
| 250 |
else:
|
| 251 |
raise ValueError(f"Unknown action: {action_name}")
|
| 252 |
|
|
@@ -412,6 +407,103 @@ class CompilerEnvironment(Environment):
|
|
| 412 |
f"Pass '{pass_name}' removed from sequence. Reward: -0.05. Current sequence: {self.current_sequence}",
|
| 413 |
)
|
| 414 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 415 |
def _get_program_info(self):
|
| 416 |
"""Return program name and baselines."""
|
| 417 |
return (
|
|
|
|
| 99 |
|
| 100 |
self.max_steps = 30
|
| 101 |
self.action_space = [
|
| 102 |
+
"add_pass", "remove_pass", "reorder_sequence", "finalize",
|
|
|
|
| 103 |
]
|
| 104 |
self.current_sequence = []
|
| 105 |
self.valid_passes = ALL_PASSES
|
|
|
|
| 238 |
obs_data, status, message = self._add_pass(action_arg)
|
| 239 |
elif action_name == "remove_pass":
|
| 240 |
obs_data, status, message = self._remove_pass(action_arg)
|
| 241 |
+
elif action_name == "reorder_sequence":
|
| 242 |
+
obs_data, status, message = self._reorder_sequence(action_arg)
|
| 243 |
elif action_name == "finalize":
|
| 244 |
obs_data, status, message = self._finalize()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 245 |
else:
|
| 246 |
raise ValueError(f"Unknown action: {action_name}")
|
| 247 |
|
|
|
|
| 407 |
f"Pass '{pass_name}' removed from sequence. Reward: -0.05. Current sequence: {self.current_sequence}",
|
| 408 |
)
|
| 409 |
|
| 410 |
+
def _reorder_sequence(self, new_order_str):
|
| 411 |
+
"""
|
| 412 |
+
Reorder the current pass sequence. Agent provides a comma-separated
|
| 413 |
+
list of the same passes in a new order.
|
| 414 |
+
|
| 415 |
+
- Must contain exactly the same passes (no additions/removals)
|
| 416 |
+
- Auto-compiles and measures
|
| 417 |
+
- If time improves -> keep new order (+0.1)
|
| 418 |
+
- If not -> revert to old order (-0.05)
|
| 419 |
+
"""
|
| 420 |
+
base_data = {
|
| 421 |
+
"current_sequence": list(self.current_sequence),
|
| 422 |
+
"sequence_length": len(self.current_sequence),
|
| 423 |
+
"best_time": self.best_time,
|
| 424 |
+
"steps_remaining": self.max_steps - self._state.step_count,
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
if not new_order_str:
|
| 428 |
+
self.episode_reward -= 0.1
|
| 429 |
+
return (
|
| 430 |
+
{**base_data, "reason": "missing_order"},
|
| 431 |
+
"error",
|
| 432 |
+
"No pass order provided. Provide comma-separated pass names.",
|
| 433 |
+
)
|
| 434 |
+
|
| 435 |
+
new_order = [p.strip() for p in new_order_str.split(",") if p.strip()]
|
| 436 |
+
|
| 437 |
+
# Validate: must be the same passes, just reordered
|
| 438 |
+
if sorted(new_order) != sorted(self.current_sequence):
|
| 439 |
+
self.episode_reward -= 0.1
|
| 440 |
+
return (
|
| 441 |
+
{**base_data, "reason": "invalid_order", "provided": new_order},
|
| 442 |
+
"error",
|
| 443 |
+
f"Invalid reorder. Must contain exactly the same passes. Current: {self.current_sequence}, Got: {new_order}",
|
| 444 |
+
)
|
| 445 |
+
|
| 446 |
+
# Same order as before — no-op
|
| 447 |
+
if new_order == self.current_sequence:
|
| 448 |
+
return (
|
| 449 |
+
base_data,
|
| 450 |
+
"success",
|
| 451 |
+
"Sequence unchanged — already in this order.",
|
| 452 |
+
)
|
| 453 |
+
|
| 454 |
+
# Tentatively apply new order
|
| 455 |
+
old_sequence = list(self.current_sequence)
|
| 456 |
+
self.current_sequence = new_order
|
| 457 |
+
|
| 458 |
+
try:
|
| 459 |
+
new_time = self._auto_compile_and_measure()
|
| 460 |
+
except (RuntimeError, subprocess.CalledProcessError, subprocess.TimeoutExpired) as e:
|
| 461 |
+
self.current_sequence = old_sequence
|
| 462 |
+
self.episode_reward -= 0.1
|
| 463 |
+
return (
|
| 464 |
+
{**base_data, "reason": "compile_failed"},
|
| 465 |
+
"compile_failed",
|
| 466 |
+
f"Compilation failed after reorder: {str(e)[:200]}",
|
| 467 |
+
)
|
| 468 |
+
|
| 469 |
+
self.current_time = new_time
|
| 470 |
+
|
| 471 |
+
if new_time < self.best_time:
|
| 472 |
+
old_best = self.best_time
|
| 473 |
+
self.best_time = new_time
|
| 474 |
+
self.episode_reward += 0.1
|
| 475 |
+
return (
|
| 476 |
+
{
|
| 477 |
+
"reordered": True,
|
| 478 |
+
"improved": True,
|
| 479 |
+
"execution_time": new_time,
|
| 480 |
+
"best_time": self.best_time,
|
| 481 |
+
"old_best_time": old_best,
|
| 482 |
+
"current_sequence": list(self.current_sequence),
|
| 483 |
+
"sequence_length": len(self.current_sequence),
|
| 484 |
+
"steps_remaining": self.max_steps - self._state.step_count,
|
| 485 |
+
},
|
| 486 |
+
"reorder_improved",
|
| 487 |
+
f"Reorder improved time! {new_time:.4f}s (was {old_best:.4f}s). New order: {self.current_sequence}",
|
| 488 |
+
)
|
| 489 |
+
else:
|
| 490 |
+
# Revert
|
| 491 |
+
self.current_sequence = old_sequence
|
| 492 |
+
self.episode_reward -= 0.05
|
| 493 |
+
return (
|
| 494 |
+
{
|
| 495 |
+
"reordered": False,
|
| 496 |
+
"improved": False,
|
| 497 |
+
"execution_time": new_time,
|
| 498 |
+
"best_time": self.best_time,
|
| 499 |
+
"current_sequence": list(self.current_sequence),
|
| 500 |
+
"sequence_length": len(self.current_sequence),
|
| 501 |
+
"steps_remaining": self.max_steps - self._state.step_count,
|
| 502 |
+
},
|
| 503 |
+
"reorder_reverted",
|
| 504 |
+
f"Reorder did NOT improve. Reverted. Time: {new_time:.4f}s vs best: {self.best_time:.4f}s",
|
| 505 |
+
)
|
| 506 |
+
|
| 507 |
def _get_program_info(self):
|
| 508 |
"""Return program name and baselines."""
|
| 509 |
return (
|