| |
|
|
| import os |
| import sys |
| import json |
| import time |
| import streamlit as st |
| import pandas as pd |
| import matplotlib.pyplot as plt |
| from pathlib import Path |
| from typing import Dict, List, Any, Optional |
| from datetime import datetime |
|
|
| |
| project_root = Path(__file__).parent.parent.parent |
| sys.path.insert(0, str(project_root)) |
|
|
| |
| from src.main import AICoScientist |
| from src.config.config import AGENT_DEFAULT_MODEL, AGENT_DEFAULT_TEMPERATURE |
|
|
|
|
| def display_hypothesis_table(hypotheses: List[Dict[str, Any]]): |
| """Display a table of hypotheses with scores and other metadata.""" |
| if not hypotheses: |
| st.info("No hypotheses available.") |
| return |
| |
| |
| data = [] |
| for i, h in enumerate(hypotheses): |
| data.append({ |
| "Rank": i + 1, |
| "Hypothesis": h.get('hypothesis', h.get('statement', '')), |
| "Score": h.get("score", "N/A"), |
| "Confidence": h.get("confidence", "N/A"), |
| "Novelty": h.get("novelty_score", "N/A"), |
| "Iteration": h.get("iteration", "N/A") |
| }) |
| |
| |
| df = pd.DataFrame(data) |
| st.dataframe(df, use_container_width=True) |
|
|
|
|
| def plot_hypothesis_scores(hypotheses: List[Dict[str, Any]]): |
| """Plot scores of hypotheses as a bar chart.""" |
| if not hypotheses or len(hypotheses) < 2: |
| return |
| |
| |
| labels = [f"H{i+1}" for i in range(len(hypotheses))] |
| scores = [h.get("score", 0) for h in hypotheses] |
| |
| |
| fig, ax = plt.subplots(figsize=(10, 6)) |
| bars = ax.bar(labels, scores, color='skyblue') |
| |
| |
| ax.set_xlabel('Hypotheses') |
| ax.set_ylabel('Score') |
| ax.set_title('Hypothesis Ranking Scores') |
| |
| |
| for bar, score in zip(bars, scores): |
| height = bar.get_height() |
| ax.text(bar.get_x() + bar.get_width() / 2, height, |
| f'{score:.2f}', ha='center', va='bottom') |
| |
| |
| st.pyplot(fig) |
|
|
|
|
| def run_app(): |
| """Run the Streamlit application.""" |
| st.set_page_config( |
| page_title="AI Co-Scientist", |
| page_icon="🧬", |
| layout="wide", |
| initial_sidebar_state="expanded" |
| ) |
| |
| st.title("🧬 AI Co-Scientist") |
| st.subheader("Multi-Agent Scientific Research Framework") |
| |
| |
| st.sidebar.header("Configuration") |
| |
| openai_api_key = st.sidebar.text_input( |
| "OpenAI API Key", |
| type="password", |
| help="Paste your OpenAI API key here. It will not be stored." |
| ) |
| |
| model = st.sidebar.selectbox( |
| "LLM Model", |
| options=[ |
| "gpt-4o", |
| "gpt-4o-mini", |
| "gpt-4-turbo", |
| "gpt-4", |
| "gpt-3.5-turbo", |
| "gpt-3.5-turbo-16k" |
| ], |
| index=0, |
| help="Select the OpenAI model to use. More powerful models provide better results but may be more expensive." |
| ) |
| |
| temperature = st.sidebar.slider( |
| "Temperature", |
| min_value=0.0, |
| max_value=1.0, |
| value=AGENT_DEFAULT_TEMPERATURE, |
| step=0.1, |
| help="Higher values (closer to 1) make output more random, while lower values make it more deterministic." |
| ) |
| |
| iterations = st.sidebar.slider( |
| "Refinement Iterations", |
| min_value=1, |
| max_value=5, |
| value=3, |
| step=1 |
| ) |
| |
| |
| if "acs" not in st.session_state: |
| st.session_state.acs = None |
| |
| if "results" not in st.session_state: |
| st.session_state.results = None |
| |
| if "progress" not in st.session_state: |
| st.session_state.progress = 0 |
| |
| if "status" not in st.session_state: |
| st.session_state.status = "" |
| |
| |
| st.header("Research Goal") |
| research_goal = st.text_area( |
| "Enter your research goal:", |
| value="To investigate the relationship between microbiome diversity and autoimmune disorders in urban populations", |
| height=100 |
| ) |
| |
| col1, col2 = st.columns([1, 3]) |
| |
| |
| if col1.button("Generate Hypotheses", type="primary", use_container_width=True): |
| |
| if openai_api_key: |
| os.environ["OPENAI_API_KEY"] = openai_api_key |
| |
| config = { |
| "model": model if model else "gpt-3.5-turbo", |
| "temperature": temperature, |
| "max_iterations": iterations, |
| "openai_api_key": openai_api_key, |
| } |
| |
| st.session_state.acs = AICoScientist(config=config) |
| st.session_state.results = None |
| st.session_state.progress = 0 |
| st.session_state.status = "initializing" |
| |
| |
| progress_bar = st.progress(0, "Initializing...") |
| |
| try: |
| |
| st.session_state.status = "setting_goal" |
| progress_bar.progress(10, "Setting research goal...") |
| st.session_state.acs.set_research_goal(research_goal) |
| st.session_state.progress = 10 |
| |
| |
| st.session_state.status = "generating" |
| progress_bar.progress(25, "Generating initial hypotheses...") |
| hypotheses = st.session_state.acs.generate_hypotheses(count=7) |
| st.session_state.progress = 25 |
| |
| |
| st.session_state.status = "ranking" |
| progress_bar.progress(40, "Ranking hypotheses...") |
| ranked = st.session_state.acs.rank_hypotheses() |
| st.session_state.progress = 40 |
| |
| |
| st.session_state.status = "refining" |
| progress_per_iteration = 30 / iterations |
| |
| for i in range(iterations): |
| progress_value = 40 + ((i + 1) * progress_per_iteration) |
| progress_bar.progress(int(progress_value), f"Refining hypotheses (iteration {i+1}/{iterations})...") |
| if i == iterations - 1: |
| refined = st.session_state.acs.refine_hypotheses(iterations=1) |
| time.sleep(0.5) |
| st.session_state.progress = progress_value |
| |
| |
| st.session_state.status = "reporting" |
| progress_bar.progress(80, "Generating research report...") |
| report = st.session_state.acs.generate_research_report() |
| st.session_state.progress = 80 |
| |
| |
| st.session_state.results = { |
| "research_goal": research_goal, |
| "hypotheses": ranked, |
| "report": report |
| } |
| st.session_state.status = "completed" |
| progress_bar.progress(100, "Research workflow completed!") |
| st.session_state.progress = 100 |
| |
| |
| st.rerun() |
| |
| except Exception as e: |
| st.error(f"Error: {str(e)}") |
| st.session_state.status = "error" |
| progress_bar.progress(100, "Error occurred!") |
| |
| |
| if col2.button("Reset", use_container_width=True): |
| st.session_state.acs = None |
| st.session_state.results = None |
| st.session_state.progress = 0 |
| st.session_state.status = "" |
| st.rerun() |
| |
| |
| if st.session_state.results is not None: |
| |
| tab1, tab2, tab3 = st.tabs(["Top Areas of Interest", "Report", "All Hypotheses"]) |
| |
| with tab1: |
| st.header("Top Areas of Interest") |
| top_areas = st.session_state.results["hypotheses"][:3] if st.session_state.results["hypotheses"] else [] |
| |
| if top_areas: |
| for i, h in enumerate(top_areas): |
| with st.expander(f"Area {i+1}: Score {h.get('score', 'N/A')}", expanded=i==0): |
| st.markdown(f"""**Area of Interest**: {h.get('hypothesis', h.get('statement', ''))}""") |
| if "research_questions" in h: |
| st.markdown("**Research Questions:**") |
| for q in h["research_questions"]: |
| st.markdown(f"- {q}") |
| if "feedback" in h: |
| st.markdown("**Feedback**:") |
| st.markdown(h["feedback"]) |
| cols = st.columns(4) |
| cols[0].metric("Score", f"{h.get('score', 'N/A')}") |
| cols[1].metric("Novelty", f"{h.get('novelty_score', 'N/A')}") |
| cols[2].metric("Testability", f"{h.get('testability', 'N/A')}") |
| cols[3].metric("Proximity", f"{h.get('proximity', {}).get('proximity_score', 'N/A')}") |
| st.subheader("Area Scores") |
| plot_hypothesis_scores(st.session_state.results["hypotheses"]) |
| else: |
| st.info("No areas of interest available.") |
| |
| with tab2: |
| st.header("Research Report") |
| |
| if "report" in st.session_state.results and st.session_state.results["report"]: |
| report = st.session_state.results["report"] |
| |
| st.subheader("Executive Summary") |
| st.markdown(report.get("executive_summary", "No summary available.")) |
| |
| st.subheader("Key Findings") |
| for i, finding in enumerate(report.get("key_findings", [])): |
| st.markdown(f"**{i+1}.** {finding}") |
| |
| st.subheader("Future Directions") |
| for i, direction in enumerate(report.get("future_directions", [])): |
| st.markdown(f"**{i+1}.** {direction}") |
| |
| if "limitations" in report: |
| st.subheader("Limitations") |
| st.markdown(report["limitations"]) |
| else: |
| st.info("No report available.") |
| |
| with tab3: |
| st.header("All Hypotheses") |
| all_hypotheses = st.session_state.results["hypotheses"] if st.session_state.results["hypotheses"] else [] |
| display_hypothesis_table(all_hypotheses) |
| |
| |
| elif st.session_state.status and st.session_state.status != "completed" and st.session_state.status != "error": |
| st.info(f"Status: {st.session_state.status} (Progress: {st.session_state.progress}%)") |
| |
| |
| st.header("Generating Research Results...") |
| st.markdown("""The AI Co-Scientist system is analyzing your research goal and generating hypotheses. This process involves: |
| |
| 1. **Generation**: Creating diverse initial hypotheses |
| 2. **Ranking**: Evaluating and ranking hypotheses by quality |
| 3. **Refinement**: Iteratively improving promising hypotheses |
| 4. **Reporting**: Synthesizing findings into a comprehensive report |
| |
| Please wait while the system completes this process.""") |
| else: |
| |
| st.info("Enter your research goal and click 'Generate Hypotheses' to start the research workflow.") |
| |
| |
| with st.expander("Sample Research Goals"): |
| st.markdown("""Click on any sample to use it: |
| |
| - To investigate the impact of intermittent fasting on cognitive performance in healthy adults |
| - To examine the relationship between urban green space exposure and mental health outcomes |
| - To explore the effectiveness of different machine learning algorithms in predicting stock market trends |
| - To analyze the effects of microplastics on marine ecosystem biodiversity |
| - To determine how social media usage patterns correlate with adolescent depression rates |
| """) |
| |
| if st.button("Use Sample", key="sample_button"): |
| |
| |
| pass |
| |
| |
| st.markdown("---") |
| st.markdown("AI Co-Scientist: Multi-Agent Scientific Research Framework | v0.1.0") |
|
|
|
|
| if __name__ == "__main__": |
| run_app() |
|
|