Spaces:
Running
Running
Update app.py
Browse files
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 |
-
|
7 |
-
|
|
|
|
|
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 #
|
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:
|
33 |
-
|
|
|
|
|
|
|
|
|
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:
|
40 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
45 |
|
46 |
|
47 |
# --- Main Orchestration Logic for Gradio ---
|
48 |
def run_algoforge_simulation_orchestrator(
|
49 |
-
problem_type_selected: str,
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
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™
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
58 |
current_model_config = AVAILABLE_MODELS_CONFIG.get(selected_model_ui_key)
|
59 |
-
if not current_model_config or current_model_config["type"] == "none":
|
60 |
-
|
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 |
-
|
|
|
67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
|
69 |
# --- STAGE 2: CRITIQUE & AUTOMATED EVALUATION ---
|
70 |
-
progress(0.25, desc="Stage 2:
|
71 |
-
log_entries.append("\n**------ STAGE 2: CRITIQUE CRUCIBLE & AUTOMATED
|
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 |
-
|
|
|
77 |
log_entries.append(f"\n--- Evaluating Candidate {i+1} ---")
|
78 |
-
evaluation_output_obj = evaluate_solution_candidate(
|
79 |
-
str(candidate_solution_text),
|
|
|
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
|
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---"
|
98 |
)
|
99 |
|
100 |
# --- STAGE 3: SELECTION OF CHAMPION ---
|
101 |
-
|
102 |
-
|
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:
|
109 |
-
|
|
|
|
|
|
|
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:
|
122 |
-
log_entries.append("\n**------ STAGE 4: EVOLUTIONARY FORGE
|
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"],
|
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 |
-
|
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 |
-
|
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 |
-
|
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 |
-
|
|
|
|
|
|
|
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"],
|
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"],
|
176 |
-
|
177 |
-
|
|
|
|
|
|
|
|
|
|
|
178 |
|
179 |
-
|
180 |
-
|
181 |
-
|
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:
|
|
|
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:
|
215 |
gr.Markdown(intro_markdown)
|
216 |
gr.HTML(ui_token_status_md)
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
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):
|
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 |
-
|
|
|
|
|
|
|
|
|
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")
|