feat: bootstrap artifact loop engine package
This commit is contained in:
parent
2968ec63a9
commit
726e512603
27
engine/__init__.py
Normal file
27
engine/__init__.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
from .models import (
|
||||||
|
ArtifactsConfig,
|
||||||
|
BudgetConfig,
|
||||||
|
ConstraintConfig,
|
||||||
|
LoggingConfig,
|
||||||
|
MutationConfig,
|
||||||
|
ObjectiveConfig,
|
||||||
|
PolicyConfig,
|
||||||
|
RunnerConfig,
|
||||||
|
ScorerConfig,
|
||||||
|
ScorerParseConfig,
|
||||||
|
TaskConfig,
|
||||||
|
)
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"ArtifactsConfig",
|
||||||
|
"BudgetConfig",
|
||||||
|
"ConstraintConfig",
|
||||||
|
"LoggingConfig",
|
||||||
|
"MutationConfig",
|
||||||
|
"ObjectiveConfig",
|
||||||
|
"PolicyConfig",
|
||||||
|
"RunnerConfig",
|
||||||
|
"ScorerConfig",
|
||||||
|
"ScorerParseConfig",
|
||||||
|
"TaskConfig",
|
||||||
|
]
|
||||||
84
engine/models.py
Normal file
84
engine/models.py
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ArtifactsConfig:
|
||||||
|
include: list[str] = field(default_factory=list)
|
||||||
|
exclude: list[str] = field(default_factory=list)
|
||||||
|
max_files_per_iteration: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class MutationConfig:
|
||||||
|
mode: str = ""
|
||||||
|
allowed_file_types: list[str] = field(default_factory=list)
|
||||||
|
max_changed_lines: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class RunnerConfig:
|
||||||
|
command: str = ""
|
||||||
|
cwd: str = "."
|
||||||
|
timeout_seconds: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ScorerParseConfig:
|
||||||
|
format: str = ""
|
||||||
|
score_field: str = ""
|
||||||
|
metrics_field: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ScorerConfig:
|
||||||
|
type: str = ""
|
||||||
|
command: str = ""
|
||||||
|
parse: ScorerParseConfig = field(default_factory=ScorerParseConfig)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ObjectiveConfig:
|
||||||
|
primary_metric: str = ""
|
||||||
|
direction: Literal["maximize", "minimize"] = "maximize"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class ConstraintConfig:
|
||||||
|
metric: str = ""
|
||||||
|
op: str = ""
|
||||||
|
value: int | float = 0
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class PolicyConfig:
|
||||||
|
keep_if: str = ""
|
||||||
|
tie_breakers: list[str] = field(default_factory=list)
|
||||||
|
on_failure: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class BudgetConfig:
|
||||||
|
max_iterations: int = 0
|
||||||
|
max_failures: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class LoggingConfig:
|
||||||
|
results_file: str = ""
|
||||||
|
candidate_dir: str = ""
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class TaskConfig:
|
||||||
|
id: str = ""
|
||||||
|
description: str = ""
|
||||||
|
artifacts: ArtifactsConfig = field(default_factory=ArtifactsConfig)
|
||||||
|
mutation: MutationConfig = field(default_factory=MutationConfig)
|
||||||
|
runner: RunnerConfig = field(default_factory=RunnerConfig)
|
||||||
|
scorer: ScorerConfig = field(default_factory=ScorerConfig)
|
||||||
|
objective: ObjectiveConfig = field(default_factory=ObjectiveConfig)
|
||||||
|
constraints: list[ConstraintConfig] = field(default_factory=list)
|
||||||
|
policy: PolicyConfig = field(default_factory=PolicyConfig)
|
||||||
|
budget: BudgetConfig = field(default_factory=BudgetConfig)
|
||||||
|
logging: LoggingConfig = field(default_factory=LoggingConfig)
|
||||||
@ -11,6 +11,7 @@ dependencies = [
|
|||||||
"pandas>=2.3.3",
|
"pandas>=2.3.3",
|
||||||
"pyarrow>=21.0.0",
|
"pyarrow>=21.0.0",
|
||||||
"requests>=2.32.0",
|
"requests>=2.32.0",
|
||||||
|
"PyYAML>=6.0.2",
|
||||||
"rustbpe>=0.1.0",
|
"rustbpe>=0.1.0",
|
||||||
"tiktoken>=0.11.0",
|
"tiktoken>=0.11.0",
|
||||||
"torch==2.9.1",
|
"torch==2.9.1",
|
||||||
|
|||||||
1
tests/__init__.py
Normal file
1
tests/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
||||||
60
tests/test_task_loader.py
Normal file
60
tests/test_task_loader.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from engine.task_loader import load_task
|
||||||
|
|
||||||
|
|
||||||
|
class TaskLoaderSmokeTest(unittest.TestCase):
|
||||||
|
def test_loads_minimal_task(self) -> None:
|
||||||
|
task_yaml = """
|
||||||
|
id: demo
|
||||||
|
description: Demo task
|
||||||
|
artifacts:
|
||||||
|
include:
|
||||||
|
- tasks/demo/sample.txt
|
||||||
|
exclude: []
|
||||||
|
max_files_per_iteration: 1
|
||||||
|
mutation:
|
||||||
|
mode: direct_edit
|
||||||
|
allowed_file_types: [".txt"]
|
||||||
|
max_changed_lines: 10
|
||||||
|
runner:
|
||||||
|
command: "python -c \\\"print('run')\\\""
|
||||||
|
cwd: "."
|
||||||
|
timeout_seconds: 10
|
||||||
|
scorer:
|
||||||
|
type: command
|
||||||
|
command: "python -c \\\"import json; print(json.dumps({'score': 1, 'metrics': {'violation_count': 0}}))\\\""
|
||||||
|
parse:
|
||||||
|
format: json
|
||||||
|
score_field: "score"
|
||||||
|
metrics_field: "metrics"
|
||||||
|
objective:
|
||||||
|
primary_metric: score
|
||||||
|
direction: maximize
|
||||||
|
constraints:
|
||||||
|
- metric: violation_count
|
||||||
|
op: "<="
|
||||||
|
value: 0
|
||||||
|
policy:
|
||||||
|
keep_if: better_primary
|
||||||
|
tie_breakers: []
|
||||||
|
on_failure: discard
|
||||||
|
budget:
|
||||||
|
max_iterations: 3
|
||||||
|
max_failures: 1
|
||||||
|
logging:
|
||||||
|
results_file: work/results.jsonl
|
||||||
|
candidate_dir: work/candidates
|
||||||
|
"""
|
||||||
|
with tempfile.TemporaryDirectory() as tmp:
|
||||||
|
task_path = Path(tmp) / "task.yaml"
|
||||||
|
task_path.write_text(task_yaml, encoding="utf-8")
|
||||||
|
task = load_task(task_path)
|
||||||
|
self.assertEqual(task.id, "demo")
|
||||||
|
self.assertEqual(task.objective.direction, "maximize")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Loading…
Reference in New Issue
Block a user