CoolFace
Apppublic

NavyDevilDoc/Writing_Tutor

sourceHugging Facemitupdated 9mo agoView on Hugging Face
0likes
app.py174 linesDownload Raw Back to root
1import streamlit as st2from openai import OpenAI3import os4 5# 1. Configuration6st.set_page_config(page_title="High School Writing Coach", layout="wide")7 8# Get the API key from Environment Variables (HF Spaces) OR st.secrets (Local)9api_key = os.environ.get("OPENAI_API_KEY")10 11if not api_key:12    try:13        # Fallback for local development if using secrets.toml14        api_key = st.secrets["OPENAI_API_KEY"]15    except (FileNotFoundError, KeyError):16        st.error("OpenAI API Key not found. Please add 'OPENAI_API_KEY' to your Hugging Face Space secrets.")17        st.stop()18 19# Initialize client with the found key20client = OpenAI(api_key=api_key)21 22# 2. System Prompt23# This enforces the "No Rewrite" rule.24# --- 1. DEFINE THE FEW-SHOT EXAMPLES FIRST ---25FEW_SHOT_EXAMPLES = """26<example_1>27USER_INPUT: "The Great Gatsby shows that money is bad. Gatsby has a lot of money but he is sad."28USER_GOAL: "Argument Analysis"29AI_RESPONSE:30**Critique:** Your point is valid, but the sentence 31structure is a bit simple and relies on "telling" 32rather than "showing." You are using two independent 33clauses joined loosely.34 35**Lesson - Complex Sentences:** Try using a subordinating 36conjunction (like "although," "while," or "despite") to 37show the relationship between wealth and happiness.38 39**Structural Example (Topic: Sports):** Instead of saying 40"The team won the game but they played bad," a stronger writer 41might say: *"Despite securing a victory on the scoreboard, the 42team's defensive breakdown revealed fundamental weaknesses in 43their strategy."*44 45**Try it:** Can you rewrite your sentence about Gatsby using the word "Although" or "Despite"?46</example_1>47 48<example_2>49USER_INPUT: "I think that climate change is a big problem because it makes the weather hot."50USER_GOAL: "Vocabulary & Tone"51AI_RESPONSE:52**Critique:** The phrase "big problem" is vague, 53and "I think" is unnecessary. Academic writing 54requires precision.55 56**Lesson - Precise Vocabulary:** Replace general 57words with specific terms that describe the 58*scale* or *nature* of the problem.59 60**Structural Example (Topic: Cooking):** Instead 61of saying "I think the soup was bad because it was 62too salty," a critic would write: *"The broth's 63overwhelming salinity completely masked the delicate 64flavors of the vegetables."*65 66**Try it:** Look at your sentence. How can you replace 67"big problem" with a word that describes *how* climate 68change affects the planet?69</example_2>70"""71 72# --- 2. DEFINE THE MASTER SYSTEM PROMPT ---73# We inject the few-shot examples at the end.74SYSTEM_PROMPT = f"""75You are an expert Writing Coach for high school students. 76Your goal is to teach writing mechanics, logic, and rhetoric without rewriting the student's essay for them.77 78CORE RULES:791. **ABSOLUTE PROHIBITION:** DO NOT rewrite the student's text. If they ask "Can you fix this?" or "Rewrite it for me", you must REFUSE and ask them to try applying the lesson themselves.802. If you see a grammatical error, quote the sentence and explain the grammar rule they broke.813. Structure your feedback in Markdown with clear headings: "General Feedback", "Strengths", and "Areas for Improvement".824. Be encouraging but rigorous. Treat them like smart young adults.83 84SOCRATIC INSTRUCTIONS (Use when critiquing logic/argument):851. Do not give the answer.862. Ask a question that exposes the gap in the student's reasoning.873. Use the "Counter-Factual" technique: "If X were true, wouldn't Y also happen?"884. Use the "Perspective Shift" technique: "How would a French soldier in 1812 respond to this claim?"89 90INSTRUCTIONS FOR EXAMPLES:911. Analyze the student's text based on their selected Focus Area.922. Identify the top 1-2 weaknesses.933. For every weakness you identify, you must provide a **"Structural Example"**.944. CRITICAL: The "Structural Example" must be about a COMPLETELY DIFFERENT TOPIC than the student's essay.955. Never rewrite their actual sentence. Only show them the *pattern* of a better sentence.96 97Here are examples of how you should respond (Few-Shot Training):98{FEW_SHOT_EXAMPLES}99"""100 101# 3. Sidebar: Settings & Reset102with st.sidebar:103    st.header("⚙️ Coach Settings")104    grade_level = st.select_slider("Grade Level", options=["9th", "10th", "11th", "12th"])105    focus_area = st.selectbox(106        "Current Focus",107        ["General Critique", "Grammar & Syntax", "Argument & Logic", "Tone & Voice"]108    )109    110    st.divider()111    112    # --- RESET BUTTON LOGIC ---113    # If clicked, we clear the session state list114    if st.button("🔄 Reset Conversation", type="primary"):115        st.session_state.messages = []116        st.rerun()117 118# 4. Initialize Session State (Memory)119if "messages" not in st.session_state:120    st.session_state.messages = []121 122# 5. Display Chat History123st.title("🎓 Digital Writing Coach")124if len(st.session_state.messages) == 0:125    st.markdown("👋 **Hello!** Paste your draft below to get started. I'm here to coach, not to copy-edit!")126 127for message in st.session_state.messages:128    with st.chat_message(message["role"]):129        st.markdown(message["content"])130 131# 6. Chat Input & Processing132if prompt := st.chat_input("Paste your text or ask a question..."):133    134    # A. Display User Message135    with st.chat_message("user"):136        st.markdown(prompt)137    138    # Add user message to history139    st.session_state.messages.append({"role": "user", "content": prompt})140    141    # B. Generate Response142    with st.chat_message("assistant"):143        message_placeholder = st.empty()144        full_response = ""145        146        # We inject the "Current Settings" into the System Prompt dynamically147        # This ensures if the user changes the "Focus Area" mid-chat, the AI knows.148        dynamic_system_prompt = SYSTEM_PROMPT + f"\n\nCURRENT CONTEXT: Student is in {grade_level} Grade. Focus on: {focus_area}."149        150        try:151            # Construct the full message history for the API152            # System prompt first, then the conversation history153            messages_payload = [{"role": "system", "content": dynamic_system_prompt}] + st.session_state.messages154            155            response = client.chat.completions.create(156                model="gpt-4o",157                messages=messages_payload,158                temperature=0.7,159                stream=True # Streaming makes it feel faster160            )161            162            # Stream the response chunk by chunk163            for chunk in response:164                if chunk.choices[0].delta.content is not None:165                    full_response += chunk.choices[0].delta.content166                    message_placeholder.markdown(full_response + "▌")167            168            message_placeholder.markdown(full_response)169            170            # Add AI response to history171            st.session_state.messages.append({"role": "assistant", "content": full_response})172 173        except Exception as e:174            st.error(f"Error: {e}")