From 9cd0b697b8b5b3aa0b619c3d73329f34c774cbec Mon Sep 17 00:00:00 2001 From: Asankhaya Sharma Date: Mon, 23 Jun 2025 11:58:44 +0800 Subject: [PATCH 1/2] Refine prompt context and bump version to 0.0.8 Updated the controller to use actual top programs for prompt context, ensuring the LLM receives only high-performing examples, and passed inspirations separately. Incremented the package version to 0.0.8 in both pyproject.toml and setup.py. --- openevolve/controller.py | 7 ++++++- pyproject.toml | 2 +- setup.py | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/openevolve/controller.py b/openevolve/controller.py index 75ade1188..2b3b9c8c3 100644 --- a/openevolve/controller.py +++ b/openevolve/controller.py @@ -263,13 +263,18 @@ async def run( # Get artifacts for the parent program if available parent_artifacts = self.database.get_artifacts(parent.id) + # Get actual top programs for prompt context (separate from inspirations) + # This ensures the LLM sees only high-performing programs as examples + actual_top_programs = self.database.get_top_programs(5) + # Build prompt prompt = self.prompt_sampler.build_prompt( current_program=parent.code, parent_program=parent.code, # We don't have the parent's code, use the same program_metrics=parent.metrics, previous_programs=[p.to_dict() for p in self.database.get_top_programs(3)], - top_programs=[p.to_dict() for p in inspirations], + top_programs=[p.to_dict() for p in actual_top_programs], # Use actual top programs + inspirations=[p.to_dict() for p in inspirations], # Pass inspirations separately language=self.language, evolution_round=i, diff_based_evolution=self.config.diff_based_evolution, diff --git a/pyproject.toml b/pyproject.toml index d357ca964..2c98893c8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "openevolve" -version = "0.0.7" +version = "0.0.8" description = "Open-source implementation of AlphaEvolve" readme = "README.md" requires-python = ">=3.9" diff --git a/setup.py b/setup.py index c8025d3bb..bfb9e54a8 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name="openevolve", - version="0.0.7", + version="0.0.8", packages=find_packages(), include_package_data=True, ) From 2dfb16753babf1c5dd3a5d4e4b1d71a9dc82235c Mon Sep 17 00:00:00 2001 From: Asankhaya Sharma Date: Mon, 23 Jun 2025 12:05:16 +0800 Subject: [PATCH 2/2] Add inspirations section to prompt evolution history Introduces an 'inspirations' parameter to PromptSampler and updates the evolution history formatting to include a new inspirations section. Adds logic for formatting, categorizing, and describing inspiration programs, and extends the templates to support this new section. This enhances prompt diversity and creativity by surfacing diverse and creative program examples. --- openevolve/prompt/sampler.py | 146 ++++++++++++++++++++++++++++++++- openevolve/prompt/templates.py | 20 +++++ 2 files changed, 164 insertions(+), 2 deletions(-) diff --git a/openevolve/prompt/sampler.py b/openevolve/prompt/sampler.py index c0b99508d..186c9fe13 100644 --- a/openevolve/prompt/sampler.py +++ b/openevolve/prompt/sampler.py @@ -51,6 +51,7 @@ def build_prompt( program_metrics: Dict[str, float] = {}, previous_programs: List[Dict[str, Any]] = [], top_programs: List[Dict[str, Any]] = [], + inspirations: List[Dict[str, Any]] = [], # Add inspirations parameter language: str = "python", evolution_round: int = 0, diff_based_evolution: bool = True, @@ -66,7 +67,8 @@ def build_prompt( parent_program: Parent program from which current was derived program_metrics: Dictionary of metric names to values previous_programs: List of previous program attempts - top_programs: List of top-performing programs + top_programs: List of top-performing programs (best by fitness) + inspirations: List of inspiration programs (diverse/creative examples) language: Programming language evolution_round: Current evolution round diff_based_evolution: Whether to use diff-based evolution (True) or full rewrites (False) @@ -110,7 +112,7 @@ def build_prompt( # Format evolution history evolution_history = self._format_evolution_history( - previous_programs, top_programs, language + previous_programs, top_programs, inspirations, language ) # Format artifacts section if enabled and available @@ -227,6 +229,7 @@ def _format_evolution_history( self, previous_programs: List[Dict[str, Any]], top_programs: List[Dict[str, Any]], + inspirations: List[Dict[str, Any]], language: str, ) -> str: """Format the evolution history for the prompt""" @@ -391,11 +394,150 @@ def _format_evolution_history( # Combine top and diverse programs combined_programs_str = top_programs_str + diverse_programs_str + # Format inspirations section + inspirations_section_str = self._format_inspirations_section(inspirations, language) + # Combine into full history return history_template.format( previous_attempts=previous_attempts_str.strip(), top_programs=combined_programs_str.strip(), + inspirations_section=inspirations_section_str, + ) + + def _format_inspirations_section( + self, inspirations: List[Dict[str, Any]], language: str + ) -> str: + """ + Format the inspirations section for the prompt + + Args: + inspirations: List of inspiration programs + language: Programming language + + Returns: + Formatted inspirations section string + """ + if not inspirations: + return "" + + # Get templates + inspirations_section_template = self.template_manager.get_template("inspirations_section") + inspiration_program_template = self.template_manager.get_template("inspiration_program") + + inspiration_programs_str = "" + + for i, program in enumerate(inspirations): + # Extract a snippet (first 8 lines) for display + program_code = program.get("code", "") + program_snippet = "\n".join(program_code.split("\n")[:8]) + if len(program_code.split("\n")) > 8: + program_snippet += "\n# ... (truncated for brevity)" + + # Calculate a composite score using safe numeric average + score = safe_numeric_average(program.get("metrics", {})) + + # Determine program type based on metadata and score + program_type = self._determine_program_type(program) + + # Extract unique features (emphasizing diversity rather than just performance) + unique_features = self._extract_unique_features(program) + + inspiration_programs_str += ( + inspiration_program_template.format( + program_number=i + 1, + score=f"{score:.4f}", + program_type=program_type, + language=language, + program_snippet=program_snippet, + unique_features=unique_features, + ) + + "\n\n" + ) + + return inspirations_section_template.format( + inspiration_programs=inspiration_programs_str.strip() ) + + def _determine_program_type(self, program: Dict[str, Any]) -> str: + """ + Determine the type/category of an inspiration program + + Args: + program: Program dictionary + + Returns: + String describing the program type + """ + metadata = program.get("metadata", {}) + score = safe_numeric_average(program.get("metrics", {})) + + # Check metadata for explicit type markers + if metadata.get("diverse", False): + return "Diverse" + if metadata.get("migrant", False): + return "Migrant" + if metadata.get("random", False): + return "Random" + + # Classify based on score ranges + if score >= 0.8: + return "High-Performer" + elif score >= 0.6: + return "Alternative" + elif score >= 0.4: + return "Experimental" + else: + return "Exploratory" + + def _extract_unique_features(self, program: Dict[str, Any]) -> str: + """ + Extract unique features of an inspiration program + + Args: + program: Program dictionary + + Returns: + String describing unique aspects of the program + """ + features = [] + + # Extract from metadata if available + metadata = program.get("metadata", {}) + if "changes" in metadata: + changes = metadata["changes"] + if isinstance(changes, str) and len(changes) < 100: + features.append(f"Modification: {changes}") + + # Analyze metrics for standout characteristics + metrics = program.get("metrics", {}) + for metric_name, value in metrics.items(): + if isinstance(value, (int, float)): + if value >= 0.9: + features.append(f"Excellent {metric_name} ({value:.3f})") + elif value <= 0.3: + features.append(f"Alternative {metric_name} approach") + + # Code-based features (simple heuristics) + code = program.get("code", "") + if code: + code_lower = code.lower() + if "class" in code_lower and "def __init__" in code_lower: + features.append("Object-oriented approach") + if "numpy" in code_lower or "np." in code_lower: + features.append("NumPy-based implementation") + if "for" in code_lower and "while" in code_lower: + features.append("Mixed iteration strategies") + if len(code.split("\n")) < 10: + features.append("Concise implementation") + elif len(code.split("\n")) > 50: + features.append("Comprehensive implementation") + + # Default if no specific features found + if not features: + program_type = self._determine_program_type(program) + features.append(f"{program_type} approach to the problem") + + return ", ".join(features[:3]) # Limit to top 3 features def _apply_template_variations(self, template: str) -> str: """Apply stochastic variations to the template""" diff --git a/openevolve/prompt/templates.py b/openevolve/prompt/templates.py index f5095080a..bbb95e196 100644 --- a/openevolve/prompt/templates.py +++ b/openevolve/prompt/templates.py @@ -96,6 +96,8 @@ ## Top Performing Programs {top_programs} + +{inspirations_section} """ # Template for formatting a previous attempt @@ -113,6 +115,22 @@ Key features: {key_features} """ +# Template for formatting inspirations section +INSPIRATIONS_SECTION_TEMPLATE = """## Inspiration Programs + +These programs represent diverse approaches and creative solutions that may inspire new ideas: + +{inspiration_programs} +""" + +# Template for formatting an individual inspiration program +INSPIRATION_PROGRAM_TEMPLATE = """### Inspiration {program_number} (Score: {score}, Type: {program_type}) +```{language} +{program_snippet} +``` +Unique approach: {unique_features} +""" + # Template for evaluating a program via an LLM EVALUATION_TEMPLATE = """Evaluate the following code on a scale of 0.0 to 1.0 for the following metrics: 1. Readability: How easy is the code to read and understand? @@ -144,6 +162,8 @@ "evolution_history": EVOLUTION_HISTORY_TEMPLATE, "previous_attempt": PREVIOUS_ATTEMPT_TEMPLATE, "top_program": TOP_PROGRAM_TEMPLATE, + "inspirations_section": INSPIRATIONS_SECTION_TEMPLATE, + "inspiration_program": INSPIRATION_PROGRAM_TEMPLATE, "evaluation": EVALUATION_TEMPLATE, }