QA-App / app.py
a7madmostafa's picture
Create app.py
ba5988b verified
Raw
History Blame Contribute Delete
3.05 kB
# Gradio App
import numpy as np
from transformers import pipeline, AutoTokenizer, AutoModelForQuestionAnswering
from sentence_transformers import SentenceTransformer
import gradio as gr
from PyPDF2 import PdfReader
# Document Reading
def read_document(file_path):
"""
Reads PDF or TXT files and returns plain text.
"""
if file_path.endswith(".pdf"):
reader = PdfReader(file_path)
text = ""
for page in reader.pages:
text += page.extract_text() + " "
return text
elif file_path.endswith(".txt"):
with open(file_path, "r", encoding="utf-8") as f:
return f.read()
else:
return None
# Chunking
def chunk_text(text, chunk_size=500):
"""
Splits the text into chunks of `chunk_size` words.
Transformers have input limits, so chunking is necessary.
"""
words = text.split()
chunks = [" ".join(words[i:i+chunk_size]) for i in range(0, len(words), chunk_size)]
return chunks
# Embeddings for retrieval
embed_model = SentenceTransformer('all-MiniLM-L6-v2')
# Pre-trained QA model for extractive answers
qa_model_name = "distilbert-base-uncased-distilled-squad"
qa_tokenizer = AutoTokenizer.from_pretrained(qa_model_name)
qa_model = AutoModelForQuestionAnswering.from_pretrained(qa_model_name)
qa_pipeline_model = pipeline("question-answering", model=qa_model, tokenizer=qa_tokenizer)
# QA Function
def answer_question(file, question, top_k=3):
"""
Takes a document file and question string,
returns the best answer from the document.
"""
if file is None:
return "Please upload a document."
# Step 1: Read & chunk document
text = read_document(file.name)
chunks = chunk_text(text, chunk_size=500)
# Step 2: Embed chunks
chunk_embeddings = embed_model.encode(chunks)
# Step 3: Embed question
question_embedding = embed_model.encode([question])[0]
# Step 4: Compute cosine similarity to find top-k relevant chunks
similarities = np.dot(chunk_embeddings, question_embedding) / (
np.linalg.norm(chunk_embeddings, axis=1) * np.linalg.norm(question_embedding)
)
top_idx = similarities.argsort()[-top_k:][::-1]
top_chunks = [chunks[i] for i in top_idx]
# Step 5: Run extractive QA on top-k chunks
best_answer = {"score": 0, "answer": "Answer not found."}
for chunk in top_chunks:
result = qa_pipeline_model(question=question, context=chunk)
if result['score'] > best_answer['score']:
best_answer = result
return best_answer['answer']
iface = gr.Interface(
fn=answer_question,
inputs=[
gr.File(label="Upload Document (.pdf or .txt)"),
gr.Textbox(label="Enter your question"),
gr.Slider(1, 5, value=3, step=1, label="Top-k chunks to consider")
],
outputs=gr.Textbox(label="Answer"),
title="Document Question Answering (Mini-RAG)",
description="Upload a document and ask questions. The system retrieves relevant chunks and extracts the answer."
)
iface.launch()