File size: 11,607 Bytes
1f0b847
e380563
9880ad2
1f0b847
9880ad2
4fdcec1
1f0b847
 
 
 
 
 
 
9880ad2
1f0b847
9880ad2
1f0b847
9880ad2
1f0b847
 
9880ad2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1f0b847
9880ad2
1f0b847
9880ad2
82e78c4
9880ad2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e380563
 
c57020d
 
 
 
 
 
 
 
 
 
 
e380563
c57020d
8330125
c57020d
 
 
8330125
c57020d
 
 
 
 
 
 
 
 
e380563
c57020d
 
 
e380563
 
 
9880ad2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3464917
 
 
 
 
 
9880ad2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8330125
1f0b847
82e78c4
c57020d
e380563
9880ad2
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
import gradio as gr
import requests
import os

# ------------------ GROQ SETTINGS ------------------
GROQ_API_KEY = os.getenv("GROQ_API_KEY") 
GROQ_MODEL = "llama3-70b-8192"

def query_gpt(prompt):
    headers = {
        "Authorization": f"Bearer {GROQ_API_KEY}",
        "Content-Type": "application/json"
    }
    data = {
        "model": GROQ_MODEL,
        "messages": [{"role": "user", "content": prompt}]
    }
    response = requests.post("https://api.groq.com/openai/v1/chat/completions", json=data, headers=headers)
    return response.json()['choices'][0]['message']['content']

# ------------------ SYLLABUS DATA ------------------
class_subject_chapters = {
    "9": {
        "Physics": ["Introduction to Physics", "Kinematics", "Dynamics", "Turning Effect of Forces", "Gravitation", "Work and Energy", "Properties of Matter", "Thermal Properties of Matter", "Transfer of Heat"],
        "Biology": ["Introduction to Biology", "Solving a Biological Problem", "Biodiversity", "Cells and Tissues", "Cell Cycle", "Enzymes", "Bioenergetics", "Nutrition", "Transport"],
        "Chemistry": ["Fundamentals of Chemistry", "Structure of Atoms", "Periodic Table", "Structure of Molecules", "Physical States of Matter", "Solutions", "Electrochemistry", "Chemical Reactivity"]
    },
    "10": {
        "Physics": ["Simple Harmonic Motion and Waves", "Sound", "Geometrical Optics", "Electrostatics", "Current Electricity", "Electromagnetism", "Basic Electronics", "Information and Communication Technology", "Atomic and Nuclear Physics"],
        "Biology": ["Gaseous Exchange", "Homeostasis", "Coordination and Control", "Support and Movement", "Reproduction", "Inheritance", "Man and His Environment", "Biotechnology", "Pharmacology"],
        "Chemistry": ["Chemical Equilibrium", "Acids, Bases and Salts", "Organic Chemistry", "Hydrocarbons", "Biochemistry", "Environmental Chemistry", "Chemical Industries"]
    },
    "11": {
        "Physics": ["Measurements", "Vectors and Equilibrium", "Motion and Force", "Work and Energy", "Circular Motion", "Fluid Dynamics", "Oscillations", "Waves", "Physical Optics", "Thermodynamics"],
        "Biology": ["Introduction to Biology", "Biological Molecules", "Enzymes", "The Cell", "Cell Cycle", "Variety of Life", "Kingdom Prokaryotae", "Kingdom Protista", "Kingdom Fungi", "Kingdom Plantae", "Kingdom Animalia"],
        "Chemistry": ["Basic Concepts", "Experimental Techniques", "Gases", "Liquids and Solids", "Atomic Structure", "Chemical Bonding", "Thermochemistry", "Chemical Equilibrium", "Ionic Equilibrium", "Redox Reactions"]
    },
    "12": {
        "Physics": ["Electrostatics", "Current Electricity", "Electromagnetism", "Electromagnetic Induction", "Alternating Current", "Physics of Solids", "Electronics", "Dawn of Modern Physics", "Atomic Spectra", "Nuclear Physics"],
        "Biology": ["Homeostasis", "Support and Movement", "Coordination and Control", "Reproduction", "Growth and Development", "Chromosomes and DNA", "Biotechnology", "Evolution", "Ecosystem", "Some Major Ecosystems"],
        "Chemistry": ["Periodic Classification", "Transition Elements", "Chemical Reactivity", "Alcohols and Phenols", "Aldehydes and Ketones", "Carboxylic Acids", "Amines", "Polymers", "Biochemistry", "Environmental Chemistry"]
    }
}

# ------------------ FILE READER ------------------
def read_uploaded_file(file):
    if file is None:
        return ""
    if file.name.endswith(".txt"):
        return file.read().decode("utf-8")
    elif file.name.endswith(".pdf"):
        from PyPDF2 import PdfReader
        reader = PdfReader(file)
        return "\n".join(page.extract_text() for page in reader.pages if page.extract_text())
    elif file.name.endswith(".docx"):
        import docx
        doc = docx.Document(file)
        return "\n".join(p.text for p in doc.paragraphs)
    else:
        return "Unsupported file format. Please upload a PDF, DOCX, or TXT file."

# ------------------ MAIN BOT FUNCTION ------------------
def tutor_bot(mode, selected_class, selected_subject, selected_chapter, action_type, uploaded_file):
    if mode == "File Upload Mode" and uploaded_file is not None:
        file_text = read_uploaded_file(uploaded_file)
        if not file_text.strip():
            return "Could not read text from the uploaded file."
        prompt = f"Based on the following content, {action_type.lower()}: \n\n{file_text[:4000]}"  # keep it under token limits
        gpt_response = query_gpt(prompt)
        return gpt_response

    elif mode == "Syllabus Mode":
        if not selected_class or not selected_subject or not selected_chapter:
            return "Please select class, subject, and chapter."
        prompt = f"The user is studying in Class {selected_class}. Give a detailed response for the chapter '{selected_chapter}' in the subject '{selected_subject}'."
        if action_type == "Summarize Important Points":
            prompt = f"Summarize the key points of the chapter '{selected_chapter}' from Class {selected_class} {selected_subject}."
        elif action_type == "Generate MCQs":
            prompt = f"Create 5 multiple choice questions (MCQs) with 4 options each for the chapter '{selected_chapter}' from Class {selected_class} {selected_subject}."
        elif action_type == "Simplify Concepts":
            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."

        gpt_response = query_gpt(prompt)
        search_query = f"{selected_class} {selected_subject} {selected_chapter} in Urdu"
        youtube_link = f"https://www.youtube.com/results?search_query={search_query.replace(' ', '+')}"
        gpt_response += f"\n\nπŸŽ₯ **Watch this topic on YouTube:** [Click here]({youtube_link})"
        return gpt_response

    return "Invalid mode or missing input."

# ------------------ HANGMAN GAME ------------------
def generate_question_answer(class_level, subject, chapter):
    prompt = f"Give one short quiz question and a one-word answer from the chapter '{chapter}' in Class {class_level} {subject}. Format:\nQuestion: ...\nAnswer: ..."
    result = query_gpt(prompt)
    lines = result.strip().split("\n")
    question = ""
    answer = ""
    for line in lines:
        if line.lower().startswith("question:"):
            question = line.split(":", 1)[1].strip()
        elif line.lower().startswith("answer:"):
            answer = line.split(":", 1)[1].strip().lower()
    answer = ''.join(filter(str.isalpha, answer))
    return question, answer

def start_hangman_game(class_level, subject, chapter):
    question, answer = generate_question_answer(class_level, subject, chapter)
    return question, "_" * len(answer), "", 6, answer, []

def guess_letter(letter, answer, current_display, wrong_guesses_left, guessed_letters):
    letter = letter.lower()
    if letter in guessed_letters or len(letter) != 1:
        return current_display, f"You already guessed '{letter}' or invalid guess.", wrong_guesses_left, guessed_letters
    guessed_letters.append(letter)
    if letter in answer:
        new_display = "".join([letter if answer[i] == letter else current_display[i] for i in range(len(answer))])
        if "_" not in new_display:
            return new_display, "πŸŽ‰ You won!", wrong_guesses_left, guessed_letters
        return new_display, f"βœ… Correct guess!", wrong_guesses_left, guessed_letters
    else:
        wrong_guesses_left -= 1
        if wrong_guesses_left == 0:
            return current_display, f"❌ Game over! The correct word was '{answer}'.", wrong_guesses_left, guessed_letters
        return current_display, f"❌ Wrong guess! {wrong_guesses_left} attempts left.", wrong_guesses_left, guessed_letters

# ------------------ GRADIO UI ------------------
with gr.Blocks(title="AI Textbook Tutor") as app:
    with gr.Tab("πŸ“˜ Tutor"):
        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.")

        mode = gr.Radio(["Syllabus Mode", "File Upload Mode"], label="Select Mode", value="Syllabus Mode")

        with gr.Row():
            class_dropdown = gr.Dropdown(label="Class", choices=list(class_subject_chapters.keys()))
            subject_dropdown = gr.Dropdown(label="Subject")
            chapter_dropdown = gr.Dropdown(label="Chapter")

        file_input = gr.File(label="Upload File (PDF, DOCX, TXT)", file_types=[".pdf", ".docx", ".txt"])
        action_dropdown = gr.Radio(["Summarize Important Points", "Generate MCQs", "Simplify Concepts"], label="Task", value="Summarize Important Points")

        run_button = gr.Button("Run Tutor 🧠")
        output_box = gr.Markdown()

        def update_subjects(selected_class):
            return gr.update(choices=list(class_subject_chapters[selected_class].keys()), value=None)

        def update_chapters(selected_class, selected_subject):
            try:
                chapters = class_subject_chapters[selected_class][selected_subject]
                return gr.update(choices=chapters, value=None)
            except Exception as e:
                return gr.update(choices=[], value="Error")


        def toggle_ui(selected_mode):
            if selected_mode == "File Upload Mode":
                return (
                    gr.update(visible=False),  # Class
                    gr.update(visible=False),  # Subject
                    gr.update(visible=False),  # Chapter
                    gr.update(visible=True)    # File input
                )
            else:
                return (
                    gr.update(visible=True),
                    gr.update(visible=True),
                    gr.update(visible=True),
                    gr.update(visible=False)
                )

        class_dropdown.change(update_subjects, inputs=class_dropdown, outputs=subject_dropdown)
        subject_dropdown.change(update_chapters, inputs=[class_dropdown, subject_dropdown], outputs=chapter_dropdown)
        mode.change(toggle_ui, inputs=mode, outputs=[class_dropdown, subject_dropdown, chapter_dropdown, file_input])

        run_button.click(
            tutor_bot,
            inputs=[mode, class_dropdown, subject_dropdown, chapter_dropdown, action_dropdown, file_input],
            outputs=output_box
        )

    with gr.Tab("🎯 Hangman Game"):
        with gr.Row():
            class_level_hg = gr.Dropdown(label="Class", choices=list(class_subject_chapters.keys()))
            subject_hg = gr.Textbox(label="Subject")
            chapter_hg = gr.Textbox(label="Chapter")
            start_btn = gr.Button("Start Hangman Game")

        question_display = gr.Textbox(label="Question", interactive=False)
        word_display = gr.Textbox(label="Word", interactive=False)
        feedback_display = gr.Textbox(label="Feedback", interactive=False)
        guess_input = gr.Textbox(label="Guess a letter")
        guess_btn = gr.Button("Guess")

        wrong_guesses_left = gr.State(6)
        correct_answer = gr.State("")
        guessed_letters = gr.State([])

        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])
        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])

app.launch()