self-evolve-framework 1.5.0 → 1.6.0
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.
- package/package.json +1 -1
- package/template/skills/skillopt-sleep/SKILL.md +42 -0
- package/template/skills/skillopt-sleep/configs/_base_/default.yaml +103 -0
- package/template/skills/skillopt-sleep/configs/alfworld/default.yaml +29 -0
- package/template/skills/skillopt-sleep/configs/docvqa/default.yaml +28 -0
- package/template/skills/skillopt-sleep/configs/features/soft_gate.yaml +47 -0
- package/template/skills/skillopt-sleep/configs/livemathematicianbench/default.yaml +22 -0
- package/template/skills/skillopt-sleep/configs/officeqa/default.yaml +34 -0
- package/template/skills/skillopt-sleep/configs/searchqa/default.yaml +32 -0
- package/template/skills/skillopt-sleep/configs/spreadsheetbench/default.yaml +34 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/__init__.py +28 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/config.py +282 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/datasets/__init__.py +7 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/datasets/base.py +512 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/engine/__init__.py +9 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/engine/trainer.py +2379 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/__init__.py +1 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/_template/README.md +43 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/_template/config_template.yaml +55 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/_template/env_template.py +151 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/_template/loader_template.py +87 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/__init__.py +5 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/adapter.py +428 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/dataloader.py +123 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/analyst_error.md +55 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/analyst_success.md +33 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/rollout_no_history.md +8 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/rollout_with_history.md +9 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/rollout_with_memory.md +16 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/reflect.py +4 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/rollout.py +366 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/skills/initial.md +45 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/__init__.py +9 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/alfworld_envs.py +221 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/alfworld_projection.py +60 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/alfworld_prompts.py +8 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/config_tw.yaml +145 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/env_base.py +84 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/env_manager.py +139 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/memory.py +87 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/base.py +329 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/__init__.py +1 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/adapter.py +90 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/dataloader.py +61 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/evaluator.py +113 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/prompts/analyst_error.md +35 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/prompts/analyst_success.md +24 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/prompts/rollout_system.md +12 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/rollout.py +391 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/skills/initial.md +11 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/__init__.py +1 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/adapter.py +129 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/dataloader.py +308 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/evaluator.py +62 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/prompts/analyst_error.md +37 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/prompts/analyst_success.md +25 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/prompts/rollout_system.md +12 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/reflect.py +4 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/rollout.py +434 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/skills/initial.md +16 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/__init__.py +1 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/adapter.py +112 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/dataloader.py +71 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/evaluator.py +46 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/prompts/analyst_error.md +37 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/prompts/analyst_success.md +25 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/prompts/rollout_system.md +15 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/rollout.py +799 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/skills/initial.md +15 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/tool_runtime.py +552 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/__init__.py +1 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/adapter.py +96 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/dataloader.py +42 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/evaluator.py +100 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/prompts/analyst_error.md +46 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/prompts/analyst_success.md +32 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/prompts/rollout_system.md +13 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/reflect.py +4 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/rollout.py +494 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/skills/initial.md +3 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/__init__.py +5 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/adapter.py +159 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/codegen_agent.py +731 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/dataloader.py +37 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/evaluator.py +158 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/executor.py +67 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/analyst_error.md +46 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/analyst_success.md +32 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/codegen_system.md +1 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/critical_rules.md +9 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/react_system.md +21 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/react_agent.py +395 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/reflect.py +4 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/rollout.py +979 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/skills/initial.md +56 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/evaluation/__init__.py +13 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/evaluation/gate.py +148 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/gradient/__init__.py +15 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/gradient/aggregate.py +253 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/gradient/reflect.py +635 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/__init__.py +514 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/azure_openai.py +915 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/backend_config.py +185 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/claude_backend.py +371 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/codex_backend.py +666 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/codex_harness.py +1057 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/common.py +229 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/minimax_backend.py +277 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/qwen_backend.py +456 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/router.py +236 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/__init__.py +15 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/appendix.py +156 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/clip.py +109 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/lr_autonomous.py +108 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/meta_skill.py +79 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/rewrite.py +59 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/scheduler.py +127 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/select.py +4 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/skill.py +201 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/skill_aware.py +206 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/slow_update.py +396 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/update_modes.py +135 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/__init__.py +63 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_error.md +41 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_error_full_rewrite.md +32 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_error_rewrite.md +44 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_success.md +36 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_success_full_rewrite.md +30 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_success_rewrite.md +33 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/lr_autonomous.md +20 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_failure.md +30 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_failure_full_rewrite.md +28 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_failure_rewrite.md +26 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_final.md +33 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_final_full_rewrite.md +28 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_final_rewrite.md +25 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_success.md +28 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_success_full_rewrite.md +28 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_success_rewrite.md +25 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/meta_skill.md +40 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/ranking.md +20 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/ranking_rewrite.md +15 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/rewrite_skill.md +25 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/slow_update.md +60 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/scheduler/__init__.py +8 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/types.py +306 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/utils/__init__.py +4 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/utils/json_utils.py +172 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/utils/scoring.py +28 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""SpreadsheetBench task dataloader."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from skillopt.datasets.base import SplitDataLoader
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SpreadsheetBenchDataLoader(SplitDataLoader):
|
|
8
|
+
"""SpreadsheetBench dataloader.
|
|
9
|
+
|
|
10
|
+
Each split directory contains a .json file (JSON array of task items).
|
|
11
|
+
Spreadsheet files referenced by items live under a separate ``data_root``.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
split_dir: str = "",
|
|
17
|
+
data_path: str = "",
|
|
18
|
+
split_mode: str = "ratio",
|
|
19
|
+
split_ratio: str = "2:1:7",
|
|
20
|
+
split_seed: int = 42,
|
|
21
|
+
split_output_dir: str = "",
|
|
22
|
+
data_root: str = "",
|
|
23
|
+
seed: int = 42,
|
|
24
|
+
limit: int = 0,
|
|
25
|
+
**kwargs,
|
|
26
|
+
) -> None:
|
|
27
|
+
super().__init__(
|
|
28
|
+
split_dir=split_dir,
|
|
29
|
+
data_path=data_path,
|
|
30
|
+
split_mode=split_mode,
|
|
31
|
+
split_ratio=split_ratio,
|
|
32
|
+
split_seed=split_seed,
|
|
33
|
+
split_output_dir=split_output_dir,
|
|
34
|
+
seed=seed,
|
|
35
|
+
limit=limit,
|
|
36
|
+
)
|
|
37
|
+
self.data_root = data_root
|
package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/evaluator.py
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""Cell-value evaluator faithful to the official SpreadsheetBench
|
|
2
|
+
`evaluation/evaluation.py` (https://github.com/RUCKBReasoning/SpreadsheetBench).
|
|
3
|
+
|
|
4
|
+
Key rules (copied from the official `transform_value` / `compare_cell_value`):
|
|
5
|
+
* numeric values (int/float and numeric strings) are compared after
|
|
6
|
+
``round(float(v), 2)`` — a fixed 2-decimal quantization (NOT a tolerance);
|
|
7
|
+
* ``datetime.time`` is stringified and the trailing microseconds stripped;
|
|
8
|
+
* ``datetime.datetime`` is converted to an Excel serial day and rounded
|
|
9
|
+
to an integer day;
|
|
10
|
+
* an empty string ``""`` and ``None`` are considered equal, but otherwise
|
|
11
|
+
``type(v1) != type(v2)`` fails the comparison.
|
|
12
|
+
|
|
13
|
+
Format/style comparison is deliberately NOT performed — the official
|
|
14
|
+
reference evaluator also skips it (the relevant lines are commented out
|
|
15
|
+
in `cell_level_compare`). soft vs hard is defined at the run_bench level
|
|
16
|
+
across a task's multiple test cases, not here.
|
|
17
|
+
"""
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import datetime
|
|
21
|
+
import os
|
|
22
|
+
import re
|
|
23
|
+
|
|
24
|
+
import openpyxl
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# ---------- value transform / compare (official port) ----------
|
|
28
|
+
|
|
29
|
+
def _datetime_to_float(dt: datetime.datetime) -> float:
|
|
30
|
+
excel_start_date = datetime.datetime(1899, 12, 30)
|
|
31
|
+
delta = dt - excel_start_date
|
|
32
|
+
return delta.days + delta.seconds / 86400.0
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _transform_value(v):
|
|
36
|
+
if isinstance(v, bool):
|
|
37
|
+
# openpyxl can return Python bool; official code doesn't special-case
|
|
38
|
+
# bools, but round(float(True), 2) == 1.0 which breaks 1 vs True. Keep
|
|
39
|
+
# parity with the official transform by promoting bool -> float.
|
|
40
|
+
return round(float(v), 2)
|
|
41
|
+
if isinstance(v, (int, float)):
|
|
42
|
+
return round(float(v), 2)
|
|
43
|
+
if isinstance(v, datetime.time):
|
|
44
|
+
return str(v)[:-3]
|
|
45
|
+
if isinstance(v, datetime.datetime):
|
|
46
|
+
return round(_datetime_to_float(v), 0)
|
|
47
|
+
if isinstance(v, str):
|
|
48
|
+
try:
|
|
49
|
+
return round(float(v), 2)
|
|
50
|
+
except ValueError:
|
|
51
|
+
return v
|
|
52
|
+
return v
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _compare_cell_value(v1, v2) -> bool:
|
|
56
|
+
v1 = _transform_value(v1)
|
|
57
|
+
v2 = _transform_value(v2)
|
|
58
|
+
if (v1 == "" and v2 is None) or (v1 is None and v2 == ""):
|
|
59
|
+
return True
|
|
60
|
+
if (v1 == "" and v2 == "") or (v1 is None and v2 is None):
|
|
61
|
+
return True
|
|
62
|
+
if type(v1) is not type(v2):
|
|
63
|
+
return False
|
|
64
|
+
return v1 == v2
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# ---------- range parsing (official port) ----------
|
|
68
|
+
|
|
69
|
+
def _col_num2name(n: int) -> str:
|
|
70
|
+
name = ""
|
|
71
|
+
while n > 0:
|
|
72
|
+
n, r = divmod(n - 1, 26)
|
|
73
|
+
name = chr(65 + r) + name
|
|
74
|
+
return name
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _col_name2num(name: str) -> int:
|
|
78
|
+
num = 0
|
|
79
|
+
for c in name:
|
|
80
|
+
num = num * 26 + (ord(c) - ord("A") + 1)
|
|
81
|
+
return num
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _parse_range(range_str: str):
|
|
85
|
+
start_cell, end_cell = range_str.split(":")
|
|
86
|
+
sc = "".join(ch for ch in start_cell if ch.isalpha())
|
|
87
|
+
sr = "".join(ch for ch in start_cell if ch.isdigit())
|
|
88
|
+
ec = "".join(ch for ch in end_cell if ch.isalpha())
|
|
89
|
+
er = "".join(ch for ch in end_cell if ch.isdigit())
|
|
90
|
+
return (_col_name2num(sc), int(sr)), (_col_name2num(ec), int(er))
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _generate_cell_names(range_str: str):
|
|
94
|
+
if ":" not in range_str:
|
|
95
|
+
return [range_str]
|
|
96
|
+
(sc, sr), (ec, er) = _parse_range(range_str)
|
|
97
|
+
cols = [_col_num2name(i) for i in range(sc, ec + 1)]
|
|
98
|
+
return [f"{c}{r}" for c in cols for r in range(sr, er + 1)]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _cell_level_compare(wb_gt, wb_proc, sheet_name: str, cell_range: str):
|
|
102
|
+
if sheet_name not in wb_proc.sheetnames:
|
|
103
|
+
return False, f"worksheet not found: {sheet_name}"
|
|
104
|
+
ws_gt = wb_gt[sheet_name]
|
|
105
|
+
ws_proc = wb_proc[sheet_name]
|
|
106
|
+
for cn in _generate_cell_names(cell_range):
|
|
107
|
+
cg = ws_gt[cn]
|
|
108
|
+
cp = ws_proc[cn]
|
|
109
|
+
if not _compare_cell_value(cg.value, cp.value):
|
|
110
|
+
return False, f"value@{sheet_name}!{cn}: gt={cg.value!r} pred={cp.value!r}"
|
|
111
|
+
return True, ""
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
# ---------- public API ----------
|
|
115
|
+
|
|
116
|
+
def compare_workbooks(gt_file: str, proc_file: str, answer_position: str) -> tuple[bool, str]:
|
|
117
|
+
"""Return (ok, msg). Single test-case comparison, official semantics."""
|
|
118
|
+
if not os.path.exists(proc_file):
|
|
119
|
+
return False, "file not exist"
|
|
120
|
+
try:
|
|
121
|
+
wb_gt = openpyxl.load_workbook(filename=gt_file, data_only=True)
|
|
122
|
+
wb_proc = openpyxl.load_workbook(filename=proc_file, data_only=True)
|
|
123
|
+
except Exception as e: # noqa: BLE001
|
|
124
|
+
return False, f"load error: {e}"
|
|
125
|
+
try:
|
|
126
|
+
ok_all = True
|
|
127
|
+
msg_first = ""
|
|
128
|
+
for scr in (answer_position or "").split(","):
|
|
129
|
+
scr = scr.strip()
|
|
130
|
+
if not scr:
|
|
131
|
+
continue
|
|
132
|
+
if "!" in scr:
|
|
133
|
+
sheet_name, cell_range = scr.split("!", 1)
|
|
134
|
+
sheet_name = sheet_name.strip().strip("'\"")
|
|
135
|
+
else:
|
|
136
|
+
sheet_name = wb_gt.sheetnames[0]
|
|
137
|
+
cell_range = scr
|
|
138
|
+
cell_range = cell_range.strip().strip("'\"")
|
|
139
|
+
ok, msg = _cell_level_compare(wb_gt, wb_proc, sheet_name, cell_range)
|
|
140
|
+
if not ok:
|
|
141
|
+
ok_all = False
|
|
142
|
+
if not msg_first:
|
|
143
|
+
msg_first = msg
|
|
144
|
+
return ok_all, msg_first
|
|
145
|
+
finally:
|
|
146
|
+
wb_gt.close()
|
|
147
|
+
wb_proc.close()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def evaluate(pred_path: str, gold_path: str,
|
|
151
|
+
instruction_type: str, answer_position: str) -> dict:
|
|
152
|
+
"""Single test-case evaluate. soft/hard aggregation happens in run_bench."""
|
|
153
|
+
ok, msg = compare_workbooks(gold_path, pred_path, answer_position)
|
|
154
|
+
return {
|
|
155
|
+
"ok": ok,
|
|
156
|
+
"reason": msg,
|
|
157
|
+
"instruction_type": instruction_type,
|
|
158
|
+
}
|
package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/executor.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Execute LLM-generated Python code against an input xlsx to produce an output xlsx."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import re
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
import tempfile
|
|
9
|
+
import textwrap
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
RUNNER_TEMPLATE = textwrap.dedent(
|
|
13
|
+
"""
|
|
14
|
+
import os, sys, traceback
|
|
15
|
+
INPUT_PATH = {input_path!r}
|
|
16
|
+
OUTPUT_PATH = {output_path!r}
|
|
17
|
+
try:
|
|
18
|
+
{user_code_indented}
|
|
19
|
+
except Exception:
|
|
20
|
+
traceback.print_exc()
|
|
21
|
+
sys.exit(2)
|
|
22
|
+
"""
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Regex to strip user-defined INPUT_PATH / OUTPUT_PATH assignments,
|
|
26
|
+
# since the runner template injects the correct values.
|
|
27
|
+
_PATH_ASSIGN_RE = re.compile(
|
|
28
|
+
r'^\s*(INPUT_PATH|OUTPUT_PATH)\s*=\s*.+$', re.MULTILINE
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _strip_path_assignments(code: str) -> str:
|
|
33
|
+
"""Remove INPUT_PATH/OUTPUT_PATH assignments from user code."""
|
|
34
|
+
return _PATH_ASSIGN_RE.sub("", code)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def run_generated_code(code: str, input_path: str, output_path: str, timeout: int | None = 120) -> tuple[bool, str]:
|
|
38
|
+
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
|
39
|
+
cleaned = _strip_path_assignments(code)
|
|
40
|
+
indented = textwrap.indent(cleaned, " ")
|
|
41
|
+
script = RUNNER_TEMPLATE.format(
|
|
42
|
+
input_path=input_path,
|
|
43
|
+
output_path=output_path,
|
|
44
|
+
user_code_indented=indented,
|
|
45
|
+
)
|
|
46
|
+
with tempfile.NamedTemporaryFile("w", suffix=".py", delete=False) as f:
|
|
47
|
+
f.write(script)
|
|
48
|
+
tmp = f.name
|
|
49
|
+
try:
|
|
50
|
+
proc = subprocess.run(
|
|
51
|
+
[sys.executable, tmp],
|
|
52
|
+
capture_output=True,
|
|
53
|
+
text=True,
|
|
54
|
+
timeout=timeout if timeout and timeout > 0 else None,
|
|
55
|
+
)
|
|
56
|
+
if proc.returncode != 0:
|
|
57
|
+
return False, (proc.stdout + "\n" + proc.stderr).strip()
|
|
58
|
+
if not os.path.exists(output_path):
|
|
59
|
+
return False, "output file was not created"
|
|
60
|
+
return True, ""
|
|
61
|
+
except subprocess.TimeoutExpired:
|
|
62
|
+
return False, f"timeout after {timeout}s"
|
|
63
|
+
finally:
|
|
64
|
+
try:
|
|
65
|
+
os.unlink(tmp)
|
|
66
|
+
except OSError:
|
|
67
|
+
pass
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
You are an expert failure-analysis agent for spreadsheet manipulation tasks.
|
|
2
|
+
|
|
3
|
+
You will be given MULTIPLE failed agent trajectories from a single minibatch
|
|
4
|
+
and the current skill document.
|
|
5
|
+
Your job is to identify the most important COMMON failure patterns across
|
|
6
|
+
the batch and propose a concise set of skill edits.
|
|
7
|
+
|
|
8
|
+
## Failure Type Categories
|
|
9
|
+
- **rule_missing**: the skill lacks a relevant rule for this type of task
|
|
10
|
+
- **rule_wrong**: an existing skill rule is misleading or incorrect
|
|
11
|
+
- **rule_ignored**: the skill has the right rule but the agent did not follow it
|
|
12
|
+
- **data_exploration**: the agent did not read enough data from the spreadsheet
|
|
13
|
+
- **code_error**: the agent's code has a bug unrelated to the skill
|
|
14
|
+
- **other**: none of the above
|
|
15
|
+
|
|
16
|
+
## Analysis Process
|
|
17
|
+
1. Read ALL failed trajectories in the minibatch.
|
|
18
|
+
2. Identify the most prevalent, systematic failure patterns across them.
|
|
19
|
+
3. For each pattern, classify its failure type.
|
|
20
|
+
4. Propose skill edits that address the COMMON patterns — not individual edge cases.
|
|
21
|
+
5. Edits must be generalizable; do not hardcode task-specific values
|
|
22
|
+
(file paths, cell addresses, expected values).
|
|
23
|
+
6. Only patch gaps in the skill — do not duplicate existing content.
|
|
24
|
+
7. If the failure is because the agent did not read enough spreadsheet rows/columns
|
|
25
|
+
to understand the data, propose a patch encouraging broader data exploration.
|
|
26
|
+
|
|
27
|
+
You will be told the maximum number of edits (the budget L). Produce AT MOST L edits,
|
|
28
|
+
focusing on the highest-impact patterns. You may produce fewer if warranted.
|
|
29
|
+
|
|
30
|
+
Respond ONLY with a valid JSON object (no markdown fences, no extra text):
|
|
31
|
+
{
|
|
32
|
+
"batch_size": <number of trajectories analysed>,
|
|
33
|
+
"failure_summary": [
|
|
34
|
+
{"failure_type": "<type>", "count": <int>, "description": "<one-line>"}
|
|
35
|
+
],
|
|
36
|
+
"patch": {
|
|
37
|
+
"reasoning": "<why these edits address the batch's common failures>",
|
|
38
|
+
"edits": [
|
|
39
|
+
{"op": "append", "content": "<markdown to add at end of skill>"},
|
|
40
|
+
{"op": "insert_after", "target": "<exact heading/text to insert after>", "content": "<markdown>"},
|
|
41
|
+
{"op": "replace", "target": "<exact text to replace>", "content": "<replacement>"},
|
|
42
|
+
{"op": "delete", "target": "<exact text to remove>"}
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
Only include edits that are needed. "edits" can be an empty list if no patch is warranted.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
You are an expert success-pattern analyst for AI spreadsheet agents.
|
|
2
|
+
|
|
3
|
+
You will be given MULTIPLE successful agent trajectories from a single minibatch
|
|
4
|
+
and the current skill document. Your job is to identify generalizable behavior
|
|
5
|
+
patterns that are COMMON across the batch and worth encoding in the skill.
|
|
6
|
+
|
|
7
|
+
## Rules
|
|
8
|
+
- Only propose patches for patterns NOT already covered in the skill.
|
|
9
|
+
- Focus on patterns that appear across MULTIPLE trajectories in the batch.
|
|
10
|
+
- Be concise. Patterns must generalize beyond specific tasks.
|
|
11
|
+
- Prefer reinforcing existing sections over adding new top-level sections.
|
|
12
|
+
- If the agents' success involved reading enough data rows or using a smart
|
|
13
|
+
exploration strategy, consider reinforcing that in the patch.
|
|
14
|
+
|
|
15
|
+
You will be told the maximum number of edits (the budget L). Produce AT MOST L edits,
|
|
16
|
+
focusing on the most broadly applicable patterns. You may produce fewer if warranted.
|
|
17
|
+
|
|
18
|
+
Respond ONLY with a valid JSON object:
|
|
19
|
+
{
|
|
20
|
+
"batch_size": <number of trajectories analysed>,
|
|
21
|
+
"success_patterns": ["<pattern 1>", "<pattern 2>"],
|
|
22
|
+
"patch": {
|
|
23
|
+
"reasoning": "<why these patterns are worth encoding>",
|
|
24
|
+
"edits": [
|
|
25
|
+
{"op": "append", "content": "<markdown>"},
|
|
26
|
+
{"op": "insert_after", "target": "<heading/text>", "content": "<markdown>"},
|
|
27
|
+
{"op": "replace", "target": "<old text>", "content": "<new text>"},
|
|
28
|
+
{"op": "delete", "target": "<exact text to remove>"}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
"edits" may be empty if the skill already covers all observed patterns.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
You are an expert Python programmer specializing in spreadsheet manipulation. You will be given a user instruction together with a preview of an input .xlsx file. Your job is to write a single self-contained Python script that reads the input file at the path stored in the variable INPUT_PATH, performs the requested manipulation, and saves the result to OUTPUT_PATH. Use only the standard library, openpyxl, and pandas. Do not print anything. Do not use input(). Do not hardcode file paths. Return ONLY the Python code inside a single ```python ... ``` fenced block.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
## Critical Rules (MUST follow)
|
|
2
|
+
1. NEVER write Excel formulas to cells that will be graded on their displayed value.
|
|
3
|
+
openpyxl does NOT compute formulas -- the evaluator will see None.
|
|
4
|
+
Instead, compute results in Python and write literal values (numbers/strings).
|
|
5
|
+
2. After saving the workbook, ALWAYS reopen and verify the written values:
|
|
6
|
+
`wb2 = openpyxl.load_workbook(OUTPUT_PATH); print(wb2[sheet][cell].value)`
|
|
7
|
+
3. Use the `write_file` tool to create solution.py -- it avoids shell escaping issues.
|
|
8
|
+
Do NOT use `echo "..." > solution.py` for multi-line scripts.
|
|
9
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
You are an expert spreadsheet manipulation agent.
|
|
2
|
+
|
|
3
|
+
{critical_rules}{skill_section}## Tools
|
|
4
|
+
You have two tools:
|
|
5
|
+
- `bash` -- execute any shell command and receive its output.
|
|
6
|
+
- `write_file` -- write content to a file (path, content). Use this for solution.py.
|
|
7
|
+
|
|
8
|
+
## Protocol
|
|
9
|
+
1. Explore the input spreadsheet to understand its structure (sheets, headers, row count).
|
|
10
|
+
2. Use the `write_file` tool to create `solution.py` in the current directory.
|
|
11
|
+
solution.py MUST start with:
|
|
12
|
+
INPUT_PATH = "<exact input path given in the task>"
|
|
13
|
+
OUTPUT_PATH = "<exact output path given in the task>"
|
|
14
|
+
Then perform the manipulation and save the result to OUTPUT_PATH.
|
|
15
|
+
Use only: standard library, openpyxl, pandas.
|
|
16
|
+
3. Run `python solution.py` via `bash` and verify the output was created.
|
|
17
|
+
4. Fix any errors and re-run until the output is correct.
|
|
18
|
+
5. Once OUTPUT_PATH exists and is correct, stop calling tools.
|
|
19
|
+
|
|
20
|
+
Do NOT use any libraries other than standard library, openpyxl, and pandas.
|
|
21
|
+
Do NOT hardcode cell values from the preview -- iterate over actual rows.
|