-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
180 lines (153 loc) · 7.21 KB
/
Copy pathapp.py
File metadata and controls
180 lines (153 loc) · 7.21 KB
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
import streamlit as st
import os
import matplotlib.pyplot as plt
from dotenv import load_dotenv
load_dotenv()
from model_use import get_responses_from_models, model_list
from llm_evaluator import LLMEvaluator
from utils import append_scores_to_csv, get_supabase_client, compute_rankings_from_csv
CSV_PATH = "evaluations.csv"
# --- Streamlit page config & theme ---
st.set_page_config(
page_title="Educhain TutorBench Evaluator",
layout="wide",
initial_sidebar_state="expanded"
)
st.markdown(
"""
<style>
.main, .block-container { background-color: #0f1724; color: #ffffff; }
.stButton>button { background-color: #2563eb; color: white; }
</style>
""",
unsafe_allow_html=True
)
st.title("🚀 Educhain TutorBench - Evaluation Interface")
st.markdown("Enter a teaching prompt, click **Run evaluation**. Judge output will be parsed and stored; use **View rankings** to visualize final ranking.")
# Display the list of models being tested
st.subheader("Models Being Tested")
try:
st.write("- " + "\n- ".join(model_list))
except Exception:
st.write("Model list not available")
# --- Sidebar ---
with st.sidebar:
st.markdown(
"<div style='text-align: center; margin: 2px 0;'>"
"<a href='https://www.buildfastwithai.com/' target='_blank' style='text-decoration: none;'>"
"<div style='border: 2px solid #e0e0e0; border-radius: 6px; padding: 4px; "
"background: linear-gradient(145deg, #ffffff, #f5f5f5); "
"box-shadow: 0 2px 6px rgba(0,0,0,0.1); "
"transition: all 0.3s ease; display: inline-block; width: 100%;'>"
"<img src='https://github.com/Shubhwithai/chat-with-qwen/blob/main/company_logo.png?raw=true' "
"style='width: 100%; max-width: 100%; height: auto; border-radius: 8px; display: block;' "
"alt='Build Fast with AI Logo'>"
"</div></a></div>", unsafe_allow_html=True
)
st.header("🔑 Configuration")
api_key = st.text_input("Enter your OpenRouter API key", type="password")
if st.button("View rankings"):
st.session_state['show_rankings'] = True
st.markdown("---")
st.markdown("Environment:")
st.code(f"OpenRouter key set: {bool(api_key)}")
st.markdown("🔍 Judge Model: `Grok-4-Fast`")
st.markdown("---")
st.subheader("📊 Metrics Being Tested")
st.write(
"- **Confusion Recognition**: Identifies the student's specific confusion point and current understanding level."
"\n- **Adaptive Response**: Tailors the response to the student's level, emotional state, and specific need."
"\n- **Learning Facilitation**: Ensures the student understands and can apply the concept."
"\n- **Strategic Decision-Making**: Chooses the best approach (direct answer, guided discovery, etc.) for the student."
"\n- **Engagement & Emotional Intelligence**: Addresses the student's emotional state and maintains motivation."
"\n- **Knowledge Pillar**: Demonstrates accurate subject knowledge and correctness in solving the student's question."
"\n- **Error Analysis**: Diagnoses the student's specific error or misconception and offers actionable feedback."
"\n- **Adaptive Capability**: Adjusts the content complexity to match the student's needs."
"\n- **Curriculum Awareness**: Aligns with age/developmental appropriateness and curriculum."
"\n- **Explanation Ability**: Provides clear and pedagogically sound explanations."
)
st.markdown("""<div class="sidebar-footer">
<p>❤️ Built by <a href="https://buildfastwithai.com" target="_blank">Build Fast with AI</a></p>
</div> """, unsafe_allow_html=True)
# --- Require API key ---
if not api_key:
st.warning("🔑 Please enter your OpenRouter API key to proceed.")
st.stop()
API_KEY = api_key
# --- Prompt input ---
prompt_text = st.text_area("Test prompt / question", height=240)
expected_output = st.text_area("Optional expected output (for judge comparison)", height=120)
run_btn = st.button("Run evaluation")
# --- Initialize evaluator & Supabase ---
evaluator = LLMEvaluator(api_key=API_KEY)
supabase = get_supabase_client()
# --- Initialize session state ---
for key in ['show_rankings', 'model_responses', 'results', 'prompt_id']:
if key not in st.session_state:
st.session_state[key] = None if key == 'prompt_id' else {}
# --- Run evaluation ---
if run_btn and prompt_text.strip():
st.info("Storing prompt and running models...")
# Store prompt
st.session_state['prompt_id'] = evaluator.store_prompt(prompt_text)
# Get model responses
st.session_state['model_responses'] = get_responses_from_models(prompt_text, API_KEY)
# Store responses in Supabase
evaluator.store_model_responses(st.session_state['prompt_id'], st.session_state['model_responses'])
st.success("Model responses collected and stored.")
# Judge evaluation
st.info("Invoking judge model and parsing scores...")
st.session_state['results'] = evaluator.judge_all_responses(
st.session_state['prompt_id'],
prompt_text,
st.session_state['model_responses'],
expected_output=expected_output
)
st.success("Evaluation complete.")
# --- Render rankings if requested ---
if st.session_state.get('show_rankings'):
st.subheader("Rankings & Insights")
if os.path.exists(CSV_PATH):
avg = compute_rankings_from_csv(CSV_PATH)
st.write("Average score per model (across prompts & metrics)")
st.dataframe(avg)
fig, ax = plt.subplots(figsize=(8, 4))
ax.barh(avg['model_name'], avg['score'])
ax.set_xlabel("Average score")
ax.set_title("Model ranking (higher is better)")
st.pyplot(fig)
else:
st.warning("No evaluations yet. Run an evaluation first.")
# --- Display results ---
if st.session_state['results']:
results = st.session_state['results']
model_responses = st.session_state['model_responses']
# Comparative output
st.subheader("Judge (Comparative) Output")
st.write(results.get("comparative"))
# Parsed scores
st.subheader("Parsed Scores (per model)")
for model_name, data in results.get("models", {}).items():
st.markdown(f"**{model_name}**")
st.json(data.get("scores") or {})
# Append to CSV
if data.get("scores"):
append_scores_to_csv(CSV_PATH, st.session_state['prompt_id'], prompt_text, model_name, data.get("scores"))
# #Raw model responses
# st.subheader("All Model Responses (raw)")
# for mname, resp in model_responses.items():
# with st.expander(mname, expanded=False):
# content = resp.get("content") if resp else None
# error = resp.get("error") if resp else None
# st.markdown("**Model output (raw):**")
# st.code(content or "(no content)", language="text")
# if error:
# st.error(f"Model error: {error}")
#
# eval_data = results.get("models", {}).get(mname)
# if eval_data:
# st.markdown("**Judge evaluation (raw):**")
# st.code(eval_data.get("evaluation", ""), language="text")
# st.markdown("**Parsed scores:**")
# st.json(eval_data.get("scores") or {})
st.balloons()