sciagent / app.py
bhoomichowksey's picture
Update app.py
39935fd verified
Raw
History Blame Contribute Delete
13.2 kB
import gradio as gr
import numpy as np
from scipy import stats
DATASETS = {
"temperature_climate": {
"name": "Climate Temperature Study",
"group_a": [22.1, 23.4, 21.8, 24.2, 22.9, 23.1, 21.5, 24.8, 22.3, 23.7],
"group_b": [25.3, 26.1, 24.8, 27.2, 25.9, 26.4, 24.5, 27.8, 25.1, 26.9],
"context": "Comparing temperatures between two climate zones (Celsius)",
"correct_test": "welch_t",
"expected_conclusion": "significant"
},
"drug_response": {
"name": "Drug Response Trial",
"group_a": [45, 52, 48, 51, 47, 50, 46, 53, 49, 44],
"group_b": [48, 51, 47, 52, 49, 50, 46, 53, 48, 51],
"context": "Comparing biomarker levels between treatment and control groups",
"correct_test": "welch_t",
"expected_conclusion": "not_significant"
},
"exam_scores": {
"name": "Teaching Method Comparison",
"group_a": [72, 68, 75, 71, 69, 73, 70, 74, 68, 76],
"group_b": [81, 85, 79, 83, 87, 82, 84, 80, 86, 88],
"context": "Comparing exam scores between two teaching methods",
"correct_test": "welch_t",
"expected_conclusion": "significant"
},
"reaction_time": {
"name": "Reaction Time Study",
"group_a": [0.231, 0.245, 0.228, 0.251, 0.239],
"group_b": [0.229, 0.241, 0.235, 0.248, 0.242],
"context": "Comparing reaction times (seconds) between two groups",
"correct_test": "welch_t",
"expected_conclusion": "not_significant"
}
}
class SciAgentEpisode:
def __init__(self):
self.reset()
def reset(self):
self.step = 0
self.dataset_key = None
self.dataset = None
self.steps_completed = []
self.total_reward = 0.0
self.history = []
episode = SciAgentEpisode()
def reward_step_completion(response):
return 0.1 if response and len(response.strip()) > 20 else 0.0
def reward_hypothesis_quality(hypothesis):
keywords = ["hypothesis", "expect", "predict", "difference", "similar", "group", "significant"]
return min(sum(0.015 for k in keywords if k.lower() in hypothesis.lower()), 0.15)
def reward_test_selection(chosen, correct):
return 0.2 if chosen == correct else 0.05
def reward_numerical_accuracy(p_guess, actual_p):
try:
error = abs(float(p_guess) - actual_p)
if error < 0.01: return 0.2
elif error < 0.05: return 0.1
return 0.05
except:
return 0.0
def reward_conclusion_correctness(conclusion, expected):
c = conclusion.lower()
if expected == "significant" and ("significant" in c or "reject" in c or "differ" in c):
return 0.25
if expected == "not_significant" and ("not significant" in c or "fail to reject" in c or "no difference" in c):
return 0.25
return 0.05
def step1_explore(dataset_choice):
episode.reset()
episode.dataset_key = dataset_choice
episode.dataset = DATASETS[dataset_choice]
episode.step = 1
d = episode.dataset
a, b = d["group_a"], d["group_b"]
r = reward_step_completion(dataset_choice)
episode.total_reward += r
episode.steps_completed.append("explore")
episode.history.append(f"Dataset: {d['name']}")
return f"""[ STEP 01 :: DATA INITIALIZED ]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
DATASET » {d['name']}
CONTEXT » {d['context']}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GROUP_A » {a}
MEAN={round(np.mean(a),3)} STD={round(np.std(a),3)} N={len(a)}
GROUP_B » {b}
MEAN={round(np.mean(b),3)} STD={round(np.std(b),3)} N={len(b)}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
REWARD » +{round(r,3)} | TOTAL={round(episode.total_reward,3)}
STATUS » PROCEED TO STEP 02"""
def step2_hypothesize(hypothesis):
if episode.step != 1:
return "[ ERROR ] Complete Step 01 first."
episode.step = 2
r = reward_step_completion(hypothesis) + reward_hypothesis_quality(hypothesis)
episode.total_reward += r
episode.steps_completed.append("hypothesize")
episode.history.append(f"Hypothesis: {hypothesis}")
return f"""[ STEP 02 :: HYPOTHESIS LOGGED ]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
INPUT » "{hypothesis}"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
QUALITY » ANALYZED
REWARD » +{round(r,3)} | TOTAL={round(episode.total_reward,3)}
STATUS » PROCEED TO STEP 03"""
def step3_plan(test_choice):
if episode.step != 2:
return "[ ERROR ] Complete Step 02 first."
episode.step = 3
correct = episode.dataset["correct_test"]
r = reward_step_completion(test_choice) + reward_test_selection(test_choice, correct)
episode.total_reward += r
episode.steps_completed.append("plan")
episode.history.append(f"Test: {test_choice}")
verdict = "OPTIMAL SELECTION" if test_choice == correct else f"SUBOPTIMAL — RECOMMENDED: {correct}"
return f"""[ STEP 03 :: TEST PROTOCOL SELECTED ]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
TEST » {test_choice.upper()}
VERDICT » {verdict}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
REWARD » +{round(r,3)} | TOTAL={round(episode.total_reward,3)}
STATUS » PROCEED TO STEP 04"""
def step4_execute(p_value_input):
if episode.step != 3:
return "[ ERROR ] Complete Step 03 first."
episode.step = 4
a, b = episode.dataset["group_a"], episode.dataset["group_b"]
t_stat, actual_p = stats.ttest_ind(a, b, equal_var=False)
r = reward_step_completion(p_value_input) + reward_numerical_accuracy(p_value_input, actual_p)
episode.total_reward += r
episode.steps_completed.append("execute")
episode.history.append(f"p={p_value_input}, actual={round(actual_p,4)}")
return f"""[ STEP 04 :: STATISTICAL ANALYSIS COMPLETE ]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
T-STAT » {round(t_stat,4)}
P-VALUE » {round(actual_p,4)} (actual)
YOUR EST » {p_value_input}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
REWARD » +{round(r,3)} | TOTAL={round(episode.total_reward,3)}
STATUS » PROCEED TO STEP 05"""
def step5_conclude(conclusion):
if episode.step != 4:
return "[ ERROR ] Complete Step 04 first."
episode.step = 5
expected = episode.dataset["expected_conclusion"]
a, b = episode.dataset["group_a"], episode.dataset["group_b"]
_, actual_p = stats.ttest_ind(a, b, equal_var=False)
r = reward_step_completion(conclusion) + reward_conclusion_correctness(conclusion, expected)
if len(episode.history) >= 3: r += 0.1
episode.total_reward += r
episode.steps_completed.append("conclude")
ground_truth = "SIGNIFICANT DIFFERENCE DETECTED" if actual_p < 0.05 else "NO SIGNIFICANT DIFFERENCE"
perf = "EXCELLENT" if episode.total_reward > 0.7 else "GOOD" if episode.total_reward > 0.5 else "NEEDS IMPROVEMENT"
return f"""[ STEP 05 :: EPISODE TERMINATED ]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CONCLUSION » "{conclusion}"
GROUND TRUTH » {ground_truth} (p={round(actual_p,4)})
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STEPS COMPLETED » {' → '.join(episode.steps_completed)}
FINAL REWARD » {round(episode.total_reward,3)} / 1.0
PERFORMANCE » {perf}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
RESET TO INITIALIZE NEW EPISODE"""
def do_reset():
episode.reset()
return "[ SYSTEM RESET ] New episode ready. Return to Step 01."
CSS = """
* { box-sizing: border-box; }
body, .gradio-container {
background: #050510 !important;
font-family: 'Courier New', monospace !important;
}
.gradio-container {
max-width: 1100px !important;
margin: 0 auto !important;
padding: 2rem !important;
}
h1 {
color: #7B61FF !important;
font-size: 2.2rem !important;
letter-spacing: 6px !important;
text-transform: uppercase !important;
text-shadow: 0 0 30px #7B61FF88 !important;
font-family: 'Courier New', monospace !important;
}
h3 {
color: #00D4FF !important;
letter-spacing: 3px !important;
font-size: 0.75rem !important;
text-transform: uppercase !important;
border-left: 2px solid #7B61FF !important;
padding-left: 10px !important;
font-family: 'Courier New', monospace !important;
}
p {
color: #8888aa !important;
font-size: 0.8rem !important;
letter-spacing: 1px !important;
font-family: 'Courier New', monospace !important;
}
.block {
background: #0a0a1a !important;
border: 1px solid #7B61FF33 !important;
border-radius: 4px !important;
}
label span {
color: #00D4FF !important;
font-size: 0.7rem !important;
letter-spacing: 2px !important;
text-transform: uppercase !important;
font-family: 'Courier New', monospace !important;
}
input, textarea, select {
background: #050510 !important;
border: 1px solid #7B61FF55 !important;
color: #00D4FF !important;
font-family: 'Courier New', monospace !important;
border-radius: 2px !important;
}
textarea {
color: #7B61FF !important;
font-size: 0.8rem !important;
line-height: 1.6 !important;
}
button {
background: transparent !important;
border: 1px solid #7B61FF !important;
color: #7B61FF !important;
font-family: 'Courier New', monospace !important;
letter-spacing: 3px !important;
text-transform: uppercase !important;
font-size: 0.7rem !important;
transition: all 0.2s !important;
}
button:hover {
background: #7B61FF22 !important;
box-shadow: 0 0 20px #7B61FF44 !important;
color: #00D4FF !important;
}
.gap { gap: 12px !important; }
"""
with gr.Blocks(css=CSS, title="SciAgent // RL Environment") as demo:
gr.Markdown("# SCIAGENT")
gr.Markdown("REINFORCEMENT LEARNING ENVIRONMENT // SCIENTIFIC HYPOTHESIS TESTING // 5-STEP PROTOCOL")
with gr.Row():
with gr.Column():
gr.Markdown("### 01 // EXPLORE")
dataset_dropdown = gr.Dropdown(
choices=list(DATASETS.keys()),
label="SELECT DATASET",
value="temperature_climate"
)
btn1 = gr.Button("INITIALIZE DATASET")
out1 = gr.Textbox(label="SYSTEM OUTPUT", lines=12)
btn1.click(step1_explore, inputs=dataset_dropdown, outputs=out1)
with gr.Column():
gr.Markdown("### 02 // HYPOTHESIZE")
hypothesis_input = gr.Textbox(
label="ENTER HYPOTHESIS",
placeholder="I expect that Group A and Group B will...",
lines=3
)
btn2 = gr.Button("TRANSMIT HYPOTHESIS")
out2 = gr.Textbox(label="SYSTEM OUTPUT", lines=7)
btn2.click(step2_hypothesize, inputs=hypothesis_input, outputs=out2)
with gr.Row():
with gr.Column():
gr.Markdown("### 03 // PLAN")
test_dropdown = gr.Dropdown(
choices=["welch_t", "student_t", "mann_whitney", "anova"],
label="SELECT TEST PROTOCOL",
value="welch_t"
)
btn3 = gr.Button("ENGAGE PROTOCOL")
out3 = gr.Textbox(label="SYSTEM OUTPUT", lines=7)
btn3.click(step3_plan, inputs=test_dropdown, outputs=out3)
with gr.Column():
gr.Markdown("### 04 // EXECUTE")
pval_input = gr.Textbox(
label="ENTER P-VALUE",
placeholder="e.g. 0.032"
)
btn4 = gr.Button("RUN ANALYSIS")
out4 = gr.Textbox(label="SYSTEM OUTPUT", lines=7)
btn4.click(step4_execute, inputs=pval_input, outputs=out4)
with gr.Row():
with gr.Column(scale=2):
gr.Markdown("### 05 // CONCLUDE")
conclusion_input = gr.Textbox(
label="ENTER CONCLUSION",
placeholder="Based on the results...",
lines=3
)
btn5 = gr.Button("FINALIZE EPISODE")
out5 = gr.Textbox(label="SYSTEM OUTPUT", lines=10)
btn5.click(step5_conclude, inputs=conclusion_input, outputs=out5)
with gr.Column(scale=1):
gr.Markdown("### SYS // RESET")
gr.Markdown("Terminate current episode and reinitialize environment.")
btn_reset = gr.Button("RESET SYSTEM", variant="secondary")
reset_out = gr.Textbox(label="STATUS")
btn_reset.click(do_reset, outputs=reset_out)
demo.launch()