self-evolve-framework 1.5.0 → 1.6.1
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/README.md +33 -23
- package/bin/cli.js +24 -67
- package/package.json +1 -1
- package/template/rules/knowledge/README.md +56 -0
- package/template/rules/knowledge/ant-design-vue.mdc +54 -0
- package/template/rules/knowledge/general.mdc +56 -0
- package/template/rules/knowledge/rust.mdc +55 -0
- package/template/rules/knowledge/shadcn-svelte.mdc +64 -0
- package/template/rules/knowledge/svelte.mdc +135 -0
- package/template/rules/knowledge/tailwind.mdc +66 -0
- package/template/rules/knowledge/tauri.mdc +65 -0
- package/template/rules/knowledge/typescript.mdc +41 -0
- package/template/rules/knowledge/vue.mdc +48 -0
- package/template/rules/ponytail.mdc +23 -98
- package/template/rules/self-evolve.mdc +24 -0
- package/template/skills/impeccable/SKILL.md +47 -174
- package/template/skills/skillopt-sleep/SKILL.md +34 -48
- package/template/skills/impeccable/agents/impeccable_asset_producer.toml +0 -92
- package/template/skills/impeccable/agents/impeccable_manual_edit_applier.toml +0 -95
- package/template/skills/impeccable/agents/openai.yaml +0 -4
- package/template/skills/impeccable/reference/adapt.md +0 -311
- package/template/skills/impeccable/reference/animate.md +0 -201
- package/template/skills/impeccable/reference/audit.md +0 -133
- package/template/skills/impeccable/reference/bolder.md +0 -113
- package/template/skills/impeccable/reference/brand.md +0 -108
- package/template/skills/impeccable/reference/clarify.md +0 -288
- package/template/skills/impeccable/reference/codex.md +0 -105
- package/template/skills/impeccable/reference/colorize.md +0 -257
- package/template/skills/impeccable/reference/craft.md +0 -123
- package/template/skills/impeccable/reference/critique.md +0 -790
- package/template/skills/impeccable/reference/delight.md +0 -302
- package/template/skills/impeccable/reference/distill.md +0 -111
- package/template/skills/impeccable/reference/document.md +0 -429
- package/template/skills/impeccable/reference/extract.md +0 -69
- package/template/skills/impeccable/reference/harden.md +0 -347
- package/template/skills/impeccable/reference/hooks.md +0 -90
- package/template/skills/impeccable/reference/init.md +0 -172
- package/template/skills/impeccable/reference/interaction-design.md +0 -189
- package/template/skills/impeccable/reference/layout.md +0 -161
- package/template/skills/impeccable/reference/live.md +0 -720
- package/template/skills/impeccable/reference/onboard.md +0 -234
- package/template/skills/impeccable/reference/optimize.md +0 -258
- package/template/skills/impeccable/reference/overdrive.md +0 -130
- package/template/skills/impeccable/reference/polish.md +0 -241
- package/template/skills/impeccable/reference/product.md +0 -60
- package/template/skills/impeccable/reference/quieter.md +0 -99
- package/template/skills/impeccable/reference/shape.md +0 -165
- package/template/skills/impeccable/reference/typeset.md +0 -279
- package/template/skills/impeccable/scripts/command-metadata.json +0 -94
- package/template/skills/impeccable/scripts/context-signals.mjs +0 -225
- package/template/skills/impeccable/scripts/context.mjs +0 -961
- package/template/skills/impeccable/scripts/critique-storage.mjs +0 -242
- package/template/skills/impeccable/scripts/detect-csp.mjs +0 -198
- package/template/skills/impeccable/scripts/detect.mjs +0 -21
- package/template/skills/impeccable/scripts/detector/browser/injected/index.mjs +0 -1937
- package/template/skills/impeccable/scripts/detector/cli/main.mjs +0 -290
- package/template/skills/impeccable/scripts/detector/design-system.mjs +0 -750
- package/template/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +0 -5138
- package/template/skills/impeccable/scripts/detector/detect-antipatterns.mjs +0 -50
- package/template/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +0 -277
- package/template/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +0 -568
- package/template/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +0 -1015
- package/template/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +0 -234
- package/template/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs +0 -189
- package/template/skills/impeccable/scripts/detector/findings.mjs +0 -12
- package/template/skills/impeccable/scripts/detector/node/file-system.mjs +0 -198
- package/template/skills/impeccable/scripts/detector/profile/profiler.mjs +0 -166
- package/template/skills/impeccable/scripts/detector/registry/antipatterns.mjs +0 -448
- package/template/skills/impeccable/scripts/detector/rules/checks.mjs +0 -2671
- package/template/skills/impeccable/scripts/detector/shared/color.mjs +0 -124
- package/template/skills/impeccable/scripts/detector/shared/constants.mjs +0 -101
- package/template/skills/impeccable/scripts/detector/shared/inline-ignores.mjs +0 -148
- package/template/skills/impeccable/scripts/detector/shared/page.mjs +0 -7
- package/template/skills/impeccable/scripts/hook-admin.mjs +0 -661
- package/template/skills/impeccable/scripts/hook-before-edit.mjs +0 -476
- package/template/skills/impeccable/scripts/hook-lib.mjs +0 -1632
- package/template/skills/impeccable/scripts/hook.mjs +0 -61
- package/template/skills/impeccable/scripts/lib/design-parser.mjs +0 -842
- package/template/skills/impeccable/scripts/lib/impeccable-config.mjs +0 -638
- package/template/skills/impeccable/scripts/lib/impeccable-paths.mjs +0 -128
- package/template/skills/impeccable/scripts/lib/is-generated.mjs +0 -69
- package/template/skills/impeccable/scripts/lib/target-args.mjs +0 -42
- package/template/skills/impeccable/scripts/live/browser-script-parts.mjs +0 -49
- package/template/skills/impeccable/scripts/live/completion.mjs +0 -19
- package/template/skills/impeccable/scripts/live/event-validation.mjs +0 -137
- package/template/skills/impeccable/scripts/live/insert-ui.mjs +0 -458
- package/template/skills/impeccable/scripts/live/manual-apply.mjs +0 -939
- package/template/skills/impeccable/scripts/live/manual-edit-routes.mjs +0 -357
- package/template/skills/impeccable/scripts/live/manual-edits-buffer.mjs +0 -152
- package/template/skills/impeccable/scripts/live/session-store.mjs +0 -289
- package/template/skills/impeccable/scripts/live/svelte-component.mjs +0 -826
- package/template/skills/impeccable/scripts/live/sveltekit-adapter.mjs +0 -274
- package/template/skills/impeccable/scripts/live/ui-core.mjs +0 -180
- package/template/skills/impeccable/scripts/live/vocabulary.mjs +0 -36
- package/template/skills/impeccable/scripts/live-accept.mjs +0 -812
- package/template/skills/impeccable/scripts/live-browser-dom.js +0 -146
- package/template/skills/impeccable/scripts/live-browser-session.js +0 -123
- package/template/skills/impeccable/scripts/live-browser.js +0 -11173
- package/template/skills/impeccable/scripts/live-commit-manual-edits.mjs +0 -1241
- package/template/skills/impeccable/scripts/live-complete.mjs +0 -75
- package/template/skills/impeccable/scripts/live-copy-edit-agent.mjs +0 -683
- package/template/skills/impeccable/scripts/live-discard-manual-edits.mjs +0 -51
- package/template/skills/impeccable/scripts/live-inject.mjs +0 -583
- package/template/skills/impeccable/scripts/live-insert.mjs +0 -272
- package/template/skills/impeccable/scripts/live-manual-edit-evidence.mjs +0 -363
- package/template/skills/impeccable/scripts/live-poll.mjs +0 -384
- package/template/skills/impeccable/scripts/live-resume.mjs +0 -94
- package/template/skills/impeccable/scripts/live-server.mjs +0 -1135
- package/template/skills/impeccable/scripts/live-status.mjs +0 -61
- package/template/skills/impeccable/scripts/live-target.mjs +0 -30
- package/template/skills/impeccable/scripts/live-wrap.mjs +0 -894
- package/template/skills/impeccable/scripts/live.mjs +0 -297
- package/template/skills/impeccable/scripts/modern-screenshot.umd.js +0 -14
- package/template/skills/impeccable/scripts/palette.mjs +0 -633
- package/template/skills/impeccable/scripts/pin.mjs +0 -214
- package/template/skills/skillopt-sleep/scripts/python/__init__.py +0 -20
- package/template/skills/skillopt-sleep/scripts/python/__main__.py +0 -343
- package/template/skills/skillopt-sleep/scripts/python/backend.py +0 -1371
- package/template/skills/skillopt-sleep/scripts/python/budget.py +0 -75
- package/template/skills/skillopt-sleep/scripts/python/config.py +0 -162
- package/template/skills/skillopt-sleep/scripts/python/consolidate.py +0 -238
- package/template/skills/skillopt-sleep/scripts/python/cycle.py +0 -291
- package/template/skills/skillopt-sleep/scripts/python/dream.py +0 -138
- package/template/skills/skillopt-sleep/scripts/python/experiments/__init__.py +0 -1
- package/template/skills/skillopt-sleep/scripts/python/experiments/gbrain_bench.py +0 -119
- package/template/skills/skillopt-sleep/scripts/python/experiments/personas.py +0 -86
- package/template/skills/skillopt-sleep/scripts/python/experiments/report.py +0 -132
- package/template/skills/skillopt-sleep/scripts/python/experiments/run_experiment.py +0 -178
- package/template/skills/skillopt-sleep/scripts/python/experiments/run_gbrain.py +0 -209
- package/template/skills/skillopt-sleep/scripts/python/experiments/run_transfer.py +0 -155
- package/template/skills/skillopt-sleep/scripts/python/experiments/sweep.py +0 -164
- package/template/skills/skillopt-sleep/scripts/python/gate.py +0 -50
- package/template/skills/skillopt-sleep/scripts/python/harvest.py +0 -304
- package/template/skills/skillopt-sleep/scripts/python/harvest_codex.py +0 -253
- package/template/skills/skillopt-sleep/scripts/python/harvest_sources.py +0 -41
- package/template/skills/skillopt-sleep/scripts/python/judges.py +0 -84
- package/template/skills/skillopt-sleep/scripts/python/llm_miner.py +0 -134
- package/template/skills/skillopt-sleep/scripts/python/memory.py +0 -129
- package/template/skills/skillopt-sleep/scripts/python/mine.py +0 -312
- package/template/skills/skillopt-sleep/scripts/python/replay.py +0 -146
- package/template/skills/skillopt-sleep/scripts/python/rollout.py +0 -153
- package/template/skills/skillopt-sleep/scripts/python/scheduler.py +0 -138
- package/template/skills/skillopt-sleep/scripts/python/slow_update.py +0 -142
- package/template/skills/skillopt-sleep/scripts/python/staging.py +0 -103
- package/template/skills/skillopt-sleep/scripts/python/state.py +0 -96
- package/template/skills/skillopt-sleep/scripts/python/tasks_file.py +0 -81
- package/template/skills/skillopt-sleep/scripts/python/types.py +0 -146
- package/template/skills/skillopt-sleep/scripts/shell/__init__.py +0 -0
- package/template/skills/skillopt-sleep/scripts/shell/eval_only.py +0 -466
- package/template/skills/skillopt-sleep/scripts/shell/materialize_searchqa.py +0 -148
- package/template/skills/skillopt-sleep/scripts/shell/run_alfworld.sh +0 -60
- package/template/skills/skillopt-sleep/scripts/shell/run_searchqa.sh +0 -40
- package/template/skills/skillopt-sleep/scripts/shell/run_spreadsheetbench.sh +0 -39
- package/template/skills/skillopt-sleep/scripts/shell/train.py +0 -556
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
"""SkillOpt-Sleep — core data types.
|
|
2
|
-
|
|
3
|
-
These dataclasses are the interfaces between the sleep-cycle stages
|
|
4
|
-
(harvest -> mine -> replay -> consolidate -> stage). They are intentionally
|
|
5
|
-
plain (no slots, no heavy deps) so the package imports cleanly on any
|
|
6
|
-
Python 3.8+ interpreter and the deterministic experiment runs with zero
|
|
7
|
-
external dependencies.
|
|
8
|
-
"""
|
|
9
|
-
from __future__ import annotations
|
|
10
|
-
|
|
11
|
-
from dataclasses import asdict, dataclass, field
|
|
12
|
-
from typing import Any, Dict, List
|
|
13
|
-
|
|
14
|
-
# ── Stage 1: harvest ──────────────────────────────────────────────────────────
|
|
15
|
-
|
|
16
|
-
@dataclass
|
|
17
|
-
class SessionDigest:
|
|
18
|
-
"""A normalized summary of one local agent session transcript.
|
|
19
|
-
|
|
20
|
-
Produced by source-specific harvesters from Claude Code transcripts or
|
|
21
|
-
Codex Desktop archived sessions.
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
session_id: str
|
|
25
|
-
project: str
|
|
26
|
-
git_branch: str = ""
|
|
27
|
-
started_at: str = ""
|
|
28
|
-
ended_at: str = ""
|
|
29
|
-
user_prompts: List[str] = field(default_factory=list)
|
|
30
|
-
assistant_finals: List[str] = field(default_factory=list)
|
|
31
|
-
tools_used: List[str] = field(default_factory=list)
|
|
32
|
-
files_touched: List[str] = field(default_factory=list)
|
|
33
|
-
feedback_signals: List[str] = field(default_factory=list) # "still broken", "perfect", ...
|
|
34
|
-
n_user_turns: int = 0
|
|
35
|
-
n_assistant_turns: int = 0
|
|
36
|
-
raw_path: str = ""
|
|
37
|
-
|
|
38
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
39
|
-
return asdict(self)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
# ── Stage 2: mine ─────────────────────────────────────────────────────────────
|
|
43
|
-
|
|
44
|
-
@dataclass
|
|
45
|
-
class TaskRecord:
|
|
46
|
-
"""A self-contained recurring task mined from one or more sessions.
|
|
47
|
-
|
|
48
|
-
This is the *training unit* of the sleep cycle — the analogue of a
|
|
49
|
-
SkillOpt benchmark item.
|
|
50
|
-
"""
|
|
51
|
-
|
|
52
|
-
id: str
|
|
53
|
-
project: str
|
|
54
|
-
intent: str # what the user wanted (the "question")
|
|
55
|
-
context_excerpt: str = "" # minimal context needed to attempt it
|
|
56
|
-
# Optional system framing for the rollout. When set (e.g. real benchmarks
|
|
57
|
-
# carrying the research repo's exact rollout_system), the backend uses THIS
|
|
58
|
-
# verbatim instead of its generic instruction wrapper — this keeps scoring
|
|
59
|
-
# faithful to the source task and avoids re-deriving framing the benchmark
|
|
60
|
-
# already bakes in.
|
|
61
|
-
system: str = ""
|
|
62
|
-
attempted_solution: str = "" # what the agent produced before
|
|
63
|
-
outcome: str = "unknown" # success | fail | mixed | unknown
|
|
64
|
-
reference_kind: str = "none" # exact | rubric | rule | none
|
|
65
|
-
reference: str = "" # exact answer, or rubric text
|
|
66
|
-
judge: Dict[str, Any] = field(default_factory=dict) # gbrain-style rule judge
|
|
67
|
-
tags: List[str] = field(default_factory=list)
|
|
68
|
-
source_sessions: List[str] = field(default_factory=list)
|
|
69
|
-
# split ∈ {train, val, test}. val + test come ONLY from real mined tasks and
|
|
70
|
-
# never overlap (val gates updates, test is the final held-out measure). train
|
|
71
|
-
# may be dream-augmented (see origin). Legacy values replay->train,
|
|
72
|
-
# holdout->val are normalized on load.
|
|
73
|
-
split: str = "train"
|
|
74
|
-
# origin ∈ {real, dream}. 'real' = mined from the user's actual sessions;
|
|
75
|
-
# 'dream' = synthetic/augmented for the training pool. Dream tasks are NEVER
|
|
76
|
-
# allowed into val/test, which is the anti-overfitting guarantee.
|
|
77
|
-
origin: str = "real"
|
|
78
|
-
derived_from: str = "" # for dream tasks: the real task id it varies
|
|
79
|
-
|
|
80
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
81
|
-
return asdict(self)
|
|
82
|
-
|
|
83
|
-
@classmethod
|
|
84
|
-
def from_dict(cls, d: Dict[str, Any]) -> "TaskRecord":
|
|
85
|
-
known = {f for f in cls.__dataclass_fields__} # type: ignore[attr-defined]
|
|
86
|
-
return cls(**{k: v for k, v in d.items() if k in known})
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
# ── Stage 3: replay ───────────────────────────────────────────────────────────
|
|
90
|
-
|
|
91
|
-
@dataclass
|
|
92
|
-
class ReplayResult:
|
|
93
|
-
"""Outcome of re-running one TaskRecord offline under a given skill+memory."""
|
|
94
|
-
|
|
95
|
-
id: str
|
|
96
|
-
hard: float = 0.0 # 0/1 exact, or continuous reward
|
|
97
|
-
soft: float = 0.0 # partial credit / judge score 0..1
|
|
98
|
-
response: str = ""
|
|
99
|
-
fail_reason: str = ""
|
|
100
|
-
task_type: str = "task"
|
|
101
|
-
judge_rationale: str = ""
|
|
102
|
-
tools_called: List[str] = field(default_factory=list)
|
|
103
|
-
tokens: int = 0 # approx tokens this rollout cost (for token objective)
|
|
104
|
-
latency_ms: float = 0.0 # wall-clock for this rollout (for latency objective)
|
|
105
|
-
|
|
106
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
107
|
-
return asdict(self)
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# ── Stage 4/5: consolidation report ───────────────────────────────────────────
|
|
111
|
-
|
|
112
|
-
@dataclass
|
|
113
|
-
class EditRecord:
|
|
114
|
-
"""One bounded edit proposed/applied to skill or memory."""
|
|
115
|
-
|
|
116
|
-
target: str # "skill" | "memory"
|
|
117
|
-
op: str # add | delete | replace
|
|
118
|
-
content: str = ""
|
|
119
|
-
anchor: str = "" # for replace/delete: text being changed
|
|
120
|
-
rationale: str = ""
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
@dataclass
|
|
124
|
-
class SleepReport:
|
|
125
|
-
"""Everything one night produced — written to staging for review."""
|
|
126
|
-
|
|
127
|
-
night: int
|
|
128
|
-
project: str
|
|
129
|
-
started_at: str = ""
|
|
130
|
-
ended_at: str = ""
|
|
131
|
-
n_sessions: int = 0
|
|
132
|
-
n_tasks: int = 0
|
|
133
|
-
n_replayed: int = 0
|
|
134
|
-
baseline_score: float = 0.0
|
|
135
|
-
candidate_score: float = 0.0
|
|
136
|
-
accepted: bool = False
|
|
137
|
-
gate_action: str = ""
|
|
138
|
-
no_edits_reason: str = ""
|
|
139
|
-
edits: List[EditRecord] = field(default_factory=list)
|
|
140
|
-
rejected_edits: List[EditRecord] = field(default_factory=list)
|
|
141
|
-
tokens_used: int = 0
|
|
142
|
-
notes: List[str] = field(default_factory=list)
|
|
143
|
-
|
|
144
|
-
def to_dict(self) -> Dict[str, Any]:
|
|
145
|
-
d = asdict(self)
|
|
146
|
-
return d
|
|
File without changes
|
|
@@ -1,466 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""SkillOpt eval-only: run a single skill on a dataset without training.
|
|
3
|
-
|
|
4
|
-
Usage
|
|
5
|
-
-----
|
|
6
|
-
python scripts/eval_only.py \
|
|
7
|
-
--config configs/spreadsheetbench/default.yaml \
|
|
8
|
-
--skill skillopt/envs/spreadsheetbench/skills/initial.md \
|
|
9
|
-
--split_dir /path/to/split \
|
|
10
|
-
--out_root outputs/eval_skill0
|
|
11
|
-
|
|
12
|
-
All YAML keys can be overridden from the CLI, same as train.py.
|
|
13
|
-
"""
|
|
14
|
-
from __future__ import annotations
|
|
15
|
-
|
|
16
|
-
import argparse
|
|
17
|
-
import datetime
|
|
18
|
-
import json
|
|
19
|
-
import os
|
|
20
|
-
import sys
|
|
21
|
-
|
|
22
|
-
_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
23
|
-
_PROJECT_ROOT = os.path.dirname(_SCRIPT_DIR)
|
|
24
|
-
if _PROJECT_ROOT not in sys.path:
|
|
25
|
-
sys.path.insert(0, _PROJECT_ROOT)
|
|
26
|
-
|
|
27
|
-
from skillopt.model import (
|
|
28
|
-
configure_azure_openai,
|
|
29
|
-
configure_claude_code_exec,
|
|
30
|
-
configure_codex_exec,
|
|
31
|
-
configure_qwen_chat,
|
|
32
|
-
set_reasoning_effort,
|
|
33
|
-
set_target_backend,
|
|
34
|
-
set_target_deployment,
|
|
35
|
-
set_optimizer_backend,
|
|
36
|
-
set_optimizer_deployment,
|
|
37
|
-
)
|
|
38
|
-
from skillopt.model.common import default_model_for_backend, normalize_backend_name
|
|
39
|
-
|
|
40
|
-
_OPENAI_DEFAULT_MODEL_SENTINELS = {"gpt-5.4", "gpt-5.5"}
|
|
41
|
-
from skillopt.utils import compute_score
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
# ── Reuse registry from train.py ───────────────────────────────────────────
|
|
45
|
-
|
|
46
|
-
_ENV_REGISTRY: dict[str, type] = {}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def _register_builtins() -> None:
|
|
50
|
-
try:
|
|
51
|
-
from skillopt.envs.alfworld.adapter import ALFWorldAdapter
|
|
52
|
-
_ENV_REGISTRY["alfworld"] = ALFWorldAdapter
|
|
53
|
-
except ImportError:
|
|
54
|
-
pass
|
|
55
|
-
try:
|
|
56
|
-
from skillopt.envs.searchqa.adapter import SearchQAAdapter
|
|
57
|
-
_ENV_REGISTRY["searchqa"] = SearchQAAdapter
|
|
58
|
-
except ImportError:
|
|
59
|
-
pass
|
|
60
|
-
try:
|
|
61
|
-
from skillopt.envs.livemathematicianbench.adapter import LiveMathematicianBenchAdapter
|
|
62
|
-
_ENV_REGISTRY["livemathematicianbench"] = LiveMathematicianBenchAdapter
|
|
63
|
-
except ImportError:
|
|
64
|
-
pass
|
|
65
|
-
try:
|
|
66
|
-
from skillopt.envs.babyvision.adapter import BabyVisionAdapter
|
|
67
|
-
_ENV_REGISTRY["babyvision"] = BabyVisionAdapter
|
|
68
|
-
except ImportError:
|
|
69
|
-
pass
|
|
70
|
-
try:
|
|
71
|
-
from skillopt.envs.spreadsheetbench.adapter import SpreadsheetBenchAdapter
|
|
72
|
-
_ENV_REGISTRY["spreadsheetbench"] = SpreadsheetBenchAdapter
|
|
73
|
-
except ImportError:
|
|
74
|
-
pass
|
|
75
|
-
try:
|
|
76
|
-
from skillopt.envs.mmrb.adapter import MMRBAdapter
|
|
77
|
-
_ENV_REGISTRY["mmrb"] = MMRBAdapter
|
|
78
|
-
except ImportError:
|
|
79
|
-
pass
|
|
80
|
-
try:
|
|
81
|
-
from skillopt.envs.docvqa.adapter import DocVQAAdapter
|
|
82
|
-
_ENV_REGISTRY["docvqa"] = DocVQAAdapter
|
|
83
|
-
except ImportError:
|
|
84
|
-
pass
|
|
85
|
-
try:
|
|
86
|
-
from skillopt.envs.mathverse.adapter import MathVerseAdapter
|
|
87
|
-
_ENV_REGISTRY["mathverse"] = MathVerseAdapter
|
|
88
|
-
except ImportError:
|
|
89
|
-
pass
|
|
90
|
-
try:
|
|
91
|
-
from skillopt.envs.officeqa.adapter import OfficeQAAdapter
|
|
92
|
-
_ENV_REGISTRY["officeqa"] = OfficeQAAdapter
|
|
93
|
-
except ImportError:
|
|
94
|
-
pass
|
|
95
|
-
try:
|
|
96
|
-
from skillopt.envs.sealqa.adapter import SealQAAdapter
|
|
97
|
-
_ENV_REGISTRY["sealqa"] = SealQAAdapter
|
|
98
|
-
except ImportError:
|
|
99
|
-
pass
|
|
100
|
-
try:
|
|
101
|
-
from skillopt.envs.swebench.adapter import SWEBenchAdapter
|
|
102
|
-
_ENV_REGISTRY["swebench"] = SWEBenchAdapter
|
|
103
|
-
except ImportError:
|
|
104
|
-
pass
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
def get_adapter(cfg: dict):
|
|
108
|
-
_register_builtins()
|
|
109
|
-
env_name = cfg.get("env", "alfworld")
|
|
110
|
-
if env_name not in _ENV_REGISTRY:
|
|
111
|
-
raise ValueError(
|
|
112
|
-
f"Unknown environment '{env_name}'. "
|
|
113
|
-
f"Available: {list(_ENV_REGISTRY.keys())}"
|
|
114
|
-
)
|
|
115
|
-
adapter_cls = _ENV_REGISTRY[env_name]
|
|
116
|
-
|
|
117
|
-
import inspect
|
|
118
|
-
sig = inspect.signature(adapter_cls.__init__)
|
|
119
|
-
accepted = set(sig.parameters.keys()) - {"self"}
|
|
120
|
-
adapter_kwargs = {k: cfg[k] for k in accepted if k in cfg}
|
|
121
|
-
return adapter_cls(**adapter_kwargs)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
# ── CLI ────────────────────────────────────────────────────────────────────
|
|
125
|
-
|
|
126
|
-
_BOOL = lambda x: str(x).lower() in ("true", "1", "yes") # noqa: E731
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def parse_args() -> argparse.Namespace:
|
|
130
|
-
p = argparse.ArgumentParser(description="SkillOpt eval-only")
|
|
131
|
-
p.add_argument("--config", type=str, required=True)
|
|
132
|
-
p.add_argument("--skill", type=str, required=True,
|
|
133
|
-
help="Path to skill .md file to evaluate")
|
|
134
|
-
p.add_argument("--split", type=str, default="all",
|
|
135
|
-
help="Which split to eval: train/valid_seen/valid_unseen/all (default: all)")
|
|
136
|
-
p.add_argument("--cfg-options", nargs="+", default=[],
|
|
137
|
-
help="Override config: section.key=value")
|
|
138
|
-
# Legacy flat overrides
|
|
139
|
-
p.add_argument("--env", type=str)
|
|
140
|
-
p.add_argument("--backend", type=str,
|
|
141
|
-
choices=["azure_openai", "codex", "codex_exec", "claude", "claude_chat", "claude_code_exec"])
|
|
142
|
-
p.add_argument("--optimizer_model", type=str)
|
|
143
|
-
p.add_argument("--target_model", type=str)
|
|
144
|
-
p.add_argument("--optimizer_backend", type=str)
|
|
145
|
-
p.add_argument("--target_backend", type=str)
|
|
146
|
-
p.add_argument("--reasoning_effort", type=str,
|
|
147
|
-
choices=["", "low", "medium", "high", "xhigh", "max"])
|
|
148
|
-
p.add_argument("--azure_endpoint", type=str)
|
|
149
|
-
p.add_argument("--azure_api_version", type=str)
|
|
150
|
-
p.add_argument("--azure_api_key", type=str)
|
|
151
|
-
p.add_argument("--azure_openai_endpoint", type=str)
|
|
152
|
-
p.add_argument("--azure_openai_api_version", type=str)
|
|
153
|
-
p.add_argument("--azure_openai_api_key", type=str)
|
|
154
|
-
p.add_argument("--azure_openai_auth_mode", type=str)
|
|
155
|
-
p.add_argument("--azure_openai_ad_scope", type=str)
|
|
156
|
-
p.add_argument("--azure_openai_managed_identity_client_id", type=str)
|
|
157
|
-
p.add_argument("--optimizer_azure_openai_endpoint", type=str)
|
|
158
|
-
p.add_argument("--optimizer_azure_openai_api_version", type=str)
|
|
159
|
-
p.add_argument("--optimizer_azure_openai_api_key", type=str)
|
|
160
|
-
p.add_argument("--optimizer_azure_openai_auth_mode", type=str)
|
|
161
|
-
p.add_argument("--optimizer_azure_openai_ad_scope", type=str)
|
|
162
|
-
p.add_argument("--optimizer_azure_openai_managed_identity_client_id", type=str)
|
|
163
|
-
p.add_argument("--target_azure_openai_endpoint", type=str)
|
|
164
|
-
p.add_argument("--target_azure_openai_api_version", type=str)
|
|
165
|
-
p.add_argument("--target_azure_openai_api_key", type=str)
|
|
166
|
-
p.add_argument("--target_azure_openai_auth_mode", type=str)
|
|
167
|
-
p.add_argument("--target_azure_openai_ad_scope", type=str)
|
|
168
|
-
p.add_argument("--target_azure_openai_managed_identity_client_id", type=str)
|
|
169
|
-
p.add_argument("--codex_exec_path", type=str)
|
|
170
|
-
p.add_argument("--codex_exec_sandbox", type=str)
|
|
171
|
-
p.add_argument("--codex_exec_profile", type=str)
|
|
172
|
-
p.add_argument("--codex_exec_full_auto", type=_BOOL)
|
|
173
|
-
p.add_argument("--codex_exec_reasoning_effort", type=str)
|
|
174
|
-
p.add_argument("--codex_exec_use_sdk", type=str)
|
|
175
|
-
p.add_argument("--codex_exec_network_access", type=_BOOL)
|
|
176
|
-
p.add_argument("--codex_exec_web_search", type=_BOOL)
|
|
177
|
-
p.add_argument("--codex_exec_approval_policy", type=str)
|
|
178
|
-
p.add_argument("--claude_code_exec_path", type=str)
|
|
179
|
-
p.add_argument("--claude_code_exec_profile", type=str)
|
|
180
|
-
p.add_argument("--claude_code_exec_use_sdk", type=str)
|
|
181
|
-
p.add_argument("--claude_code_exec_effort", type=str)
|
|
182
|
-
p.add_argument("--claude_code_exec_max_thinking_tokens", type=int)
|
|
183
|
-
p.add_argument("--out_root", type=str)
|
|
184
|
-
p.add_argument("--data_path", type=str)
|
|
185
|
-
p.add_argument("--split_mode", type=str,
|
|
186
|
-
choices=["ratio", "split_dir"])
|
|
187
|
-
p.add_argument("--split_ratio", type=str)
|
|
188
|
-
p.add_argument("--split_seed", type=int)
|
|
189
|
-
p.add_argument("--split_dir", type=str)
|
|
190
|
-
p.add_argument("--split_output_dir", type=str)
|
|
191
|
-
p.add_argument("--data_root", type=str)
|
|
192
|
-
p.add_argument("--max_turns", type=int)
|
|
193
|
-
p.add_argument("--workers", type=int)
|
|
194
|
-
p.add_argument("--max_api_workers", type=int)
|
|
195
|
-
p.add_argument("--seed", type=int)
|
|
196
|
-
p.add_argument("--test_env_num", type=int)
|
|
197
|
-
p.add_argument("--mode", type=str,
|
|
198
|
-
help="SpreadsheetBench: single/multi/react (default comes from config)")
|
|
199
|
-
return p.parse_args()
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
def main() -> None:
|
|
203
|
-
args = parse_args()
|
|
204
|
-
|
|
205
|
-
from skillopt.config import load_config as _load, flatten_config, is_structured
|
|
206
|
-
|
|
207
|
-
cfg = _load(args.config, overrides=args.cfg_options)
|
|
208
|
-
structured = is_structured(cfg)
|
|
209
|
-
|
|
210
|
-
# Apply legacy --key value overrides
|
|
211
|
-
cli = {k: v for k, v in vars(args).items()
|
|
212
|
-
if v is not None and k not in ("config", "skill", "split", "cfg_options")}
|
|
213
|
-
if cli:
|
|
214
|
-
if structured:
|
|
215
|
-
from skillopt.config import apply_overrides
|
|
216
|
-
_MAP = {
|
|
217
|
-
"backend": "model.backend",
|
|
218
|
-
"optimizer_model": "model.optimizer",
|
|
219
|
-
"target_model": "model.target",
|
|
220
|
-
"optimizer_backend": "model.optimizer_backend",
|
|
221
|
-
"target_backend": "model.target_backend",
|
|
222
|
-
"reasoning_effort": "model.reasoning_effort",
|
|
223
|
-
"azure_endpoint": "model.azure_endpoint",
|
|
224
|
-
"azure_api_version": "model.azure_api_version",
|
|
225
|
-
"azure_api_key": "model.azure_api_key",
|
|
226
|
-
"azure_openai_endpoint": "model.azure_openai_endpoint",
|
|
227
|
-
"azure_openai_api_version": "model.azure_openai_api_version",
|
|
228
|
-
"azure_openai_api_key": "model.azure_openai_api_key",
|
|
229
|
-
"azure_openai_auth_mode": "model.azure_openai_auth_mode",
|
|
230
|
-
"azure_openai_ad_scope": "model.azure_openai_ad_scope",
|
|
231
|
-
"azure_openai_managed_identity_client_id": "model.azure_openai_managed_identity_client_id",
|
|
232
|
-
"optimizer_azure_openai_endpoint": "model.optimizer_azure_openai_endpoint",
|
|
233
|
-
"optimizer_azure_openai_api_version": "model.optimizer_azure_openai_api_version",
|
|
234
|
-
"optimizer_azure_openai_api_key": "model.optimizer_azure_openai_api_key",
|
|
235
|
-
"optimizer_azure_openai_auth_mode": "model.optimizer_azure_openai_auth_mode",
|
|
236
|
-
"optimizer_azure_openai_ad_scope": "model.optimizer_azure_openai_ad_scope",
|
|
237
|
-
"optimizer_azure_openai_managed_identity_client_id": "model.optimizer_azure_openai_managed_identity_client_id",
|
|
238
|
-
"target_azure_openai_endpoint": "model.target_azure_openai_endpoint",
|
|
239
|
-
"target_azure_openai_api_version": "model.target_azure_openai_api_version",
|
|
240
|
-
"target_azure_openai_api_key": "model.target_azure_openai_api_key",
|
|
241
|
-
"target_azure_openai_auth_mode": "model.target_azure_openai_auth_mode",
|
|
242
|
-
"target_azure_openai_ad_scope": "model.target_azure_openai_ad_scope",
|
|
243
|
-
"target_azure_openai_managed_identity_client_id": "model.target_azure_openai_managed_identity_client_id",
|
|
244
|
-
"codex_exec_path": "model.codex_exec_path",
|
|
245
|
-
"codex_exec_sandbox": "model.codex_exec_sandbox",
|
|
246
|
-
"codex_exec_profile": "model.codex_exec_profile",
|
|
247
|
-
"codex_exec_full_auto": "model.codex_exec_full_auto",
|
|
248
|
-
"codex_exec_reasoning_effort": "model.codex_exec_reasoning_effort",
|
|
249
|
-
"codex_exec_use_sdk": "model.codex_exec_use_sdk",
|
|
250
|
-
"codex_exec_network_access": "model.codex_exec_network_access",
|
|
251
|
-
"codex_exec_web_search": "model.codex_exec_web_search",
|
|
252
|
-
"codex_exec_approval_policy": "model.codex_exec_approval_policy",
|
|
253
|
-
"claude_code_exec_path": "model.claude_code_exec_path",
|
|
254
|
-
"claude_code_exec_profile": "model.claude_code_exec_profile",
|
|
255
|
-
"claude_code_exec_use_sdk": "model.claude_code_exec_use_sdk",
|
|
256
|
-
"claude_code_exec_effort": "model.claude_code_exec_effort",
|
|
257
|
-
"claude_code_exec_max_thinking_tokens": "model.claude_code_exec_max_thinking_tokens",
|
|
258
|
-
"seed": "train.seed",
|
|
259
|
-
"test_env_num": "evaluation.test_env_num",
|
|
260
|
-
"env": "env.name",
|
|
261
|
-
"out_root": "env.out_root",
|
|
262
|
-
}
|
|
263
|
-
mapped = []
|
|
264
|
-
for k, v in cli.items():
|
|
265
|
-
dotted = _MAP.get(k)
|
|
266
|
-
if dotted:
|
|
267
|
-
mapped.append(f"{dotted}={v}")
|
|
268
|
-
else:
|
|
269
|
-
mapped.append(f"env.{k}={v}")
|
|
270
|
-
apply_overrides(cfg, mapped)
|
|
271
|
-
else:
|
|
272
|
-
cfg.update(cli)
|
|
273
|
-
|
|
274
|
-
cfg = flatten_config(cfg) if structured else cfg
|
|
275
|
-
|
|
276
|
-
for new_key, old_key in (
|
|
277
|
-
("azure_openai_endpoint", "azure_endpoint"),
|
|
278
|
-
("azure_openai_api_version", "azure_api_version"),
|
|
279
|
-
("azure_openai_api_key", "azure_api_key"),
|
|
280
|
-
):
|
|
281
|
-
if cfg.get(new_key) in (None, "") and cfg.get(old_key) not in (None, ""):
|
|
282
|
-
cfg[new_key] = cfg[old_key]
|
|
283
|
-
|
|
284
|
-
explicit_backend = getattr(args, "backend", None)
|
|
285
|
-
if explicit_backend is None:
|
|
286
|
-
for option in args.cfg_options or []:
|
|
287
|
-
key = str(option).split("=", 1)[0].strip()
|
|
288
|
-
if key == "model.backend":
|
|
289
|
-
explicit_backend = str(option).split("=", 1)[1].strip()
|
|
290
|
-
break
|
|
291
|
-
|
|
292
|
-
backend = normalize_backend_name(cfg.get("model_backend") or cfg.get("target_backend") or "azure_openai")
|
|
293
|
-
|
|
294
|
-
def _has_model_override(dotted_key: str, legacy_key: str) -> bool:
|
|
295
|
-
if getattr(args, legacy_key, None) is not None:
|
|
296
|
-
return True
|
|
297
|
-
for option in args.cfg_options or []:
|
|
298
|
-
key = str(option).split("=", 1)[0].strip()
|
|
299
|
-
if key == dotted_key:
|
|
300
|
-
return True
|
|
301
|
-
return False
|
|
302
|
-
|
|
303
|
-
if explicit_backend is not None:
|
|
304
|
-
backend = normalize_backend_name(explicit_backend)
|
|
305
|
-
cfg["model_backend"] = backend
|
|
306
|
-
if backend in {"claude", "claude_chat"}:
|
|
307
|
-
cfg.setdefault("optimizer_backend", "claude_chat")
|
|
308
|
-
cfg.setdefault("target_backend", "claude_chat")
|
|
309
|
-
elif backend in {"codex", "codex_exec"}:
|
|
310
|
-
cfg.setdefault("optimizer_backend", "openai_chat")
|
|
311
|
-
cfg.setdefault("target_backend", "codex_exec")
|
|
312
|
-
elif backend == "claude_code_exec":
|
|
313
|
-
cfg.setdefault("optimizer_backend", "openai_chat")
|
|
314
|
-
cfg.setdefault("target_backend", "claude_code_exec")
|
|
315
|
-
else:
|
|
316
|
-
cfg.setdefault("optimizer_backend", "openai_chat")
|
|
317
|
-
cfg.setdefault("target_backend", "openai_chat")
|
|
318
|
-
else:
|
|
319
|
-
cfg.setdefault("optimizer_backend", "openai_chat")
|
|
320
|
-
cfg.setdefault("target_backend", "openai_chat")
|
|
321
|
-
|
|
322
|
-
if cfg.get("optimizer_backend") == "claude_chat":
|
|
323
|
-
if (
|
|
324
|
-
str(cfg.get("optimizer_model", "") or "").strip() in _OPENAI_DEFAULT_MODEL_SENTINELS
|
|
325
|
-
and not _has_model_override("model.optimizer", "optimizer_model")
|
|
326
|
-
):
|
|
327
|
-
cfg["optimizer_model"] = default_model_for_backend("claude_chat")
|
|
328
|
-
if cfg.get("target_backend") == "claude_chat":
|
|
329
|
-
if (
|
|
330
|
-
str(cfg.get("target_model", "") or "").strip() in _OPENAI_DEFAULT_MODEL_SENTINELS
|
|
331
|
-
and not _has_model_override("model.target", "target_model")
|
|
332
|
-
):
|
|
333
|
-
cfg["target_model"] = default_model_for_backend("claude_chat")
|
|
334
|
-
if cfg.get("target_backend") == "claude_code_exec":
|
|
335
|
-
if (
|
|
336
|
-
str(cfg.get("target_model", "") or "").strip() in _OPENAI_DEFAULT_MODEL_SENTINELS
|
|
337
|
-
and not _has_model_override("model.target", "target_model")
|
|
338
|
-
):
|
|
339
|
-
cfg["target_model"] = default_model_for_backend("claude_chat")
|
|
340
|
-
|
|
341
|
-
if not cfg.get("out_root"):
|
|
342
|
-
env = cfg.get("env", "unknown")
|
|
343
|
-
model = cfg.get("target_model", "unknown").replace("/", "-")
|
|
344
|
-
ts = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
345
|
-
cfg["out_root"] = os.path.join("outputs", f"eval_{env}_{model}_{ts}")
|
|
346
|
-
|
|
347
|
-
cfg["out_root"] = os.path.abspath(cfg["out_root"])
|
|
348
|
-
|
|
349
|
-
out_root = cfg["out_root"]
|
|
350
|
-
os.makedirs(out_root, exist_ok=True)
|
|
351
|
-
|
|
352
|
-
# Load skill
|
|
353
|
-
skill_path = os.path.abspath(args.skill)
|
|
354
|
-
with open(skill_path) as f:
|
|
355
|
-
skill_content = f.read()
|
|
356
|
-
print(f" [skill] {skill_path} ({len(skill_content)} chars)")
|
|
357
|
-
|
|
358
|
-
# Configure models
|
|
359
|
-
configure_azure_openai(
|
|
360
|
-
endpoint=(cfg.get("azure_openai_endpoint") or cfg.get("azure_endpoint") or None),
|
|
361
|
-
api_version=(cfg.get("azure_openai_api_version") or cfg.get("azure_api_version") or None),
|
|
362
|
-
api_key=(cfg.get("azure_openai_api_key") or cfg.get("azure_api_key") or None),
|
|
363
|
-
auth_mode=cfg.get("azure_openai_auth_mode") or None,
|
|
364
|
-
ad_scope=cfg.get("azure_openai_ad_scope") or None,
|
|
365
|
-
managed_identity_client_id=cfg.get("azure_openai_managed_identity_client_id") or None,
|
|
366
|
-
optimizer_endpoint=cfg.get("optimizer_azure_openai_endpoint") or None,
|
|
367
|
-
optimizer_api_version=cfg.get("optimizer_azure_openai_api_version") or None,
|
|
368
|
-
optimizer_api_key=cfg.get("optimizer_azure_openai_api_key") or None,
|
|
369
|
-
optimizer_auth_mode=cfg.get("optimizer_azure_openai_auth_mode") or None,
|
|
370
|
-
optimizer_ad_scope=cfg.get("optimizer_azure_openai_ad_scope") or None,
|
|
371
|
-
optimizer_managed_identity_client_id=(
|
|
372
|
-
cfg.get("optimizer_azure_openai_managed_identity_client_id") or None
|
|
373
|
-
),
|
|
374
|
-
target_endpoint=cfg.get("target_azure_openai_endpoint") or None,
|
|
375
|
-
target_api_version=cfg.get("target_azure_openai_api_version") or None,
|
|
376
|
-
target_api_key=cfg.get("target_azure_openai_api_key") or None,
|
|
377
|
-
target_auth_mode=cfg.get("target_azure_openai_auth_mode") or None,
|
|
378
|
-
target_ad_scope=cfg.get("target_azure_openai_ad_scope") or None,
|
|
379
|
-
target_managed_identity_client_id=(
|
|
380
|
-
cfg.get("target_azure_openai_managed_identity_client_id") or None
|
|
381
|
-
),
|
|
382
|
-
)
|
|
383
|
-
set_optimizer_backend(cfg.get("optimizer_backend", "openai_chat"))
|
|
384
|
-
set_target_backend(cfg.get("target_backend", "openai_chat"))
|
|
385
|
-
set_optimizer_deployment(cfg.get("optimizer_model", default_model_for_backend(backend)))
|
|
386
|
-
set_target_deployment(cfg.get("target_model", default_model_for_backend(backend)))
|
|
387
|
-
configure_codex_exec(
|
|
388
|
-
path=cfg.get("codex_exec_path", "codex"),
|
|
389
|
-
sandbox=cfg.get("codex_exec_sandbox", "workspace-write"),
|
|
390
|
-
profile=cfg.get("codex_exec_profile", ""),
|
|
391
|
-
full_auto=cfg.get("codex_exec_full_auto", False),
|
|
392
|
-
reasoning_effort=cfg.get("codex_exec_reasoning_effort", "none"),
|
|
393
|
-
use_sdk=cfg.get("codex_exec_use_sdk", None),
|
|
394
|
-
network_access=cfg.get("codex_exec_network_access", False),
|
|
395
|
-
web_search=cfg.get("codex_exec_web_search", False),
|
|
396
|
-
approval_policy=cfg.get("codex_exec_approval_policy", "never"),
|
|
397
|
-
)
|
|
398
|
-
configure_claude_code_exec(
|
|
399
|
-
path=cfg.get("claude_code_exec_path", "claude"),
|
|
400
|
-
profile=cfg.get("claude_code_exec_profile", ""),
|
|
401
|
-
use_sdk=cfg.get("claude_code_exec_use_sdk", None),
|
|
402
|
-
effort=cfg.get("claude_code_exec_effort", cfg.get("reasoning_effort", "medium")),
|
|
403
|
-
max_thinking_tokens=cfg.get("claude_code_exec_max_thinking_tokens", 16384),
|
|
404
|
-
)
|
|
405
|
-
configure_qwen_chat(
|
|
406
|
-
base_url=cfg.get("qwen_chat_base_url") or None,
|
|
407
|
-
api_key=cfg.get("qwen_chat_api_key") or None,
|
|
408
|
-
temperature=cfg.get("qwen_chat_temperature"),
|
|
409
|
-
timeout_seconds=cfg.get("qwen_chat_timeout_seconds"),
|
|
410
|
-
max_tokens=cfg.get("qwen_chat_max_tokens"),
|
|
411
|
-
enable_thinking=cfg.get("qwen_chat_enable_thinking"),
|
|
412
|
-
target_base_url=cfg.get("target_qwen_chat_base_url") or None,
|
|
413
|
-
target_api_key=cfg.get("target_qwen_chat_api_key") or None,
|
|
414
|
-
target_temperature=cfg.get("target_qwen_chat_temperature"),
|
|
415
|
-
target_timeout_seconds=cfg.get("target_qwen_chat_timeout_seconds"),
|
|
416
|
-
target_max_tokens=cfg.get("target_qwen_chat_max_tokens"),
|
|
417
|
-
target_enable_thinking=cfg.get("target_qwen_chat_enable_thinking"),
|
|
418
|
-
)
|
|
419
|
-
set_reasoning_effort(cfg.get("reasoning_effort", "") or None)
|
|
420
|
-
|
|
421
|
-
# Build adapter
|
|
422
|
-
adapter = get_adapter(cfg)
|
|
423
|
-
adapter.setup(cfg)
|
|
424
|
-
|
|
425
|
-
seed = cfg.get("seed", 42)
|
|
426
|
-
split = args.split or "all"
|
|
427
|
-
|
|
428
|
-
if split == "all":
|
|
429
|
-
items = (
|
|
430
|
-
adapter.build_eval_env(0, "train", seed)
|
|
431
|
-
+ adapter.build_eval_env(0, "valid_seen", seed)
|
|
432
|
-
+ adapter.build_eval_env(0, "valid_unseen", seed)
|
|
433
|
-
)
|
|
434
|
-
else:
|
|
435
|
-
env_num = cfg.get("test_env_num", 0)
|
|
436
|
-
items = adapter.build_eval_env(env_num, split, seed)
|
|
437
|
-
|
|
438
|
-
print(f"\n [eval] split={split} items={len(items)}")
|
|
439
|
-
print(f" [eval] out_root={out_root}")
|
|
440
|
-
print(f"{'='*60}")
|
|
441
|
-
|
|
442
|
-
# Run rollout
|
|
443
|
-
results = adapter.rollout(items, skill_content, out_root)
|
|
444
|
-
|
|
445
|
-
# Score
|
|
446
|
-
hard, soft = compute_score(results)
|
|
447
|
-
print(f"\n{'='*60}")
|
|
448
|
-
print(f" Results: hard={hard:.4f} soft={soft:.4f} (n={len(results)})")
|
|
449
|
-
print(f"{'='*60}")
|
|
450
|
-
|
|
451
|
-
# Save summary
|
|
452
|
-
summary = {
|
|
453
|
-
"skill": skill_path,
|
|
454
|
-
"split": split,
|
|
455
|
-
"n_items": len(results),
|
|
456
|
-
"hard": hard,
|
|
457
|
-
"soft": soft,
|
|
458
|
-
}
|
|
459
|
-
with open(os.path.join(out_root, "eval_summary.json"), "w") as f:
|
|
460
|
-
json.dump(summary, f, indent=2, ensure_ascii=False)
|
|
461
|
-
|
|
462
|
-
print(f" Saved to: {out_root}")
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
if __name__ == "__main__":
|
|
466
|
-
main()
|