Skip to content

Commit 7e6e58e

Browse files
authored
Merge pull request #95 from codelion/fix-separate-inspirations-from-top-programs
Refine prompt context and bump version to 0.0.8
2 parents 241b334 + 2dfb167 commit 7e6e58e

File tree

5 files changed

+172
-5
lines changed

5 files changed

+172
-5
lines changed

openevolve/controller.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,13 +263,18 @@ async def run(
263263
# Get artifacts for the parent program if available
264264
parent_artifacts = self.database.get_artifacts(parent.id)
265265

266+
# Get actual top programs for prompt context (separate from inspirations)
267+
# This ensures the LLM sees only high-performing programs as examples
268+
actual_top_programs = self.database.get_top_programs(5)
269+
266270
# Build prompt
267271
prompt = self.prompt_sampler.build_prompt(
268272
current_program=parent.code,
269273
parent_program=parent.code, # We don't have the parent's code, use the same
270274
program_metrics=parent.metrics,
271275
previous_programs=[p.to_dict() for p in self.database.get_top_programs(3)],
272-
top_programs=[p.to_dict() for p in inspirations],
276+
top_programs=[p.to_dict() for p in actual_top_programs], # Use actual top programs
277+
inspirations=[p.to_dict() for p in inspirations], # Pass inspirations separately
273278
language=self.language,
274279
evolution_round=i,
275280
diff_based_evolution=self.config.diff_based_evolution,

openevolve/prompt/sampler.py

Lines changed: 144 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def build_prompt(
5151
program_metrics: Dict[str, float] = {},
5252
previous_programs: List[Dict[str, Any]] = [],
5353
top_programs: List[Dict[str, Any]] = [],
54+
inspirations: List[Dict[str, Any]] = [], # Add inspirations parameter
5455
language: str = "python",
5556
evolution_round: int = 0,
5657
diff_based_evolution: bool = True,
@@ -66,7 +67,8 @@ def build_prompt(
6667
parent_program: Parent program from which current was derived
6768
program_metrics: Dictionary of metric names to values
6869
previous_programs: List of previous program attempts
69-
top_programs: List of top-performing programs
70+
top_programs: List of top-performing programs (best by fitness)
71+
inspirations: List of inspiration programs (diverse/creative examples)
7072
language: Programming language
7173
evolution_round: Current evolution round
7274
diff_based_evolution: Whether to use diff-based evolution (True) or full rewrites (False)
@@ -110,7 +112,7 @@ def build_prompt(
110112

111113
# Format evolution history
112114
evolution_history = self._format_evolution_history(
113-
previous_programs, top_programs, language
115+
previous_programs, top_programs, inspirations, language
114116
)
115117

116118
# Format artifacts section if enabled and available
@@ -227,6 +229,7 @@ def _format_evolution_history(
227229
self,
228230
previous_programs: List[Dict[str, Any]],
229231
top_programs: List[Dict[str, Any]],
232+
inspirations: List[Dict[str, Any]],
230233
language: str,
231234
) -> str:
232235
"""Format the evolution history for the prompt"""
@@ -391,11 +394,150 @@ def _format_evolution_history(
391394
# Combine top and diverse programs
392395
combined_programs_str = top_programs_str + diverse_programs_str
393396

397+
# Format inspirations section
398+
inspirations_section_str = self._format_inspirations_section(inspirations, language)
399+
394400
# Combine into full history
395401
return history_template.format(
396402
previous_attempts=previous_attempts_str.strip(),
397403
top_programs=combined_programs_str.strip(),
404+
inspirations_section=inspirations_section_str,
405+
)
406+
407+
def _format_inspirations_section(
408+
self, inspirations: List[Dict[str, Any]], language: str
409+
) -> str:
410+
"""
411+
Format the inspirations section for the prompt
412+
413+
Args:
414+
inspirations: List of inspiration programs
415+
language: Programming language
416+
417+
Returns:
418+
Formatted inspirations section string
419+
"""
420+
if not inspirations:
421+
return ""
422+
423+
# Get templates
424+
inspirations_section_template = self.template_manager.get_template("inspirations_section")
425+
inspiration_program_template = self.template_manager.get_template("inspiration_program")
426+
427+
inspiration_programs_str = ""
428+
429+
for i, program in enumerate(inspirations):
430+
# Extract a snippet (first 8 lines) for display
431+
program_code = program.get("code", "")
432+
program_snippet = "\n".join(program_code.split("\n")[:8])
433+
if len(program_code.split("\n")) > 8:
434+
program_snippet += "\n# ... (truncated for brevity)"
435+
436+
# Calculate a composite score using safe numeric average
437+
score = safe_numeric_average(program.get("metrics", {}))
438+
439+
# Determine program type based on metadata and score
440+
program_type = self._determine_program_type(program)
441+
442+
# Extract unique features (emphasizing diversity rather than just performance)
443+
unique_features = self._extract_unique_features(program)
444+
445+
inspiration_programs_str += (
446+
inspiration_program_template.format(
447+
program_number=i + 1,
448+
score=f"{score:.4f}",
449+
program_type=program_type,
450+
language=language,
451+
program_snippet=program_snippet,
452+
unique_features=unique_features,
453+
)
454+
+ "\n\n"
455+
)
456+
457+
return inspirations_section_template.format(
458+
inspiration_programs=inspiration_programs_str.strip()
398459
)
460+
461+
def _determine_program_type(self, program: Dict[str, Any]) -> str:
462+
"""
463+
Determine the type/category of an inspiration program
464+
465+
Args:
466+
program: Program dictionary
467+
468+
Returns:
469+
String describing the program type
470+
"""
471+
metadata = program.get("metadata", {})
472+
score = safe_numeric_average(program.get("metrics", {}))
473+
474+
# Check metadata for explicit type markers
475+
if metadata.get("diverse", False):
476+
return "Diverse"
477+
if metadata.get("migrant", False):
478+
return "Migrant"
479+
if metadata.get("random", False):
480+
return "Random"
481+
482+
# Classify based on score ranges
483+
if score >= 0.8:
484+
return "High-Performer"
485+
elif score >= 0.6:
486+
return "Alternative"
487+
elif score >= 0.4:
488+
return "Experimental"
489+
else:
490+
return "Exploratory"
491+
492+
def _extract_unique_features(self, program: Dict[str, Any]) -> str:
493+
"""
494+
Extract unique features of an inspiration program
495+
496+
Args:
497+
program: Program dictionary
498+
499+
Returns:
500+
String describing unique aspects of the program
501+
"""
502+
features = []
503+
504+
# Extract from metadata if available
505+
metadata = program.get("metadata", {})
506+
if "changes" in metadata:
507+
changes = metadata["changes"]
508+
if isinstance(changes, str) and len(changes) < 100:
509+
features.append(f"Modification: {changes}")
510+
511+
# Analyze metrics for standout characteristics
512+
metrics = program.get("metrics", {})
513+
for metric_name, value in metrics.items():
514+
if isinstance(value, (int, float)):
515+
if value >= 0.9:
516+
features.append(f"Excellent {metric_name} ({value:.3f})")
517+
elif value <= 0.3:
518+
features.append(f"Alternative {metric_name} approach")
519+
520+
# Code-based features (simple heuristics)
521+
code = program.get("code", "")
522+
if code:
523+
code_lower = code.lower()
524+
if "class" in code_lower and "def __init__" in code_lower:
525+
features.append("Object-oriented approach")
526+
if "numpy" in code_lower or "np." in code_lower:
527+
features.append("NumPy-based implementation")
528+
if "for" in code_lower and "while" in code_lower:
529+
features.append("Mixed iteration strategies")
530+
if len(code.split("\n")) < 10:
531+
features.append("Concise implementation")
532+
elif len(code.split("\n")) > 50:
533+
features.append("Comprehensive implementation")
534+
535+
# Default if no specific features found
536+
if not features:
537+
program_type = self._determine_program_type(program)
538+
features.append(f"{program_type} approach to the problem")
539+
540+
return ", ".join(features[:3]) # Limit to top 3 features
399541

400542
def _apply_template_variations(self, template: str) -> str:
401543
"""Apply stochastic variations to the template"""

openevolve/prompt/templates.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@
9696
## Top Performing Programs
9797
9898
{top_programs}
99+
100+
{inspirations_section}
99101
"""
100102

101103
# Template for formatting a previous attempt
@@ -113,6 +115,22 @@
113115
Key features: {key_features}
114116
"""
115117

118+
# Template for formatting inspirations section
119+
INSPIRATIONS_SECTION_TEMPLATE = """## Inspiration Programs
120+
121+
These programs represent diverse approaches and creative solutions that may inspire new ideas:
122+
123+
{inspiration_programs}
124+
"""
125+
126+
# Template for formatting an individual inspiration program
127+
INSPIRATION_PROGRAM_TEMPLATE = """### Inspiration {program_number} (Score: {score}, Type: {program_type})
128+
```{language}
129+
{program_snippet}
130+
```
131+
Unique approach: {unique_features}
132+
"""
133+
116134
# Template for evaluating a program via an LLM
117135
EVALUATION_TEMPLATE = """Evaluate the following code on a scale of 0.0 to 1.0 for the following metrics:
118136
1. Readability: How easy is the code to read and understand?
@@ -144,6 +162,8 @@
144162
"evolution_history": EVOLUTION_HISTORY_TEMPLATE,
145163
"previous_attempt": PREVIOUS_ATTEMPT_TEMPLATE,
146164
"top_program": TOP_PROGRAM_TEMPLATE,
165+
"inspirations_section": INSPIRATIONS_SECTION_TEMPLATE,
166+
"inspiration_program": INSPIRATION_PROGRAM_TEMPLATE,
147167
"evaluation": EVALUATION_TEMPLATE,
148168
}
149169

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "openevolve"
7-
version = "0.0.7"
7+
version = "0.0.8"
88
description = "Open-source implementation of AlphaEvolve"
99
readme = "README.md"
1010
requires-python = ">=3.9"

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name="openevolve",
5-
version="0.0.7",
5+
version="0.0.8",
66
packages=find_packages(),
77
include_package_data=True,
88
)

0 commit comments

Comments
 (0)