File size: 5,472 Bytes
c53d978 00eb76e 0fd97ae 4f2bd66 00eb76e c53d978 00eb76e 07f9cb7 00eb76e 4f2bd66 00eb76e 4f2bd66 00eb76e 4f2bd66 00eb76e 4f2bd66 00eb76e 4f2bd66 00eb76e 4f2bd66 00eb76e 0fd97ae 4f2bd66 00eb76e 0fd97ae 00eb76e 0fd97ae 00eb76e 0fd97ae 00eb76e 0fd97ae 00eb76e 4f2bd66 00eb76e 0fd97ae 00eb76e 0fd97ae 00eb76e 0fd97ae 00eb76e e4efe09 0fd97ae 00eb76e 0fd97ae 00eb76e 4f2bd66 0fd97ae 4f2bd66 0fd97ae c53d978 00eb76e 0fd97ae 00eb76e 0fd97ae 00eb76e 0fd97ae c53d978 4f2bd66 0fd97ae 00eb76e e4efe09 00eb76e 0fd97ae 00eb76e 4f2bd66 0fd97ae 00eb76e 0fd97ae 00eb76e 0fd97ae 00eb76e 0fd97ae 00eb76e 0fd97ae 00eb76e e4efe09 00eb76e 4f2bd66 0fd97ae 00eb76e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
import gradio as gr
from sentence_transformers import SentenceTransformer
import numpy as np
from pypdf import PdfReader
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
# Global variables
chunks = []
embeddings = []
model = None
tokenizer = None
embed_model = None
def initialize_models():
"""Initialize models on startup"""
global model, tokenizer, embed_model
print("Loading models...")
# Load embedding model
embed_model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2')
# Load language model
model_name = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float32,
low_cpu_mem_usage=True
)
print("Models loaded successfully!")
def process_pdf(pdf_file):
"""Process PDF and create embeddings"""
global chunks, embeddings, embed_model
if pdf_file is None:
return "β Please upload a PDF file!", None
try:
# Read PDF
pdf_reader = PdfReader(pdf_file.name)
text = ""
for page in pdf_reader.pages:
text += page.extract_text() + "\n"
if not text.strip():
return "β Could not extract text from PDF!", None
# Split into chunks
chunk_size = 1000
overlap = 200
chunks = []
for i in range(0, len(text), chunk_size - overlap):
chunk = text[i:i + chunk_size]
if chunk.strip():
chunks.append(chunk)
# Create embeddings
embeddings = embed_model.encode(chunks, show_progress_bar=False)
return f"β
PDF processed! Created {len(chunks)} chunks. You can now ask questions!", None
except Exception as e:
return f"β Error: {str(e)}", None
def find_relevant_chunks(query, top_k=3):
"""Find most relevant chunks using cosine similarity"""
global chunks, embeddings, embed_model
if not chunks:
return []
query_embedding = embed_model.encode([query])[0]
# Calculate cosine similarity
similarities = np.dot(embeddings, query_embedding) / (
np.linalg.norm(embeddings, axis=1) * np.linalg.norm(query_embedding)
)
# Get top k indices
top_indices = np.argsort(similarities)[-top_k:][::-1]
return [chunks[i] for i in top_indices]
def generate_response(question, context):
"""Generate response using the language model"""
global model, tokenizer
prompt = f"""<|system|>
You are a helpful assistant. Answer the question based on the provided context. Be concise and accurate.
</s>
<|user|>
Context: {context}
Question: {question}
</s>
<|assistant|>
"""
inputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=2048)
with torch.no_grad():
outputs = model.generate(
**inputs,
max_new_tokens=300,
temperature=0.7,
top_p=0.9,
do_sample=True,
pad_token_id=tokenizer.eos_token_id
)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
# Extract only the assistant's response
if "<|assistant|>" in response:
response = response.split("<|assistant|>")[-1].strip()
return response
def chat(message, history):
"""Handle chat"""
global chunks
if not chunks:
return history + [[message, "β οΈ Please upload and process a PDF first!"]]
if not message.strip():
return history
try:
# Find relevant context
relevant_chunks = find_relevant_chunks(message)
context = "\n\n".join(relevant_chunks)
# Generate response
response = generate_response(message, context)
return history + [[message, response]]
except Exception as e:
return history + [[message, f"β Error: {str(e)}"]]
def clear_all():
"""Clear everything"""
global chunks, embeddings
chunks = []
embeddings = []
return None, "Ready to process a new PDF"
# Create UI
with gr.Blocks(title="Chat with PDF") as demo:
gr.Markdown("# π Chat with PDF - Simple Version")
with gr.Row():
with gr.Column(scale=1):
pdf_input = gr.File(label="π Upload PDF", file_types=[".pdf"])
process_btn = gr.Button("π Process PDF", variant="primary")
status = gr.Textbox(label="Status", lines=3)
clear_all_btn = gr.Button("ποΈ Clear All")
with gr.Column(scale=2):
chatbot = gr.Chatbot(label="π¬ Chat", height=400)
msg = gr.Textbox(label="Question", placeholder="Ask about the PDF...")
with gr.Row():
send_btn = gr.Button("Send", variant="primary")
clear_btn = gr.Button("Clear Chat")
# Events
process_btn.click(process_pdf, [pdf_input], [status, chatbot])
msg.submit(chat, [msg, chatbot], [chatbot]).then(lambda: "", None, [msg])
send_btn.click(chat, [msg, chatbot], [chatbot]).then(lambda: "", None, [msg])
clear_btn.click(lambda: None, None, [chatbot])
clear_all_btn.click(clear_all, None, [chatbot, status])
# Initialize on startup
initialize_models()
if __name__ == "__main__":
demo.launch() |