Skip to content

Commit 30e8a65

Browse files
codeliontotoluo
authored andcommitted
feature: Add evolution trace logging for RL training support
- Add EvolutionTracer class for real-time trace logging - Support JSONL, JSON, and HDF5 formats - Add checkpoint extraction functions for lineage analysis - Include prompts, LLM responses, and improvement metrics - Add comprehensive test suite (25 tests) - Update configuration to support evolution_trace settings related to #210
2 parents 139cbc7 + 2495dd3 commit 30e8a65

File tree

10 files changed

+1905
-8
lines changed

10 files changed

+1905
-8
lines changed

configs/default_config.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,14 @@ evaluator:
159159
# LLM-based feedback (experimental)
160160
use_llm_feedback: false # Use LLM to evaluate code quality
161161
llm_feedback_weight: 0.1 # Weight for LLM feedback in final score
162+
163+
# Evolution trace configuration
164+
# Logs detailed traces of program evolution for RL training and analysis
165+
evolution_trace:
166+
enabled: false # Enable evolution trace logging
167+
format: 'jsonl' # Output format: 'jsonl', 'json', or 'hdf5'
168+
include_code: false # Include full program code in traces
169+
include_prompts: true # Include prompts and LLM responses
170+
output_path: null # Path for trace output (defaults to output_dir/evolution_trace.{format})
171+
buffer_size: 10 # Number of traces to buffer before writing
172+
compress: false # Compress output file (jsonl only)

openevolve/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Version information for openevolve package."""
22

3-
__version__ = "0.2.12"
3+
__version__ = "0.2.13"

openevolve/config.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ class LLMModelConfig:
3838

3939
# Reproducibility
4040
random_seed: Optional[int] = None
41+
42+
# Reasoning parameters
43+
reasoning_effort: Optional[str] = None
4144

4245

4346
@dataclass
@@ -69,6 +72,9 @@ class LLMConfig(LLMModelConfig):
6972
primary_model_weight: float = None
7073
secondary_model: str = None
7174
secondary_model_weight: float = None
75+
76+
# Reasoning parameters (inherited from LLMModelConfig but can be overridden)
77+
reasoning_effort: Optional[str] = None
7278

7379
def __post_init__(self):
7480
"""Post-initialization to set up model configurations"""
@@ -121,6 +127,7 @@ def __post_init__(self):
121127
"retries": self.retries,
122128
"retry_delay": self.retry_delay,
123129
"random_seed": self.random_seed,
130+
"reasoning_effort": self.reasoning_effort,
124131
}
125132
self.update_model_params(shared_config)
126133

@@ -173,6 +180,7 @@ def rebuild_models(self) -> None:
173180
"retries": self.retries,
174181
"retry_delay": self.retry_delay,
175182
"random_seed": self.random_seed,
183+
"reasoning_effort": self.reasoning_effort,
176184
}
177185
self.update_model_params(shared_config)
178186

@@ -305,6 +313,19 @@ class EvaluatorConfig:
305313
max_artifact_storage: int = 100 * 1024 * 1024 # 100MB per program
306314

307315

316+
@dataclass
317+
class EvolutionTraceConfig:
318+
"""Configuration for evolution trace logging"""
319+
320+
enabled: bool = False
321+
format: str = "jsonl" # Options: "jsonl", "json", "hdf5"
322+
include_code: bool = False
323+
include_prompts: bool = True
324+
output_path: Optional[str] = None
325+
buffer_size: int = 10
326+
compress: bool = False
327+
328+
308329
@dataclass
309330
class Config:
310331
"""Master configuration for OpenEvolve"""
@@ -322,6 +343,7 @@ class Config:
322343
prompt: PromptConfig = field(default_factory=PromptConfig)
323344
database: DatabaseConfig = field(default_factory=DatabaseConfig)
324345
evaluator: EvaluatorConfig = field(default_factory=EvaluatorConfig)
346+
evolution_trace: EvolutionTraceConfig = field(default_factory=EvolutionTraceConfig)
325347

326348
# Evolution settings
327349
diff_based_evolution: bool = True
@@ -347,7 +369,7 @@ def from_dict(cls, config_dict: Dict[str, Any]) -> "Config":
347369

348370
# Update top-level fields
349371
for key, value in config_dict.items():
350-
if key not in ["llm", "prompt", "database", "evaluator"] and hasattr(config, key):
372+
if key not in ["llm", "prompt", "database", "evaluator", "evolution_trace"] and hasattr(config, key):
351373
setattr(config, key, value)
352374

353375
# Update nested configs
@@ -370,6 +392,8 @@ def from_dict(cls, config_dict: Dict[str, Any]) -> "Config":
370392
config.database.random_seed = config.random_seed
371393
if "evaluator" in config_dict:
372394
config.evaluator = EvaluatorConfig(**config_dict["evaluator"])
395+
if "evolution_trace" in config_dict:
396+
config.evolution_trace = EvolutionTraceConfig(**config_dict["evolution_trace"])
373397

374398
return config
375399

@@ -438,6 +462,15 @@ def to_dict(self) -> Dict[str, Any]:
438462
"use_llm_feedback": self.evaluator.use_llm_feedback,
439463
"llm_feedback_weight": self.evaluator.llm_feedback_weight,
440464
},
465+
"evolution_trace": {
466+
"enabled": self.evolution_trace.enabled,
467+
"format": self.evolution_trace.format,
468+
"include_code": self.evolution_trace.include_code,
469+
"include_prompts": self.evolution_trace.include_prompts,
470+
"output_path": self.evolution_trace.output_path,
471+
"buffer_size": self.evolution_trace.buffer_size,
472+
"compress": self.evolution_trace.compress,
473+
},
441474
# Evolution settings
442475
"diff_based_evolution": self.diff_based_evolution,
443476
"max_code_length": self.max_code_length,

openevolve/controller.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from openevolve.config import Config, load_config
1515
from openevolve.database import Program, ProgramDatabase
1616
from openevolve.evaluator import Evaluator
17+
from openevolve.evolution_trace import EvolutionTracer
1718
from openevolve.llm.ensemble import LLMEnsemble
1819
from openevolve.prompt.sampler import PromptSampler
1920
from openevolve.process_parallel import ProcessParallelController
@@ -163,6 +164,29 @@ def __init__(
163164

164165
logger.info(f"Initialized OpenEvolve with {initial_program_path}")
165166

167+
# Initialize evolution tracer
168+
if self.config.evolution_trace.enabled:
169+
trace_output_path = self.config.evolution_trace.output_path
170+
if not trace_output_path:
171+
# Default to output_dir/evolution_trace.{format}
172+
trace_output_path = os.path.join(
173+
self.output_dir,
174+
f"evolution_trace.{self.config.evolution_trace.format}"
175+
)
176+
177+
self.evolution_tracer = EvolutionTracer(
178+
output_path=trace_output_path,
179+
format=self.config.evolution_trace.format,
180+
include_code=self.config.evolution_trace.include_code,
181+
include_prompts=self.config.evolution_trace.include_prompts,
182+
enabled=True,
183+
buffer_size=self.config.evolution_trace.buffer_size,
184+
compress=self.config.evolution_trace.compress
185+
)
186+
logger.info(f"Evolution tracing enabled: {trace_output_path}")
187+
else:
188+
self.evolution_tracer = None
189+
166190
# Initialize improved parallel processing components
167191
self.parallel_controller = None
168192

@@ -276,7 +300,7 @@ async def run(
276300
# Initialize improved parallel processing
277301
try:
278302
self.parallel_controller = ProcessParallelController(
279-
self.config, self.evaluation_file, self.database
303+
self.config, self.evaluation_file, self.database, self.evolution_tracer
280304
)
281305

282306
# Set up signal handlers for graceful shutdown
@@ -319,6 +343,11 @@ def force_exit_handler(signum, frame):
319343
if self.parallel_controller:
320344
self.parallel_controller.stop()
321345
self.parallel_controller = None
346+
347+
# Close evolution tracer
348+
if self.evolution_tracer:
349+
self.evolution_tracer.close()
350+
logger.info("Evolution tracer closed")
322351

323352
# Get the best program
324353
best_program = None

0 commit comments

Comments
 (0)