Prior Work Deep-Dive · 소스 코드 근거
논문: “SkillOpt: Executive Strategy for Self-Evolving Agent Skills” (arXiv:2605.23904, microsoft/SkillOpt).
이 페이지의 모든 시그니처와 인용은 클론된 구현 /home/v-seungplee/SkillOpt
(skillopt/engine/trainer.py, skillopt/evaluation/gate.py, skillopt/optimizer/*, skillopt/prompts/*,
skillopt_sleep/*) 원문에서 그대로 가져왔다. 함수 카드와 파이프라인 단계는 접힌 토글이다 —
제목을 클릭하면 원문 코드와 입출력 예시가 펼쳐진다.
모델 가중치는 동결하고, 스킬 문서(.md) 하나를 “학습 가능한 상태”로 삼아 에폭 · 미니배치 · 러닝레이트 · 검증 게이트라는 딥러닝 훈련 규율로 최적화하는 시스템이다. 별도의 옵티마이저 LLM이 채점된 롤아웃을 bounded add / delete / replace 편집으로 바꾸고, 후보 편집은 held-out 검증 점수를 엄격히(strictly) 올릴 때만 수용된다. README의 자기 설명(원문): “SkillOpt treats the skill document as the trainable state of a frozen agent … A textual learning-rate budget, a rejected-edit buffer, and an epoch-wise slow / meta update make skill training stable while adding zero inference-time model calls at deployment.”
배포 산출물은 압축된 best_skill.md(전형적으로 300–2,000 토큰)이며,
변경되지 않은 타깃 모델에 그대로 붙는다 — 추론 시점 추가 모델 호출이 0이다.
클론된 레포에는 루프가 두 벌 있다: 논문 본체인 skillopt 패키지의
ReflACTTrainer(벤치마크 훈련 루프 — 코드 내부명은 ReflACT다), 그리고 같은
기계를 야간 오프라인 자기진화로 옮긴 skillopt_sleep
(harvest → mine → replay → consolidate(gate) → stage → adopt)이다.
논문이 말하는 4상(Rollout → Reflect → Edit → Gate)은 코드에서 6단계로 구현되어 있다: Edit이 Aggregate + Select + Update 세 단계로, Gate가 Evaluate 단계로 펼쳐진다. 아래 플로우차트는 코드의 6단계를 논문 4상에 접어 표기했다.
skillopt/engine/trainer.py — 모듈 docstring 원문
"""ReflACT Trainer — the main training loop. Orchestrates the 6-stage ReflACT pipeline: 1. Rollout — execute episodes with current skill 2. Reflect — analyze trajectories, generate patches 3. Aggregate — hierarchical merge of patches 4. Select — rank and select top edits 5. Update — apply edits to skill document 6. Evaluate — validate candidate skill, accept/reject """
adapter.rollout(train_env, current_skill, rollout_dir, use_eval_feedback=True).
각 결과 dict는 hard(exact-match 0/1)와 soft(F1/부분점수) 점수,
fail_reason, 전체 trajectory를 담는다. 배치는 고정 시드 풀에서 에폭마다 셔플된다
(base_seeds, 신경망 훈련의 데이터로더 대응물).run_minibatch_reflect가 실패 궤적과 성공 궤적을 따로 미니배치(기본 8개)로 묶어
analyst 프롬프트(analyst_error.md / analyst_success.md)를 병렬 호출한다.
각 미니배치가 patch(편집 제안 목록)를 반환하고, _normalise_patches가
source_type: failure|success와 support_count(몇 개 궤적이 지지하는가)를 붙인다.
이때 이전 스텝들의 실패 패턴 + 기각된 편집 요약(step_buffer_context)이 함께 주입된다.merge_patches가 실패-우선 계층 병합(failure-first hierarchical merge)으로
패치들을 하나로 합친다. Select: 편집 예산(= 러닝레이트)을 정한다 —
lr_control_mode=fixed면 스케줄러(edit_budget max, min_edit_budget min, constant/cosine 등),
autonomous면 옵티마이저 LLM이 직접 개수를 결정(textual learning rate).
그 뒤 rank_and_select가 중요도 순으로 상위 L개만 남긴다.
Update: apply_patch_with_report(patch 모드) 또는
rewrite_skill_from_suggestions(rewrite 모드)로 후보 스킬 문서를 만든다.valid_seen split)에 통째로 롤아웃해 채점하고
(해시 캐시 sel_cache로 중복 평가 방지), 순수 결정 함수
evaluate_gate가 accept_new_best | accept | reject를 판정한다.
수용 기준은 엄격 부등호: cand_score > current_score가 아니면 REJECT이고
스킬은 이전 상태로 롤백된다. 기각 시 시도한 편집 전부와 점수 하락 폭이
step buffer에 “부정 피드백”으로 적재된다(rejected-edit buffer).slow_update.md)가 스킬 문서의 보호 영역
(SLOW_UPDATE 마커 사이)에 에폭 수준 지침을 쓴다 — 직전 에폭에 자신이 쓴 지침이
실제로 도움됐는지 반성하는 절차가 프롬프트에 내장돼 있다.
Meta skill: run_meta_skill이 같은 비교쌍에서 옵티마이저 쪽 메타 지식을 증류해
다음 에폭의 모든 Reflect/Select 호출 컨텍스트로 주입한다(타깃 스킬이 아니라 옵티마이저가 학습).out_root/best_skill.md로 매 스텝 덮어써지고,
runtime_state.json이 current/best 점수 · 출처(origin) · 경로를 기록해 재시작(resume)을 지원한다.
force-accept 모드의 slow update 지침은 current_skill에만 주입되고 best_skill은
“검증 최고 스텝의 충실한 스냅샷”으로 보호된다(소스 주석 원문:
“best_skill must remain a faithful snapshot of the val-best step”).run_sleep_cycle() docstring 원문: “harvest -> mine -> replay ->
consolidate(gate) -> stage (-> optional adopt)”. 벤치마크 대신 사용자의 지난 Claude Code / Codex
세션 트랜스크립트에서 반복 태스크를 채굴해 훈련 데이터로 쓰고, 게이트 통과분만 스테이징한다.
harvest_for_config가 트랜스크립트를 SessionDigest로 정규화하고
(마지막 수확 시각 이후만; 첫 실행은 lookback_hours=72),
mine이 채점 가능한 TaskRecord(intent + 판정 기준, train/val 분할
holdout_fraction=0.34)를 뽑는다. 실백엔드면 LLM 마이너, 아니면 휴리스틱.consolidate() docstring 원문: “Run one consolidation epoch:
reflect -> bounded edit -> gate.” train 태스크가 reflect를 구동하고 val 태스크가 게이트를 구동한다.
옵션으로 dream rollouts(같은 태스크 K회 굴려 good-vs-bad 대조)와 associative recall
(아카이브에서 유사 과거 태스크 K개 소환)이 train 쪽만 증강한다 — val은 절대 오염하지 않는다.write_staging이 proposed_SKILL.md / proposed_CLAUDE.md / report.md / diagnostics.json을
.skillopt-sleep/staging/<ts>/에 쓰고(시크릿 redaction 포함), 별도의 명시적
adopt 스텝이 백업을 뜬 뒤에야 라이브 파일 위로 복사한다. 편집은
<!-- SKILLOPT-SLEEP:LEARNED START/END --> 보호 영역 안에서만 일어나
사용자의 손 편집 내용은 절대 침범하지 않는다.skillopt/gradient/reflect.py — 시그니처 원문
def run_minibatch_reflect( results: list[dict], skill_content: str, prediction_dir: str, patches_dir: str, workers: int, failure_only: bool, minibatch_size: int = 8, edit_budget: int = 4, random_seed: int | None = None, *, error_system: str | None = None, success_system: str | None = None, rejection_context: str = "", trajectory_memory_context: str = "", step_buffer_context: str = "", meta_skill_context: str = "", update_mode: str = "patch", skill_aware_reflection: bool | None = None, skill_aware_appendix_source: str | None = None, ) -> list[dict | None]: """Full minibatch reflect stage: group → parallel optimizer calls → patches. Separates failure and success trajectories, splits each into minibatches of size M, runs all minibatches in parallel, and saves patch files."""
궤적을 실패/성공으로 분리해서 각각 다른 analyst 프롬프트로 미니배치 분석한다 — 실패에서는 고칠 것을, 성공에서는 보존/일반화할 것을 뽑는다. 반환되는 각 원소가 RawPatch다.
입력 → 출력 예시 (RawPatch 한 개의 형태)
run_minibatch_reflect(rollout_results, current_skill, pred_dir, patches_dir, workers=16, failure_only=False) # -> [ {"patch": {"edits": [ # {"op": "add", "content": "When the sheet has merged cells, unmerge before ...", # "source_type": "failure", "support_count": 3}, ...]}, # "source_type": "failure", "batch_size": 8, "failure_summary": [...]}, ... ]
skillopt/gradient/aggregate.py — 시그니처 + docstring 원문
def merge_patches( skill_content: str, failure_patches: list[dict], success_patches: list[dict], batch_size: int = 8, verbose: bool = True, workers: int = 16, update_mode: str = "patch", meta_skill_context: str = "", ) -> dict: """Failure-first hierarchical merge with support count tracking. 1. Merge failure patches independently (parallel) 2. Merge success patches independently (parallel) 3. Final merge: combine both groups with failure priority"""
신경망의 gradient accumulation 대응물. 여러 미니배치의 편집 제안을 계층적으로 병합하되
실패 유래 편집에 우선권을 주고, 각 편집이 몇 개 궤적의 지지를 받는지(support_count)를 보존한다
— 이 값이 Select 단계의 랭킹 근거가 된다.
skillopt/optimizer/lr_autonomous.py + skillopt/prompts/lr_autonomous.md
def decide_autonomous_learning_rate(*, skill_content: str, merged_patch: dict, update_mode: str, rollout_hard: float, rollout_soft: float, rollout_n: int, step_buffer_context: str = "", meta_skill_context: str = "", ) -> dict: """Ask the optimizer to choose the number of update items for this step. The prompt intentionally avoids default budgets, candidate budget lists, or scheduler history. The only hard post-processing is validity: the returned integer is clamped to the available item count."""
“러닝레이트”가 실수 스텝 크기가 아니라 이번 스텝에 적용할 편집 개수다.
fixed 모드에서는 스케줄러가 정한다: build_scheduler(mode=cfg["lr_scheduler"],
max_lr=cfg["edit_budget"], min_lr=cfg.get("min_edit_budget", 2), total_steps=total_steps) 후 매 스텝
edit_budget = scheduler.step(). autonomous 모드에서는 옵티마이저 LLM이 증거만 보고
개수를 정한다. 프롬프트 원문의 응답 계약:
Respond ONLY with a valid JSON object:
{
"learning_rate": <non-negative integer>,
"reasoning": "<brief evidence-based reason>",
"confidence": "low|medium|high",
"risk_notes": ["<short note>", ...]
}
입력 → 출력 예시 (lr_decision.json에 저장되는 레코드)
decide_autonomous_learning_rate(skill_content=skill, merged_patch=merged, update_mode="patch", rollout_hard=0.4375, rollout_soft=0.5211, rollout_n=16) # -> {"learning_rate": 3, "raw_learning_rate": 3, "available_update_items": 9, # "clamped": false, "fallback": false, "confidence": "medium", # "reasoning": "...", "risk_notes": [...], "raw_response": "..."} # 파싱 실패 시 learning_rate=0(fallback=true) — 이번 스텝은 무편집으로 안전 폴백
skillopt/optimizer/clip.py — 시그니처 + docstring 원문
def rank_and_select( skill_content: str, patch: dict, max_edits: int, meta_skill_context: str = "", update_mode: str = "patch", ) -> dict: """Use a optimizer LLM to rank edits by importance, then keep top-L. If the edit pool is within budget, returns the patch unchanged. Otherwise, calls the optimizer to rank and select the most impactful edits."""
gradient clipping 대응물. 병합된 편집 풀이 예산(위 카드의 러닝레이트)을 넘으면
옵티마이저가 중요도 랭킹을 매겨 상위 L개만 통과시킨다. 결과는 스텝 디렉토리의
ranked_edits.json으로 영속된다.
skillopt/evaluation/gate.py — dataclass + 결정 로직 원문
@dataclass(frozen=True) class GateResult: action: GateAction # "accept_new_best" | "accept" | "reject" current_skill: str; current_score: float best_skill: str; best_score: float; best_step: int def evaluate_gate(candidate_skill, cand_hard, current_skill, current_score, best_skill, best_score, best_step, global_step, *, cand_soft=0.0, metric="hard", mixed_weight=0.5) -> GateResult: cand_score = select_gate_score(cand_hard, cand_soft, metric, mixed_weight) if cand_score > current_score: # 엄격 부등호 — 동점도 기각 if cand_score > best_score: return GateResult(action="accept_new_best", ...) return GateResult(action="accept", ...) return GateResult(action="reject", ...) # current/best 그대로 = 롤백
모듈 docstring 원문: “Analogous to validation-based early stopping and model
selection in neural network training … This module is the pure decision function.”
부작용(캐시 조회, 롤아웃, 상태 변이)은 전부 트레이너가 소유하고 게이트는 순수 함수다.
metric은 hard | soft | mixed(가중평균 (1-w)·hard + w·soft) 셋 중 하나.
입력 → 출력 예시
evaluate_gate(candidate_skill=cand, cand_hard=0.6250, current_skill=cur, current_score=0.5625,
best_skill=best, best_score=0.6000, best_step=7, global_step=12)
# -> GateResult(action="accept_new_best", current_score=0.625, best_score=0.625, best_step=12)
# cand_hard=0.5625였다면 -> GateResult(action="reject", ...) # 동점은 통과 못 함
skillopt/engine/trainer.py — buf_entry 구성(원문 발췌) + _format_step_buffer
# 매 스텝 EVALUATE 직후 (trainer.py): buf_entry = {"step": global_step, "action": action, "n_total": n_total, "n_fail": n_fail, "failure_patterns": failure_patterns} if "reject" in action and ranked_patch: # 기각된 스텝만 편집 내역을 첨부 buf_entry["score_before"] = current_score buf_entry["score_after"] = cand_gate_score buf_entry["rejected_edits"] = rejected_edits step_buffer.append(buf_entry)
에폭 내 모든 이전 스텝의 실패 패턴과, 기각된 스텝의 “시도한 편집 + 점수 하락”을
누적하는 버퍼다. _format_step_buffer가 이것을 한 컨텍스트 블록으로 렌더링해
다음 스텝의 Reflect · LR 결정 · Rewrite 프롬프트에 전부 주입한다. 렌더링 서두(원문):
“Below is a summary of previous steps in this epoch. Use it to avoid repeating ineffective
edits and to prioritise failure patterns that remain unsolved.”
렌더링 출력 예시 (형식은 소스 문자열 그대로)
### Step 4 — REJECT (5/16 failed)
- "wrong_tool: used pandas where openpyxl is required" (×3, tasks: t12, t18, t27)
Rejected edits (score 0.5625 → 0.5):
1. [add] "Always coerce date columns with pd.to_datetime before comparison"
2. [replace] target="..." → "..."
skillopt/optimizer/slow_update.py + skillopt/prompts/slow_update.md
def run_slow_update( skill_content: str, results_prev: list[dict], results_curr: list[dict], items: list[dict], *, prev_skill: str = "", prev_slow_update_content: str = "", prev_rollout_dir: str = "", curr_rollout_dir: str = "", comparison_pairs: list[dict] | None = None, system_prompt: str | None = None, ) -> dict | None: ... def build_comparison_pairs(results_prev, results_curr, items, ...) -> list[dict]: # category ∈ {improved, regressed, persistent_fail, stable_success}
에폭 말에 같은 태스크 20개(slow_update_samples)를 이전/현재 스킬로 둘 다 굴려
종단 비교쌍을 만들고, 스텝 단위 편집이 못 잡는 systemic drift를 겨냥한다. 프롬프트 원문:
“The per-step analyst sees individual trajectories and proposes local patches. YOU see how the
skill has evolved across an entire epoch … identify systemic drift, regressions, and persistent
blind spots that step-level edits cannot catch.” 산출 지침은 스킬 문서의
SLOW_UPDATE 보호 영역에 들어가며, 직전 에폭 지침이 도움됐는지의 자기 반성이 의무다.
수용은 두 모드: 기본은 current_skill에만 강제 주입(force-accept; best_skill은 불가침),
slow_update_gate_with_selection=true면 스텝과 동일한 검증 게이트를 통과해야 한다.
skillopt/optimizer/meta_skill.py — 시그니처 원문
def run_meta_skill( prev_skill: str, curr_skill: str, comparison_pairs: list[dict], *, prev_meta_skill_content: str = "", system_prompt: str | None = None, ) -> dict | None: """Produce updated optimizer-side meta skill from adjacent epochs."""
slow update와 같은 종단 비교쌍을 먹지만 방향이 다르다: 타깃 스킬이 아니라
옵티마이저 자신이 “어떤 편집이 이 환경에서 통하더라”를 학습한다. 결과는
meta_skill/epoch_NN/meta_skill_result.json에 저장되고, 다음 에폭의 Reflect ·
Aggregate · Select · LR 결정 호출 전부에 컨텍스트로 주입된다
(active_meta_skill = _load_meta_skill_content(out_root, epoch - 1)).
skillopt/engine/trainer.py — 매 스텝 저장 경로 (원문 발췌)
_save_skill(out_root, global_step, current_skill) # skills/skill_v0012.md — 전 궤적 보존 with open(os.path.join(out_root, "best_skill.md"), "w") as f: f.write(best_skill) # 검증 최고 스킬 = 배포 산출물 _persist_runtime_state(global_step) # runtime_state.json: current/best 점수·origin·경로
모든 스텝의 스킬 버전이 skills/skill_v<NNNN>.md로 남고,
게이트 기준 최고본만 best_skill.md로 계속 덮어써진다. README 기준 이 파일이
“typically 300–2,000 tokens”의 최종 배포 아티팩트이고, 6개 벤치마크 × 7개 타깃 모델 ×
3개 하네스의 52개 셀 전부에서 best 또는 tied-best, GPT-5.5에서 no-skill 대비
+23.5(직접 챗) / +24.8(Codex 루프) / +19.1(Claude Code)을 보고한다.
runtime_state.json은 last_completed_step,
current_origin/best_origin(예: step_0012,
slow_update_epoch_02)을 기록해 중단-재개를 지원한다.
skillopt_sleep/cycle.py + consolidate.py + dream.py — 시그니처 원문
def run_sleep_cycle(cfg=None, *, seed_tasks=None, dry_run=False, clock=None) -> CycleOutcome # CycleOutcome: (report: SleepReport, staging_dir: str, adopted: bool, adopted_paths: list[str]) def consolidate(backend, tasks, skill, memory, *, edit_budget: int = 4, gate_metric: str = "mixed", gate_mixed_weight: float = 0.5, gate_mode: str = "on", rollouts_k: int = 1, ...) -> ConsolidationResult """Run one consolidation epoch: reflect -> bounded edit -> gate.""" def dream_consolidate(backend, tasks, skill, memory, *, history_tasks=None, recall_k=0, dream_rollouts=1, dream_factor=0, ...) -> ConsolidationResult
밤마다 한 번 도는 SkillOpt 1 에폭. ConsolidationResult가
applied_edits / rejected_edits(EditRecord 리스트)와 holdout
baseline/candidate 점수를 들고 나오고, 리포트에는 기각분이
“Rejected by gate (kept as negative feedback)” 섹션으로 그대로 노출된다.
dream(합성 변형 K배) / recall(유사 과거 태스크 소환)은 기본 OFF이며 train 분할만 증강한다.
출력 예시 (report.md 렌더링, _render_report_md 형식 그대로)
# SkillOpt-Sleep — night 7 report - held-out score: 0.500 -> 0.667 - gate: **accept_new_best** (accepted=True) ## Accepted edits - [skill/add] Use uv, not pip, in this repo _why: 3 sessions re-derived this_ ## Rejected by gate (kept as negative feedback) - [memory/add] Always run the full test suite before every commit
skillopt_sleep/memory.py + types.py — 원문
LEARNED_START = "<!-- SKILLOPT-SLEEP:LEARNED START -->" LEARNED_END = "<!-- SKILLOPT-SLEEP:LEARNED END -->" @dataclass class EditRecord: """One bounded edit proposed/applied to skill or memory.""" target: str # "skill" | "memory" op: str # add | delete | replace content: str = "" anchor: str = "" # for replace/delete: text being changed rationale: str = "" def apply_edits(doc: str, edits: List[EditRecord]) -> Tuple[str, List[EditRecord]]: """Apply add/delete/replace edits to the protected learned region. Returns (new_doc, applied_edits). Dedups: an `add` whose content already exists (normalized) is skipped."""
편집 연산이 add / delete / replace 셋뿐이고, 마커로 둘러싼 보호 영역 안에서만 작동한다 (모듈 docstring 원문: “the sleep cycle never clobbers the user's hand-written content”). 정규화 중복 add는 조용히 스킵되고 delete/replace는 정규화된 anchor 부분 문자열로 매칭된다. 본체 트레이너의 patch 모드도 같은 3연산 계약을 쓴다.
입력 → 출력 예시
apply_edits(claude_md, [EditRecord(target="memory", op="add", content="Use uv, not pip, in this repo")]) # -> (LEARNED 영역에 "- Use uv, not pip, in this repo" 불릿이 추가된 새 문서, [적용된 EditRecord])
skillopt_sleep/state.py + scheduler.py — 원문
DEFAULT_STATE = {
"version": 1,
"night": 0,
"last_harvest": {}, # project -> iso timestamp of last harvested record
"slow_memory": "", # cross-night consolidated lessons (meta-skill analogue)
"history": [], # list of per-night summaries
"task_archive": [], # capped(300) past mined tasks (for associative recall)
}
state.json이 ~/.skillopt-sleep에 살며 밤 에피소드를 장기 능력으로 잇는다
(docstring 원문: “the ‘long-term’ store that turns nightly episodes into durable
competence”). slow_memory 필드는 본체의 meta-skill 대응물이라고 소스가 직접
주석한다. 스케줄러는 crontab에 관리 블록을 심어 기본 03:17에 발화한다 —
정각(:00)을 피하는 이유가 주석에 있다: “so many users don't all hit the API at the same
instant.” 크론이 하는 일은 스테이징까지다: “it only STAGES a proposal — adopt is
still manual.”
SkillOpt은 텍스트 스킬 문서를, 우리는 실행 가능한 세계 모델 + 확률 달린 스킬 라이브러리를 최적화한다. 그러나 루프의 문법은 정확히 겹친다 — 아래 각 행이 1:1 대응이다.
| SkillOpt (코드 근거) | 우리 엔진 | 대응의 내용 |
|---|---|---|
Rollout — adapter.rollout(train_env, current_skill, …)이 현재 스킬로 훈련 배치를 실행해 궤적+점수를 수확 |
wake OBSERVED log | 둘 다 “현재 지식으로 행동해 본 기록”이 학습의 유일한 원료다. 우리는 게임 wake 단계의 관측 로그(액션 → 프레임 변화)가 그 배치에 해당한다. |
Reflect — run_minibatch_reflect가 실패 궤적과 성공 궤적을 분리해 서로 다른 analyst 프롬프트로 분석 |
passing / failing split | 실패에서 수정 신호를, 성공에서 보존 신호를 따로 뽑는 이분법. 우리 sleep의 관측 분할(스킬이 통한 라운드 / 깨진 라운드)이 동형이다. |
Edit — edit_budget(스케줄러) 또는 decide_autonomous_learning_rate가 이번 스텝의 편집 개수를 제한 |
EDIT MAGNITUDE | 텍스트 학습에서 스텝 크기 = 허용 편집량. 우리 프롬프트의 EDIT MAGNITUDE 지시(residual에 비례한 편집 폭)가 같은 레버다. |
Gate — evaluate_gate: held-out selection set에서 cand_score > current_score일 때만 수용, 아니면 롤백 |
advantage + unseen confirm | “생성자를 믿지 말고 보류 데이터로 판정하라”. 우리는 judge의 advantage 채점과 미관측 상태에서의 확증(unseen confirm)이 그 게이트다. |
| rejected-edit buffer — 기각 스텝의 편집 전부와 점수 하락이 step buffer로 다음 프롬프트에 재주입 | hypothesis ledger REFUTED | 실패한 시도를 버리지 않고 “다시 하지 말 것”의 명시 컨텍스트로 순환시킨다. 우리 가설 원장의 REFUTED 항목이 같은 역할이다. |
slow / meta update — run_slow_update/run_meta_skill이 에폭 종단 비교에서 systemic 교훈을 증류 |
reasoning_log distillation | 스텝 단위 편집 위에 더 느린 시간축의 요약 학습을 얹는다. 우리는 reasoning_log를 주기적으로 증류해 같은 2계층 시간축을 만든다. |
| best_skill.md — 검증 최고 스킬 문서 하나가 배포 아티팩트 (300–2,000 토큰) | living note | 학습의 결과가 “계속 갱신되는 단일 문서”로 응축된다. 우리의 living note가 그 배포면이다. |
SkillOpt의 검증 신호는 결국 스칼라 점수 하나(hard/soft/mixed)이고, 학습 대상은 비실행 텍스트이며, 데이터는 고정된 벤치마크 배치다. 우리는 이 세 지점을 각각 확장했다.
게이트의 accept/reject 이진 판정 대신, 스킬마다 Beta 스타일 사후확률
(confirm_n, falsify_n)을 달아 증거가 누적적으로 갱신된다. SkillOpt에서는 기각된
지식이 버퍼 속 텍스트로만 남지만, 우리는 반증된 스킬이 격리(quarantine)된 채 사후확률과 함께
살아남아 “얼마나 틀렸는지”까지 정량으로 이월된다.
SkillOpt의 스킬 문서는 타깃 모델이 읽고 해석해야만 효력이 생기는 텍스트다. 우리의 세계 모델은 엔진 fork로 실행되어 예측 프레임을 내놓고, 실측과의 픽셀 단위 대조로 검증된다 — 게이트가 “점수가 올랐는가”가 아니라 “예측이 맞았는가”를 직접 묻는다. 재롤아웃 평가보다 훨씬 싸고 국소적인(어느 셀이 틀렸는지까지) 신호다.
SkillOpt은 다음에 무엇을 굴릴지 정하지 않는다 — 배치는 데이터셋이 준다. 우리는 다음 행동 자체를 기대 정보 이득(EIG)과 정보 가치(VoI) 게이트로 고른다: 어떤 프로브가 경합 가설을 가장 크게 가르는가, 그 관측이 지금 계획을 바꿀 만큼 가치 있는가. 수동적 데이터 소비를 능동적 실험 설계로 바꾼 것이 세 번째 확장이다.
공정한 역방향 표기: SkillOpt이 우리보다 정교한 것도 있다 — 러닝레이트의 autonomous 모드(옵티마이저가 스텝 크기를 스스로 결정), 실패-우선 계층 병합의 support count, 그리고 slow update의 “직전 지침이 실제로 도움됐는지” 자기 반성 프로토콜은 우리 sleep 루프가 아직 갖추지 못한 규율이다.