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