RAGify / app.py
Fakhir1's picture
Update app.py
b5ce09d verified
Raw
History Blame Contribute Delete
5.45 kB
# =======================================
# πŸ“˜ RAG App Pro – Gemini + Smart Embeddings (Multi-User Safe)
# =======================================
import os, re, shutil, textwrap, requests, uuid
from bs4 import BeautifulSoup
import google.generativeai as genai
from sentence_transformers import SentenceTransformer
import chromadb
import gradio as gr
from langchain_community.document_loaders import UnstructuredPDFLoader
import camelot
# ======================
# πŸ”Ή Gemini + Local Setup
# ======================
genai.configure(api_key="AQ.Ab8RN6I4za-ifPTOLhC78wesRWQxGaWeQQZZa44Cv7dBtaxX6A") # πŸ”‘ apni Gemini key
MODEL = "gemini-3.5-flash"
embedder = SentenceTransformer("all-MiniLM-L6-v2")
chroma_client = chromadb.Client()
# ======================
# πŸ”Ή Utils
# ======================
def clean_text(text):
return re.sub(r"\s+", " ", text).strip()
def adaptive_chunk_text(text):
length = len(text)
if length < 3000:
size = 500
elif length < 10000:
size = 1000
else:
size = 1500
chunks = []
for i in range(0, len(text), size - 150):
chunks.append(text[i:i + size])
return chunks
def extract_pdf_text(pdf_path):
"""Smart PDF extractor (tables + text)"""
full_text = ""
try:
tables = camelot.read_pdf(pdf_path, pages="all")
for i, table in enumerate(tables):
full_text += f"\n\n[Table {i+1}]\n" + table.df.to_string(index=False)
except Exception:
pass
try:
loader = UnstructuredPDFLoader(pdf_path)
docs = loader.load()
full_text += "\n\n".join([doc.page_content for doc in docs])
except Exception as e:
full_text += f"\n\n[Error extracting text: {e}]"
return clean_text(full_text)
# ======================
# πŸ”Ή Session Handling
# ======================
def create_user_collection():
"""Each user/session gets unique collection"""
session_id = f"user_{str(uuid.uuid4())[:8]}"
collection = chroma_client.create_collection(name=session_id)
return session_id, collection
def reset_collection(collection_name):
"""Delete previous data for same user"""
try:
chroma_client.delete_collection(name=collection_name)
except Exception:
pass
return chroma_client.create_collection(name=collection_name)
# ======================
# πŸ”Ή Ingestion Logic
# ======================
def ingest_source(source, from_url, collection_name):
# Delete previous user data
collection = reset_collection(collection_name)
if from_url:
html = requests.get(source, timeout=15).text
soup = BeautifulSoup(html, "html.parser")
text = clean_text(soup.get_text())
else:
text = extract_pdf_text(source)
if not text.strip():
return "⚠️ No readable text found (maybe image-only PDF)."
chunks = adaptive_chunk_text(text)
embeddings = embedder.encode(chunks).tolist()
for i, emb in enumerate(embeddings):
collection.add(ids=[f"{collection_name}_{i}"], embeddings=[emb], documents=[chunks[i]])
return f"βœ… [{collection_name}] Ingested {len(chunks)} chunks successfully!"
# ======================
# πŸ”Ή Query Logic
# ======================
def rag_query(query, collection_name):
try:
collection = chroma_client.get_collection(name=collection_name)
q_emb = embedder.encode([query]).tolist()
results = collection.query(query_embeddings=q_emb, n_results=4)
if not results["documents"]:
return "⚠️ No context found. Try ingesting data first."
context = "\n\n".join(results["documents"][0])
prompt = f"""
You are a knowledgeable AI assistant.
Use the context below to answer clearly and in multiple lines.
Context:
{context}
Question: {query}
Answer:
"""
response = genai.GenerativeModel(MODEL).generate_content(prompt)
ans = response.text.replace(". ", ".\n")
return ans
except Exception as e:
return f"⚠️ Error: {e}"
# ======================
# πŸ”Ή Gradio UI
# ======================
def start_new_session():
session_id, _ = create_user_collection()
return session_id
session_id = start_new_session()
def ingest_website(url):
return ingest_source(url, True, session_id)
def ingest_pdf(file):
return ingest_source(file.name, False, session_id)
def query_ask(q):
return rag_query(q, session_id)
with gr.Blocks(theme=gr.themes.Soft(primary_hue="emerald")) as demo:
gr.Markdown("# πŸ€– Smart RAG App Pro (Gemini + Adaptive PDF + Multi-User Mode)")
gr.Markdown(f"πŸ†• **Private Session ID:** `{session_id}` – Your data is isolated and auto-clears on refresh.")
with gr.Tab("🌐 Ingest Website"):
url_in = gr.Textbox(label="Enter Website URL")
url_btn = gr.Button("Ingest Website")
url_out = gr.Textbox(label="Status")
url_btn.click(fn=ingest_website, inputs=url_in, outputs=url_out)
with gr.Tab("πŸ“„ Ingest PDF"):
pdf_in = gr.File(label="Upload PDF")
pdf_btn = gr.Button("Ingest PDF")
pdf_out = gr.Textbox(label="Status")
pdf_btn.click(fn=ingest_pdf, inputs=pdf_in, outputs=pdf_out)
with gr.Tab("πŸ’¬ Ask Questions"):
q_in = gr.Textbox(label="Ask anything from ingested data")
q_btn = gr.Button("Ask Gemini")
q_out = gr.Markdown(label="Answer")
q_btn.click(fn=query_ask, inputs=q_in, outputs=q_out)
demo.launch()