Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -1,28 +1,340 @@
|
|
1 |
import gradio as gr
|
2 |
-
import requests
|
3 |
import json
|
4 |
-
|
|
|
|
|
5 |
import os
|
|
|
|
|
6 |
|
7 |
-
#
|
8 |
-
|
|
|
9 |
|
10 |
-
|
11 |
-
def
|
12 |
-
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
15 |
def chat_interface(message, history):
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
# Create Gradio interface
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
iface = gr.ChatInterface(
|
22 |
fn=chat_interface,
|
23 |
-
title="RAGtim Bot -
|
24 |
-
description="
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
)
|
26 |
|
27 |
if __name__ == "__main__":
|
28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import gradio as gr
|
|
|
2 |
import json
|
3 |
+
import numpy as np
|
4 |
+
from transformers import pipeline, AutoTokenizer, AutoModel
|
5 |
+
import torch
|
6 |
import os
|
7 |
+
from typing import List, Dict, Any
|
8 |
+
import time
|
9 |
|
10 |
+
# Configure device
|
11 |
+
device = "cuda" if torch.cuda.is_available() else "cpu"
|
12 |
+
print(f"Using device: {device}")
|
13 |
|
14 |
+
class RAGtimBot:
|
15 |
+
def __init__(self):
|
16 |
+
self.embedder = None
|
17 |
+
self.knowledge_base = []
|
18 |
+
self.embeddings = []
|
19 |
+
self.initialize_models()
|
20 |
+
self.load_knowledge_base()
|
21 |
+
|
22 |
+
def initialize_models(self):
|
23 |
+
"""Initialize the embedding model"""
|
24 |
+
try:
|
25 |
+
print("Loading embedding model...")
|
26 |
+
self.embedder = pipeline(
|
27 |
+
'feature-extraction',
|
28 |
+
'sentence-transformers/all-MiniLM-L6-v2',
|
29 |
+
device=0 if device == "cuda" else -1
|
30 |
+
)
|
31 |
+
print("β
Embedding model loaded successfully")
|
32 |
+
except Exception as e:
|
33 |
+
print(f"β Error loading embedding model: {e}")
|
34 |
+
raise e
|
35 |
+
|
36 |
+
def load_knowledge_base(self):
|
37 |
+
"""Load and process the knowledge base"""
|
38 |
+
print("Loading knowledge base...")
|
39 |
+
|
40 |
+
# Comprehensive knowledge base about Raktim Mondol
|
41 |
+
self.knowledge_base = [
|
42 |
+
{
|
43 |
+
"id": "about_1",
|
44 |
+
"content": "Raktim Mondol is a PhD candidate in Computer Science & Engineering at UNSW Sydney. He is a researcher, data scientist, bioinformatician, biostatistician, LLM engineer, and father. His research focuses on deep learning-based prognosis and explainability for breast cancer. He is located at the School of Computer Science and Engineering, Building K17, UNSW Sydney, NSW 2052. Contact: [email protected], Phone: +61 412 936 237.",
|
45 |
+
"metadata": {"type": "about", "priority": 10}
|
46 |
+
},
|
47 |
+
{
|
48 |
+
"id": "education_1",
|
49 |
+
"content": "Raktim Mondol is pursuing a PhD in Computer Science & Engineering at UNSW Sydney (2021-2025 Expected). His thesis is on 'Deep Learning Based Prognosis and Explainability for Breast Cancer'. He completed his MS by Research in Computer Science & Bioinformatics at RMIT University (2017-2019) with High Distinction. His master's thesis was 'Deep learning in classifying cancer subtypes, extracting relevant genes and identifying novel mutations'.",
|
50 |
+
"metadata": {"type": "education", "priority": 9}
|
51 |
+
},
|
52 |
+
{
|
53 |
+
"id": "research_llm",
|
54 |
+
"content": "Raktim's research focuses on Large Language Models (LLMs) including training, fine-tuning, and evaluating LLMs using parameter-efficient techniques like LoRA and QLoRA, with applications in retrieval-augmented generation, summarisation, and multi-hop reasoning. He works on Agentic AI & Multi-Agent Systems, designing autonomous, tool-using agents for reasoning, planning, and collaboration using frameworks like the Agent Development Kit.",
|
55 |
+
"metadata": {"type": "research", "priority": 9}
|
56 |
+
},
|
57 |
+
{
|
58 |
+
"id": "research_rag",
|
59 |
+
"content": "His expertise includes Retrieval-Augmented Generation (RAG), building hybrid search and generation pipelines integrating semantic and keyword-based retrieval using technologies like FAISS, BM25, ChromaDB, Weaviate, and Milvus for vector search and retrieval systems.",
|
60 |
+
"metadata": {"type": "research", "priority": 9}
|
61 |
+
},
|
62 |
+
{
|
63 |
+
"id": "skills_ai",
|
64 |
+
"content": "Raktim has expertise in Generative AI & LLM Toolkits including Hugging Face Transformers, LoRA/QLoRA (PEFT), LangChain, OpenAI API/Gemini Pro, GPTQ/GGUF, Prompt Engineering, Agent Development Kit, and RAG Pipelines. He is skilled in Multimodal & CV + NLP including CLIP/BLIP/LLaVA, Segment Anything (SAM), Visual Question Answering, and Multimodal Transformers.",
|
65 |
+
"metadata": {"type": "skills", "priority": 7}
|
66 |
+
},
|
67 |
+
{
|
68 |
+
"id": "skills_programming",
|
69 |
+
"content": "Programming languages: Python, R, SQL, LaTeX. Deep Learning Frameworks: PyTorch, TensorFlow. Cloud Computing: AWS, GCP, Galaxy. Development tools: Git, Jupyter Notebook, RStudio, Spyder. Statistical Analysis: Stata, SPSS, SAS, NCSS.",
|
70 |
+
"metadata": {"type": "skills", "priority": 7}
|
71 |
+
},
|
72 |
+
{
|
73 |
+
"id": "experience_current",
|
74 |
+
"content": "Raktim Mondol has been working as a Casual Academic at UNSW since July 2021, conducting laboratory and tutorial classes for Computer Vision, Neural Networks and Deep Learning, and Artificial Intelligence courses. He provides guidance to students and assists in course material development.",
|
75 |
+
"metadata": {"type": "experience", "priority": 8}
|
76 |
+
},
|
77 |
+
{
|
78 |
+
"id": "experience_rmit",
|
79 |
+
"content": "Previously, he was a Teaching Assistant at RMIT University (July 2017 - Oct 2019), conducting laboratory classes for Electronics, Software Engineering Design, Engineering Computing, and Introduction to Embedded Systems.",
|
80 |
+
"metadata": {"type": "experience", "priority": 8}
|
81 |
+
},
|
82 |
+
{
|
83 |
+
"id": "experience_lecturer",
|
84 |
+
"content": "He worked as a full-time Lecturer at World University of Bangladesh (Sep 2013 - Dec 2016), teaching Electrical Circuit I & II, Engineering Materials, Electronics I & II, Digital Logic Design, and supervising student projects and thesis.",
|
85 |
+
"metadata": {"type": "experience", "priority": 8}
|
86 |
+
},
|
87 |
+
{
|
88 |
+
"id": "publication_biofusion",
|
89 |
+
"content": "BioFusionNet: Deep Learning-Based Survival Risk Stratification in ER+ Breast Cancer Through Multifeature and Multimodal Data Fusion published in IEEE Journal of Biomedical and Health Informatics (2024). This work demonstrates novel multimodal fusion architecture combining histopathology, genomics, and clinical data with attention-based feature selection for interpretability.",
|
90 |
+
"metadata": {"type": "publications", "priority": 8}
|
91 |
+
},
|
92 |
+
{
|
93 |
+
"id": "publication_hist2rna",
|
94 |
+
"content": "hist2RNA: An Efficient Deep Learning Architecture to Predict Gene Expression from Breast Cancer Histopathology Images published in Cancers journal (2023). This enables gene expression profiling without expensive molecular assays, making personalized medicine more accessible.",
|
95 |
+
"metadata": {"type": "publications", "priority": 8}
|
96 |
+
},
|
97 |
+
{
|
98 |
+
"id": "publication_afexnet",
|
99 |
+
"content": "AFExNet: An Adversarial Autoencoder for Differentiating Breast Cancer Sub-types and Extracting Biologically Relevant Genes published in IEEE/ACM Transactions on Computational Biology and Bioinformatics (2021). Provides insights into cancer biology while achieving high classification accuracy.",
|
100 |
+
"metadata": {"type": "publications", "priority": 8}
|
101 |
+
},
|
102 |
+
{
|
103 |
+
"id": "statistics_expertise",
|
104 |
+
"content": "Raktim demonstrates exceptional proficiency in advanced statistical methods including survival analysis with weighted Cox proportional hazards models, multivariate regression analysis, hypothesis testing, correlation analysis with multiple-testing control, and comprehensive biostatistical applications. His BioFusionNet work achieved mean concordance index of 0.77 and time-dependent AUC of 0.84.",
|
105 |
+
"metadata": {"type": "statistics", "priority": 9}
|
106 |
+
},
|
107 |
+
{
|
108 |
+
"id": "awards",
|
109 |
+
"content": "Awards include: Doctoral Research Scholarship from UNSW Sydney (2021), Masters by Research with High Distinction from RMIT University (2019), RMIT Research Scholarships (2017), B.Sc. with High Distinction from BRAC University (2013), Vice Chancellor Award from BRAC University (2013), and Dean Awards (2010-2011).",
|
110 |
+
"metadata": {"type": "awards", "priority": 6}
|
111 |
+
}
|
112 |
+
]
|
113 |
+
|
114 |
+
# Generate embeddings for knowledge base
|
115 |
+
print("Generating embeddings for knowledge base...")
|
116 |
+
self.embeddings = []
|
117 |
+
for doc in self.knowledge_base:
|
118 |
+
try:
|
119 |
+
embedding = self.embedder(doc["content"], return_tensors="pt")
|
120 |
+
# Convert to numpy and flatten
|
121 |
+
embedding_np = embedding[0].mean(dim=0).detach().cpu().numpy()
|
122 |
+
self.embeddings.append(embedding_np)
|
123 |
+
except Exception as e:
|
124 |
+
print(f"Error generating embedding for doc {doc['id']}: {e}")
|
125 |
+
# Fallback to zero embedding
|
126 |
+
self.embeddings.append(np.zeros(384))
|
127 |
+
|
128 |
+
print(f"β
Knowledge base loaded with {len(self.knowledge_base)} documents")
|
129 |
+
|
130 |
+
def cosine_similarity(self, a, b):
|
131 |
+
"""Calculate cosine similarity between two vectors"""
|
132 |
+
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
|
133 |
+
|
134 |
+
def search_knowledge_base(self, query: str, top_k: int = 5) -> List[Dict]:
|
135 |
+
"""Search the knowledge base using semantic similarity"""
|
136 |
+
try:
|
137 |
+
# Generate query embedding
|
138 |
+
query_embedding = self.embedder(query, return_tensors="pt")
|
139 |
+
query_vector = query_embedding[0].mean(dim=0).detach().cpu().numpy()
|
140 |
+
|
141 |
+
# Calculate similarities
|
142 |
+
similarities = []
|
143 |
+
for i, doc_embedding in enumerate(self.embeddings):
|
144 |
+
similarity = self.cosine_similarity(query_vector, doc_embedding)
|
145 |
+
similarities.append({
|
146 |
+
"id": self.knowledge_base[i]["id"],
|
147 |
+
"content": self.knowledge_base[i]["content"],
|
148 |
+
"metadata": self.knowledge_base[i]["metadata"],
|
149 |
+
"score": float(similarity),
|
150 |
+
"index": i
|
151 |
+
})
|
152 |
+
|
153 |
+
# Sort by similarity and return top_k
|
154 |
+
similarities.sort(key=lambda x: x["score"], reverse=True)
|
155 |
+
return similarities[:top_k]
|
156 |
+
|
157 |
+
except Exception as e:
|
158 |
+
print(f"Error in search: {e}")
|
159 |
+
# Fallback to keyword search
|
160 |
+
return self.keyword_search(query, top_k)
|
161 |
+
|
162 |
+
def keyword_search(self, query: str, top_k: int = 5) -> List[Dict]:
|
163 |
+
"""Fallback keyword search"""
|
164 |
+
query_terms = query.lower().split()
|
165 |
+
results = []
|
166 |
+
|
167 |
+
for i, doc in enumerate(self.knowledge_base):
|
168 |
+
content_lower = doc["content"].lower()
|
169 |
+
score = sum(content_lower.count(term) for term in query_terms)
|
170 |
+
|
171 |
+
if score > 0:
|
172 |
+
results.append({
|
173 |
+
"id": doc["id"],
|
174 |
+
"content": doc["content"],
|
175 |
+
"metadata": doc["metadata"],
|
176 |
+
"score": score,
|
177 |
+
"index": i
|
178 |
+
})
|
179 |
+
|
180 |
+
results.sort(key=lambda x: x["score"], reverse=True)
|
181 |
+
return results[:top_k]
|
182 |
+
|
183 |
+
# Initialize the bot
|
184 |
+
print("Initializing RAGtim Bot...")
|
185 |
+
bot = RAGtimBot()
|
186 |
+
|
187 |
+
def search_only_api(query, top_k=5):
|
188 |
+
"""API endpoint for search-only functionality"""
|
189 |
+
try:
|
190 |
+
results = bot.search_knowledge_base(query, top_k)
|
191 |
+
return {
|
192 |
+
"results": results,
|
193 |
+
"query": query,
|
194 |
+
"top_k": top_k,
|
195 |
+
"search_type": "semantic"
|
196 |
+
}
|
197 |
+
except Exception as e:
|
198 |
+
print(f"Error in search API: {e}")
|
199 |
+
return {"error": str(e), "results": []}
|
200 |
+
|
201 |
+
def get_stats_api():
|
202 |
+
"""API endpoint for knowledge base statistics"""
|
203 |
+
return {
|
204 |
+
"total_documents": len(bot.knowledge_base),
|
205 |
+
"model_name": "sentence-transformers/all-MiniLM-L6-v2",
|
206 |
+
"embedding_dimension": 384,
|
207 |
+
"search_capabilities": ["Semantic Search", "GPU Accelerated", "Transformer Embeddings"],
|
208 |
+
"backend_type": "Hugging Face Space"
|
209 |
+
}
|
210 |
|
211 |
def chat_interface(message, history):
|
212 |
+
"""Main chat interface function - now just for demo purposes"""
|
213 |
+
if not message.strip():
|
214 |
+
return "Please ask me something about Raktim Mondol!"
|
215 |
+
|
216 |
+
try:
|
217 |
+
# Search knowledge base
|
218 |
+
search_results = bot.search_knowledge_base(message, top_k=5)
|
219 |
+
|
220 |
+
# Simple response for demo (in hybrid mode, DeepSeek will handle this)
|
221 |
+
if search_results:
|
222 |
+
best_match = search_results[0]
|
223 |
+
return f"Based on the search results (similarity: {best_match['score']:.2f}):\n\n{best_match['content']}\n\n[Note: In hybrid mode, DeepSeek LLM will generate more natural responses using this context]"
|
224 |
+
else:
|
225 |
+
return "I don't have specific information about that topic. Could you please ask something else about Raktim Mondol?"
|
226 |
+
|
227 |
+
except Exception as e:
|
228 |
+
print(f"Error in chat interface: {e}")
|
229 |
+
return "I'm sorry, I encountered an error while processing your question. Please try again."
|
230 |
|
231 |
# Create Gradio interface
|
232 |
+
print("Creating Gradio interface...")
|
233 |
+
|
234 |
+
# Custom CSS for better styling
|
235 |
+
css = """
|
236 |
+
.gradio-container {
|
237 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
238 |
+
}
|
239 |
+
.chat-message {
|
240 |
+
padding: 10px;
|
241 |
+
margin: 5px 0;
|
242 |
+
border-radius: 10px;
|
243 |
+
}
|
244 |
+
"""
|
245 |
+
|
246 |
+
# Create the main chat interface
|
247 |
iface = gr.ChatInterface(
|
248 |
fn=chat_interface,
|
249 |
+
title="π€ RAGtim Bot - Hybrid Search Engine",
|
250 |
+
description="""
|
251 |
+
**Hybrid RAG System**: This Hugging Face Space provides GPU-accelerated semantic search that can be combined with external LLMs like DeepSeek for response generation.
|
252 |
+
|
253 |
+
**Search Capabilities:**
|
254 |
+
- π Semantic similarity search using transformers
|
255 |
+
- π GPU-accelerated embeddings
|
256 |
+
- π Relevance scoring and ranking
|
257 |
+
- π― Context-aware retrieval
|
258 |
+
|
259 |
+
**API Endpoints:**
|
260 |
+
- `/api/search` - Search-only functionality
|
261 |
+
- `/api/stats` - Knowledge base statistics
|
262 |
+
|
263 |
+
**Ask me about Raktim Mondol:**
|
264 |
+
- π¬ Research in LLMs, RAG, and AI for healthcare
|
265 |
+
- π Publications and academic work
|
266 |
+
- π» Technical skills and programming expertise
|
267 |
+
- π Education and academic background
|
268 |
+
- π¨βπ« Teaching and professional experience
|
269 |
+
- π Statistical methods and biostatistics
|
270 |
+
|
271 |
+
**Note**: This demo shows search results. In hybrid mode, these results are passed to DeepSeek LLM for natural response generation.
|
272 |
+
""",
|
273 |
+
examples=[
|
274 |
+
"What is Raktim's research about?",
|
275 |
+
"Tell me about his publications",
|
276 |
+
"What programming languages does he know?",
|
277 |
+
"What is his educational background?",
|
278 |
+
"How can I contact Raktim?",
|
279 |
+
"What is BioFusionNet?",
|
280 |
+
"Tell me about his LLM research",
|
281 |
+
"What statistical methods does he use?"
|
282 |
+
],
|
283 |
+
css=css,
|
284 |
+
theme=gr.themes.Soft(
|
285 |
+
primary_hue="green",
|
286 |
+
secondary_hue="blue",
|
287 |
+
neutral_hue="slate"
|
288 |
+
),
|
289 |
+
chatbot=gr.Chatbot(
|
290 |
+
height=500,
|
291 |
+
show_label=False,
|
292 |
+
container=True,
|
293 |
+
bubble_full_width=False
|
294 |
+
),
|
295 |
+
textbox=gr.Textbox(
|
296 |
+
placeholder="Ask me anything about Raktim Mondol...",
|
297 |
+
container=False,
|
298 |
+
scale=7
|
299 |
+
),
|
300 |
+
submit_btn="Search",
|
301 |
+
retry_btn="π Retry",
|
302 |
+
undo_btn="β©οΈ Undo",
|
303 |
+
clear_btn="ποΈ Clear"
|
304 |
+
)
|
305 |
+
|
306 |
+
# Create API interface for search-only functionality
|
307 |
+
search_api = gr.Interface(
|
308 |
+
fn=search_only_api,
|
309 |
+
inputs=[
|
310 |
+
gr.Textbox(label="Search Query", placeholder="Enter your search query..."),
|
311 |
+
gr.Slider(minimum=1, maximum=10, value=5, step=1, label="Top K Results")
|
312 |
+
],
|
313 |
+
outputs=gr.JSON(label="Search Results"),
|
314 |
+
title="π Search API",
|
315 |
+
description="Direct access to the semantic search functionality"
|
316 |
+
)
|
317 |
+
|
318 |
+
stats_api = gr.Interface(
|
319 |
+
fn=get_stats_api,
|
320 |
+
inputs=[],
|
321 |
+
outputs=gr.JSON(label="Knowledge Base Statistics"),
|
322 |
+
title="π Stats API",
|
323 |
+
description="Knowledge base statistics and capabilities"
|
324 |
+
)
|
325 |
+
|
326 |
+
# Combine interfaces
|
327 |
+
demo = gr.TabbedInterface(
|
328 |
+
[iface, search_api, stats_api],
|
329 |
+
["π¬ Chat Demo", "π Search API", "π Stats API"],
|
330 |
+
title="π€ RAGtim Bot - Hybrid Search System"
|
331 |
)
|
332 |
|
333 |
if __name__ == "__main__":
|
334 |
+
print("π Launching RAGtim Bot Hybrid Search System...")
|
335 |
+
demo.launch(
|
336 |
+
server_name="0.0.0.0",
|
337 |
+
server_port=7860,
|
338 |
+
share=False,
|
339 |
+
show_error=True
|
340 |
+
)
|