Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -11,6 +11,9 @@ import numpy as np
|
|
11 |
from PIL import Image
|
12 |
from transformers import AutoProcessor, VisionEncoderDecoderModel, Gemma3nForConditionalGeneration, pipeline
|
13 |
import torch
|
|
|
|
|
|
|
14 |
import os
|
15 |
import tempfile
|
16 |
import uuid
|
@@ -312,6 +315,15 @@ except Exception as e:
|
|
312 |
dolphin_model = None
|
313 |
model_status = f"β Model failed to load: {str(e)}"
|
314 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
315 |
# Initialize chatbot model
|
316 |
try:
|
317 |
import os
|
@@ -350,12 +362,57 @@ except Exception as e:
|
|
350 |
# Global state for managing tabs
|
351 |
processed_markdown = ""
|
352 |
show_results_tab = False
|
|
|
|
|
|
|
353 |
# chatbot_model is initialized above
|
354 |
|
355 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
356 |
def process_uploaded_pdf(pdf_file, progress=gr.Progress()):
|
357 |
"""Main processing function for uploaded PDF"""
|
358 |
-
global processed_markdown, show_results_tab
|
359 |
|
360 |
if dolphin_model is None:
|
361 |
return "β Model not loaded", gr.Tabs(visible=False)
|
@@ -368,6 +425,13 @@ def process_uploaded_pdf(pdf_file, progress=gr.Progress()):
|
|
368 |
|
369 |
if status == "processing_complete":
|
370 |
processed_markdown = combined_markdown
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
371 |
show_results_tab = True
|
372 |
return "β
PDF processed successfully! Check the 'Document' tab above.", gr.Tabs(visible=True)
|
373 |
else:
|
@@ -446,11 +510,13 @@ with gr.Blocks(
|
|
446 |
# Home Tab
|
447 |
with gr.TabItem("π Home", id="home"):
|
448 |
chatbot_status = "β
Chatbot ready" if chatbot_model else "β Chatbot not loaded"
|
|
|
449 |
gr.Markdown(
|
450 |
"# Scholar Express\n"
|
451 |
"### Upload a research paper to get a web-friendly version, an AI chatbot, and a podcast summary. Because of our reliance on Generative AI, some errors are inevitable.\n"
|
452 |
f"**PDF Processing:** {model_status}\n"
|
453 |
-
f"**Chatbot:** {chatbot_status}"
|
|
|
454 |
)
|
455 |
|
456 |
with gr.Column(elem_classes="upload-container"):
|
@@ -521,7 +587,7 @@ with gr.Blocks(
|
|
521 |
send_btn = gr.Button("Send", variant="primary", scale=1)
|
522 |
|
523 |
gr.Markdown(
|
524 |
-
"*Ask questions about your processed document. The AI
|
525 |
elem_id="chat-notice"
|
526 |
)
|
527 |
|
@@ -562,18 +628,23 @@ with gr.Blocks(
|
|
562 |
return history + [[message, "β Please process a PDF document first before asking questions."]]
|
563 |
|
564 |
try:
|
565 |
-
#
|
566 |
-
|
|
|
|
|
|
|
|
|
|
|
567 |
|
568 |
# Create chat messages
|
569 |
messages = [
|
570 |
{
|
571 |
"role": "system",
|
572 |
-
"content": [{"type": "text", "text": "You are a helpful assistant that answers questions about documents. Use the provided document content to answer questions accurately."}]
|
573 |
},
|
574 |
{
|
575 |
"role": "user",
|
576 |
-
"content": [{"type": "text", "text": f"{context}\n\nQuestion: {message}"}]
|
577 |
}
|
578 |
]
|
579 |
|
|
|
11 |
from PIL import Image
|
12 |
from transformers import AutoProcessor, VisionEncoderDecoderModel, Gemma3nForConditionalGeneration, pipeline
|
13 |
import torch
|
14 |
+
from sentence_transformers import SentenceTransformer
|
15 |
+
import numpy as np
|
16 |
+
from sklearn.metrics.pairwise import cosine_similarity
|
17 |
import os
|
18 |
import tempfile
|
19 |
import uuid
|
|
|
315 |
dolphin_model = None
|
316 |
model_status = f"β Model failed to load: {str(e)}"
|
317 |
|
318 |
+
# Initialize embedding model for RAG
|
319 |
+
try:
|
320 |
+
print("Loading embedding model...")
|
321 |
+
embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
|
322 |
+
print("β
Embedding model loaded successfully")
|
323 |
+
except Exception as e:
|
324 |
+
print(f"β Error loading embedding model: {e}")
|
325 |
+
embedding_model = None
|
326 |
+
|
327 |
# Initialize chatbot model
|
328 |
try:
|
329 |
import os
|
|
|
362 |
# Global state for managing tabs
|
363 |
processed_markdown = ""
|
364 |
show_results_tab = False
|
365 |
+
document_chunks = []
|
366 |
+
document_embeddings = None
|
367 |
+
embedding_model = None
|
368 |
# chatbot_model is initialized above
|
369 |
|
370 |
|
371 |
+
def chunk_document(text, chunk_size=500, overlap=50):
|
372 |
+
"""Split document into overlapping chunks for RAG"""
|
373 |
+
words = text.split()
|
374 |
+
chunks = []
|
375 |
+
|
376 |
+
for i in range(0, len(words), chunk_size - overlap):
|
377 |
+
chunk = ' '.join(words[i:i + chunk_size])
|
378 |
+
if chunk.strip():
|
379 |
+
chunks.append(chunk)
|
380 |
+
|
381 |
+
return chunks
|
382 |
+
|
383 |
+
def create_embeddings(chunks):
|
384 |
+
"""Create embeddings for document chunks"""
|
385 |
+
if embedding_model is None:
|
386 |
+
return None
|
387 |
+
|
388 |
+
try:
|
389 |
+
embeddings = embedding_model.encode(chunks)
|
390 |
+
return embeddings
|
391 |
+
except Exception as e:
|
392 |
+
print(f"Error creating embeddings: {e}")
|
393 |
+
return None
|
394 |
+
|
395 |
+
def retrieve_relevant_chunks(question, chunks, embeddings, top_k=3):
|
396 |
+
"""Retrieve most relevant chunks for a question"""
|
397 |
+
if embedding_model is None or embeddings is None:
|
398 |
+
return chunks[:3] # Fallback to first 3 chunks
|
399 |
+
|
400 |
+
try:
|
401 |
+
question_embedding = embedding_model.encode([question])
|
402 |
+
similarities = cosine_similarity(question_embedding, embeddings)[0]
|
403 |
+
|
404 |
+
# Get top-k most similar chunks
|
405 |
+
top_indices = np.argsort(similarities)[-top_k:][::-1]
|
406 |
+
relevant_chunks = [chunks[i] for i in top_indices]
|
407 |
+
|
408 |
+
return relevant_chunks
|
409 |
+
except Exception as e:
|
410 |
+
print(f"Error retrieving chunks: {e}")
|
411 |
+
return chunks[:3] # Fallback
|
412 |
+
|
413 |
def process_uploaded_pdf(pdf_file, progress=gr.Progress()):
|
414 |
"""Main processing function for uploaded PDF"""
|
415 |
+
global processed_markdown, show_results_tab, document_chunks, document_embeddings
|
416 |
|
417 |
if dolphin_model is None:
|
418 |
return "β Model not loaded", gr.Tabs(visible=False)
|
|
|
425 |
|
426 |
if status == "processing_complete":
|
427 |
processed_markdown = combined_markdown
|
428 |
+
|
429 |
+
# Create chunks and embeddings for RAG
|
430 |
+
print("Creating document chunks for RAG...")
|
431 |
+
document_chunks = chunk_document(processed_markdown)
|
432 |
+
document_embeddings = create_embeddings(document_chunks)
|
433 |
+
print(f"Created {len(document_chunks)} chunks")
|
434 |
+
|
435 |
show_results_tab = True
|
436 |
return "β
PDF processed successfully! Check the 'Document' tab above.", gr.Tabs(visible=True)
|
437 |
else:
|
|
|
510 |
# Home Tab
|
511 |
with gr.TabItem("π Home", id="home"):
|
512 |
chatbot_status = "β
Chatbot ready" if chatbot_model else "β Chatbot not loaded"
|
513 |
+
embedding_status = "β
RAG ready" if embedding_model else "β RAG not loaded"
|
514 |
gr.Markdown(
|
515 |
"# Scholar Express\n"
|
516 |
"### Upload a research paper to get a web-friendly version, an AI chatbot, and a podcast summary. Because of our reliance on Generative AI, some errors are inevitable.\n"
|
517 |
f"**PDF Processing:** {model_status}\n"
|
518 |
+
f"**Chatbot:** {chatbot_status}\n"
|
519 |
+
f"**RAG System:** {embedding_status}"
|
520 |
)
|
521 |
|
522 |
with gr.Column(elem_classes="upload-container"):
|
|
|
587 |
send_btn = gr.Button("Send", variant="primary", scale=1)
|
588 |
|
589 |
gr.Markdown(
|
590 |
+
"*Ask questions about your processed document. The AI uses RAG (Retrieval-Augmented Generation) to find relevant sections and provide accurate answers.*",
|
591 |
elem_id="chat-notice"
|
592 |
)
|
593 |
|
|
|
628 |
return history + [[message, "β Please process a PDF document first before asking questions."]]
|
629 |
|
630 |
try:
|
631 |
+
# Use RAG to get relevant chunks instead of full document
|
632 |
+
if document_chunks and len(document_chunks) > 0:
|
633 |
+
relevant_chunks = retrieve_relevant_chunks(message, document_chunks, document_embeddings)
|
634 |
+
context = "\n\n".join(relevant_chunks)
|
635 |
+
else:
|
636 |
+
# Fallback to truncated document if RAG fails
|
637 |
+
context = processed_markdown[:1500] + "..." if len(processed_markdown) > 1500 else processed_markdown
|
638 |
|
639 |
# Create chat messages
|
640 |
messages = [
|
641 |
{
|
642 |
"role": "system",
|
643 |
+
"content": [{"type": "text", "text": "You are a helpful assistant that answers questions about documents. Use the provided document content to answer questions accurately and concisely."}]
|
644 |
},
|
645 |
{
|
646 |
"role": "user",
|
647 |
+
"content": [{"type": "text", "text": f"Document content:\n{context}\n\nQuestion: {message}"}]
|
648 |
}
|
649 |
]
|
650 |
|