Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,55 +1,94 @@
|
|
| 1 |
-
|
| 2 |
import gradio as gr
|
| 3 |
-
import os
|
| 4 |
import requests
|
|
|
|
| 5 |
|
| 6 |
-
|
|
|
|
| 7 |
GROQ_MODEL = "llama3-70b-8192"
|
| 8 |
|
| 9 |
-
# ------------------ GPT QUERY FUNCTION ------------------
|
| 10 |
def query_gpt(prompt):
|
| 11 |
headers = {
|
| 12 |
"Authorization": f"Bearer {GROQ_API_KEY}",
|
| 13 |
"Content-Type": "application/json"
|
| 14 |
}
|
| 15 |
-
|
| 16 |
"model": GROQ_MODEL,
|
| 17 |
-
"messages": [
|
| 18 |
-
{"role": "user", "content": prompt}
|
| 19 |
-
]
|
| 20 |
}
|
| 21 |
-
response = requests.post("https://api.groq.com/openai/v1/chat/completions",
|
| 22 |
return response.json()['choices'][0]['message']['content']
|
| 23 |
|
| 24 |
-
# ------------------
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
elif file.name.endswith(".docx"):
|
|
|
|
| 39 |
doc = docx.Document(file)
|
| 40 |
-
for
|
| 41 |
-
text += para.text + "\n"
|
| 42 |
else:
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
def
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
# ------------------ HANGMAN GAME ------------------
|
| 52 |
-
|
| 53 |
def generate_question_answer(class_level, subject, chapter):
|
| 54 |
prompt = f"Give one short quiz question and a one-word answer from the chapter '{chapter}' in Class {class_level} {subject}. Format:\nQuestion: ...\nAnswer: ..."
|
| 55 |
result = query_gpt(prompt)
|
|
@@ -84,48 +123,78 @@ def guess_letter(letter, answer, current_display, wrong_guesses_left, guessed_le
|
|
| 84 |
return current_display, f"β Game over! The correct word was '{answer}'.", wrong_guesses_left, guessed_letters
|
| 85 |
return current_display, f"β Wrong guess! {wrong_guesses_left} attempts left.", wrong_guesses_left, guessed_letters
|
| 86 |
|
| 87 |
-
# ------------------ UI ------------------
|
| 88 |
-
with gr.Blocks() as app:
|
| 89 |
-
gr.
|
| 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 |
app.launch()
|
| 129 |
|
| 130 |
|
| 131 |
|
|
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
|
|
|
| 2 |
import requests
|
| 3 |
+
import os
|
| 4 |
|
| 5 |
+
# ------------------ GROQ SETTINGS ------------------
|
| 6 |
+
GROQ_API_KEY = os.getenv("GROQ_API_KEY") or "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"
|
| 7 |
GROQ_MODEL = "llama3-70b-8192"
|
| 8 |
|
|
|
|
| 9 |
def query_gpt(prompt):
|
| 10 |
headers = {
|
| 11 |
"Authorization": f"Bearer {GROQ_API_KEY}",
|
| 12 |
"Content-Type": "application/json"
|
| 13 |
}
|
| 14 |
+
data = {
|
| 15 |
"model": GROQ_MODEL,
|
| 16 |
+
"messages": [{"role": "user", "content": prompt}]
|
|
|
|
|
|
|
| 17 |
}
|
| 18 |
+
response = requests.post("https://api.groq.com/openai/v1/chat/completions", json=data, headers=headers)
|
| 19 |
return response.json()['choices'][0]['message']['content']
|
| 20 |
|
| 21 |
+
# ------------------ SYLLABUS DATA ------------------
|
| 22 |
+
class_subject_chapters = {
|
| 23 |
+
"9": {
|
| 24 |
+
"Physics": ["Introduction to Physics", "Kinematics", "Dynamics", "Turning Effect of Forces", "Gravitation", "Work and Energy", "Properties of Matter", "Thermal Properties of Matter", "Transfer of Heat"],
|
| 25 |
+
"Biology": ["Introduction to Biology", "Solving a Biological Problem", "Biodiversity", "Cells and Tissues", "Cell Cycle", "Enzymes", "Bioenergetics", "Nutrition", "Transport"],
|
| 26 |
+
"Chemistry": ["Fundamentals of Chemistry", "Structure of Atoms", "Periodic Table", "Structure of Molecules", "Physical States of Matter", "Solutions", "Electrochemistry", "Chemical Reactivity"]
|
| 27 |
+
},
|
| 28 |
+
"10": {
|
| 29 |
+
"Physics": ["Simple Harmonic Motion and Waves", "Sound", "Geometrical Optics", "Electrostatics", "Current Electricity", "Electromagnetism", "Basic Electronics", "Information and Communication Technology", "Atomic and Nuclear Physics"],
|
| 30 |
+
"Biology": ["Gaseous Exchange", "Homeostasis", "Coordination and Control", "Support and Movement", "Reproduction", "Inheritance", "Man and His Environment", "Biotechnology", "Pharmacology"],
|
| 31 |
+
"Chemistry": ["Chemical Equilibrium", "Acids, Bases and Salts", "Organic Chemistry", "Hydrocarbons", "Biochemistry", "Environmental Chemistry", "Chemical Industries"]
|
| 32 |
+
},
|
| 33 |
+
"11": {
|
| 34 |
+
"Physics": ["Measurements", "Vectors and Equilibrium", "Motion and Force", "Work and Energy", "Circular Motion", "Fluid Dynamics", "Oscillations", "Waves", "Physical Optics", "Thermodynamics"],
|
| 35 |
+
"Biology": ["Introduction to Biology", "Biological Molecules", "Enzymes", "The Cell", "Cell Cycle", "Variety of Life", "Kingdom Prokaryotae", "Kingdom Protista", "Kingdom Fungi", "Kingdom Plantae", "Kingdom Animalia"],
|
| 36 |
+
"Chemistry": ["Basic Concepts", "Experimental Techniques", "Gases", "Liquids and Solids", "Atomic Structure", "Chemical Bonding", "Thermochemistry", "Chemical Equilibrium", "Ionic Equilibrium", "Redox Reactions"]
|
| 37 |
+
},
|
| 38 |
+
"12": {
|
| 39 |
+
"Physics": ["Electrostatics", "Current Electricity", "Electromagnetism", "Electromagnetic Induction", "Alternating Current", "Physics of Solids", "Electronics", "Dawn of Modern Physics", "Atomic Spectra", "Nuclear Physics"],
|
| 40 |
+
"Biology": ["Homeostasis", "Support and Movement", "Coordination and Control", "Reproduction", "Growth and Development", "Chromosomes and DNA", "Biotechnology", "Evolution", "Ecosystem", "Some Major Ecosystems"],
|
| 41 |
+
"Chemistry": ["Periodic Classification", "Transition Elements", "Chemical Reactivity", "Alcohols and Phenols", "Aldehydes and Ketones", "Carboxylic Acids", "Amines", "Polymers", "Biochemistry", "Environmental Chemistry"]
|
| 42 |
+
}
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
# ------------------ FILE READER ------------------
|
| 46 |
+
def read_uploaded_file(file):
|
| 47 |
+
if file is None:
|
| 48 |
+
return ""
|
| 49 |
+
if file.name.endswith(".txt"):
|
| 50 |
+
return file.read().decode("utf-8")
|
| 51 |
+
elif file.name.endswith(".pdf"):
|
| 52 |
+
from PyPDF2 import PdfReader
|
| 53 |
+
reader = PdfReader(file)
|
| 54 |
+
return "\n".join(page.extract_text() for page in reader.pages if page.extract_text())
|
| 55 |
elif file.name.endswith(".docx"):
|
| 56 |
+
import docx
|
| 57 |
doc = docx.Document(file)
|
| 58 |
+
return "\n".join(p.text for p in doc.paragraphs)
|
|
|
|
| 59 |
else:
|
| 60 |
+
return "Unsupported file format. Please upload a PDF, DOCX, or TXT file."
|
| 61 |
+
|
| 62 |
+
# ------------------ MAIN BOT FUNCTION ------------------
|
| 63 |
+
def tutor_bot(mode, selected_class, selected_subject, selected_chapter, action_type, uploaded_file):
|
| 64 |
+
if mode == "File Upload Mode" and uploaded_file is not None:
|
| 65 |
+
file_text = read_uploaded_file(uploaded_file)
|
| 66 |
+
if not file_text.strip():
|
| 67 |
+
return "Could not read text from the uploaded file."
|
| 68 |
+
prompt = f"Based on the following content, {action_type.lower()}: \n\n{file_text[:4000]}" # keep it under token limits
|
| 69 |
+
gpt_response = query_gpt(prompt)
|
| 70 |
+
return gpt_response
|
| 71 |
+
|
| 72 |
+
elif mode == "Syllabus Mode":
|
| 73 |
+
if not selected_class or not selected_subject or not selected_chapter:
|
| 74 |
+
return "Please select class, subject, and chapter."
|
| 75 |
+
prompt = f"The user is studying in Class {selected_class}. Give a detailed response for the chapter '{selected_chapter}' in the subject '{selected_subject}'."
|
| 76 |
+
if action_type == "Summarize Important Points":
|
| 77 |
+
prompt = f"Summarize the key points of the chapter '{selected_chapter}' from Class {selected_class} {selected_subject}."
|
| 78 |
+
elif action_type == "Generate MCQs":
|
| 79 |
+
prompt = f"Create 5 multiple choice questions (MCQs) with 4 options each for the chapter '{selected_chapter}' from Class {selected_class} {selected_subject}."
|
| 80 |
+
elif action_type == "Simplify Concepts":
|
| 81 |
+
prompt = f"Explain in very simple terms the important concepts from the chapter '{selected_chapter}' from Class {selected_class} {selected_subject} for a 14-year-old student."
|
| 82 |
+
|
| 83 |
+
gpt_response = query_gpt(prompt)
|
| 84 |
+
search_query = f"{selected_class} {selected_subject} {selected_chapter} in Urdu"
|
| 85 |
+
youtube_link = f"https://www.youtube.com/results?search_query={search_query.replace(' ', '+')}"
|
| 86 |
+
gpt_response += f"\n\nπ₯ **Watch this topic on YouTube:** [Click here]({youtube_link})"
|
| 87 |
+
return gpt_response
|
| 88 |
+
|
| 89 |
+
return "Invalid mode or missing input."
|
| 90 |
|
| 91 |
# ------------------ HANGMAN GAME ------------------
|
|
|
|
| 92 |
def generate_question_answer(class_level, subject, chapter):
|
| 93 |
prompt = f"Give one short quiz question and a one-word answer from the chapter '{chapter}' in Class {class_level} {subject}. Format:\nQuestion: ...\nAnswer: ..."
|
| 94 |
result = query_gpt(prompt)
|
|
|
|
| 123 |
return current_display, f"β Game over! The correct word was '{answer}'.", wrong_guesses_left, guessed_letters
|
| 124 |
return current_display, f"β Wrong guess! {wrong_guesses_left} attempts left.", wrong_guesses_left, guessed_letters
|
| 125 |
|
| 126 |
+
# ------------------ GRADIO UI ------------------
|
| 127 |
+
with gr.Blocks(title="AI Textbook Tutor") as app:
|
| 128 |
+
with gr.Tab("π Tutor"):
|
| 129 |
+
gr.Markdown("## π AI Textbook Tutor\nChoose a mode to either upload your file or select chapter-wise content to get summaries, MCQs, or simplified explanations.")
|
| 130 |
+
|
| 131 |
+
mode = gr.Radio(["Syllabus Mode", "File Upload Mode"], label="Select Mode", value="Syllabus Mode")
|
| 132 |
+
|
| 133 |
+
with gr.Row():
|
| 134 |
+
class_dropdown = gr.Dropdown(label="Class", choices=list(class_subject_chapters.keys()))
|
| 135 |
+
subject_dropdown = gr.Dropdown(label="Subject")
|
| 136 |
+
chapter_dropdown = gr.Dropdown(label="Chapter")
|
| 137 |
+
|
| 138 |
+
file_input = gr.File(label="Upload File (PDF, DOCX, TXT)", file_types=[".pdf", ".docx", ".txt"])
|
| 139 |
+
action_dropdown = gr.Radio(["Summarize Important Points", "Generate MCQs", "Simplify Concepts"], label="Task", value="Summarize Important Points")
|
| 140 |
+
|
| 141 |
+
run_button = gr.Button("Run Tutor π§ ")
|
| 142 |
+
output_box = gr.Markdown()
|
| 143 |
+
|
| 144 |
+
def update_subjects(selected_class):
|
| 145 |
+
return gr.update(choices=list(class_subject_chapters[selected_class].keys()), value=None)
|
| 146 |
+
|
| 147 |
+
def update_chapters(selected_class, selected_subject):
|
| 148 |
+
return gr.update(choices=class_subject_chapters[selected_class][selected_subject], value=None)
|
| 149 |
+
|
| 150 |
+
def toggle_ui(selected_mode):
|
| 151 |
+
if selected_mode == "File Upload Mode":
|
| 152 |
+
return (
|
| 153 |
+
gr.update(visible=False), # Class
|
| 154 |
+
gr.update(visible=False), # Subject
|
| 155 |
+
gr.update(visible=False), # Chapter
|
| 156 |
+
gr.update(visible=True) # File input
|
| 157 |
+
)
|
| 158 |
+
else:
|
| 159 |
+
return (
|
| 160 |
+
gr.update(visible=True),
|
| 161 |
+
gr.update(visible=True),
|
| 162 |
+
gr.update(visible=True),
|
| 163 |
+
gr.update(visible=False)
|
| 164 |
+
)
|
| 165 |
+
|
| 166 |
+
class_dropdown.change(update_subjects, inputs=class_dropdown, outputs=subject_dropdown)
|
| 167 |
+
subject_dropdown.change(update_chapters, inputs=[class_dropdown, subject_dropdown], outputs=chapter_dropdown)
|
| 168 |
+
mode.change(toggle_ui, inputs=mode, outputs=[class_dropdown, subject_dropdown, chapter_dropdown, file_input])
|
| 169 |
+
|
| 170 |
+
run_button.click(
|
| 171 |
+
tutor_bot,
|
| 172 |
+
inputs=[mode, class_dropdown, subject_dropdown, chapter_dropdown, action_dropdown, file_input],
|
| 173 |
+
outputs=output_box
|
| 174 |
+
)
|
| 175 |
+
|
| 176 |
+
with gr.Tab("π― Hangman Game"):
|
| 177 |
+
with gr.Row():
|
| 178 |
+
class_level_hg = gr.Dropdown(label="Class", choices=list(class_subject_chapters.keys()))
|
| 179 |
+
subject_hg = gr.Textbox(label="Subject")
|
| 180 |
+
chapter_hg = gr.Textbox(label="Chapter")
|
| 181 |
+
start_btn = gr.Button("Start Hangman Game")
|
| 182 |
+
|
| 183 |
+
question_display = gr.Textbox(label="Question", interactive=False)
|
| 184 |
+
word_display = gr.Textbox(label="Word", interactive=False)
|
| 185 |
+
feedback_display = gr.Textbox(label="Feedback", interactive=False)
|
| 186 |
+
guess_input = gr.Textbox(label="Guess a letter")
|
| 187 |
+
guess_btn = gr.Button("Guess")
|
| 188 |
+
|
| 189 |
+
wrong_guesses_left = gr.State(6)
|
| 190 |
+
correct_answer = gr.State("")
|
| 191 |
+
guessed_letters = gr.State([])
|
| 192 |
+
|
| 193 |
+
start_btn.click(fn=start_hangman_game, inputs=[class_level_hg, subject_hg, chapter_hg], outputs=[question_display, word_display, feedback_display, wrong_guesses_left, correct_answer, guessed_letters])
|
| 194 |
+
guess_btn.click(fn=guess_letter, inputs=[guess_input, correct_answer, word_display, wrong_guesses_left, guessed_letters], outputs=[word_display, feedback_display, wrong_guesses_left, guessed_letters])
|
| 195 |
|
| 196 |
app.launch()
|
| 197 |
|
| 198 |
|
| 199 |
|
| 200 |
+
|