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",
|
||||
"pyarrow>=21.0.0",
|
||||
"requests>=2.32.0",
|
||||
"PyYAML>=6.0.2",
|
||||
"rustbpe>=0.1.0",
|
||||
"tiktoken>=0.11.0",
|
||||
"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