1rahu commited on
Commit
044e4c7
Β·
verified Β·
1 Parent(s): 8f14735

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +399 -0
  2. requirements.txt +2 -0
app.py ADDED
@@ -0,0 +1,399 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ CarmelGPT β€” Hugging Face Spaces deployment
3
+ Carmel Convent Senior Secondary School, Ujjain
4
+
5
+ HOW TO UPDATE β€” HF Space β†’ Files β†’ app.py β†’ pencil icon:
6
+ β€’ Add facts to CUSTOM_QA (Section 2)
7
+ β€’ Add facts to SCHOOL_FACTS string (Section 3) so Qwen knows them too
8
+ """
9
+
10
+ import re
11
+ import difflib
12
+ import gradio as gr
13
+
14
+ # ─────────────────────────────────────────────────────────────────────────────
15
+ # SECTION 1 β€” BUILT-IN Q&A (short keys β†’ reliable matching)
16
+ # Rule: keys have 1-3 important words only. ANY key word found = strong match.
17
+ # ─────────────────────────────────────────────────────────────────────────────
18
+
19
+ BUILTIN_QA = {
20
+ "principal":
21
+ "The principal of Carmel Convent School, Ujjain is **Dr. Sr. Kripa Maria, PhD**. "
22
+ "She took charge on June 10, 2023.",
23
+
24
+ "school name":
25
+ "The full name is **Carmel Convent Senior Secondary School, Ujjain**.",
26
+
27
+ "address location":
28
+ "**Address:** Agar Road, Chak Kamed, Ujjain, Madhya Pradesh - 456001. \n"
29
+ "πŸ“ž 8871850918 | πŸ“§ carmelkamedujn@yahoo.com | 🌐 www.carmelujjain.com",
30
+
31
+ "phone contact mobile":
32
+ "The phone number is **8871850918**.",
33
+
34
+ "email mail":
35
+ "The email address is **carmelkamedujn@yahoo.com**.",
36
+
37
+ "website online":
38
+ "The official website is **www.carmelujjain.com**.",
39
+
40
+ "cbse board affiliated":
41
+ "Carmel Convent School is affiliated to **CBSE** (Central Board of Secondary Education), "
42
+ "New Delhi, since February 2007. Affiliation number: **1030281**.",
43
+
44
+ "affiliation number":
45
+ "The CBSE affiliation number is **1030281**.",
46
+
47
+ "established founded year":
48
+ "Carmel Convent School, Ujjain was **established in 1997** by the Sisters of the "
49
+ "Congregation of Mother of Carmel (C.M.C.). CBSE affiliation: February 2007.",
50
+
51
+ "cmc congregation sisters":
52
+ "**CMC** = Congregation of Mother of Carmel β€” an indigenous religious congregation. "
53
+ "CMC entered Madhya Pradesh in 1968. The Mount Carmel Province was established in 1997.",
54
+
55
+ "managed management society":
56
+ "Managed by the **Mount Carmel Education Society**, run by the CMC sisters.",
57
+
58
+ "vision mission goal":
59
+ "The vision is the **all-round development** of every learner β€” academically, socially, "
60
+ "culturally, physically, and psychologically.",
61
+
62
+ "classes nursery grades":
63
+ "Classes from **Nursery (age 3+) to Class 12**. Nursery/KG I entry: 60 seats.",
64
+
65
+ "streams science commerce":
66
+ "Classes 11–12 offer four streams: \n"
67
+ "β€’ Science PCM (Physics, Chemistry, Mathematics) \n"
68
+ "β€’ Science PCB (Physics, Chemistry, Biology) \n"
69
+ "β€’ Commerce \n"
70
+ "β€’ Arts",
71
+
72
+ "medium language english":
73
+ "The medium of instruction is **English**.",
74
+
75
+ "classrooms rooms":
76
+ "**61 air-conditioned smart classrooms** with digital boards.",
77
+
78
+ "teachers staff faculty":
79
+ "**64 staff members**: 36 PRTs, 15 TGTs, 11 PGTs, 2 non-teaching.",
80
+
81
+ "campus area size":
82
+ "The campus spans **11,412 square metres**.",
83
+
84
+ "facilities infrastructure":
85
+ "Facilities: library, **6 computer labs**, science lab, auditorium, activity room, "
86
+ "smart classrooms, Wi-Fi, medical centre, transport, NCC, Scouts & Guides, "
87
+ "indoor and outdoor sports, AC classrooms.",
88
+
89
+ "computer labs laboratory":
90
+ "Yes β€” **6 computer labs**.",
91
+
92
+ "library books":
93
+ "Yes β€” Carmel Convent School has a **library**.",
94
+
95
+ "wifi internet":
96
+ "Yes β€” **Wi-Fi** connectivity across the campus.",
97
+
98
+ "transport bus":
99
+ "Yes β€” **transport services** are available for students.",
100
+
101
+ "coeducational boys girls":
102
+ "Yes β€” **co-educational**, welcoming both boys and girls.",
103
+
104
+ "admission apply enroll":
105
+ "**Admission process:** \n"
106
+ "1. Register online at carmelujjain.com/registration2025-26 \n"
107
+ "2. Print and submit with: birth certificate, 5 passport photos, "
108
+ "Aadhar cards of both parents and student. \n"
109
+ "Minimum age for Nursery: **3 years**.",
110
+
111
+ "documents required admission":
112
+ "Documents for admission: birth certificate, 5 passport photos, "
113
+ "filled form, Aadhar cards of parents and student.",
114
+
115
+ "minimum age nursery":
116
+ "Minimum age for Nursery: **3 years**.",
117
+
118
+ "activities ncc sports extracurricular":
119
+ "Activities: NCC, Scouts & Guides, sports, yoga, debates, drama, music, "
120
+ "science exhibitions, cooking classes, cultural programs.",
121
+
122
+ "fees cost charges":
123
+ "For fee details, contact: πŸ“ž **8871850918** or visit **www.carmelujjain.com**.",
124
+ }
125
+
126
+ # ─────────────────────────────────────────────────────────────────────────────
127
+ # SECTION 2 β€” YOUR CUSTOM Q&A (add new pairs here anytime)
128
+ # ─────────────────────────────────────────────────────────────────────────────
129
+
130
+ CUSTOM_QA = {
131
+ # Format: "keyword1 keyword2": "Answer text",
132
+ # EXAMPLES (remove # to activate):
133
+ # "commerce rini faculty": "The Commerce faculty includes **Sr. Rini Maria**.",
134
+ # "robotics teacher": "Our Robotics teachers include Ritu Ma'am and others.",
135
+ # "founder chavara cmc": "CMC was founded by Blessed Chavara Kuriakose Elias.",
136
+ }
137
+
138
+ # ─────────────────────────────────────────────────────────────────────────────
139
+ # SECTION 3 β€” FACTS FOR QWEN (Qwen reads this as its knowledge base)
140
+ # Update this whenever you add new custom facts above.
141
+ # ─────────────────────────────────────────────────────────────────────────────
142
+
143
+ SCHOOL_FACTS = """
144
+ CARMEL CONVENT SENIOR SECONDARY SCHOOL, UJJAIN β€” VERIFIED FACTS
145
+
146
+ - Full name: Carmel Convent Senior Secondary School, Ujjain
147
+ - Principal: Dr. Sr. Kripa Maria, PhD (joined June 10, 2023)
148
+ - Address: Agar Road, Chak Kamed, Ujjain, Madhya Pradesh - 456001
149
+ - Phone: 8871850918 | Email: carmelkamedujn@yahoo.com | Website: www.carmelujjain.com
150
+ - Board: CBSE, affiliated since February 2007, affiliation number 1030281
151
+ - Established: 1997 by Sisters of the Congregation of Mother of Carmel (CMC)
152
+ - Managed by: Mount Carmel Education Society
153
+ - Type: Co-educational, English medium, CBSE Day School
154
+ - Classes: Nursery (age 3+) to Class 12
155
+ - Class 11-12 streams: Science PCM, Science PCB, Commerce, Arts
156
+ - Campus: 11,412 sq metres, 61 air-conditioned smart classrooms
157
+ - Staff: 64 total (36 PRTs, 15 TGTs, 11 PGTs, 2 non-teaching)
158
+ - Facilities: 6 computer labs, 1 science lab, library, auditorium, Wi-Fi, transport
159
+ - Activities: NCC, Scouts & Guides, sports, yoga, debates, drama, music, cultural programs
160
+ - Admission: Register at carmelujjain.com; minimum age 3 years for Nursery
161
+ - Admission documents: birth certificate, 5 photos, filled form, Aadhar cards of parents+student
162
+ """
163
+
164
+ CUSTOM_FACTS = "" # Add custom facts here as bullet points if needed
165
+
166
+ ALL_FACTS = SCHOOL_FACTS + CUSTOM_FACTS
167
+
168
+ # ─────────────────────────────────────────────────────────────────────────────
169
+ # SECTION 4 β€” TYPO CORRECTION (do not edit)
170
+ # ─────────────────────────────────────────────────────────────────────────────
171
+
172
+ CORRECTIONS = {
173
+ "principle": "principal", "prinicpal": "principal",
174
+ "princpal": "principal", "principel": "principal",
175
+ "admision": "admission", "admmission": "admission",
176
+ "facilites": "facilities", "facilty": "facility",
177
+ "afiliation": "affiliation", "affilitation":"affiliation",
178
+ "establised": "established", "transprt": "transport",
179
+ "tranport": "transport", "scince": "science",
180
+ "commerse": "commerce", "streems": "streams",
181
+ "clases": "classes", "ujain": "ujjain",
182
+ "karmel": "carmel", "carmell": "carmel",
183
+ "whos": "who", "whats": "what",
184
+ "hows": "how", "wheres": "where",
185
+ }
186
+
187
+ KNOWN_WORDS = [
188
+ "principal", "admission", "facilities", "affiliation", "established",
189
+ "transport", "science", "commerce", "streams", "classes", "ujjain",
190
+ "carmel", "cbse", "board", "campus", "library", "laboratory",
191
+ "teacher", "faculty", "staff", "nursery", "website", "contact",
192
+ "phone", "email", "fees", "activities", "ncc", "medium", "english",
193
+ "classrooms", "auditorium", "wifi", "internet", "management",
194
+ ]
195
+
196
+ def correct_typos(text: str):
197
+ words = text.lower().split()
198
+ corrected, corrections_made = [], []
199
+ for word in words:
200
+ clean = re.sub(r"[^\w]", "", word)
201
+ if clean in CORRECTIONS:
202
+ fix = CORRECTIONS[clean]
203
+ corrected.append(fix)
204
+ if fix != clean:
205
+ corrections_made.append((clean, fix))
206
+ elif len(clean) > 4:
207
+ matches = difflib.get_close_matches(clean, KNOWN_WORDS, n=1, cutoff=0.82)
208
+ if matches and matches[0] != clean:
209
+ corrected.append(matches[0])
210
+ corrections_made.append((clean, matches[0]))
211
+ else:
212
+ corrected.append(clean)
213
+ else:
214
+ corrected.append(clean)
215
+ return " ".join(corrected), corrections_made
216
+
217
+ # ─────────────────────────────────────────────────────────────────────────────
218
+ # SECTION 5 β€” MATCHING ENGINE (do not edit)
219
+ # ─────────────────────────────────────────────────────────────────────────────
220
+
221
+ ALL_QA = {**BUILTIN_QA, **CUSTOM_QA}
222
+
223
+ # Words that mean the question IS about this school
224
+ SCHOOL_SIGNALS = {
225
+ "school", "carmel", "principal", "admission", "teacher", "faculty",
226
+ "class", "stream", "science", "commerce", "cbse", "board", "campus",
227
+ "library", "transport", "ncc", "ujjain", "cmc", "fees", "address",
228
+ "staff", "nursery", "facilities", "established", "founded", "vision",
229
+ "website", "email", "phone", "contact", "classrooms", "head",
230
+ "headmistress", "director", "kripa", "medium", "wifi", "auditorium",
231
+ "affiliation", "congregation", "sisters", "activities", "uniform",
232
+ }
233
+
234
+ def _score(stored_keywords: str, user_q: str) -> float:
235
+ """
236
+ Short-key scoring:
237
+ - Extract key words (len > 3) from stored key
238
+ - ANY long word match (len > 6) = strong signal β†’ score 0.9
239
+ - Fraction of key words found for shorter words
240
+ """
241
+ keywords = [w for w in stored_keywords.split() if len(w) > 3]
242
+ if not keywords:
243
+ return 0.0
244
+ matched = [w for w in keywords if w in user_q]
245
+ if not matched:
246
+ return 0.0
247
+ # Long specific word matched β†’ very strong signal
248
+ if any(len(w) > 6 for w in matched):
249
+ return 0.9
250
+ # Short word matched β†’ score by fraction
251
+ return len(matched) / len(keywords)
252
+
253
+ def direct_lookup(q: str):
254
+ best_score, best_answer = 0.0, None
255
+ for stored_keywords, answer in ALL_QA.items():
256
+ s = _score(stored_keywords, q)
257
+ if s > best_score:
258
+ best_score, best_answer = s, answer
259
+ return best_answer, best_score
260
+
261
+ def is_school_question(q: str) -> bool:
262
+ return bool(set(q.split()) & SCHOOL_SIGNALS)
263
+
264
+ # ─────────────────────────────────────────────────────────────────────────────
265
+ # SECTION 6 β€” QWEN FALLBACK (handles unusual phrasings)
266
+ # ─────────────────────────────────────────────────────────────────────────────
267
+
268
+ try:
269
+ from huggingface_hub import InferenceClient
270
+ _client = InferenceClient("Qwen/Qwen2.5-1.5B-Instruct")
271
+ QWEN_AVAILABLE = True
272
+ except Exception:
273
+ QWEN_AVAILABLE = False
274
+
275
+ QWEN_SYSTEM = f"""You are CarmelGPT β€” a chatbot ONLY for Carmel Convent Senior Secondary School, Ujjain, India.
276
+
277
+ RULES (never break):
278
+ 1. Answer ONLY using the SCHOOL FACTS below. Never invent names, numbers, or details.
279
+ 2. If not in SCHOOL FACTS, say exactly: "I don't have that information. Contact: 8871850918"
280
+ 3. If asked about anything unrelated to this school, say exactly: "I can only answer questions about Carmel Convent Senior Secondary School, Ujjain."
281
+ 4. Keep answers short and factual.
282
+
283
+ SCHOOL FACTS:
284
+ {ALL_FACTS}"""
285
+
286
+ def ask_qwen(question: str):
287
+ if not QWEN_AVAILABLE:
288
+ return None
289
+ try:
290
+ r = _client.chat_completion(
291
+ messages=[
292
+ {"role": "system", "content": QWEN_SYSTEM},
293
+ {"role": "user", "content": question},
294
+ ],
295
+ max_tokens=250,
296
+ temperature=0.1,
297
+ )
298
+ return r.choices[0].message.content.strip()
299
+ except Exception:
300
+ return None
301
+
302
+ # ─────────────────────────────────────────────────────────────────────────────
303
+ # SECTION 7 β€” CHAT FUNCTION (do not edit)
304
+ # ─────────────────────────────────────────────────────────────────────────────
305
+
306
+ OUT_OF_SCOPE = (
307
+ "Sorry, I can only answer questions about "
308
+ "**Carmel Convent Senior Secondary School, Ujjain**. \n"
309
+ "Please ask about admissions, facilities, faculty, streams, or other school topics."
310
+ )
311
+
312
+ NO_INFO = (
313
+ "I don't have that specific information right now. \n"
314
+ "Please contact the school: \n"
315
+ "πŸ“ž **8871850918** | πŸ“§ carmelkamedujn@yahoo.com | 🌐 www.carmelujjain.com"
316
+ )
317
+
318
+ def chat(message: str, history) -> str:
319
+ if not message.strip():
320
+ return ""
321
+
322
+ # Step 1 β€” Typo correction
323
+ corrected_q, corrections = correct_typos(message)
324
+ note = ""
325
+ if corrections:
326
+ fixes = ", ".join(f'"{a}" β†’ "{b}"' for a, b in corrections)
327
+ note = f"*(Correcting spelling: {fixes})* \n\n"
328
+
329
+ # Step 2 β€” Direct lookup (fast, 100% accurate)
330
+ answer, score = direct_lookup(corrected_q)
331
+ if score >= 0.3:
332
+ return note + answer
333
+
334
+ # Step 3 β€” Scope check
335
+ if not is_school_question(corrected_q):
336
+ return OUT_OF_SCOPE
337
+
338
+ # Step 4 β€” Qwen with guardrails (handles unusual phrasings)
339
+ qwen_ans = ask_qwen(message)
340
+ if qwen_ans:
341
+ return note + qwen_ans
342
+
343
+ # Step 5 β€” Fallback
344
+ return note + NO_INFO
345
+
346
+ # ─────────────────────────────────────────────────────────────────────────────
347
+ # SECTION 8 β€” UI
348
+ # ─────────────────────────────────────────────────────────────────────────────
349
+
350
+ EXAMPLES = [
351
+ "Who is the principal?",
352
+ "Whos is the principle?",
353
+ "Do you have a principal?",
354
+ "What is the name of your principal?",
355
+ "Don't you have a principal?",
356
+ "What streams are available in Class 11?",
357
+ "How do I get admission?",
358
+ "What is the CBSE affiliation number?",
359
+ "Does the school have NCC?",
360
+ "Who is the President of India?",
361
+ ]
362
+
363
+ with gr.Blocks(title="CarmelGPT") as demo:
364
+ gr.Markdown("# CarmelGPT")
365
+ gr.Markdown(
366
+ "**Carmel Convent Senior Secondary School, Ujjain** \n"
367
+ "Ask me anything about the school."
368
+ )
369
+ with gr.Row():
370
+ with gr.Column(scale=3):
371
+ chatbot = gr.Chatbot(height=460, label="CarmelGPT")
372
+ msg = gr.Textbox(
373
+ placeholder="Ask about admissions, principal, facilities...",
374
+ label="Your question", lines=1)
375
+ with gr.Row():
376
+ send_btn = gr.Button("Ask", variant="primary")
377
+ clear_btn = gr.Button("Clear")
378
+ with gr.Column(scale=1):
379
+ gr.Markdown("### Try these")
380
+ for q in EXAMPLES:
381
+ gr.Button(q, size="sm").click(lambda x=q: x, outputs=msg)
382
+ gr.Markdown("---")
383
+ gr.Markdown(
384
+ "**Contact** \nπŸ“ž 8871850918 \n"
385
+ "πŸ“§ carmelkamedujn@yahoo.com \n"
386
+ "🌐 [carmelujjain.com](http://www.carmelujjain.com)")
387
+
388
+ def submit(m, h):
389
+ if not m.strip():
390
+ return h, ""
391
+ reply = chat(m, h)
392
+ return h + [{"role": "user", "content": m},
393
+ {"role": "assistant", "content": reply}], ""
394
+
395
+ send_btn.click(submit, [msg, chatbot], [chatbot, msg])
396
+ msg.submit(submit, [msg, chatbot], [chatbot, msg])
397
+ clear_btn.click(lambda: ([], ""), outputs=[chatbot, msg])
398
+
399
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ gradio
2
+ huggingface_hub