Redfire-1234 commited on
Commit
3391f7c
·
verified ·
1 Parent(s): aa8087f

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +194 -0
app.py ADDED
@@ -0,0 +1,194 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify, render_template_string
2
+ from sentence_transformers import SentenceTransformer
3
+ from transformers import AutoModelForCausalLM, AutoTokenizer
4
+ from huggingface_hub import hf_hub_download
5
+ import faiss
6
+ import pickle
7
+ import torch
8
+
9
+ app = Flask(__name__)
10
+
11
+ print("Loading models and data...")
12
+
13
+ # Download FAISS index and chunks
14
+ faiss_path = hf_hub_download(
15
+ repo_id="Redfire-1234/PCB",
16
+ filename="faiss_index.bin",
17
+ repo_type="dataset"
18
+ )
19
+ chunks_path = hf_hub_download(
20
+ repo_id="Redfire-1234/PCB",
21
+ filename="all_chunks.pkl",
22
+ repo_type="dataset"
23
+ )
24
+
25
+ # Load FAISS and chunks
26
+ index = faiss.read_index(faiss_path)
27
+ with open(chunks_path, "rb") as f:
28
+ all_chunks = pickle.load(f)
29
+
30
+ # Load models
31
+ embed_model = SentenceTransformer("all-MiniLM-L6-v2")
32
+ model_name = "Qwen/Qwen2.5-1.5B-Instruct"
33
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
34
+ device = "cuda" if torch.cuda.is_available() else "cpu"
35
+ model = AutoModelForCausalLM.from_pretrained(model_name).to(device)
36
+
37
+ print(f"All models loaded! Device: {device}")
38
+
39
+ def search(query, k=3):
40
+ q_emb = embed_model.encode([query]).astype("float32")
41
+ D, I = index.search(q_emb, k)
42
+ return "\n".join([all_chunks[i] for i in I[0]])
43
+
44
+ def generate_answer(query, context, mode="answer"):
45
+ if mode == "mcq":
46
+ prompt = f"""Generate 1 MCQ from this text:
47
+ - 4 options (A, B, C, D)
48
+ - Mark correct answer
49
+ Text: {context}
50
+ Question:"""
51
+ else:
52
+ prompt = f"""Answer based on this text:
53
+ Text: {context}
54
+ Question: {query}
55
+ Answer:"""
56
+
57
+ inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=1024).to(device)
58
+ outputs = model.generate(**inputs, max_new_tokens=200)
59
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
60
+
61
+ HTML_TEMPLATE = """
62
+ <!DOCTYPE html>
63
+ <html>
64
+ <head>
65
+ <title>Class 12 PCB AI Tutor</title>
66
+ <style>
67
+ body { font-family: Arial; max-width: 800px; margin: 50px auto; padding: 20px; background: #f5f5f5; }
68
+ .container { background: white; padding: 40px; border-radius: 15px; box-shadow: 0 5px 20px rgba(0,0,0,0.1); }
69
+ h1 { color: #6366f1; text-align: center; margin-bottom: 10px; }
70
+ p { text-align: center; color: #666; margin-bottom: 30px; }
71
+ textarea { width: 100%; padding: 15px; border: 2px solid #ddd; border-radius: 8px; font-size: 16px; margin-bottom: 15px; min-height: 100px; font-family: inherit; }
72
+ button { width: 100%; padding: 15px; background: #6366f1; color: white; border: none; border-radius: 8px; font-size: 16px; cursor: pointer; font-weight: 600; }
73
+ button:hover { background: #4f46e5; }
74
+ button:disabled { background: #ccc; cursor: not-allowed; }
75
+ .tabs { display: flex; gap: 10px; margin-bottom: 20px; }
76
+ .tab { flex: 1; padding: 12px; background: #f0f0f0; border: none; cursor: pointer; border-radius: 8px; font-weight: 600; }
77
+ .tab.active { background: #6366f1; color: white; }
78
+ .tab-content { display: none; }
79
+ .tab-content.active { display: block; }
80
+ .result { margin-top: 25px; padding: 20px; background: #f9fafb; border-radius: 8px; border-left: 4px solid #6366f1; display: none; }
81
+ .result.show { display: block; }
82
+ .result h3 { color: #6366f1; margin-bottom: 15px; }
83
+ .result .answer { background: white; padding: 15px; border-radius: 6px; line-height: 1.6; white-space: pre-wrap; }
84
+ .loading { text-align: center; margin-top: 15px; color: #666; display: none; }
85
+ .loading.show { display: block; }
86
+ </style>
87
+ </head>
88
+ <body>
89
+ <div class="container">
90
+ <h1>🎓 Class 12 PCB AI Tutor</h1>
91
+ <p>Ask questions or generate MCQs from Physics, Chemistry & Biology</p>
92
+
93
+ <div class="tabs">
94
+ <button class="tab active" onclick="switchTab('answer')">Ask Question</button>
95
+ <button class="tab" onclick="switchTab('mcq')">Generate MCQ</button>
96
+ </div>
97
+
98
+ <div id="answer-tab" class="tab-content active">
99
+ <textarea id="queryInput" placeholder="Ask any question from Class 12 PCB..."></textarea>
100
+ <button onclick="getAnswer()">Get Answer</button>
101
+ </div>
102
+
103
+ <div id="mcq-tab" class="tab-content">
104
+ <textarea id="mcqTopic" placeholder="Enter topic for MCQ generation..."></textarea>
105
+ <button onclick="generateMCQ()">Generate MCQ</button>
106
+ </div>
107
+
108
+ <div class="loading" id="loading">Processing...</div>
109
+
110
+ <div class="result" id="result">
111
+ <h3 id="resultTitle">Answer:</h3>
112
+ <div class="answer" id="answer"></div>
113
+ </div>
114
+ </div>
115
+
116
+ <script>
117
+ function switchTab(tab) {
118
+ document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
119
+ document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
120
+ event.target.classList.add('active');
121
+ document.getElementById(tab + '-tab').classList.add('active');
122
+ document.getElementById('result').classList.remove('show');
123
+ }
124
+
125
+ async function getAnswer() {
126
+ const query = document.getElementById('queryInput').value.trim();
127
+ if (!query) { alert('Please enter a question!'); return; }
128
+ await makeRequest(query, 'answer');
129
+ }
130
+
131
+ async function generateMCQ() {
132
+ const topic = document.getElementById('mcqTopic').value.trim();
133
+ if (!topic) { alert('Please enter a topic!'); return; }
134
+ await makeRequest(topic, 'mcq');
135
+ }
136
+
137
+ async function makeRequest(query, mode) {
138
+ const loading = document.getElementById('loading');
139
+ const result = document.getElementById('result');
140
+
141
+ loading.classList.add('show');
142
+ result.classList.remove('show');
143
+
144
+ try {
145
+ const response = await fetch('/query', {
146
+ method: 'POST',
147
+ headers: {'Content-Type': 'application/json'},
148
+ body: JSON.stringify({query, mode})
149
+ });
150
+
151
+ const data = await response.json();
152
+ if (data.error) { alert('Error: ' + data.error); return; }
153
+
154
+ document.getElementById('resultTitle').textContent = mode === 'mcq' ? 'Generated MCQ:' : 'Answer:';
155
+ document.getElementById('answer').textContent = data.answer;
156
+ result.classList.add('show');
157
+ } catch (error) {
158
+ alert('Error: ' + error.message);
159
+ } finally {
160
+ loading.classList.remove('show');
161
+ }
162
+ }
163
+ </script>
164
+ </body>
165
+ </html>
166
+ """
167
+
168
+ @app.route('/')
169
+ def home():
170
+ return render_template_string(HTML_TEMPLATE)
171
+
172
+ @app.route('/query', methods=['POST'])
173
+ def query():
174
+ try:
175
+ data = request.get_json()
176
+ if not data or 'query' not in data:
177
+ return jsonify({'error': 'No query provided'}), 400
178
+
179
+ query_text = data['query']
180
+ mode = data.get('mode', 'answer')
181
+
182
+ context = search(query_text, k=3)
183
+ answer = generate_answer(query_text, context, mode)
184
+
185
+ return jsonify({'query': query_text, 'answer': answer, 'mode': mode})
186
+ except Exception as e:
187
+ return jsonify({'error': str(e)}), 500
188
+
189
+ @app.route('/health')
190
+ def health():
191
+ return jsonify({'status': 'healthy'})
192
+
193
+ if __name__ == '__main__':
194
+ app.run(host='0.0.0.0', port=7860)