| import gradio as gr |
| import os |
| import requests |
| from huggingface_hub import InferenceClient |
|
|
| HF_TOKEN = os.environ.get("HF_TOKEN", "") |
| GEMINI_KEY = os.environ.get("GEMINI_API_KEY", "") |
| PINECONE_KEY = os.environ.get("PINECONE_API_KEY", "") |
| PINECONE_HOST = "https://feeled-ai-syllabus-5hnhu9u.svc.aped-4627-b74a.pinecone.io" |
|
|
| GRADES = ["Grade 9", "Grade 10", "Grade 11", "Grade 12"] |
| SUBJECTS = ["Commerce", "Economics", "Accountancy", "Business Mathematics", |
| "Physics", "Chemistry", "Biology", "Mathematics", |
| "History", "Geography", "Tamil", "English", "Computer Science"] |
| LANGUAGES = ["Tanglish (Tamil + English)", "Tamil மட்டும்", "English Only"] |
| MODES = ["📚 Chat Tutor", "✨ Story Mode", "🎯 Exam Mode"] |
| STORY_STYLES = ["🌟 Deep", "🎉 Funny", "🚀 Adventure", "💙 Emotional"] |
|
|
| SYSTEM_PROMPT = """You are FeelEd Lite, a warm and friendly AI tutor for TN Board students in Tamil Nadu, India. |
| Language instruction: {language} |
| |
| CRITICAL RULES: |
| 1. If Textbook Context is provided, use it as your PRIMARY source. Base your answer on it directly. |
| 2. Quote key phrases from the context to make answers accurate. |
| 3. If no context, use general TN Board knowledge clearly. |
| 4. Always give COMPLETE structured answers — never cut short. |
| 5. Be warm, encouraging, and student-friendly.""" |
|
|
| def embed_query(text): |
| if not GEMINI_KEY: return [] |
| try: |
| r = requests.post( |
| f"https://generativelanguage.googleapis.com/v1beta/models/gemini-embedding-001:embedContent?key={GEMINI_KEY}", |
| json={"content":{"parts":[{"text":text}]},"outputDimensionality":768}, timeout=10) |
| if r.ok: return r.json().get("embedding",{}).get("values",[]) |
| except: pass |
| return [] |
|
|
| def rag_search(query, grade="11", subject="", top_k=5): |
| if not GEMINI_KEY or not PINECONE_KEY: return "" |
| vec = embed_query(query) |
| if not vec: return "" |
| filt = {"grade":{"$eq":grade.replace("Grade ","")}} |
| if subject: filt["subject"] = {"$eq":subject} |
| try: |
| r = requests.post(f"{PINECONE_HOST}/query", |
| headers={"Api-Key":PINECONE_KEY,"Content-Type":"application/json"}, |
| json={"vector":vec,"topK":top_k,"includeMetadata":True,"filter":filt}, timeout=10) |
| if not r.ok: return "" |
| return "\n\n".join([m["metadata"].get("text","").strip() |
| for m in r.json().get("matches",[]) |
| if m.get("score",0)>0.3 and m.get("metadata",{}).get("text","")]) |
| except: return "" |
|
|
| def get_lang(lang): |
| if "Tamil மட்டும்" in lang: return "Answer ONLY in Tamil" |
| if "English Only" in lang: return "Answer ONLY in English" |
| return "Answer in Tamil + English mix (Tanglish)" |
|
|
| |
| TAMIL_TO_ENGLISH = { |
| "தேவை விதி": "law of demand", |
| "தேவை": "demand", |
| "விநியோகம்": "supply", |
| "விநியோக விதி": "law of supply", |
| "இரட்டை பதிவு": "double entry", |
| "இரட்டை பதிவு முறை": "double entry bookkeeping", |
| "மொத்த உள்நாட்டு உற்பத்தி": "GDP gross domestic product", |
| "தொழில் முனைவோர்": "entrepreneur entrepreneurship", |
| "நுகர்வோர் உரிமைகள்": "consumer rights", |
| "பணவீக்கம்": "inflation", |
| "வங்கி": "bank banking", |
| "வரி": "tax taxation", |
| "இலாபம்": "profit", |
| "நஷ்டம்": "loss", |
| "சொத்து": "assets", |
| "பொறுப்பு": "liability", |
| "மூலதனம்": "capital", |
| } |
|
|
| def get_rag_query(message): |
| """Convert Tamil query to English for better vector search""" |
| msg_lower = message.lower() |
| for tamil, english in TAMIL_TO_ENGLISH.items(): |
| if tamil in message: |
| return english |
| |
| tamil_chars = sum(1 for c in message if '' <= c <= '') |
| if tamil_chars > len(message) * 0.3: |
| return message |
| return message |
|
|
| def generate(message, mode, grade, subject, language, story_style): |
| rag_query = get_rag_query(message) |
| ctx = rag_search(rag_query, grade=grade, subject=subject) |
| ctx_text = f"Textbook Context:\n{ctx}" if ctx else "(Use general TN Board knowledge)" |
| system = SYSTEM_PROMPT.format(language=get_lang(language)) |
| if mode == "📚 Chat Tutor": |
| user = f"""{ctx_text} |
| |
| IMPORTANT: Use the textbook context above to answer accurately. |
| |
| Student Question: {message} |
| |
| Give a complete structured answer based on the context: |
| 📖 **Definition:** [accurate definition from context] |
| 🔑 **Key Points:** |
| • [key point 1 from context] |
| • [key point 2 from context] |
| • [key point 3 from context] |
| 💡 **Example:** [real-life Tamil student example] |
| 📝 **Exam Tip:** [important exam tip] |
| |
| Write complete sentences. Do not cut short.""" |
| elif mode == "✨ Story Mode": |
| styles = {"🌟 Deep":"thoughtful and educational","🎉 Funny":"funny and playful","🚀 Adventure":"adventurous and exciting","💙 Emotional":"emotional and heartwarming"} |
| user = f"""{ctx_text}\n\nWrite a {styles.get(story_style,'educational')} story (8-10 sentences) teaching: {message}\nTamil characters (Ramu, Priya, Anna) must EXPERIENCE the concept.\n\n🌟 **கதை / Story:**\n[story]\n\n📚 **பாடம் / Lesson:**\n[concept]""" |
| else: |
| user = f"""{ctx_text}\n\nTN Board exam questions for {grade} {subject}: {message}\n\n**கேள்வி 1 — 2 மதிப்பெண்கள்:** [question]\n**விடை:** [answer]\n\n**கேள்வி 2 — 5 மதிப்பெண்கள்:** [question]\n**விடை:** [structured answer]\n\n**கேள்வி 3 — 8 மதிப்பெண்கள்:** [question]\n**விடை:** [detailed answer]\n\n⭐ **Key Terms:** [4 terms]""" |
| for model_id, provider in [ |
| ("Qwen/Qwen2.5-72B-Instruct", "nebius"), |
| ("Qwen/Qwen2.5-7B-Instruct", "novita"), |
| ("meta-llama/Llama-3.1-8B-Instruct", "novita"), |
| ("Qwen/Qwen2.5-32B-Instruct", "nebius"), |
| ]: |
| try: |
| client = InferenceClient(model=model_id, token=HF_TOKEN, provider=provider) |
| resp = client.chat_completion(messages=[{"role":"system","content":system},{"role":"user","content":user}], max_tokens=2048, temperature=0.3) |
| return resp.choices[0].message.content.strip() |
| except: continue |
| return "மன்னிக்கவும், இப்போது busy. சற்று நேரம் கழித்து முயற்சிக்கவும்." |
|
|
| def chat(message, history, mode, grade, subject, language, story_style): |
| if not message.strip(): return history, "" |
| history = history or [] |
| loading = {"📚 Chat Tutor":["📖 பாடப்புத்தகத்தில் தேடுகிறோம்..."],"✨ Story Mode":["✨ கதை உருவாக்குகிறோம்..."],"🎯 Exam Mode":["📝 கேள்விகள் தயாராகிறது..."]} |
| history.append({"role":"user","content":message}) |
| history.append({"role":"assistant","content":loading.get(mode,["⏳ தயாராகிறது..."])[0]}) |
| yield history, "" |
| response = generate(message, mode, grade, subject, language, story_style) |
| history[-1] = {"role":"assistant","content":response} |
| yield history, "" |
|
|
| CSS = """ |
| @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Tamil:wght@400;500;600;700&family=Inter:wght@400;500;600;700;800&display=swap'); |
| |
| /* ── RESET & BASE ── */ |
| *, *::before, *::after { |
| box-sizing: border-box; |
| font-family: 'Noto Sans Tamil', 'Inter', sans-serif !important; |
| letter-spacing: 0 !important; |
| word-spacing: 0 !important; |
| } |
| |
| /* ONE CONSISTENT DARK THEME */ |
| body, .gradio-container, .gr-panel, .gr-box, |
| .contain, .wrap, .gap, .border-none { |
| background: #111827 !important; |
| color: #F9FAFB !important; |
| } |
| .gradio-container { |
| max-width: 820px !important; |
| margin: 0 auto !important; |
| padding: 12px !important; |
| } |
| |
| /* ── HERO ── */ |
| #fl-hero { |
| background: linear-gradient(135deg, #4338CA 0%, #6D28D9 50%, #7C3AED 100%); |
| border-radius: 20px; |
| padding: 24px 20px 20px; |
| margin-bottom: 10px; |
| text-align: center; |
| box-shadow: 0 8px 32px rgba(109,40,217,0.4); |
| position: relative; overflow: hidden; |
| } |
| #fl-hero::before { |
| content:''; position:absolute; top:-50px; right:-50px; |
| width:180px; height:180px; border-radius:50%; |
| background:rgba(255,255,255,0.07); pointer-events:none; |
| } |
| #fl-hero h1 { |
| font-size: 2rem !important; font-weight: 800 !important; |
| color: white !important; -webkit-text-fill-color: white !important; |
| margin: 0 0 6px 0 !important; letter-spacing: -0.3px !important; |
| } |
| #fl-hero .fl-tagline { |
| color: rgba(255,255,255,0.95) !important; |
| font-size: 1.25rem; font-weight: 600; margin: 2px 0 6px 0; |
| letter-spacing: 0.5px !important; |
| } |
| #fl-hero .fl-sub { |
| color: rgba(255,255,255,0.65) !important; |
| font-size: 0.78rem; margin: 0 0 14px 0; |
| } |
| #fl-hero .fl-chips { |
| display: flex; gap: 6px; justify-content: center; flex-wrap: wrap; |
| } |
| #fl-hero .fl-chip { |
| background: rgba(255,255,255,0.15); |
| border: 1px solid rgba(255,255,255,0.22); |
| color: white; padding: 4px 12px; |
| border-radius: 50px; font-size: 0.72rem; font-weight: 500; |
| } |
| |
| /* ── STUDENT SIGNAL ── */ |
| #fl-signal { |
| background: rgba(124,58,237,0.1); |
| border: none; |
| border-left: 3px solid #7C3AED; |
| border-radius: 8px; |
| padding: 9px 16px; |
| margin-bottom: 10px; |
| font-size: 0.8rem; |
| color: #A78BFA; |
| text-align: center; |
| } |
| |
| /* ── CONTROLS CARD ── */ |
| #fl-controls { |
| background: #1F2937 !important; |
| border: 1px solid #374151 !important; |
| border-radius: 14px !important; |
| padding: 14px 16px !important; |
| margin-bottom: 10px !important; |
| } |
| #fl-controls label { |
| color: #A78BFA !important; |
| font-size: 0.7rem !important; font-weight: 700 !important; |
| text-transform: uppercase; letter-spacing: 0.6px !important; |
| margin-bottom: 4px !important; |
| } |
| #fl-controls select { |
| background: #111827 !important; |
| border: 1px solid #374151 !important; |
| border-radius: 8px !important; |
| color: #F9FAFB !important; |
| font-size: 0.88rem !important; |
| padding: 9px 12px !important; |
| width: 100% !important; |
| cursor: pointer !important; |
| transition: border-color 0.2s !important; |
| -webkit-appearance: auto !important; |
| } |
| #fl-controls select:focus { |
| border-color: #7C3AED !important; |
| outline: none !important; |
| box-shadow: 0 0 0 2px rgba(124,58,237,0.25) !important; |
| } |
| #fl-controls option { |
| background: #1F2937 !important; |
| color: #F9FAFB !important; |
| } |
| |
| /* ── STORY PILLS CARD ── */ |
| #fl-story-wrap { |
| background: #1F2937 !important; |
| border: 1px solid #78350F !important; |
| border-radius: 12px !important; |
| padding: 12px 16px !important; |
| margin-bottom: 10px !important; |
| } |
| #fl-story-wrap label.svelte-1gfkn6j { |
| color: #FCD34D !important; font-size: 0.7rem !important; |
| font-weight: 700 !important; text-transform: uppercase; |
| letter-spacing: 0.6px !important; |
| } |
| /* 2-column grid for story pills */ |
| .fl-sr .gr-radio-group { |
| display: grid !important; |
| grid-template-columns: 1fr 1fr !important; |
| gap: 8px !important; |
| margin-top: 8px !important; |
| } |
| .fl-sr label { |
| border-radius: 10px !important; |
| padding: 9px 14px !important; |
| font-size: 0.85rem !important; font-weight: 600 !important; |
| cursor: pointer !important; transition: all 0.18s !important; |
| border: 1.5px solid !important; text-align: center !important; |
| letter-spacing: 0 !important; |
| } |
| .fl-sr label:nth-child(1){background:#1e1b4b!important;border-color:#4338ca!important;color:#a5b4fc!important;} |
| .fl-sr label:nth-child(2){background:#1c1200!important;border-color:#b45309!important;color:#fcd34d!important;} |
| .fl-sr label:nth-child(3){background:#1c0f00!important;border-color:#c2410c!important;color:#fb923c!important;} |
| .fl-sr label:nth-child(4){background:#1c001a!important;border-color:#be185d!important;color:#f9a8d4!important;} |
| .fl-sr label:has(input:checked):nth-child(1){background:#4338ca!important;color:white!important;border-color:#4338ca!important;box-shadow:0 3px 12px rgba(67,56,202,0.5)!important;} |
| .fl-sr label:has(input:checked):nth-child(2){background:#b45309!important;color:white!important;border-color:#b45309!important;box-shadow:0 3px 12px rgba(180,83,9,0.5)!important;} |
| .fl-sr label:has(input:checked):nth-child(3){background:#c2410c!important;color:white!important;border-color:#c2410c!important;box-shadow:0 3px 12px rgba(194,65,12,0.5)!important;} |
| .fl-sr label:has(input:checked):nth-child(4){background:#be185d!important;color:white!important;border-color:#be185d!important;box-shadow:0 3px 12px rgba(190,24,93,0.5)!important;} |
| |
| /* ── CHAT AREA ── */ |
| #fl-chat { |
| background: #1F2937 !important; |
| border: 1px solid #374151 !important; |
| border-radius: 16px !important; |
| overflow: hidden !important; |
| margin-bottom: 10px !important; |
| } |
| .gr-chatbot, [data-testid="chatbot"] { |
| background: #1F2937 !important; |
| border: none !important; |
| border-radius: 0 !important; |
| } |
| |
| /* User bubble */ |
| [data-testid="user"] > div { |
| background: linear-gradient(135deg, #4338CA, #7C3AED) !important; |
| color: white !important; |
| border-radius: 18px 18px 4px 18px !important; |
| padding: 12px 16px !important; |
| max-width: 80% !important; |
| margin-left: auto !important; |
| box-shadow: 0 3px 12px rgba(109,40,217,0.35) !important; |
| font-size: 0.93rem !important; |
| line-height: 1.65 !important; |
| } |
| [data-testid="user"] > div * { color: white !important; } |
| |
| /* Bot bubble */ |
| [data-testid="bot"] > div { |
| background: #111827 !important; |
| color: #F9FAFB !important; |
| border: 1px solid #374151 !important; |
| border-radius: 4px 18px 18px 18px !important; |
| padding: 14px 18px !important; |
| max-width: 90% !important; |
| box-shadow: 0 2px 8px rgba(0,0,0,0.3) !important; |
| font-size: 0.92rem !important; |
| line-height: 1.8 !important; |
| } |
| [data-testid="bot"] > div * { color: #F9FAFB !important; } |
| [data-testid="bot"] strong { color: #A78BFA !important; font-weight: 700 !important; } |
| [data-testid="bot"] ul, [data-testid="bot"] ol { padding-left: 18px !important; margin: 6px 0 !important; } |
| [data-testid="bot"] li { margin: 5px 0 !important; color: #D1D5DB !important; } |
| [data-testid="bot"] p { margin-bottom: 8px !important; } |
| |
| /* ── INPUT AREA ── */ |
| #fl-input { |
| border-top: 1px solid #374151 !important; |
| padding: 14px 14px 12px !important; |
| background: #1F2937 !important; |
| } |
| #fl-input textarea { |
| background: #111827 !important; |
| border: 1.5px solid #4B5563 !important; |
| border-radius: 12px !important; |
| color: #F9FAFB !important; |
| font-size: 0.95rem !important; |
| padding: 12px 16px !important; |
| line-height: 1.65 !important; |
| resize: none !important; |
| transition: border-color 0.2s, box-shadow 0.2s !important; |
| } |
| #fl-input textarea:focus { |
| border-color: #7C3AED !important; |
| box-shadow: 0 0 0 3px rgba(124,58,237,0.2) !important; |
| outline: none !important; |
| } |
| #fl-input textarea::placeholder { color: #6B7280 !important; } |
| |
| #fl-send { |
| background: linear-gradient(135deg, #4338CA, #7C3AED) !important; |
| border: none !important; border-radius: 10px !important; |
| color: white !important; font-weight: 700 !important; |
| font-size: 0.93rem !important; height: 46px !important; |
| box-shadow: 0 4px 16px rgba(109,40,217,0.4) !important; |
| transition: all 0.2s !important; |
| height: 40px !important; |
| } |
| #fl-send:hover { |
| transform: translateY(-2px) !important; |
| box-shadow: 0 6px 22px rgba(109,40,217,0.55) !important; |
| } |
| #fl-clear { |
| background: transparent !important; |
| border: 1px solid #374151 !important; |
| border-radius: 10px !important; |
| color: #6B7280 !important; |
| height: 40px !important; |
| font-size: 0.82rem !important; |
| transition: all 0.18s !important; |
| } |
| #fl-clear:hover { |
| border-color: #4B5563 !important; |
| color: #9CA3AF !important; |
| } |
| |
| /* ── EXAMPLES ── */ |
| #fl-examples { margin-top: 4px; } |
| .gr-examples .label { |
| color: #6B7280 !important; font-size: 0.7rem !important; |
| font-weight: 700 !important; text-transform: uppercase; |
| letter-spacing: 0.5px !important; margin-bottom: 8px !important; |
| } |
| .gr-examples button { |
| background: #1F2937 !important; |
| border: 1px solid #374151 !important; |
| border-radius: 50px !important; |
| color: #A78BFA !important; |
| font-size: 0.82rem !important; font-weight: 500 !important; |
| padding: 7px 16px !important; margin: 3px !important; |
| transition: all 0.18s !important; |
| } |
| .gr-examples button:hover { |
| background: #2D3748 !important; |
| border-color: #7C3AED !important; |
| color: #C4B5FD !important; |
| transform: translateY(-1px) !important; |
| } |
| |
| /* ── FOOTER ── */ |
| #fl-footer { |
| text-align: center; color: #4B5563; |
| font-size: 0.75rem; padding: 12px 0 4px; line-height: 1.9; |
| } |
| #fl-footer strong { color: #7C3AED; } |
| #fl-footer a { color: #6D28D9; text-decoration: none; } |
| |
| /* ── MOBILE ── */ |
| @media (max-width: 640px) { |
| .gradio-container { padding: 8px !important; } |
| #fl-hero { padding: 20px 14px 16px; border-radius: 16px; } |
| #fl-hero h1 { font-size: 1.7rem !important; } |
| #fl-hero .fl-tagline { font-size: 0.88rem; } |
| #fl-hero .fl-sub { font-size: 0.74rem; } |
| #fl-hero .fl-chip { font-size: 0.68rem; padding: 3px 10px; } |
| #fl-controls { padding: 12px !important; } |
| #fl-controls select { font-size: 0.85rem !important; padding: 8px 10px !important; } |
| .fl-sr .gr-radio-group { grid-template-columns: 1fr 1fr !important; gap: 6px !important; } |
| .fl-sr label { padding: 8px 10px !important; font-size: 0.82rem !important; } |
| [data-testid="user"] > div { max-width: 88% !important; font-size: 0.9rem !important; } |
| [data-testid="bot"] > div { max-width: 96% !important; font-size: 0.88rem !important; } |
| #fl-input { padding: 10px 10px 8px !important; } |
| #fl-input textarea { font-size: 0.92rem !important; } |
| #fl-send { height: 48px !important; font-size: 0.9rem !important; } |
| #fl-clear { height: 38px !important; font-size: 0.82rem !important; } |
| .gr-examples button { font-size: 0.78rem !important; padding: 6px 12px !important; } |
| } |
| """ |
|
|
| with gr.Blocks(css=CSS, title="FeelEd Lite — Tamil TN Board AI Tutor") as demo: |
|
|
| gr.HTML(""" |
| <div id="fl-hero"> |
| <h1>📚 FeelEd Lite</h1> |
| <p class="fl-tagline">கற்க கசடற</p> |
| <p class="fl-sub">Tamil Medium · Grades 9–12 · TN Samacheer AI Tutor</p> |
| <div class="fl-chips"> |
| <span class="fl-chip">🏫 Grades 9–12</span> |
| <span class="fl-chip">📖 21k+ Passages</span> |
| <span class="fl-chip">🌐 Tamil + English</span> |
| <span class="fl-chip">🔒 No Data Stored</span> |
| <span class="fl-chip">⚡ Fast & Private</span> |
| </div> |
| </div> |
| """) |
|
|
| gr.HTML(""" |
| <div id="fl-signal"> |
| 👩🎓 Tested with Tamil-medium Grade 11 TN Board students preparing for exams. |
| Built for students across the Global South. |
| </div> |
| """) |
|
|
| with gr.Row(elem_id="fl-controls"): |
| mode = gr.Dropdown(choices=MODES, value="📚 Chat Tutor", label="🎯 Mode", scale=1, filterable=False) |
| grade = gr.Dropdown(choices=GRADES, value="Grade 11", label="🎓 Grade", scale=1, filterable=False) |
| subject = gr.Dropdown(choices=SUBJECTS, value="Commerce", label="📘 Subject", scale=1, filterable=False) |
| language = gr.Dropdown(choices=LANGUAGES, value="Tanglish (Tamil + English)", label="🌐 Language",scale=1, filterable=False) |
|
|
| with gr.Row(elem_id="fl-story-wrap", visible=False) as story_row: |
| story_style = gr.Radio( |
| choices=STORY_STYLES, value="🌟 Deep", |
| label="✨ Story Style", |
| elem_classes=["fl-sr"], |
| ) |
|
|
| with gr.Column(elem_id="fl-chat"): |
| chatbot = gr.Chatbot( |
| type="messages", height=320, |
| show_label=False, bubble_full_width=False, |
| placeholder="""<div style='text-align:center;padding:24px 16px;background:#1F2937;'> |
| <div style='font-size:2rem;margin-bottom:8px;'>📚</div> |
| <p style='color:#A78BFA;font-size:0.9rem;font-weight:600;margin:0 0 4px 0;'>வணக்கம்! FeelEd Lite 🙏</p> |
| <p style='color:#6B7280;font-size:0.82rem;line-height:1.6;margin:0;'> |
| TN Board கேள்விகளை Tamil, English அல்லது Tanglish-ல் கேளுங்கள். |
| </p> |
| </div>""", |
| ) |
| with gr.Column(elem_id="fl-input"): |
| msg = gr.Textbox( |
| placeholder="உங்கள் கேள்வியை இங்கே தட்டச்சு செய்யுங்கள்...", |
| show_label=False, lines=2, |
| ) |
| with gr.Row(): |
| send_btn = gr.Button("▶ அனுப்பு / Send", elem_id="fl-send", variant="primary", scale=4) |
| clear_btn = gr.Button("🗑 Clear", elem_id="fl-clear", scale=1) |
|
|
| with gr.Column(elem_id="fl-examples"): |
| gr.Examples( |
| examples=[ |
| ["தேவை விதி என்றால் என்ன?"], |
| ["இரட்டை பதிவு முறை விளக்கு"], |
| ["GDP என்றால் என்ன?"], |
| ["தொழில் முனைவோர் பண்புகள்"], |
| ["Consumer rights in Tamil"], |
| ["Newton's laws of motion"], |
| ], |
| inputs=msg, |
| label="💡 Try these questions:", |
| ) |
|
|
| gr.HTML(""" |
| <div id="fl-footer"> |
| <strong>FeelEd Lite v0.9</strong> · Built for Tamil-medium students across the Global South.<br> |
| Part of <a href="https://feeledai.com" target="_blank">FeelEd AI</a> · |
| 🏆 Build Small Hackathon 2026 · Track: Backyard AI 🏡 |
| </div> |
| """) |
|
|
| mode.change(fn=lambda m: gr.update(visible=(m=="✨ Story Mode")), inputs=mode, outputs=story_row) |
| send_btn.click(fn=chat, inputs=[msg,chatbot,mode,grade,subject,language,story_style], outputs=[chatbot,msg]) |
| msg.submit(fn=chat, inputs=[msg,chatbot,mode,grade,subject,language,story_style], outputs=[chatbot,msg]) |
| clear_btn.click(lambda: ([],""), outputs=[chatbot,msg]) |
|
|
| if __name__ == "__main__": |
| demo.launch() |
|
|