akazmi commited on
Commit
4cb39e2
Β·
verified Β·
1 Parent(s): e7d139e

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +92 -0
app.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ from PyPDF2 import PdfReader
4
+ from sentence_transformers import SentenceTransformer
5
+ from transformers import pipeline, AutoTokenizer, AutoModelForCausalLM
6
+ import torch
7
+ import numpy as np
8
+ from sklearn.metrics.pairwise import cosine_similarity
9
+
10
+ # Load sentence transformer for embeddings
11
+ embedder = SentenceTransformer("all-MiniLM-L6-v2")
12
+
13
+ # Load Zephyr model (use accelerate for GPU/CPU device map)
14
+ model_name = "HuggingFaceH4/zephyr-7b-beta"
15
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
16
+ model = AutoModelForCausalLM.from_pretrained(
17
+ model_name,
18
+ torch_dtype=torch.float16,
19
+ device_map="auto" # βœ… Works if 'accelerate' is installed
20
+ )
21
+ rag_pipeline = pipeline("text-generation", model=model, tokenizer=tokenizer)
22
+
23
+ # Function to extract text from PDF
24
+ def read_pdf(file_path):
25
+ try:
26
+ with open(file_path, "rb") as file:
27
+ reader = PdfReader(file)
28
+ text = ""
29
+ for page in reader.pages:
30
+ page_text = page.extract_text()
31
+ if page_text:
32
+ text += page_text + "\n"
33
+ return text
34
+ except Exception as e:
35
+ return f"Error reading PDF: {str(e)}"
36
+
37
+ # Function to split text into chunks (~500 words)
38
+ def chunk_text(text, chunk_size=500):
39
+ words = text.split()
40
+ return [" ".join(words[i:i+chunk_size]) for i in range(0, len(words), chunk_size)]
41
+
42
+ # Function to find top-k most relevant chunks
43
+ def retrieve_relevant_chunks(question, chunks, top_k=3):
44
+ chunk_embeddings = embedder.encode(chunks)
45
+ question_embedding = embedder.encode([question])
46
+ scores = cosine_similarity(question_embedding, chunk_embeddings)[0]
47
+ top_indices = np.argsort(scores)[-top_k:][::-1]
48
+ return "\n\n".join([chunks[i] for i in top_indices])
49
+
50
+ # Main function to process question and return answer
51
+ def answer_question(uploaded_file, user_question):
52
+ if uploaded_file is None:
53
+ return "❌ Please upload a PDF file."
54
+
55
+ file_path = uploaded_file.name
56
+ document_text = read_pdf(file_path)
57
+
58
+ if not document_text or not isinstance(document_text, str):
59
+ return "❌ Document is empty or could not be read."
60
+
61
+ chunks = chunk_text(document_text)
62
+ if not chunks:
63
+ return "❌ Document is too short to process."
64
+
65
+ relevant_context = retrieve_relevant_chunks(user_question, chunks)
66
+
67
+ prompt = f"""You are a helpful assistant. Use the context below to answer the user's question.\n\nContext:\n{relevant_context}\n\nQuestion: {user_question}\nAnswer:"""
68
+
69
+ try:
70
+ result = rag_pipeline(prompt, max_new_tokens=300, do_sample=True, temperature=0.7)
71
+ answer = result[0]["generated_text"].split("Answer:")[-1].strip()
72
+ return str(answer)
73
+ except Exception as e:
74
+ return f"❌ Error generating answer: {str(e)}"
75
+
76
+ # Gradio interface
77
+ def create_interface():
78
+ with gr.Blocks() as demo:
79
+ gr.Markdown("## πŸ“„ Ask Questions from a PDF Document (RAG using Zephyr 7B)")
80
+
81
+ file_input = gr.File(label="Upload PDF", file_types=[".pdf"])
82
+ question_input = gr.Textbox(label="Enter your question")
83
+ answer_output = gr.Textbox(label="Answer", lines=10)
84
+
85
+ ask_button = gr.Button("Ask")
86
+ ask_button.click(fn=answer_question, inputs=[file_input, question_input], outputs=answer_output)
87
+
88
+ return demo
89
+
90
+ if __name__ == "__main__":
91
+ demo = create_interface()
92
+ demo.launch()