99from openevolve .config import PromptConfig
1010from openevolve .prompt .templates import TemplateManager
1111from openevolve .utils .format_utils import format_metrics_safe
12- from openevolve .utils .metrics_utils import safe_numeric_average
12+ from openevolve .utils .metrics_utils import safe_numeric_average , get_fitness_score , format_feature_coordinates
1313
1414logger = logging .getLogger (__name__ )
1515
@@ -19,7 +19,7 @@ class PromptSampler:
1919
2020 def __init__ (self , config : PromptConfig ):
2121 self .config = config
22- self .template_manager = TemplateManager (config .template_dir )
22+ self .template_manager = TemplateManager (custom_template_dir = config .template_dir )
2323
2424 # Initialize the random number generator
2525 random .seed ()
@@ -60,6 +60,7 @@ def build_prompt(
6060 diff_based_evolution : bool = True ,
6161 template_key : Optional [str ] = None ,
6262 program_artifacts : Optional [Dict [str , Union [str , bytes ]]] = None ,
63+ feature_dimensions : Optional [List [str ]] = None ,
6364 ** kwargs : Any ,
6465 ) -> Dict [str , str ]:
6566 """
@@ -110,7 +111,7 @@ def build_prompt(
110111
111112 # Identify areas for improvement
112113 improvement_areas = self ._identify_improvement_areas (
113- current_program , parent_program , program_metrics , previous_programs
114+ current_program , parent_program , program_metrics , previous_programs , feature_dimensions
114115 )
115116
116117 # Format evolution history
@@ -127,9 +128,17 @@ def build_prompt(
127128 if self .config .use_template_stochasticity :
128129 user_template = self ._apply_template_variations (user_template )
129130
131+ # Calculate fitness and feature coordinates for the new template format
132+ feature_dimensions = feature_dimensions or []
133+ fitness_score = get_fitness_score (program_metrics , feature_dimensions )
134+ feature_coords = format_feature_coordinates (program_metrics , feature_dimensions )
135+
130136 # Format the final user message
131137 user_message = user_template .format (
132138 metrics = metrics_str ,
139+ fitness_score = f"{ fitness_score :.4f} " ,
140+ feature_coords = feature_coords ,
141+ feature_dimensions = ", " .join (feature_dimensions ) if feature_dimensions else "None" ,
133142 improvement_areas = improvement_areas ,
134143 evolution_history = evolution_history ,
135144 current_program = current_program ,
@@ -163,74 +172,70 @@ def _identify_improvement_areas(
163172 parent_program : str ,
164173 metrics : Dict [str , float ],
165174 previous_programs : List [Dict [str , Any ]],
175+ feature_dimensions : Optional [List [str ]] = None ,
166176 ) -> str :
167- """Identify potential areas for improvement"""
168- # This method could be expanded to include more sophisticated analysis
169- # For now, we'll use a simple approach
170-
177+ """Identify improvement areas with proper fitness/feature separation"""
178+
171179 improvement_areas = []
172-
173- # Check program length
174- # Support both old and new parameter names for backward compatibility
180+ feature_dimensions = feature_dimensions or []
181+
182+ # Calculate fitness (excluding feature dimensions)
183+ current_fitness = get_fitness_score (metrics , feature_dimensions )
184+
185+ # Track fitness changes (not individual metrics)
186+ if previous_programs :
187+ prev_metrics = previous_programs [- 1 ].get ("metrics" , {})
188+ prev_fitness = get_fitness_score (prev_metrics , feature_dimensions )
189+
190+ if current_fitness > prev_fitness :
191+ msg = self .template_manager .get_fragment (
192+ "fitness_improved" ,
193+ prev = prev_fitness ,
194+ current = current_fitness
195+ )
196+ improvement_areas .append (msg )
197+ elif current_fitness < prev_fitness :
198+ msg = self .template_manager .get_fragment (
199+ "fitness_declined" ,
200+ prev = prev_fitness ,
201+ current = current_fitness
202+ )
203+ improvement_areas .append (msg )
204+ elif abs (current_fitness - prev_fitness ) < 1e-6 : # Essentially unchanged
205+ msg = self .template_manager .get_fragment (
206+ "fitness_stable" ,
207+ current = current_fitness
208+ )
209+ improvement_areas .append (msg )
210+
211+ # Note feature exploration (not good/bad, just informational)
212+ if feature_dimensions :
213+ feature_coords = format_feature_coordinates (metrics , feature_dimensions )
214+ if feature_coords != "No feature coordinates" :
215+ msg = self .template_manager .get_fragment (
216+ "exploring_region" ,
217+ features = feature_coords
218+ )
219+ improvement_areas .append (msg )
220+
221+ # Code length check (configurable threshold)
175222 threshold = (
176223 self .config .suggest_simplification_after_chars or self .config .code_length_threshold
177224 )
178225 if threshold and len (current_program ) > threshold :
179- improvement_areas .append (
180- "Consider simplifying the code to improve readability and maintainability"
226+ msg = self .template_manager .get_fragment (
227+ "code_too_long" ,
228+ threshold = threshold
181229 )
182-
183- # Check for performance patterns in previous attempts
184- if len (previous_programs ) >= 2 :
185- recent_attempts = previous_programs [- 2 :]
186- metrics_improved = []
187- metrics_regressed = []
188-
189- for metric , value in metrics .items ():
190- # Only compare numeric metrics
191- if not isinstance (value , (int , float )) or isinstance (value , bool ):
192- continue
193-
194- improved = True
195- regressed = True
196-
197- for attempt in recent_attempts :
198- attempt_value = attempt ["metrics" ].get (metric , 0 )
199- # Only compare if both values are numeric
200- if isinstance (value , (int , float )) and isinstance (attempt_value , (int , float )):
201- if attempt_value <= value :
202- regressed = False
203- if attempt_value >= value :
204- improved = False
205- else :
206- # If either value is non-numeric, skip comparison
207- improved = False
208- regressed = False
209-
210- if improved and metric not in metrics_improved :
211- metrics_improved .append (metric )
212- if regressed and metric not in metrics_regressed :
213- metrics_regressed .append (metric )
214-
215- if metrics_improved :
216- improvement_areas .append (
217- f"Metrics showing improvement: { ', ' .join (metrics_improved )} . "
218- "Consider continuing with similar changes."
219- )
220-
221- if metrics_regressed :
222- improvement_areas .append (
223- f"Metrics showing regression: { ', ' .join (metrics_regressed )} . "
224- "Consider reverting or revising recent changes in these areas."
225- )
226-
227- # If we don't have specific improvements to suggest
230+ improvement_areas .append (msg )
231+
232+ # Default guidance if nothing specific
228233 if not improvement_areas :
229234 improvement_areas .append (
230- "Focus on optimizing the code for better performance on the target metrics"
235+ self . template_manager . get_fragment ( "no_specific_guidance" )
231236 )
232-
233- return "\n " .join ([ f"- { area } " for area in improvement_areas ] )
237+
238+ return "\n " .join (f"- { area } " for area in improvement_areas )
234239
235240 def _format_evolution_history (
236241 self ,
0 commit comments