Spaces:
Sleeping
Sleeping
import gradio as gr | |
import os | |
import json | |
import time | |
from typing import List, Dict, Optional, Tuple | |
import logging | |
# Import the existing app components | |
from app.models import ResearchGoal, ContextMemory | |
from app.agents import SupervisorAgent | |
from app.utils import logger, is_huggingface_space, get_deployment_environment, filter_free_models | |
from app.tools.arxiv_search import ArxivSearchTool | |
import requests | |
# Global state for the Gradio app | |
global_context = ContextMemory() | |
supervisor = SupervisorAgent() | |
current_research_goal: Optional[ResearchGoal] = None | |
available_models: List[str] = [] | |
# Configure logging for Gradio | |
logging.basicConfig(level=logging.INFO) | |
def fetch_available_models(): | |
"""Fetch available models from OpenRouter with environment-based filtering.""" | |
global available_models | |
# Detect deployment environment | |
deployment_env = get_deployment_environment() | |
is_hf_spaces = is_huggingface_space() | |
logger.info(f"Detected deployment environment: {deployment_env}") | |
logger.info(f"Is Hugging Face Spaces: {is_hf_spaces}") | |
try: | |
response = requests.get("https://openrouter.ai/api/v1/models", timeout=10) | |
response.raise_for_status() | |
models_data = response.json().get("data", []) | |
# Extract all model IDs | |
all_models = sorted([model.get("id") for model in models_data if model.get("id")]) | |
# Create filtered free models list | |
free_models = filter_free_models(all_models) | |
# Apply filtering based on environment | |
if is_hf_spaces: | |
# Use only free models for Hugging Face Spaces | |
available_models = free_models | |
logger.info(f"Hugging Face Spaces: Filtered to {len(available_models)} free models") | |
else: | |
# Use all models in local/development environment | |
available_models = all_models | |
logger.info(f"Local/Development: Using all {len(available_models)} models") | |
except Exception as e: | |
logger.error(f"Failed to fetch models from OpenRouter: {e}") | |
# Fallback to safe defaults | |
if is_hf_spaces: | |
# Use a known free model as fallback | |
available_models = ["google/gemini-2.0-flash-001:free"] | |
else: | |
available_models = ["google/gemini-2.0-flash-001"] | |
return available_models | |
def get_deployment_status(): | |
"""Get deployment status information.""" | |
deployment_env = get_deployment_environment() | |
is_hf_spaces = is_huggingface_space() | |
if is_hf_spaces: | |
status = f"π Running in {deployment_env} | Models filtered for cost control ({len(available_models)} available)" | |
color = "orange" | |
else: | |
status = f"π» Running in {deployment_env} | All models available ({len(available_models)} total)" | |
color = "blue" | |
return status, color | |
def set_research_goal( | |
description: str, | |
llm_model: str = None, | |
num_hypotheses: int = 3, | |
generation_temperature: float = 0.7, | |
reflection_temperature: float = 0.5, | |
elo_k_factor: int = 32, | |
top_k_hypotheses: int = 2 | |
) -> Tuple[str, str]: | |
"""Set the research goal and initialize the system.""" | |
global current_research_goal, global_context | |
if not description.strip(): | |
return "β Error: Please enter a research goal.", "" | |
try: | |
# Create research goal with settings | |
current_research_goal = ResearchGoal( | |
description=description.strip(), | |
constraints={}, | |
llm_model=llm_model if llm_model and llm_model != "-- Select Model --" else None, | |
num_hypotheses=num_hypotheses, | |
generation_temperature=generation_temperature, | |
reflection_temperature=reflection_temperature, | |
elo_k_factor=elo_k_factor, | |
top_k_hypotheses=top_k_hypotheses | |
) | |
# Reset context | |
global_context = ContextMemory() | |
logger.info(f"Research goal set: {description}") | |
logger.info(f"Settings: model={current_research_goal.llm_model}, num={current_research_goal.num_hypotheses}") | |
status_msg = f"β Research goal set successfully!\n\n**Goal:** {description}\n**Model:** {current_research_goal.llm_model or 'Default'}\n**Hypotheses per cycle:** {num_hypotheses}" | |
return status_msg, "Ready to run first cycle. Click 'Run Cycle' to begin." | |
except Exception as e: | |
error_msg = f"β Error setting research goal: {str(e)}" | |
logger.error(error_msg) | |
return error_msg, "" | |
def run_cycle() -> Tuple[str, str, str]: | |
"""Run a single research cycle with detailed step logging for debugging.""" | |
import datetime | |
global current_research_goal, global_context, supervisor | |
if not current_research_goal: | |
return "β Error: No research goal set. Please set a research goal first.", "", "" | |
# Prepare log file | |
log_dir = "results" | |
os.makedirs(log_dir, exist_ok=True) | |
timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") | |
log_file = os.path.join(log_dir, f"app_log_{timestamp}.txt") | |
with open(log_file, "w") as f: | |
f.write(f"LOGGING FOR THIS GOAL: {current_research_goal.description}\n") | |
f.write(f"--- Endpoint /run_cycle START ---\n") | |
try: | |
iteration = global_context.iteration_number + 1 | |
logger.info(f"Running cycle {iteration}") | |
# Run the cycle | |
cycle_details = supervisor.run_cycle(current_research_goal, global_context) | |
# Log all steps and hypotheses | |
steps = cycle_details.get("steps", {}) | |
with open(log_file, "a") as f: | |
for step_name, step_data in steps.items(): | |
hypos = step_data.get("hypotheses", []) | |
f.write(f"Step: {step_name} | {len(hypos)} hypotheses\n") | |
for h in hypos: | |
f.write(f" - ID: {h.get('id')} | Title: {h.get('title')} | Elo: {h.get('elo_score', 'N/A')}\n") | |
# Format results for display (also logs final rankings) | |
results_html = format_cycle_results(cycle_details, log_file=log_file) | |
# Get references | |
references_html = get_references_html(cycle_details) | |
# Status message | |
status_msg = f"β Cycle {iteration} completed successfully! Log: {log_file}" | |
return status_msg, results_html, references_html | |
except Exception as e: | |
error_msg = f"β Error during cycle execution: {str(e)}" | |
logger.error(error_msg, exc_info=True) | |
return error_msg, "", "" | |
def format_cycle_results(cycle_details: Dict, log_file: str = None) -> str: | |
"""Format cycle results as HTML with expandable sections. Optionally log final rankings to log_file.""" | |
html = f"<h2>π¬ Iteration {cycle_details.get('iteration', 'Unknown')}</h2>" | |
# Process steps in order | |
steps = cycle_details.get('steps', {}) | |
# Display steps in the order they appear in the steps dict (preserves backend execution order) | |
for step_name, step_data in steps.items(): | |
step_title = { | |
'generation': 'π― Generation', | |
'reflection': 'π Reflection', | |
'ranking': 'π Ranking', | |
'evolution': '𧬠Evolution', | |
'reflection_evolved': 'π Reflection (Evolved)', | |
'ranking_final': 'π Final Ranking', | |
'proximity': 'π Proximity Analysis', | |
'meta_review': 'π Meta-Review' | |
}.get(step_name, step_name.title()) | |
html += f""" | |
<details style="margin: 15px 0; border: 1px solid #ddd; border-radius: 8px; padding: 10px;"> | |
<summary style="font-weight: bold; font-size: 1.1em; cursor: pointer; padding: 5px;"> | |
{step_title} | |
</summary> | |
<div style="margin-top: 10px; padding: 10px; background-color: #f8f9fa; border-radius: 5px;"> | |
""" | |
# Step-specific content | |
if step_name == 'generation': | |
hypotheses = step_data.get('hypotheses', []) | |
html += f"<p><strong>Generated {len(hypotheses)} new hypotheses:</strong></p>" | |
for i, hypo in enumerate(hypotheses): | |
html += f""" | |
<div style="border-left: 3px solid #28a745; padding-left: 10px; margin: 10px 0;"> | |
<h5>#{i+1}: {hypo.get('title', 'Untitled')} (ID: {hypo.get('id', 'Unknown')})</h5> | |
<p>{hypo.get('text', 'No description')}</p> | |
</div> | |
""" | |
elif step_name in ['reflection', 'reflection_evolved']: | |
hypotheses = step_data.get('hypotheses', []) | |
html += f"<p><strong>Reviewed {len(hypotheses)} hypotheses:</strong></p>" | |
for hypo in hypotheses: | |
html += f""" | |
<div style="border-left: 3px solid #17a2b8; padding-left: 10px; margin: 10px 0;"> | |
<h5>{hypo.get('title', 'Untitled')} (ID: {hypo.get('id', 'Unknown')})</h5> | |
<p><strong>Novelty:</strong> {hypo.get('novelty_review', 'Not assessed')} | | |
<strong>Feasibility:</strong> {hypo.get('feasibility_review', 'Not assessed')}</p> | |
{f"<p><strong>Comments:</strong> {hypo.get('comments', 'No comments')}</p>" if hypo.get('comments') else ""} | |
</div> | |
""" | |
elif step_name.startswith('ranking'): | |
hypotheses = step_data.get('hypotheses', []) | |
if hypotheses: | |
# Sort by Elo score | |
sorted_hypotheses = sorted(hypotheses, key=lambda h: h.get('elo_score', 0), reverse=True) | |
html += f"<p><strong>Ranking results ({len(hypotheses)} hypotheses):</strong></p>" | |
html += "<ol>" | |
for hypo in sorted_hypotheses: | |
html += f""" | |
<li style="margin: 5px 0;"> | |
<strong>{hypo.get('title', 'Untitled')}</strong> (ID: {hypo.get('id', 'Unknown')}) | |
- Elo: {hypo.get('elo_score', 0):.2f} | |
</li> | |
""" | |
html += "</ol>" | |
elif step_name == 'evolution': | |
hypotheses = step_data.get('hypotheses', []) | |
html += f"<p><strong>Evolved {len(hypotheses)} new hypotheses by combining top performers:</strong></p>" | |
for hypo in hypotheses: | |
html += f""" | |
<div style="border-left: 3px solid #ffc107; padding-left: 10px; margin: 10px 0;"> | |
<h5>{hypo.get('title', 'Untitled')} (ID: {hypo.get('id', 'Unknown')})</h5> | |
<p>{hypo.get('text', 'No description')}</p> | |
</div> | |
""" | |
elif step_name == 'proximity': | |
adjacency_graph = step_data.get('adjacency_graph', {}) | |
nodes = step_data.get('nodes', []) | |
edges = step_data.get('edges', []) | |
# Debug logging | |
logger.info(f"Proximity data - adjacency_graph keys: {list(adjacency_graph.keys()) if adjacency_graph else 'None'}") | |
logger.info(f"Proximity data - nodes count: {len(nodes) if nodes else 0}") | |
logger.info(f"Proximity data - edges count: {len(edges) if edges else 0}") | |
if adjacency_graph: | |
num_hypotheses = len(adjacency_graph) | |
html += f"<p><strong>Similarity Analysis:</strong></p>" | |
html += f"<p>Analyzed relationships between {num_hypotheses} hypotheses</p>" | |
# Calculate and display average similarity | |
all_similarities = [] | |
for hypo_id, connections in adjacency_graph.items(): | |
for conn in connections: | |
all_similarities.append(conn.get('similarity', 0)) | |
if all_similarities: | |
avg_sim = sum(all_similarities) / len(all_similarities) | |
html += f"<p>Average similarity: {avg_sim:.3f}</p>" | |
html += f"<p>Total connections analyzed: {len(all_similarities)}</p>" | |
# Show top similar pairs | |
similarity_pairs = [] | |
for hypo_id, connections in adjacency_graph.items(): | |
for conn in connections: | |
similarity_pairs.append((hypo_id, conn.get('other_id'), conn.get('similarity', 0))) | |
# Sort by similarity and show top 5 | |
similarity_pairs.sort(key=lambda x: x[2], reverse=True) | |
if similarity_pairs: | |
html += "<h6>Top Similar Hypothesis Pairs:</h6><ul>" | |
for i, (id1, id2, sim) in enumerate(similarity_pairs[:5]): | |
html += f"<li>{id1} β {id2}: {sim:.3f}</li>" | |
html += "</ul>" | |
else: | |
html += "<p>No proximity data available.</p>" | |
elif step_name == 'meta_review': | |
# Debug: log the actual meta_review data structure | |
import sys | |
print("DEBUG: meta_review step_data =", step_data, file=sys.stderr) | |
assert isinstance(step_data, dict), "meta_review step_data is not a dict" | |
# Accept both direct dict or nested under 'meta_review' | |
if "meta_review" in step_data and isinstance(step_data["meta_review"], dict): | |
meta_review = step_data["meta_review"] | |
else: | |
meta_review = step_data | |
assert "meta_review_critique" in meta_review, f"meta_review_critique missing in meta_review: {meta_review}" | |
assert "research_overview" in meta_review, f"research_overview missing in meta_review: {meta_review}" | |
# Critique section | |
if meta_review.get('meta_review_critique'): | |
html += "<h5>Critique:</h5><ul>" | |
for critique in meta_review['meta_review_critique']: | |
html += f"<li>{critique}</li>" | |
html += "</ul>" | |
# Top ranked hypotheses section | |
top_hypos = meta_review.get('research_overview', {}).get('top_ranked_hypotheses', []) | |
assert isinstance(top_hypos, list), f"top_ranked_hypotheses is not a list: {top_hypos}" | |
if top_hypos: | |
html += "<h5>Top Ranked Hypotheses:</h5>" | |
for i, hypo in enumerate(top_hypos): | |
html += f""" | |
<div style="border-left: 3px solid #28a745; padding-left: 10px; margin: 10px 0;"> | |
<h6>#{i+1}: {hypo.get('title', 'Untitled')}</h6> | |
<p><strong>ID:</strong> {hypo.get('id', 'Unknown')} | | |
<strong>Elo Score:</strong> {hypo.get('elo_score', 0):.2f}</p> | |
<p><strong>Description:</strong> {hypo.get('text', 'No description')}</p> | |
<p><strong>Novelty:</strong> {hypo.get('novelty_review', 'Not assessed')} | | |
<strong>Feasibility:</strong> {hypo.get('feasibility_review', 'Not assessed')}</p> | |
</div> | |
""" | |
# Suggested next steps section | |
if meta_review.get('research_overview', {}).get('suggested_next_steps'): | |
html += "<h5>Suggested Next Steps:</h5><ul>" | |
for step in meta_review['research_overview']['suggested_next_steps']: | |
html += f"<li>{step}</li>" | |
html += "</ul>" | |
# Add timing information if available | |
if step_data.get('duration'): | |
html += f"<p><em>Duration: {step_data['duration']:.2f}s</em></p>" | |
html += "</div></details>" | |
# Final summary section - always expanded | |
# Prefer ranking steps, else fallback to step with most hypotheses | |
final_hypotheses = [] | |
final_step = None | |
step_order = ['ranking_final', 'ranking2', 'ranking', 'ranking1'] | |
for step_name in step_order: | |
if step_name in steps and steps[step_name].get("hypotheses"): | |
final_hypotheses = steps[step_name]["hypotheses"] | |
final_step = step_name | |
break | |
# Fallback: use step with most hypotheses if no ranking step exists | |
if not final_hypotheses: | |
max_count = 0 | |
for sname, sdata in steps.items(): | |
hypos = sdata.get("hypotheses", []) | |
if len(hypos) > max_count: | |
final_hypotheses = hypos | |
final_step = sname | |
max_count = len(hypos) | |
# Assertions: final list should not be empty and no duplicate IDs (only for ranking steps) | |
ranking_steps = ['ranking_final', 'ranking2', 'ranking', 'ranking1'] | |
if final_hypotheses: | |
ids = [h.get('id') for h in final_hypotheses] | |
if final_step in ranking_steps: | |
assert len(ids) == len(set(ids)), "Duplicate hypothesis IDs found in final rankings!" | |
assert len(final_hypotheses) > 0, "Final hypothesis list is empty!" | |
# Sort by Elo score if present, else by ID | |
if any('elo_score' in h for h in final_hypotheses): | |
final_hypotheses = sorted(final_hypotheses, key=lambda h: h.get('elo_score', 0), reverse=True) | |
else: | |
final_hypotheses = sorted(final_hypotheses, key=lambda h: h.get('id', '')) | |
html += """ | |
<div style="margin: 20px 0; padding: 15px; border: 2px solid #28a745; border-radius: 8px; background-color: #f8fff8;"> | |
<h3>π Final Rankings - Top Hypotheses</h3> | |
""" | |
if final_step not in ranking_steps: | |
html += '<p style="color: #e67e22;">Warning: No ranking step found. Showing hypotheses from the latest available step ("{}"). These may not be ranked.</p>'.format(final_step) | |
# Log final rankings if log_file is provided | |
if log_file: | |
with open(log_file, "a") as f: | |
f.write(f"--- Final Rankings Section (step: {final_step}) ---\n") | |
for i, hypo in enumerate(final_hypotheses[:10]): | |
f.write(f" #{i+1}: ID: {hypo.get('id')} | Title: {hypo.get('title')} | Elo: {hypo.get('elo_score', 'N/A')}\n") | |
for i, hypo in enumerate(final_hypotheses[:10]): # Show top 10 | |
rank_color = "#28a745" if i < 3 else "#17a2b8" if i < 6 else "#6c757d" | |
html += f""" | |
<div style="border-left: 4px solid {rank_color}; padding: 15px; margin: 10px 0; background-color: white; border-radius: 5px;"> | |
<h4>#{i+1}: {hypo.get('title', 'Untitled')}</h4> | |
<p><strong>ID:</strong> {hypo.get('id', 'Unknown')} | | |
<strong>Elo Score:</strong> {hypo.get('elo_score', 0):.2f}</p> | |
<p><strong>Description:</strong> {hypo.get('text', 'No description')}</p> | |
<p><strong>Novelty:</strong> {hypo.get('novelty_review', 'Not assessed')} | | |
<strong>Feasibility:</strong> {hypo.get('feasibility_review', 'Not assessed')}</p> | |
</div> | |
""" | |
html += "</div>" | |
else: | |
html += """ | |
<div style="margin: 20px 0; padding: 15px; border: 2px solid #e74c3c; border-radius: 8px; background-color: #fff5f5;"> | |
<h3>π Final Rankings - Top Hypotheses</h3> | |
<p style="color: #e74c3c;">No hypotheses available for final ranking. This may indicate an error in the workflow.</p> | |
</div> | |
""" | |
# Log missing final rankings if log_file is provided | |
if log_file: | |
with open(log_file, "a") as f: | |
f.write("--- Final Rankings Section: No hypotheses available for final ranking. ---\n") | |
return html | |
def get_references_html(cycle_details: Dict) -> str: | |
"""Get references HTML for the cycle.""" | |
try: | |
# Search for arXiv papers related to the research goal | |
if current_research_goal and current_research_goal.description: | |
arxiv_tool = ArxivSearchTool(max_results=5) | |
papers = arxiv_tool.search_papers( | |
query=current_research_goal.description, | |
max_results=5, | |
sort_by="relevance" | |
) | |
if papers: | |
html = "<h3>π Related arXiv Papers</h3>" | |
for paper in papers: | |
html += f""" | |
<div style="border: 1px solid #e0e0e0; padding: 15px; margin: 10px 0; border-radius: 8px; background-color: #fafafa;"> | |
<h4>{paper.get('title', 'Untitled')}</h4> | |
<p><strong>Authors:</strong> {', '.join(paper.get('authors', [])[:5])}</p> | |
<p><strong>arXiv ID:</strong> {paper.get('arxiv_id', 'Unknown')} | | |
<strong>Published:</strong> {paper.get('published', 'Unknown')}</p> | |
<p><strong>Abstract:</strong> {paper.get('abstract', 'No abstract')[:300]}...</p> | |
<p> | |
<a href="{paper.get('arxiv_url', '#')}" target="_blank">π View on arXiv</a> | | |
<a href="{paper.get('pdf_url', '#')}" target="_blank">π Download PDF</a> | |
</p> | |
</div> | |
""" | |
return html | |
else: | |
return "<p>No related arXiv papers found.</p>" | |
else: | |
return "<p>No research goal set for reference search.</p>" | |
except Exception as e: | |
logger.error(f"Error fetching references: {e}") | |
return f"<p>Error loading references: {str(e)}</p>" | |
def create_gradio_interface(): | |
"""Create the Gradio interface.""" | |
# Fetch models on startup | |
fetch_available_models() | |
# Get deployment status | |
status_text, status_color = get_deployment_status() | |
with gr.Blocks( | |
title="Open AI Co-Scientist - Hypothesis Evolution System", | |
theme=gr.themes.Soft(), | |
css=""" | |
.status-box { | |
padding: 10px; | |
border-radius: 8px; | |
margin-bottom: 20px; | |
font-weight: bold; | |
} | |
.orange { background-color: #fff3cd; border: 1px solid #ffeaa7; } | |
.blue { background-color: #d1ecf1; border: 1px solid #bee5eb; } | |
""" | |
) as demo: | |
# Header | |
gr.Markdown("# π¬ Open AI Co-Scientist - Hypothesis Evolution System") | |
gr.Markdown("Generate, review, rank, and evolve research hypotheses using AI agents.") | |
# Deployment status | |
gr.HTML(f'<div class="status-box {status_color}">π§ Deployment Status: {status_text}</div>') | |
# Main interface | |
with gr.Row(): | |
with gr.Column(scale=2): | |
# Research goal input | |
research_goal_input = gr.Textbox( | |
label="Research Goal", | |
placeholder="Enter your research goal (e.g., 'Develop new methods for increasing the efficiency of solar panels')", | |
lines=3 | |
) | |
# Advanced settings | |
with gr.Accordion("βοΈ Advanced Settings", open=False): | |
model_dropdown = gr.Dropdown( | |
choices=["-- Select Model --"] + available_models, | |
value="-- Select Model --", | |
label="LLM Model", | |
info="Leave as default to use system default model" | |
) | |
with gr.Row(): | |
num_hypotheses = gr.Slider( | |
minimum=1, maximum=10, value=3, step=1, | |
label="Hypotheses per Cycle" | |
) | |
top_k_hypotheses = gr.Slider( | |
minimum=2, maximum=5, value=2, step=1, | |
label="Top K for Evolution" | |
) | |
with gr.Row(): | |
generation_temp = gr.Slider( | |
minimum=0.1, maximum=1.0, value=0.7, step=0.1, | |
label="Generation Temperature (Creativity)" | |
) | |
reflection_temp = gr.Slider( | |
minimum=0.1, maximum=1.0, value=0.5, step=0.1, | |
label="Reflection Temperature (Analysis)" | |
) | |
elo_k_factor = gr.Slider( | |
minimum=1, maximum=100, value=32, step=1, | |
label="Elo K-Factor (Ranking Sensitivity)" | |
) | |
# Single action button | |
with gr.Row(): | |
run_cycle_btn = gr.Button("π Run Cycle", variant="primary") | |
# Status display | |
status_output = gr.Textbox( | |
label="Status", | |
value="Enter a research goal and click 'Run Cycle' to begin.", | |
interactive=False, | |
lines=3 | |
) | |
with gr.Column(scale=1): | |
# Instructions | |
gr.Markdown(""" | |
### π Instructions | |
1. **Enter Research Goal**: Describe what you want to research. | |
2. **Adjust Settings** (optional): Customize model and parameters. | |
3. **Click "Run Cycle"**: The system will set your goal and immediately generate, review, rank, and evolve hypotheses in one step. | |
### π‘ Tips | |
- Start with 3-5 hypotheses per cycle | |
- Higher generation temperature = more creative ideas | |
- Lower reflection temperature = more analytical reviews | |
- Each cycle builds on previous results | |
**Note:** Since it uses the free version of Gemini, it may occasionally return zero hypotheses if rate limits are reached. Please try again in this case. | |
""") | |
# Results section | |
with gr.Row(): | |
with gr.Column(): | |
results_output = gr.HTML( | |
label="Results", | |
value="<p>Results will appear here after running cycles.</p>" | |
) | |
# References section | |
with gr.Row(): | |
with gr.Column(): | |
references_output = gr.HTML( | |
label="References", | |
value="<p>Related research papers will appear here.</p>" | |
) | |
# Event handler: single button sets research goal and runs cycle | |
def run_full_cycle( | |
research_goal, | |
llm_model, | |
num_hypotheses, | |
generation_temp, | |
reflection_temp, | |
elo_k_factor, | |
top_k_hypotheses | |
): | |
# Set research goal | |
status_msg, _ = set_research_goal( | |
research_goal, | |
llm_model, | |
num_hypotheses, | |
generation_temp, | |
reflection_temp, | |
elo_k_factor, | |
top_k_hypotheses | |
) | |
# Run cycle | |
status, results, references = run_cycle() | |
# Combine status messages | |
return f"{status_msg}\n\n{status}", results, references | |
run_cycle_btn.click( | |
fn=run_full_cycle, | |
inputs=[ | |
research_goal_input, | |
model_dropdown, | |
num_hypotheses, | |
generation_temp, | |
reflection_temp, | |
elo_k_factor, | |
top_k_hypotheses | |
], | |
outputs=[status_output, results_output, references_output] | |
) | |
# Example inputs | |
gr.Examples( | |
examples=[ | |
["Develop new methods for increasing the efficiency of solar panels"], | |
["Create novel approaches to treat Alzheimer's disease"], | |
["Design sustainable materials for construction"], | |
["Improve machine learning model interpretability"], | |
["Develop new quantum computing algorithms"] | |
], | |
inputs=[research_goal_input], | |
label="Example Research Goals" | |
) | |
# GitHub icon and link at the bottom | |
gr.HTML( | |
''' | |
<div style="text-align:center; margin-top: 30px;"> | |
<a href="https://github.com/chunhualiao/ai-co-scientist" target="_blank" style="text-decoration:none; display:inline-flex; align-items:center; gap:8px;"> | |
<svg height="32" width="32" viewBox="0 0 16 16" fill="currentColor" style="vertical-align:middle;"> | |
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 | |
0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52 | |
-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2 | |
-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64 | |
-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 | |
2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 | |
1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/> | |
</svg> | |
<span style="font-size: 1.1em; vertical-align:middle;">View on GitHub</span> | |
</a> | |
</div> | |
''' | |
) | |
return demo | |
if __name__ == "__main__": | |
# Check for API key | |
if not os.getenv("OPENROUTER_API_KEY"): | |
print("β οΈ Warning: OPENROUTER_API_KEY environment variable not set.") | |
print("The app will start but may not function properly without an API key.") | |
# Create and launch the Gradio app | |
demo = create_gradio_interface() | |
# Launch with appropriate settings for HF Spaces | |
demo.launch( | |
server_name="0.0.0.0", | |
server_port=7860, | |
share=False, | |
show_error=True | |
) | |