Spaces:
Running
Running
File size: 17,344 Bytes
3d46076 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 | """LLM control plane (STAGE K): typed, schema-validated commands.
The LLM scientist may SPAWN, START, PAUSE, STOP, SAVE, LOAD, CONFIGURE,
REQUEST_EXPERIMENTS and PROPOSE hypotheses/curricula — through this strictly
validated command surface only. No shell, no code mutation, no direct weight
or memory edits, no fabricated results. Every execution is logged with
provenance; every rejection states the exact reason.
"""
import hashlib
import json
import re
import time
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional
COMMAND_SCHEMA_VERSION = "control_v1"
# command -> {required params: {name: type}, optional params, constraints}
COMMAND_SPECS: Dict[str, Dict[str, Any]] = {
"SPAWN_POPULATION": {
"required": {"size": int},
"optional": {"world_seed": int, "config_name": str},
"constraints": {"size": (1, 64)},
},
"START_RUN": {"required": {}, "optional": {"ticks": int},
"constraints": {"ticks": (1, 10000)}},
"PAUSE_RUN": {"required": {}, "optional": {}, "constraints": {}},
"STOP_RUN": {"required": {}, "optional": {}, "constraints": {}},
"SAVE_CHECKPOINT": {"required": {"name": str}, "optional": {},
"constraints": {"name": (1, 200)}},
"LOAD_CHECKPOINT": {"required": {"name": str}, "optional": {},
"constraints": {"name": (1, 200)}},
"SET_WORLD_CONFIG": {
"required": {"n_resources": int},
"optional": {"n_hazards": int, "regrow_interval": int},
"constraints": {"n_resources": (4, 512), "n_hazards": (0, 64),
"regrow_interval": (1, 100)},
},
"SET_EVOLUTION_CONFIG": {
"required": {"offspring_per_generation": int},
"optional": {"reproduction_mode": str},
"constraints": {"offspring_per_generation": (0, 32)},
"enum": {"reproduction_mode": ["sexual", "asexual"]},
},
"REQUEST_EXPERIMENT": {
"required": {"experiment_type": str, "seed": int},
"optional": {"ticks": int, "population_size": int},
"constraints": {"seed": (0, 2 ** 31), "ticks": (1, 2000),
"population_size": (1, 32)},
"enum": {"experiment_type": ["baseline", "ablation_no_teaching",
"ablation_no_growth", "comparison"]},
},
"REQUEST_COMPARISON": {
"required": {"experiment_a": str, "experiment_b": str},
"optional": {}, "constraints": {},
},
"REQUEST_REPLAY": {"required": {"checkpoint_name": str}, "optional": {"ticks": int},
"constraints": {"ticks": (1, 2000)}},
"PROPOSE_HYPOTHESIS": {
"required": {"text": str, "based_on_experiments": list},
"optional": {}, "constraints": {"text": (1, 2000)},
},
"PROPOSE_TASK": {
"required": {"description": str, "success_criterion": str},
"optional": {}, "constraints": {"description": (1, 500),
"success_criterion": (1, 500)},
},
"PROPOSE_CURRICULUM": {
"required": {"stages": list},
"optional": {}, "constraints": {"stages": (1, 8)},
},
}
# Capability allowlist: role -> commands the role may invoke. Typed dispatch is
# the security boundary (text params are data, never executed). Identifier
# params (checkpoint names, experiment ids, ...) must additionally match
# _IDENTIFIER_RE; free-text fields (hypothesis text, descriptions, curriculum
# stages) are never scanned and never executed.
CAPABILITY_ROLES: Dict[str, frozenset] = {
"llm-scientist": frozenset(COMMAND_SPECS.keys()),
"viewer": frozenset({"REQUEST_COMPARISON", "REQUEST_REPLAY", "PROPOSE_HYPOTHESIS"}),
}
# Identifier-shaped params: strict allowlist, no shell metachars possible.
_IDENTIFIER_RE = re.compile(r"[A-Za-z0-9][A-Za-z0-9._-]{0,199}")
IDENTIFIER_PARAMS = {"name", "checkpoint_name", "experiment_a", "experiment_b",
"config_name", "reproduction_mode", "experiment_type"}
# Deprecated: whole-blob substring blacklists were fragile (false positives on
# legitimate scientific text, false negatives via obfuscation). Kept as an
# empty tuple for backward-compatible imports; enforcement is capability-based.
FORBIDDEN_SUBSTRINGS: tuple = ()
@dataclass
class CommandEnvelope:
command: str
params: Dict[str, Any] = field(default_factory=dict)
requested_by: str = "llm-scientist"
schema_version: str = COMMAND_SCHEMA_VERSION
timestamp: float = 0.0
def to_dict(self) -> Dict[str, Any]:
return {"command": self.command, "params": self.params,
"requested_by": self.requested_by,
"schema_version": self.schema_version,
"timestamp": self.timestamp or time.time()}
def validate_envelope(envelope: Any, role: str = "llm-scientist") -> tuple:
"""Returns (ok, error). Structural + schema + capability validation, no execution."""
if not isinstance(envelope, CommandEnvelope):
return False, "payload is not a CommandEnvelope"
if envelope.schema_version != COMMAND_SCHEMA_VERSION:
return False, f"unsupported schema version {envelope.schema_version!r}"
spec = COMMAND_SPECS.get(envelope.command)
if spec is None:
return False, f"unknown command {envelope.command!r}"
allowed_cmds = CAPABILITY_ROLES.get(role, frozenset())
if envelope.command not in allowed_cmds:
return False, f"command {envelope.command!r} not permitted for role {role!r}"
params = envelope.params
if not isinstance(params, dict):
return False, "params must be a dict"
for name, typ in spec["required"].items():
if name not in params:
return False, f"missing required param {name!r}"
if typ is int and isinstance(params[name], bool):
return False, f"param {name!r} must be int"
if typ is int and not isinstance(params[name], int):
return False, f"param {name!r} must be int"
if typ is str and not isinstance(params[name], str):
return False, f"param {name!r} must be str"
if typ is list and not isinstance(params[name], list):
return False, f"param {name!r} must be list"
allowed = set(spec["required"]) | set(spec["optional"])
extra = set(params) - allowed
if extra:
return False, f"unknown params {sorted(extra)}"
for name, (lo, hi) in spec["constraints"].items():
if name in params:
v = params[name]
if isinstance(v, str):
if not (lo <= len(v) <= hi):
return False, f"param {name!r} length outside [{lo},{hi}]"
elif isinstance(v, list):
if not (lo <= len(v) <= hi):
return False, f"param {name!r} list length outside [{lo},{hi}]"
elif not (lo <= v <= hi):
return False, f"param {name!r}={v} outside [{lo},{hi}]"
for name, allowed_vals in spec.get("enum", {}).items():
if name in params and params[name] not in allowed_vals:
return False, f"param {name!r} must be one of {allowed_vals}"
# Capability-based identifier guard: identifier params must match the
# strict allowlist (no shell metachars can pass). Free-text params
# (text/description/success_criterion/stages) are data, never executed,
# and are intentionally NOT scanned.
for name in IDENTIFIER_PARAMS:
if name in params and isinstance(params[name], str):
if _IDENTIFIER_RE.fullmatch(params[name]) is None:
return False, f"param {name!r} is not a valid identifier"
return True, ""
class ResearchRuntime:
"""Headless research facade the control plane operates on. Owns the
population, checkpoints and the experiment ledger. NO source mutation."""
def __init__(self, experiment_seed: int = 42):
self.experiment_seed = int(experiment_seed)
self.population = None
self.running = False
self.checkpoints: Dict[str, Dict[str, Any]] = {}
self.experiment_ledger: Dict[str, Dict[str, Any]] = {}
self.hypotheses: List[Dict[str, Any]] = []
self.curricula: List[Dict[str, Any]] = []
self.tasks: List[Dict[str, Any]] = []
self.execution_log: List[Dict[str, Any]] = []
self._ticks_target = 0
self._ticks_done = 0
# ---- operations invoked by the control plane ----
def op_spawn_population(self, size: int, world_seed: int = 47, **_):
from src.common.determinism import SeedBundle
from src.population.population import Population
from src.connectome.types import GraphMode
if self.population is not None:
return {"status": "FAILED", "reason": "population already exists; STOP+RESET first"}
seeds = SeedBundle(experiment_seed=self.experiment_seed,
generation_seed=self.experiment_seed + 1,
organism_seed=self.experiment_seed + 2,
development_seed=self.experiment_seed + 3,
mutation_seed=self.experiment_seed + 4,
world_seed=world_seed,
teacher_seed=self.experiment_seed + 6)
self.population = Population(size, seeds, GraphMode.SYNTHETIC_TEST, 32,
experiment_seed=self.experiment_seed,
autonomy_mode=True, genome_version="2.0")
return {"status": "EXECUTED", "population_size": size,
"population_hash": self.population.population_hash()}
def op_start_run(self, ticks: int = 10, **_):
if self.population is None:
return {"status": "FAILED", "reason": "no population"}
self.running = True
self._ticks_target = int(ticks)
self._ticks_done = 0
self.population.step(int(ticks))
self._ticks_done = int(ticks)
self.running = False
return {"status": "EXECUTED", "ticks_run": self._ticks_done,
"population_hash": self.population.population_hash()}
def op_pause_run(self, **_):
self.running = False
return {"status": "EXECUTED", "paused": True}
def op_stop_run(self, **_):
self.running = False
return {"status": "EXECUTED", "stopped": True,
"tick": self.population.tick if self.population else 0}
def op_save_checkpoint(self, name: str, **_):
if self.population is None:
return {"status": "FAILED", "reason": "no population"}
self.checkpoints[name] = self.population.snapshot()
return {"status": "EXECUTED", "checkpoint": name,
"population_hash": self.population.population_hash()}
def op_load_checkpoint(self, name: str, **_):
if name not in self.checkpoints:
return {"status": "FAILED", "reason": f"unknown checkpoint {name!r}"}
from src.common.determinism import SeedBundle
from src.population.population import Population
seeds = SeedBundle(experiment_seed=self.experiment_seed,
generation_seed=self.experiment_seed + 1,
organism_seed=self.experiment_seed + 2,
development_seed=self.experiment_seed + 3,
mutation_seed=self.experiment_seed + 4,
world_seed=self.experiment_seed + 5,
teacher_seed=self.experiment_seed + 6)
self.population = Population.restore(self.checkpoints[name], seeds)
return {"status": "EXECUTED", "checkpoint": name,
"population_hash": self.population.population_hash()}
def op_request_experiment(self, experiment_type: str, seed: int,
ticks: int = 20, population_size: int = 4, **_):
from src.common.determinism import SeedBundle
from src.population.population import Population
from src.connectome.types import GraphMode
exp_id = f"exp-{experiment_type}-{seed}"
seeds = SeedBundle(experiment_seed=seed, generation_seed=seed + 1,
organism_seed=seed + 2, development_seed=seed + 3,
mutation_seed=seed + 4, world_seed=seed + 5,
teacher_seed=seed + 6)
pop = Population(population_size, seeds, GraphMode.SYNTHETIC_TEST, 32,
experiment_seed=seed, autonomy_mode=(experiment_type != "baseline"),
genome_version="2.0")
pop.step(int(ticks))
pop.reproduce(2)
result = {
"experiment_id": exp_id, "type": experiment_type, "seed": seed,
"ticks": ticks, "population_size": population_size,
"final_population_hash": pop.population_hash(),
"teaching_sessions": len(pop.teaching_sessions),
"living": len(pop.living()), "total_organisms": len(pop.organisms),
"generations": sorted({o.generation for o in pop.organisms}),
}
self.experiment_ledger[exp_id] = result
return {"status": "EXECUTED", "result": result}
def op_request_comparison(self, experiment_a: str, experiment_b: str, **_):
ra, rb = self.experiment_ledger.get(experiment_a), self.experiment_ledger.get(experiment_b)
if ra is None or rb is None:
return {"status": "FAILED", "reason": "unknown experiment id(s)"}
comparison = {
"a": experiment_a, "b": experiment_b,
"hash_equal": ra["final_population_hash"] == rb["final_population_hash"],
"teaching_sessions": {"a": ra["teaching_sessions"], "b": rb["teaching_sessions"]},
"living": {"a": ra["living"], "b": rb["living"]},
"generations": {"a": ra["generations"], "b": rb["generations"]},
}
return {"status": "EXECUTED", "comparison": comparison}
def op_propose_hypothesis(self, text: str, based_on_experiments: list, **_):
known = [e for e in based_on_experiments if e in self.experiment_ledger]
unknown = [e for e in based_on_experiments if e not in self.experiment_ledger]
# Deterministic research identity (V4 §34): content + sequence, never wall-clock.
hid = hashlib.sha256(
f"{text}|{len(self.hypotheses)}|{self.experiment_seed}".encode()).hexdigest()[:12]
rec = {"hypothesis_id": hid, "text": text, "based_on_experiments": known,
"unknown_references": unknown, "status": "HYPOTHESIS"}
self.hypotheses.append(rec)
return {"status": "EXECUTED", "hypothesis": rec}
def op_propose_task(self, description: str, success_criterion: str, **_):
tid = hashlib.sha256(
f"{description}|{success_criterion}|{len(self.tasks)}|{self.experiment_seed}"
.encode()).hexdigest()[:12]
rec = {"task_id": tid, "description": description,
"success_criterion": success_criterion, "status": "PROPOSED"}
self.tasks.append(rec)
return {"status": "EXECUTED", "task": rec}
def op_propose_curriculum(self, stages: list, **_):
if not all(isinstance(s, str) for s in stages):
return {"status": "REJECTED", "reason": "curriculum stages must be strings"}
cid = hashlib.sha256(
f"{'|'.join(stages)}|{len(self.curricula)}|{self.experiment_seed}"
.encode()).hexdigest()[:12]
rec = {"curriculum_id": cid, "stages": stages, "status": "PROPOSED"}
self.curricula.append(rec)
return {"status": "EXECUTED", "curriculum": rec}
class ControlPlane:
"""Validates and executes LLM command envelopes against a ResearchRuntime."""
def __init__(self, runtime: Optional[ResearchRuntime] = None,
role: str = "llm-scientist"):
self.runtime = runtime if runtime is not None else ResearchRuntime()
self.role = role
def execute(self, envelope: Any) -> Dict[str, Any]:
ok, err = validate_envelope(envelope, role=self.role)
if not ok:
result = {"status": "REJECTED", "reason": err,
"command": getattr(envelope, "command", str(envelope)[:80])}
self.runtime.execution_log.append({**result, "ts": time.time()})
return result
op = getattr(self.runtime, f"op_{envelope.command.lower()}", None)
if op is None:
result = {"status": "REJECTED", "reason": "command has no executor",
"command": envelope.command}
else:
try:
result = op(**envelope.params)
except Exception as e: # noqa: BLE001
result = {"status": "FAILED", "command": envelope.command,
"reason": f"{type(e).__name__}: {e}"}
self.runtime.execution_log.append({**result, "command": envelope.command,
"ts": time.time()})
return result
|