mgbam commited on
Commit
d706935
·
verified ·
1 Parent(s): dd9dfb2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +132 -94
app.py CHANGED
@@ -1,27 +1,31 @@
1
  # algoforge_prime/app.py
2
  import gradio as gr
3
  import os
4
- import time
5
 
6
- from core.llm_clients import initialize_all_clients, is_gemini_api_configured, is_hf_api_configured
7
- initialize_all_clients()
 
 
8
 
 
9
  GEMINI_API_READY = is_gemini_api_configured()
10
  HF_API_READY = is_hf_api_configured()
11
 
12
  from core.generation_engine import generate_initial_solutions
13
- from core.evaluation_engine import evaluate_solution_candidate, EvaluationResultOutput # Use new class name
14
  from core.evolution_engine import evolve_solution
15
  from prompts.system_prompts import get_system_prompt
16
  from prompts.prompt_templates import format_code_test_analysis_user_prompt
17
  from core.safe_executor import execute_python_code_with_tests, ExecutionResult # For re-evaluating evolved code
18
 
19
  # --- Application Configuration (Models, Defaults) ---
20
- # ... (Keep your AVAILABLE_MODELS_CONFIG and UI_DEFAULT_MODEL_KEY logic as in the previous full app.py)
21
  AVAILABLE_MODELS_CONFIG = {}
22
  UI_DEFAULT_MODEL_KEY = None
 
23
  GEMINI_1_5_PRO_LATEST_ID = "gemini-1.5-pro-latest"
24
  GEMINI_1_5_FLASH_LATEST_ID = "gemini-1.5-flash-latest"
 
25
  if GEMINI_API_READY:
26
  AVAILABLE_MODELS_CONFIG.update({
27
  f"Google Gemini 1.5 Pro (API - Recommended)": {"id": GEMINI_1_5_PRO_LATEST_ID, "type": "google_gemini"},
@@ -29,60 +33,101 @@ if GEMINI_API_READY:
29
  "Google Gemini 1.0 Pro (API - Legacy)": {"id": "gemini-1.0-pro-latest", "type": "google_gemini"},
30
  })
31
  UI_DEFAULT_MODEL_KEY = f"Google Gemini 1.5 Pro (API - Recommended)"
32
- if UI_DEFAULT_MODEL_KEY not in AVAILABLE_MODELS_CONFIG: UI_DEFAULT_MODEL_KEY = f"Google Gemini 1.5 Flash (API - Fast)"
33
- else: print("WARNING: app.py - Gemini API not configured; Gemini models will be unavailable.")
 
 
 
 
34
  if HF_API_READY:
35
  AVAILABLE_MODELS_CONFIG.update({
36
  "Google Gemma 2B (HF - Quick Test)": {"id": "google/gemma-2b-it", "type": "hf"},
37
  "Mistral 7B Instruct (HF)": {"id": "mistralai/Mistral-7B-Instruct-v0.2", "type": "hf"},
 
38
  })
39
- if not UI_DEFAULT_MODEL_KEY: UI_DEFAULT_MODEL_KEY = "Google Gemma 2B (HF - Quick Test)"
40
- else: print("WARNING: app.py - Hugging Face API not configured; HF models will be unavailable.")
 
 
 
 
 
 
41
  if not AVAILABLE_MODELS_CONFIG:
 
42
  AVAILABLE_MODELS_CONFIG["No Models Available (Check API Keys & Restart)"] = {"id": "dummy_error", "type": "none"}
43
  UI_DEFAULT_MODEL_KEY = "No Models Available (Check API Keys & Restart)"
44
- elif not UI_DEFAULT_MODEL_KEY and AVAILABLE_MODELS_CONFIG: UI_DEFAULT_MODEL_KEY = list(AVAILABLE_MODELS_CONFIG.keys())[0]
 
 
45
 
46
 
47
  # --- Main Orchestration Logic for Gradio ---
48
  def run_algoforge_simulation_orchestrator(
49
- problem_type_selected: str, problem_description_text: str, initial_hints_text: str,
50
- user_provided_tests_code: str, num_initial_solutions_to_gen: int, selected_model_ui_key: str,
51
- genesis_temp: float, genesis_max_tokens: int, critique_temp: float, critique_max_tokens: int,
 
 
 
 
 
52
  evolution_temp: float, evolution_max_tokens: int,
53
- progress=gr.Progress(track_tqdm=True)
54
  ):
 
 
 
55
  progress(0, desc="Initializing AlgoForge Prime™...")
56
- log_entries = [f"**AlgoForge Prime™ Omega Conceptual Cycle Starting at {time.strftime('%Y-%m-%d %H:%M:%S')}**"]
57
- # ... (input validation and model config setup as before) ...
 
 
 
 
 
58
  current_model_config = AVAILABLE_MODELS_CONFIG.get(selected_model_ui_key)
59
- if not current_model_config or current_model_config["type"] == "none": # Handle missing config
60
- return "ERROR: Model configuration not found or invalid. Check API keys.", "", "", "\n".join(log_entries), ""
61
- # ...
 
 
 
 
 
62
 
63
- # --- STAGE 1: GENESIS ---
64
- # ... (generate_initial_solutions call as before) ...
65
  llm_config_genesis = {"type": current_model_config["type"], "model_id": current_model_config["id"], "temp": genesis_temp, "max_tokens": genesis_max_tokens}
66
- initial_raw_solutions = generate_initial_solutions(problem_description_text, initial_hints_text, problem_type_selected, num_initial_solutions_to_gen, llm_config_genesis)
 
67
 
 
 
 
 
 
 
 
 
 
 
68
 
69
  # --- STAGE 2: CRITIQUE & AUTOMATED EVALUATION ---
70
- progress(0.25, desc="Stage 2: Evaluating Candidates with LLM & (Simulated) Tests...")
71
- log_entries.append("\n**------ STAGE 2: CRITIQUE CRUCIBLE & AUTOMATED EXECUTION/EVALUATION ------**")
72
- evaluated_candidates_list = []
73
- llm_config_critique = {"type": current_model_config["type"], "model_id": current_model_config["id"], "temp": critique_temp, "max_tokens": critique_max_tokens}
74
-
75
  for i, candidate_solution_text in enumerate(initial_raw_solutions):
76
- # ... (progress update) ...
 
77
  log_entries.append(f"\n--- Evaluating Candidate {i+1} ---")
78
- evaluation_output_obj = evaluate_solution_candidate( # type: EvaluationResultOutput
79
- str(candidate_solution_text), problem_description_text, problem_type_selected,
 
80
  user_provided_tests_code, llm_config_critique
81
  )
82
  evaluated_candidates_list.append({
83
  "id": i + 1,
84
- "solution_text": str(candidate_solution_text),
85
- "evaluation_obj": evaluation_output_obj # Store the whole object
86
  })
87
  log_entries.append(f" Combined Score: {evaluation_output_obj.combined_score}/10")
88
  if evaluation_output_obj.execution_details:
@@ -94,21 +139,27 @@ def run_algoforge_simulation_orchestrator(
94
  for data in evaluated_candidates_list:
95
  initial_solutions_display_markdown.append(
96
  f"**Candidate {data['id']}:**\n```python\n{data['solution_text']}\n```\n\n"
97
- f"**Evaluation Verdict (Combined Score: {data['evaluation_obj'].combined_score}/10):**\n{data['evaluation_obj'].get_display_critique()}\n---" # Use method
98
  )
99
 
100
  # --- STAGE 3: SELECTION OF CHAMPION ---
101
- # ... (selection logic as before, but use `data['evaluation_obj'].combined_score`) ...
102
- progress(0.7, desc="Stage 3: Selecting Champion...")
103
  potentially_viable_candidates = [
104
  cand for cand in evaluated_candidates_list
105
  if cand["evaluation_obj"] and cand["evaluation_obj"].combined_score > 0 and \
106
  cand["solution_text"] and not str(cand["solution_text"]).startswith("ERROR")
107
  ]
108
- if not potentially_viable_candidates: # Handle no viable candidates
109
- return "\n\n".join(initial_solutions_display_markdown), "No viable candidates after evaluation.", "", "\n".join(log_entries), ""
 
 
 
110
  potentially_viable_candidates.sort(key=lambda x: x["evaluation_obj"].combined_score, reverse=True)
111
  champion_candidate_data = potentially_viable_candidates[0]
 
 
 
112
  champion_display_markdown = (
113
  f"**Champion Candidate ID: {champion_candidate_data['id']} "
114
  f"(Original Combined Score: {champion_candidate_data['evaluation_obj'].combined_score}/10):**\n"
@@ -116,38 +167,30 @@ def run_algoforge_simulation_orchestrator(
116
  f"**Original Comprehensive Evaluation for this Champion:**\n{champion_candidate_data['evaluation_obj'].get_display_critique()}"
117
  )
118
 
119
-
120
  # --- STAGE 4: EVOLUTIONARY FORGE ---
121
- progress(0.75, desc="Stage 4: Evolving Champion...")
122
- log_entries.append("\n**------ STAGE 4: EVOLUTIONARY FORGE (Informed by Tests) ------**")
123
- llm_config_evolution = {"type": current_model_config["type"], "model_id": current_model_config["id"], "temp": evolution_temp, "max_tokens": evolution_max_tokens}
124
-
125
  evolved_solution_code = evolve_solution(
126
  str(champion_candidate_data["solution_text"]),
127
- champion_candidate_data["evaluation_obj"], # Pass the whole EvaluationResultOutput object
128
- # champion_candidate_data["evaluation_obj"].combined_score, # Score is inside the object
129
  problem_description_text,
130
  problem_type_selected,
131
  llm_config_evolution
132
  )
133
- # ... (log evolved solution snippet) ...
134
  evolved_solution_display_markdown = ""
135
- ai_test_analysis_markdown = ""
136
 
137
  if str(evolved_solution_code).startswith("ERROR"):
138
  evolved_solution_display_markdown = f"**Evolution Stage Failed:**\n{evolved_solution_code}"
139
  else:
140
  evolved_solution_display_markdown = f"**✨ AlgoForge Omega™ Evolved Artifact ✨:**\n```python\n{evolved_solution_code}\n```"
141
-
142
- # Re-evaluate the evolved solution with unit tests
143
  if "python" in problem_type_selected.lower() and user_provided_tests_code.strip():
144
  progress(0.9, desc="Post-Evolution: Re-testing Evolved Code...")
145
  log_entries.append("\n--- Post-Evolution Test of Evolved Code ---")
146
- # Use the actual safe_executor here directly for testing evolved code
147
- evolved_code_exec_result = execute_python_code_with_tests( # type: ExecutionResult
148
  str(evolved_solution_code), user_provided_tests_code, timeout_seconds=10
149
  )
150
-
151
  evolved_solution_display_markdown += (
152
  f"\n\n**Post-Evolution Automated Test Results (Simulated):**\n"
153
  f" Tests Attempted: {evolved_code_exec_result.total_tests}\n"
@@ -158,76 +201,69 @@ def run_algoforge_simulation_orchestrator(
158
  evolved_solution_display_markdown += f" Execution Error/Output: {evolved_code_exec_result.error}\n"
159
  elif evolved_code_exec_result.output:
160
  evolved_solution_display_markdown += f" Execution Output (stdout):\n```\n{evolved_code_exec_result.output[:300]}\n```\n"
161
-
162
  log_entries.append(f" Evolved Code Test Results: {evolved_code_exec_result}")
163
 
164
- # Get LLM to explain the test results of the evolved code
165
- if evolved_code_exec_result.total_tests > 0 :
166
- # ... (AI Test Analysis call as before, using evolved_code_exec_result.error or .output for summary) ...
167
  progress(0.95, desc="Post-Evolution: AI Analyzing Test Results...")
 
168
  analysis_exec_summary = evolved_code_exec_result.error if evolved_code_exec_result.error else (evolved_code_exec_result.output if evolved_code_exec_result.output else "Tests completed.")
169
  analysis_user_prompt = format_code_test_analysis_user_prompt(str(evolved_solution_code), user_provided_tests_code, f"Passed: {evolved_code_exec_result.passed_tests}/{evolved_code_exec_result.total_tests}. Detail: {analysis_exec_summary}")
170
- # ... (rest of AI analysis call) ...
 
 
 
171
  from core.llm_clients import call_huggingface_api, call_gemini_api
172
- llm_analysis_config = {"type": current_model_config["type"], "model_id": current_model_config["id"], "temp": 0.3, "max_tokens": critique_max_tokens + 150}
173
  explanation_response_obj = None
174
- if llm_analysis_config["type"] == "hf": explanation_response_obj = call_huggingface_api(analysis_user_prompt, llm_analysis_config["model_id"], llm_analysis_config["temp"], llm_analysis_config["max_tokens"], get_system_prompt("code_execution_explainer"))
175
- elif llm_analysis_config["type"] == "google_gemini": explanation_response_obj = call_gemini_api(analysis_user_prompt, llm_analysis_config["model_id"], llm_analysis_config["temp"], llm_analysis_config["max_tokens"], get_system_prompt("code_execution_explainer"))
176
- if explanation_response_obj and explanation_response_obj.success: ai_test_analysis_markdown = f"**AI Analysis of Evolved Code's Test Performance:**\n{explanation_response_obj.text}"
177
- elif explanation_response_obj: ai_test_analysis_markdown = f"**AI Analysis Failed:**\n{explanation_response_obj.error}"
 
 
 
 
 
178
 
179
-
180
- # ... (Total time logging and return statement as before) ...
181
- total_time = time.time() - start_time
182
- log_entries.append(f"\n**AlgoForge Omega Cycle Complete. Total time: {total_time:.2f} seconds.**")
183
  progress(1.0, desc="Cycle Complete!")
 
184
  return "\n\n".join(initial_solutions_display_markdown), champion_display_markdown, evolved_solution_display_markdown, "\n".join(log_entries), ai_test_analysis_markdown
185
 
186
 
187
  # --- Gradio UI Definition ---
188
- # (This is IDENTICAL to the UI in the previous full app.py where you introduced the user_tests_tb)
189
- # For brevity, ensure it's copied correctly. Key parts:
190
- # - `intro_markdown` with updated title "AlgoForge Omega™ Conceptual Demo"
191
- # - `ui_token_status_md` based on GEMINI_API_READY, HF_API_READY
192
- # - `user_tests_tb` Gradio Textbox component
193
- # - All sliders and dropdowns
194
- # - `engage_button.click` connecting to `run_algoforge_simulation_orchestrator` with all inputs/outputs.
195
- # ... PASTE THE FULL UI DEFINITION HERE from your last complete app.py version ...
196
  intro_markdown = """
197
  # ✨ AlgoForge Omega™ ✨: Conceptual Demo with (Simulated) Execution
198
  This version demonstrates a conceptual workflow for AI-assisted algorithm discovery and refinement,
199
  featuring **(simulated) execution of generated Python code against user-provided unit tests**.
200
 
201
  **API Keys Required in Space Secrets:**
202
- - `GOOGLE_API_KEY` (Primary): For Google Gemini API models.
203
  - `HF_TOKEN` (Secondary): For Hugging Face hosted models.
204
  """
205
- # ... (ui_token_status_md as before) ...
206
  ui_token_status_md = ""
207
- if not GEMINI_API_READY and not HF_API_READY: ui_token_status_md = "<p style='color:red;'>⚠️ CRITICAL: NEITHER API IS CONFIGURED. APP NON-FUNCTIONAL.</p>"
 
208
  else:
209
  if GEMINI_API_READY: ui_token_status_md += "<p style='color:green;'>✅ Google Gemini API Configured.</p>"
210
- else: ui_token_status_md += "<p style='color:orange;'>⚠️ GOOGLE_API_KEY missing/failed.</p>"
211
  if HF_API_READY: ui_token_status_md += "<p style='color:green;'>✅ Hugging Face API Configured.</p>"
212
- else: ui_token_status_md += "<p style='color:orange;'>⚠️ HF_TOKEN missing/failed.</p>"
213
 
214
- with gr.Blocks(theme=gr.themes.Soft(primary_hue="purple", secondary_hue="pink"), title="AlgoForge Omega™ Demo") as app_demo: # New theme
215
  gr.Markdown(intro_markdown)
216
  gr.HTML(ui_token_status_md)
217
- # ... (Full UI layout as provided in the "write all the files" response, ensuring all inputs/outputs match orchestrator)
218
- # This is the same UI structure as the last full app.py I provided.
219
- # Ensure all inputs to engage_button.click match the orchestrator's signature.
220
- # For brevity, I'm showing the structure. Copy from the previous full version.
221
- usable_models_available = any(AVAILABLE_MODELS_CONFIG.get(key, {}).get("type") != "none" for key in AVAILABLE_MODELS_CONFIG)
222
  if not usable_models_available:
223
- gr.Markdown("<h2 style='color:red;'>No LLM models available for use. Check API keys and restart.</h2>")
224
  else:
225
  with gr.Row():
226
- with gr.Column(scale=2): # Input Column
227
- # ... (problem_type_dropdown, problem_description_textbox, initial_hints_textbox, user_tests_textbox)
228
- # ... (model_selection_dropdown, num_initial_solutions_slider)
229
- # ... (Accordion with LLM parameter sliders)
230
- # ... (engage_button)
231
  gr.Markdown("## 💡 1. Define the Challenge")
232
  problem_type_dropdown = gr.Dropdown(choices=["Python Algorithm with Tests", "Python Algorithm (Critique Only)", "General Algorithm Idea"], label="Problem Type", value="Python Algorithm with Tests")
233
  problem_description_textbox = gr.Textbox(lines=5, label="Problem Description")
@@ -245,8 +281,7 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="purple", secondary_hue="pink"),
245
  evolution_max_tokens_slider = gr.Slider(256, 4096, value=1536, step=128, label="Evolution Max Tokens")
246
  engage_button = gr.Button("🚀 ENGAGE ALGOFORGE OMEGA™ 🚀", variant="primary")
247
 
248
-
249
- with gr.Column(scale=3): # Output Column
250
  gr.Markdown("## 🔥 3. The Forge's Output")
251
  with gr.Tabs():
252
  with gr.TabItem("📜 Candidates & Evaluations"): output_initial_solutions_markdown = gr.Markdown()
@@ -264,12 +299,15 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="purple", secondary_hue="pink"),
264
  gr.Markdown("---")
265
  gr.Markdown("**Disclaimer:** Conceptual Omega Demo. (Simulated) unit testing. **NEVER run untrusted LLM code without robust sandboxing.**")
266
 
267
-
268
  # --- Entry Point for Running the Gradio App ---
269
  if __name__ == "__main__":
270
  print("="*80)
271
  print("AlgoForge Omega™ Conceptual Demo - Launching...")
272
  print(f" Gemini API Ready: {GEMINI_API_READY}")
273
  print(f" HF API Ready: {HF_API_READY}")
274
- # ... (other startup prints)
 
 
 
 
275
  app_demo.launch(debug=True, server_name="0.0.0.0")
 
1
  # algoforge_prime/app.py
2
  import gradio as gr
3
  import os
4
+ import time # For progress updates and timing
5
 
6
+ # --- Core Logic Imports ---
7
+ # Initialize clients first to ensure API keys are loaded before other modules use them.
8
+ from core.llm_clients import initialize_all_clients, is_gemini_api_configured, is_hf_api_configured # Use getters
9
+ initialize_all_clients() # CRITICAL: Call initialization first
10
 
11
+ # Now get the status AFTER initialization
12
  GEMINI_API_READY = is_gemini_api_configured()
13
  HF_API_READY = is_hf_api_configured()
14
 
15
  from core.generation_engine import generate_initial_solutions
16
+ from core.evaluation_engine import evaluate_solution_candidate, EvaluationResultOutput # Using the renamed class
17
  from core.evolution_engine import evolve_solution
18
  from prompts.system_prompts import get_system_prompt
19
  from prompts.prompt_templates import format_code_test_analysis_user_prompt
20
  from core.safe_executor import execute_python_code_with_tests, ExecutionResult # For re-evaluating evolved code
21
 
22
  # --- Application Configuration (Models, Defaults) ---
 
23
  AVAILABLE_MODELS_CONFIG = {}
24
  UI_DEFAULT_MODEL_KEY = None
25
+
26
  GEMINI_1_5_PRO_LATEST_ID = "gemini-1.5-pro-latest"
27
  GEMINI_1_5_FLASH_LATEST_ID = "gemini-1.5-flash-latest"
28
+
29
  if GEMINI_API_READY:
30
  AVAILABLE_MODELS_CONFIG.update({
31
  f"Google Gemini 1.5 Pro (API - Recommended)": {"id": GEMINI_1_5_PRO_LATEST_ID, "type": "google_gemini"},
 
33
  "Google Gemini 1.0 Pro (API - Legacy)": {"id": "gemini-1.0-pro-latest", "type": "google_gemini"},
34
  })
35
  UI_DEFAULT_MODEL_KEY = f"Google Gemini 1.5 Pro (API - Recommended)"
36
+ if UI_DEFAULT_MODEL_KEY not in AVAILABLE_MODELS_CONFIG:
37
+ UI_DEFAULT_MODEL_KEY = f"Google Gemini 1.5 Flash (API - Fast)"
38
+ print(f"INFO: app.py - Gemini models populated. Default set to: {UI_DEFAULT_MODEL_KEY}")
39
+ else:
40
+ print("WARNING: app.py - Gemini API not configured; Gemini models will be unavailable.")
41
+
42
  if HF_API_READY:
43
  AVAILABLE_MODELS_CONFIG.update({
44
  "Google Gemma 2B (HF - Quick Test)": {"id": "google/gemma-2b-it", "type": "hf"},
45
  "Mistral 7B Instruct (HF)": {"id": "mistralai/Mistral-7B-Instruct-v0.2", "type": "hf"},
46
+ "CodeLlama 7B Instruct (HF)": {"id": "codellama/CodeLlama-7b-Instruct-hf", "type": "hf"},
47
  })
48
+ if not UI_DEFAULT_MODEL_KEY:
49
+ UI_DEFAULT_MODEL_KEY = "Google Gemma 2B (HF - Quick Test)"
50
+ print("INFO: app.py - HF models populated; default set as Gemini was not available.")
51
+ else:
52
+ print("INFO: app.py - HF models also populated as alternatives.")
53
+ else:
54
+ print("WARNING: app.py - Hugging Face API not configured; HF models will be unavailable.")
55
+
56
  if not AVAILABLE_MODELS_CONFIG:
57
+ print("CRITICAL APP ERROR: No models could be configured. Check API keys and restart Space.")
58
  AVAILABLE_MODELS_CONFIG["No Models Available (Check API Keys & Restart)"] = {"id": "dummy_error", "type": "none"}
59
  UI_DEFAULT_MODEL_KEY = "No Models Available (Check API Keys & Restart)"
60
+ elif not UI_DEFAULT_MODEL_KEY and AVAILABLE_MODELS_CONFIG:
61
+ UI_DEFAULT_MODEL_KEY = list(AVAILABLE_MODELS_CONFIG.keys())[0]
62
+ print(f"WARNING: app.py - UI_DEFAULT_MODEL_KEY was not set by primary logic, falling back to: {UI_DEFAULT_MODEL_KEY}")
63
 
64
 
65
  # --- Main Orchestration Logic for Gradio ---
66
  def run_algoforge_simulation_orchestrator(
67
+ problem_type_selected: str,
68
+ problem_description_text: str,
69
+ initial_hints_text: str,
70
+ user_provided_tests_code: str,
71
+ num_initial_solutions_to_gen: int,
72
+ selected_model_ui_key: str,
73
+ genesis_temp: float, genesis_max_tokens: int,
74
+ critique_temp: float, critique_max_tokens: int,
75
  evolution_temp: float, evolution_max_tokens: int,
76
+ progress=gr.Progress(track_tqdm=True)
77
  ):
78
+ # CORRECTED: start_time defined at the beginning of the function
79
+ start_time = time.time()
80
+
81
  progress(0, desc="Initializing AlgoForge Prime™...")
82
+ log_entries = [f"**AlgoForge Prime™ Cycle Starting at {time.strftime('%Y-%m-%d %H:%M:%S')}**"]
83
+
84
+ if not problem_description_text.strip():
85
+ error_msg = "CRITICAL INPUT ERROR: Problem Description is mandatory. Please describe the problem."
86
+ log_entries.append(error_msg)
87
+ return error_msg, "", "", "\n".join(log_entries), ""
88
+
89
  current_model_config = AVAILABLE_MODELS_CONFIG.get(selected_model_ui_key)
90
+ if not current_model_config or current_model_config["type"] == "none":
91
+ error_msg = f"CRITICAL CONFIG ERROR: No valid LLM selected ('{selected_model_ui_key}'). API keys might be missing or failed initialization. Please check Space Secrets & restart."
92
+ log_entries.append(error_msg)
93
+ return error_msg, "", "", "\n".join(log_entries), ""
94
+
95
+ log_entries.append(f"Selected Model: {selected_model_ui_key} (Type: {current_model_config['type']}, ID: {current_model_config['id']})")
96
+ log_entries.append(f"Problem Type: {problem_type_selected}")
97
+ log_entries.append(f"User Unit Tests Provided: {'Yes' if user_provided_tests_code.strip() else 'No'}")
98
 
 
 
99
  llm_config_genesis = {"type": current_model_config["type"], "model_id": current_model_config["id"], "temp": genesis_temp, "max_tokens": genesis_max_tokens}
100
+ llm_config_critique = {"type": current_model_config["type"], "model_id": current_model_config["id"], "temp": critique_temp, "max_tokens": critique_max_tokens}
101
+ llm_config_evolution = {"type": current_model_config["type"], "model_id": current_model_config["id"], "temp": evolution_temp, "max_tokens": evolution_max_tokens}
102
 
103
+ # --- STAGE 1: GENESIS ---
104
+ progress(0.05, desc="Stage 1: Genesis Engine - Generating Solutions...")
105
+ log_entries.append("\n**------ STAGE 1: GENESIS ENGINE ------**")
106
+ initial_raw_solutions = generate_initial_solutions(
107
+ problem_description_text, initial_hints_text, problem_type_selected,
108
+ num_initial_solutions_to_gen, llm_config_genesis
109
+ )
110
+ log_entries.append(f"Genesis Engine produced {len(initial_raw_solutions)} raw solution candidate(s).")
111
+ for i, sol_text in enumerate(initial_raw_solutions):
112
+ log_entries.append(f" Candidate {i+1} (Raw Snippet): {str(sol_text)[:120]}...")
113
 
114
  # --- STAGE 2: CRITIQUE & AUTOMATED EVALUATION ---
115
+ progress(0.25, desc="Stage 2: Critique Crucible - Evaluating Candidates...")
116
+ log_entries.append("\n**------ STAGE 2: CRITIQUE CRUCIBLE & AUTOMATED EVALUATION ------**")
117
+ evaluated_candidates_list = []
 
 
118
  for i, candidate_solution_text in enumerate(initial_raw_solutions):
119
+ current_progress = 0.25 + ( (i + 1) / num_initial_solutions_to_gen ) * 0.4
120
+ progress(current_progress, desc=f"Evaluating Candidate {i+1} of {num_initial_solutions_to_gen}...")
121
  log_entries.append(f"\n--- Evaluating Candidate {i+1} ---")
122
+ evaluation_output_obj = evaluate_solution_candidate(
123
+ str(candidate_solution_text),
124
+ problem_description_text, problem_type_selected,
125
  user_provided_tests_code, llm_config_critique
126
  )
127
  evaluated_candidates_list.append({
128
  "id": i + 1,
129
+ "solution_text": str(candidate_solution_text),
130
+ "evaluation_obj": evaluation_output_obj
131
  })
132
  log_entries.append(f" Combined Score: {evaluation_output_obj.combined_score}/10")
133
  if evaluation_output_obj.execution_details:
 
139
  for data in evaluated_candidates_list:
140
  initial_solutions_display_markdown.append(
141
  f"**Candidate {data['id']}:**\n```python\n{data['solution_text']}\n```\n\n"
142
+ f"**Evaluation Verdict (Combined Score: {data['evaluation_obj'].combined_score}/10):**\n{data['evaluation_obj'].get_display_critique()}\n---"
143
  )
144
 
145
  # --- STAGE 3: SELECTION OF CHAMPION ---
146
+ progress(0.7, desc="Stage 3: Selecting Champion Candidate...")
147
+ log_entries.append("\n**------ STAGE 3: CHAMPION SELECTION ------**")
148
  potentially_viable_candidates = [
149
  cand for cand in evaluated_candidates_list
150
  if cand["evaluation_obj"] and cand["evaluation_obj"].combined_score > 0 and \
151
  cand["solution_text"] and not str(cand["solution_text"]).startswith("ERROR")
152
  ]
153
+ if not potentially_viable_candidates:
154
+ final_error_msg = "No viable candidate solutions found after generation and evaluation. All attempts may have failed or scored too low."
155
+ log_entries.append(f" CRITICAL: {final_error_msg}")
156
+ return "\n\n".join(initial_solutions_display_markdown), final_error_msg, "", "\n".join(log_entries), ""
157
+
158
  potentially_viable_candidates.sort(key=lambda x: x["evaluation_obj"].combined_score, reverse=True)
159
  champion_candidate_data = potentially_viable_candidates[0]
160
+ log_entries.append(f"Champion Selected: Candidate {champion_candidate_data['id']} "
161
+ f"(Solution Snippet: {str(champion_candidate_data['solution_text'])[:60]}...) "
162
+ f"with evaluation score {champion_candidate_data['evaluation_obj'].combined_score}/10.")
163
  champion_display_markdown = (
164
  f"**Champion Candidate ID: {champion_candidate_data['id']} "
165
  f"(Original Combined Score: {champion_candidate_data['evaluation_obj'].combined_score}/10):**\n"
 
167
  f"**Original Comprehensive Evaluation for this Champion:**\n{champion_candidate_data['evaluation_obj'].get_display_critique()}"
168
  )
169
 
 
170
  # --- STAGE 4: EVOLUTIONARY FORGE ---
171
+ progress(0.75, desc="Stage 4: Evolutionary Forge - Refining Champion...")
172
+ log_entries.append("\n**------ STAGE 4: EVOLUTIONARY FORGE ------**")
 
 
173
  evolved_solution_code = evolve_solution(
174
  str(champion_candidate_data["solution_text"]),
175
+ champion_candidate_data["evaluation_obj"],
 
176
  problem_description_text,
177
  problem_type_selected,
178
  llm_config_evolution
179
  )
180
+ log_entries.append(f"Raw Evolved Solution Text (Snippet): {str(evolved_solution_code)[:150]}...")
181
  evolved_solution_display_markdown = ""
182
+ ai_test_analysis_markdown = ""
183
 
184
  if str(evolved_solution_code).startswith("ERROR"):
185
  evolved_solution_display_markdown = f"**Evolution Stage Failed:**\n{evolved_solution_code}"
186
  else:
187
  evolved_solution_display_markdown = f"**✨ AlgoForge Omega™ Evolved Artifact ✨:**\n```python\n{evolved_solution_code}\n```"
 
 
188
  if "python" in problem_type_selected.lower() and user_provided_tests_code.strip():
189
  progress(0.9, desc="Post-Evolution: Re-testing Evolved Code...")
190
  log_entries.append("\n--- Post-Evolution Test of Evolved Code ---")
191
+ evolved_code_exec_result = execute_python_code_with_tests(
 
192
  str(evolved_solution_code), user_provided_tests_code, timeout_seconds=10
193
  )
 
194
  evolved_solution_display_markdown += (
195
  f"\n\n**Post-Evolution Automated Test Results (Simulated):**\n"
196
  f" Tests Attempted: {evolved_code_exec_result.total_tests}\n"
 
201
  evolved_solution_display_markdown += f" Execution Error/Output: {evolved_code_exec_result.error}\n"
202
  elif evolved_code_exec_result.output:
203
  evolved_solution_display_markdown += f" Execution Output (stdout):\n```\n{evolved_code_exec_result.output[:300]}\n```\n"
 
204
  log_entries.append(f" Evolved Code Test Results: {evolved_code_exec_result}")
205
 
206
+ if evolved_code_exec_result.total_tests > 0 :
 
 
207
  progress(0.95, desc="Post-Evolution: AI Analyzing Test Results...")
208
+ log_entries.append("\n--- AI Analysis of Evolved Code's Test Results ---")
209
  analysis_exec_summary = evolved_code_exec_result.error if evolved_code_exec_result.error else (evolved_code_exec_result.output if evolved_code_exec_result.output else "Tests completed.")
210
  analysis_user_prompt = format_code_test_analysis_user_prompt(str(evolved_solution_code), user_provided_tests_code, f"Passed: {evolved_code_exec_result.passed_tests}/{evolved_code_exec_result.total_tests}. Detail: {analysis_exec_summary}")
211
+ analysis_system_prompt = get_system_prompt("code_execution_explainer")
212
+ llm_analysis_config = {"type": current_model_config["type"], "model_id": current_model_config["id"],
213
+ "temp": 0.3, "max_tokens": critique_max_tokens + 150}
214
+
215
  from core.llm_clients import call_huggingface_api, call_gemini_api
 
216
  explanation_response_obj = None
217
+ if llm_analysis_config["type"] == "hf": explanation_response_obj = call_huggingface_api(analysis_user_prompt, llm_analysis_config["model_id"], llm_analysis_config["temp"], llm_analysis_config["max_tokens"], analysis_system_prompt)
218
+ elif llm_analysis_config["type"] == "google_gemini": explanation_response_obj = call_gemini_api(analysis_user_prompt, llm_analysis_config["model_id"], llm_analysis_config["temp"], llm_analysis_config["max_tokens"], analysis_system_prompt)
219
+
220
+ if explanation_response_obj and explanation_response_obj.success:
221
+ ai_test_analysis_markdown = f"**AI Analysis of Evolved Code's Test Performance:**\n{explanation_response_obj.text}"
222
+ log_entries.append(f" AI Test Analysis (Snippet): {str(explanation_response_obj.text)[:100]}...")
223
+ elif explanation_response_obj:
224
+ ai_test_analysis_markdown = f"**AI Analysis of Test Performance Failed:**\n{explanation_response_obj.error}"
225
+ log_entries.append(f" AI Test Analysis Error: {explanation_response_obj.error}")
226
 
227
+ # CORRECTED: total_time definition using the start_time from the function scope
228
+ total_time = time.time() - start_time
229
+ log_entries.append(f"\n**AlgoForge Omega™ Cycle Complete. Total time: {total_time:.2f} seconds.**")
 
230
  progress(1.0, desc="Cycle Complete!")
231
+
232
  return "\n\n".join(initial_solutions_display_markdown), champion_display_markdown, evolved_solution_display_markdown, "\n".join(log_entries), ai_test_analysis_markdown
233
 
234
 
235
  # --- Gradio UI Definition ---
 
 
 
 
 
 
 
 
236
  intro_markdown = """
237
  # ✨ AlgoForge Omega™ ✨: Conceptual Demo with (Simulated) Execution
238
  This version demonstrates a conceptual workflow for AI-assisted algorithm discovery and refinement,
239
  featuring **(simulated) execution of generated Python code against user-provided unit tests**.
240
 
241
  **API Keys Required in Space Secrets:**
242
+ - `GOOGLE_API_KEY` (Primary): For Google Gemini API models. Ensure the "Generative Language API" (or similar) is enabled for your project.
243
  - `HF_TOKEN` (Secondary): For Hugging Face hosted models.
244
  """
 
245
  ui_token_status_md = ""
246
+ if not GEMINI_API_READY and not HF_API_READY:
247
+ ui_token_status_md = "<p style='color:red;'>⚠️ **CRITICAL: NEITHER API IS CONFIGURED. APP NON-FUNCTIONAL.**</p>"
248
  else:
249
  if GEMINI_API_READY: ui_token_status_md += "<p style='color:green;'>✅ Google Gemini API Configured.</p>"
250
+ else: ui_token_status_md += "<p style='color:orange;'>⚠️ **GOOGLE_API_KEY missing/failed.** Gemini models disabled.</p>"
251
  if HF_API_READY: ui_token_status_md += "<p style='color:green;'>✅ Hugging Face API Configured.</p>"
252
+ else: ui_token_status_md += "<p style='color:orange;'>⚠️ **HF_TOKEN missing/failed.** HF models disabled.</p>"
253
 
254
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="purple", secondary_hue="pink"), title="AlgoForge Omega™ Demo") as app_demo:
255
  gr.Markdown(intro_markdown)
256
  gr.HTML(ui_token_status_md)
257
+
258
+ usable_models_available = any(
259
+ AVAILABLE_MODELS_CONFIG.get(key, {}).get("type") != "none"
260
+ for key in AVAILABLE_MODELS_CONFIG
261
+ )
262
  if not usable_models_available:
263
+ gr.Markdown("<h2 style='color:red;'>No LLM models are available for use. Check API keys and restart.</h2>")
264
  else:
265
  with gr.Row():
266
+ with gr.Column(scale=2):
 
 
 
 
267
  gr.Markdown("## 💡 1. Define the Challenge")
268
  problem_type_dropdown = gr.Dropdown(choices=["Python Algorithm with Tests", "Python Algorithm (Critique Only)", "General Algorithm Idea"], label="Problem Type", value="Python Algorithm with Tests")
269
  problem_description_textbox = gr.Textbox(lines=5, label="Problem Description")
 
281
  evolution_max_tokens_slider = gr.Slider(256, 4096, value=1536, step=128, label="Evolution Max Tokens")
282
  engage_button = gr.Button("🚀 ENGAGE ALGOFORGE OMEGA™ 🚀", variant="primary")
283
 
284
+ with gr.Column(scale=3):
 
285
  gr.Markdown("## 🔥 3. The Forge's Output")
286
  with gr.Tabs():
287
  with gr.TabItem("📜 Candidates & Evaluations"): output_initial_solutions_markdown = gr.Markdown()
 
299
  gr.Markdown("---")
300
  gr.Markdown("**Disclaimer:** Conceptual Omega Demo. (Simulated) unit testing. **NEVER run untrusted LLM code without robust sandboxing.**")
301
 
 
302
  # --- Entry Point for Running the Gradio App ---
303
  if __name__ == "__main__":
304
  print("="*80)
305
  print("AlgoForge Omega™ Conceptual Demo - Launching...")
306
  print(f" Gemini API Ready: {GEMINI_API_READY}")
307
  print(f" HF API Ready: {HF_API_READY}")
308
+ if not GEMINI_API_READY and not HF_API_READY:
309
+ print(" CRITICAL WARNING: No API keys seem to be configured correctly. The application will likely be non-functional.")
310
+ print(f" UI Default Model Key: {UI_DEFAULT_MODEL_KEY}")
311
+ print(f" Available models for UI: {list(AVAILABLE_MODELS_CONFIG.keys())}")
312
+ print("="*80)
313
  app_demo.launch(debug=True, server_name="0.0.0.0")