Spaces:
Sleeping
Sleeping
File size: 10,607 Bytes
c255744 67804a9 c255744 515f909 c255744 515f909 c255744 b8b792b c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 515f909 c255744 | 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 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | import streamlit as st
import openai
from dotenv import load_dotenv
import os
import json
from openai import Client
load_dotenv()
# Set up the OpenAI API key
openai.api_key = os.getenv("OPENAI_API_KEY")
MODEL = 'gpt-3.5-turbo'
client = Client()
# Define theme and style suggestions
THEMES = [
"Ambition",
"Good vs. Evil",
"Lady Macbeth's Influence",
"Guilt and Regret",
"Regicide and Natural Order",
"The Supernatural"
]
STYLES = [
"Formal and Analytical",
"Casual and Conversational",
"Humorous and Engaging",
"Historical Context Focused"
]
# Common weaknesses to track and address
WEAKNESSES = {
"thesis_formation": "Struggles with forming clear, arguable thesis statements",
"evidence_selection": "Has difficulty selecting appropriate textual evidence",
"analysis_depth": "Needs help deepening analysis of quotations",
"structure": "Challenges with organizing essay structure",
"context": "Difficulty connecting to historical/social context",
"conventions": "Issues with grammar, citations, or academic conventions"
}
class StudentProfile:
def __init__(self):
self.weaknesses = {key: 0 for key in WEAKNESSES.keys()}
self.identified_weaknesses = []
self.strengths = []
def update_weaknesses(self, weakness_types):
for weakness in weakness_types:
self.weaknesses[weakness] += 1
self._evaluate_weaknesses()
def _evaluate_weaknesses(self):
self.identified_weaknesses = []
total_interactions = sum(self.weaknesses.values())
if total_interactions == 0:
return
for weakness, count in self.weaknesses.items():
if count / total_interactions > 0.3:
self.identified_weaknesses.append(weakness)
def add_strength(self, strength):
if strength not in self.strengths:
self.strengths.append(strength)
def get_personalized_prompt(self):
if not self.identified_weaknesses:
return "How would you like to develop your analysis further?"
weakness_descriptions = [WEAKNESSES[w] for w in self.identified_weaknesses]
if "thesis_formation" in self.identified_weaknesses:
return ("Let's work on crafting a stronger thesis. Can you state your main argument in one clear sentence? "
"Remember, a good thesis is specific, debatable, and sets up your entire essay.")
elif "evidence_selection" in self.identified_weaknesses:
return ("I notice you could use help selecting the best quotations. What moment in the play best illustrates "
"your point? Look for passages that are rich in language and thematic significance.")
elif "analysis_depth" in self.identified_weaknesses:
return ("Let's dig deeper into your analysis. For your chosen quotation, can you explain: "
"1) What the words literally mean, 2) How the language techniques work, "
"3) Why this matters to your overall argument?")
elif len(self.identified_weaknesses) > 1:
return (f"I notice we should focus on: {', '.join(weakness_descriptions)}. "
"Let's tackle these one at a time. Which area would you like to work on first?")
else:
return (f"Let's focus on improving your {weakness_descriptions[0]}. "
"Can you show me how you would approach this in your next point?")
class EssayTutor:
def __init__(self, selected_theme, selected_style):
self.conversation = []
self.selected_theme = selected_theme
self.selected_style = selected_style
self.student_profile = StudentProfile()
system_message = {
"role": "system",
"content": (
"You are a friendly, humorous, and intelligent personalized tutor for Shakespeare's 'Macbeth'. "
f"Today, the students (which are 14 to 17 years old) will focus on the theme of '{selected_theme}' using a '{selected_style}' style - they are not experts"
"Your goal is to help the student develop a well-argued essay by guiding them to craft a clear thesis, "
"integrate key quotations, and link ideas to historical context (including references to King James I). "
"Be engaging and offer continuous assessment of the student's progress. "
"Additionally, identify and address the student's specific weaknesses in essay writing by: "
"1) Noticing patterns in their responses, "
"2) Providing targeted exercises to improve those areas, "
"3) Adjusting your feedback to their needs"
)
}
self.conversation.append(system_message)
init_message = {
"role": "assistant",
"content": (
f"Welcome, future Shakespeare scholar! Today, we'll build your essay on *Macbeth* focusing on '{selected_theme}'. "
"First, I'd like to understand your current approach. Could you share:\n"
"1) Your initial thoughts about this theme in Macbeth\n"
"2) Any specific challenges you face when writing about Shakespeare\n"
"This will help me personalize our session to your needs."
)
}
self.conversation.append(init_message)
def get_response(self):
response = client.chat.completions.create(
model=MODEL,
messages=self.conversation
)
return response.choices[0].message.content
def add_message(self, role, message):
self.conversation.append({"role": role, "content": message})
def analyze_student_response(self, student_message):
analysis_prompt = {
"role": "user",
"content": (
f"Analyze this student response for essay writing strengths and weaknesses:\n\n"
f"'{student_message}'\n\n"
"Consider these potential weaknesses:\n"
f"{WEAKNESSES}\n\n"
"Return a JSON format analysis with:\n"
"- 'weaknesses': list of weakness keys present (from the list above)\n"
"- 'strengths': list of demonstrated strengths\n"
"- 'feedback': brief constructive feedback\n"
"Only return valid JSON, no additional text."
)
}
try:
analysis_convo = self.conversation.copy()
analysis_convo.append(analysis_prompt)
response = client.chat.completions.create(
model=MODEL,
messages=analysis_convo,
response_format={"type": "json_object"}
)
analysis = json.loads(response.choices[0].message.content)
return analysis
except Exception as e:
print(f"Analysis error: {e}")
return {"weaknesses": [], "strengths": [], "feedback": ""}
def assess_progress(self):
if self.student_profile.identified_weaknesses:
prompt = self.student_profile.get_personalized_prompt()
else:
prompt = (
"Let's assess the student progress. Can you explain how user inputs, questions and ideas connect to the theme? "
"Try to be specific about quotations or examples from *Macbeth* that support your argument."
"check for typos, style and creativity of the student's input so far."
)
self.add_message("assistant", prompt)
return self.get_response()
if "tutor" not in st.session_state:
st.session_state.tutor = None
if "chat_history" not in st.session_state:
st.session_state.chat_history = []
st.sidebar.title("Settings")
selected_theme = st.sidebar.selectbox("Select a Theme", THEMES)
selected_style = st.sidebar.selectbox("Select a Tutor Style", STYLES)
st.title("Macbeth Essay Tutor")
if st.sidebar.button("Start New Session"):
st.session_state.tutor = EssayTutor(selected_theme, selected_style)
st.session_state.chat_history = [{"role": "assistant", "content": st.session_state.tutor.conversation[1]["content"]}]
st.success("Session started! The tutor is ready to help you.")
if st.session_state.tutor is not None:
for chat in st.session_state.chat_history:
if chat["role"] == "assistant":
st.markdown(f"**Tutor:** {chat['content']}")
else:
st.markdown(f"**You:** {chat['content']}")
with st.form(key="input_form", clear_on_submit=True):
user_input = st.text_area("Your response:", key="user_input", height=150)
submitted = st.form_submit_button("Send")
if submitted and user_input:
analysis = st.session_state.tutor.analyze_student_response(user_input)
st.session_state.tutor.student_profile.update_weaknesses(analysis.get("weaknesses", []))
for strength in analysis.get("strengths", []):
st.session_state.tutor.student_profile.add_strength(strength)
st.session_state.tutor.add_message("user", user_input)
st.session_state.chat_history.append({"role": "user", "content": user_input})
tutor_reply = st.session_state.tutor.get_response()
st.session_state.tutor.add_message("assistant", tutor_reply)
st.session_state.chat_history.append({"role": "assistant", "content": tutor_reply})
#replace st.experimental_rerun() with this.
st.rerun()
if len(st.session_state.chat_history) > 2:
if st.button("Get Personalized Feedback"):
assessment_feedback = st.session_state.tutor.assess_progress()
st.session_state.chat_history.append({"role": "assistant", "content": assessment_feedback})
#replace st.experimental_rerun() with this.
st.rerun()
st.sidebar.subheader("Your Writing Profile")
if st.session_state.tutor.student_profile.identified_weaknesses:
st.sidebar.warning("Areas to Improve:")
for weakness in st.session_state.tutor.student_profile.identified_weaknesses:
st.sidebar.write(f"- {WEAKNESSES[weakness]}")
else:
st.sidebar.success("No major weaknesses identified yet - keep going!")
if st.session_state.tutor.student_profile.strengths:
st.sidebar.info("Your Strengths:")
for strength in st.session_state.tutor.student_profile.strengths:
st.sidebar.write(f"- {strength}")
else:
st.info("Please start a new session using the sidebar.") |