Fakhir1 commited on
Commit
8f55ee4
Β·
verified Β·
1 Parent(s): d3e4bc6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +172 -108
app.py CHANGED
@@ -1,108 +1,172 @@
1
- # =======================================
2
- # πŸ“˜ RAG App – Gemini + Local Embeddings
3
- # =======================================
4
-
5
- #!pip install google-generativeai sentence-transformers chromadb beautifulsoup4 PyPDF2 gradio
6
-
7
- import os, textwrap, re
8
- import google.generativeai as genai
9
- from sentence_transformers import SentenceTransformer
10
- from bs4 import BeautifulSoup
11
- import requests
12
- import chromadb
13
- from PyPDF2 import PdfReader
14
- import gradio as gr
15
-
16
- # ======================
17
- # πŸ”Ή API Key Setup
18
- # ======================
19
- genai.configure(api_key="AIzaSyDr2X5N-hHt9EqUNy7JCm58aG1FpeGVpgs") # apni key yahan daalo
20
-
21
- MODEL = 'gemini-2.5-flash'
22
- embedder = SentenceTransformer('all-MiniLM-L6-v2') # local free embedding model
23
- chroma_client = chromadb.Client()
24
- collection = chroma_client.create_collection(name="rag_store")
25
-
26
- # ======================
27
- # πŸ”Ή Helper Functions
28
- # ======================
29
-
30
- def chunk_text(text, size=1000, overlap=100):
31
- chunks = []
32
- for i in range(0, len(text), size - overlap):
33
- chunks.append(text[i:i+size])
34
- return chunks
35
-
36
- def clean_text(text):
37
- text = re.sub(r'\s+', ' ', text)
38
- return text.strip()
39
-
40
- def ingest_source(source, from_url=True):
41
- """
42
- βœ… Web URL ya PDF se text nikaalo aur Chroma me store karo
43
- """
44
- if from_url:
45
- html = requests.get(source).text
46
- soup = BeautifulSoup(html, "html.parser")
47
- text = clean_text(soup.get_text())
48
- else:
49
- reader = PdfReader(source)
50
- text = " ".join([page.extract_text() for page in reader.pages])
51
-
52
- chunks = chunk_text(text)
53
- embeddings = embedder.encode(chunks).tolist()
54
-
55
- for i, emb in enumerate(embeddings):
56
- collection.add(ids=[f"doc_{i}"], embeddings=[emb], documents=[chunks[i]])
57
- print(f"βœ… Ingested {len(chunks)} chunks into Chroma DB")
58
-
59
- def rag_query(query):
60
- """
61
- βœ… Query kare aur best-matched chunks Gemini ko dekar answer banaye
62
- """
63
- q_emb = embedder.encode([query]).tolist()
64
- results = collection.query(query_embeddings=q_emb, n_results=4)
65
- context = " ".join(results['documents'][0])
66
-
67
- prompt = f"""
68
- You are an AI assistant. Use the context below to answer clearly:
69
- Context: {context}
70
- Question: {query}
71
- Answer:
72
- """
73
- response = genai.GenerativeModel(MODEL).generate_content(prompt)
74
- return textwrap.fill(response.text, width=100)
75
-
76
- # ======================
77
- # πŸ”Ή Gradio UI
78
- # ======================
79
- def web_ingest_ui(url):
80
- ingest_source(url, from_url=True)
81
- return f"βœ… Website data added: {url}"
82
-
83
- def pdf_ingest_ui(file):
84
- ingest_source(file.name, from_url=False)
85
- return f"βœ… PDF data added: {file.name}"
86
-
87
- with gr.Blocks(theme=gr.themes.Soft(primary_hue="teal")) as demo:
88
- gr.Markdown("## πŸ€– RAG App (Gemini + Local Embeddings)")
89
-
90
- with gr.Tab("🌐 Ingest Website"):
91
- url_in = gr.Textbox(label="Enter Website URL")
92
- url_btn = gr.Button("Ingest Website")
93
- url_out = gr.Textbox(label="Status")
94
- url_btn.click(fn=web_ingest_ui, inputs=url_in, outputs=url_out)
95
-
96
- with gr.Tab("πŸ“„ Ingest PDF"):
97
- pdf_in = gr.File(label="Upload PDF")
98
- pdf_btn = gr.Button("Ingest PDF")
99
- pdf_out = gr.Textbox(label="Status")
100
- pdf_btn.click(fn=pdf_ingest_ui, inputs=pdf_in, outputs=pdf_out)
101
-
102
- with gr.Tab("πŸ’¬ Ask Questions"):
103
- q_in = gr.Textbox(label="Ask anything from ingested sources")
104
- q_btn = gr.Button("Ask")
105
- q_out = gr.Markdown(label="Answer") # βœ… Markdown shows multi-line output
106
- q_btn.click(fn=rag_query, inputs=q_in, outputs=q_out)
107
-
108
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # =======================================
2
+ # πŸ“˜ RAG App Pro – Gemini + Smart Embeddings (Multi-User Safe)
3
+ # =======================================
4
+
5
+ import os, re, shutil, textwrap, requests, uuid
6
+ from bs4 import BeautifulSoup
7
+ import google.generativeai as genai
8
+ from sentence_transformers import SentenceTransformer
9
+ import chromadb
10
+ import gradio as gr
11
+ from langchain_community.document_loaders import UnstructuredPDFLoader
12
+ import camelot
13
+
14
+ # ======================
15
+ # πŸ”Ή Gemini + Local Setup
16
+ # ======================
17
+ genai.configure(api_key="AIzaSyDr2X5N-hHt9EqUNy7JCm58aG1FpeGVpgs") # πŸ”‘ apni Gemini key
18
+ MODEL = "gemini-2.5-flash"
19
+
20
+ embedder = SentenceTransformer("all-MiniLM-L6-v2")
21
+ chroma_client = chromadb.Client()
22
+
23
+ # ======================
24
+ # πŸ”Ή Utils
25
+ # ======================
26
+ def clean_text(text):
27
+ return re.sub(r"\s+", " ", text).strip()
28
+
29
+ def adaptive_chunk_text(text):
30
+ length = len(text)
31
+ if length < 3000:
32
+ size = 500
33
+ elif length < 10000:
34
+ size = 1000
35
+ else:
36
+ size = 1500
37
+ chunks = []
38
+ for i in range(0, len(text), size - 150):
39
+ chunks.append(text[i:i + size])
40
+ return chunks
41
+
42
+ def extract_pdf_text(pdf_path):
43
+ """Smart PDF extractor (tables + text)"""
44
+ full_text = ""
45
+ try:
46
+ tables = camelot.read_pdf(pdf_path, pages="all")
47
+ for i, table in enumerate(tables):
48
+ full_text += f"\n\n[Table {i+1}]\n" + table.df.to_string(index=False)
49
+ except Exception:
50
+ pass
51
+
52
+ try:
53
+ loader = UnstructuredPDFLoader(pdf_path)
54
+ docs = loader.load()
55
+ full_text += "\n\n".join([doc.page_content for doc in docs])
56
+ except Exception as e:
57
+ full_text += f"\n\n[Error extracting text: {e}]"
58
+
59
+ return clean_text(full_text)
60
+
61
+ # ======================
62
+ # πŸ”Ή Session Handling
63
+ # ======================
64
+ def create_user_collection():
65
+ """Each user/session gets unique collection"""
66
+ session_id = f"user_{str(uuid.uuid4())[:8]}"
67
+ collection = chroma_client.create_collection(name=session_id)
68
+ return session_id, collection
69
+
70
+ def reset_collection(collection_name):
71
+ """Delete previous data for same user"""
72
+ try:
73
+ chroma_client.delete_collection(name=collection_name)
74
+ except Exception:
75
+ pass
76
+ return chroma_client.create_collection(name=collection_name)
77
+
78
+ # ======================
79
+ # πŸ”Ή Ingestion Logic
80
+ # ======================
81
+ def ingest_source(source, from_url, collection_name):
82
+ # Delete previous user data
83
+ collection = reset_collection(collection_name)
84
+
85
+ if from_url:
86
+ html = requests.get(source, timeout=15).text
87
+ soup = BeautifulSoup(html, "html.parser")
88
+ text = clean_text(soup.get_text())
89
+ else:
90
+ text = extract_pdf_text(source)
91
+
92
+ if not text.strip():
93
+ return "⚠️ No readable text found (maybe image-only PDF)."
94
+
95
+ chunks = adaptive_chunk_text(text)
96
+ embeddings = embedder.encode(chunks).tolist()
97
+
98
+ for i, emb in enumerate(embeddings):
99
+ collection.add(ids=[f"{collection_name}_{i}"], embeddings=[emb], documents=[chunks[i]])
100
+
101
+ return f"βœ… [{collection_name}] Ingested {len(chunks)} chunks successfully!"
102
+
103
+ # ======================
104
+ # πŸ”Ή Query Logic
105
+ # ======================
106
+ def rag_query(query, collection_name):
107
+ try:
108
+ collection = chroma_client.get_collection(name=collection_name)
109
+ q_emb = embedder.encode([query]).tolist()
110
+ results = collection.query(query_embeddings=q_emb, n_results=4)
111
+ if not results["documents"]:
112
+ return "⚠️ No context found. Try ingesting data first."
113
+
114
+ context = "\n\n".join(results["documents"][0])
115
+ prompt = f"""
116
+ You are a knowledgeable AI assistant.
117
+ Use the context below to answer clearly and in multiple lines.
118
+
119
+ Context:
120
+ {context}
121
+
122
+ Question: {query}
123
+ Answer:
124
+ """
125
+ response = genai.GenerativeModel(MODEL).generate_content(prompt)
126
+ ans = response.text.replace(". ", ".\n")
127
+ return ans
128
+ except Exception as e:
129
+ return f"⚠️ Error: {e}"
130
+
131
+ # ======================
132
+ # πŸ”Ή Gradio UI
133
+ # ======================
134
+ def start_new_session():
135
+ session_id, _ = create_user_collection()
136
+ return session_id
137
+
138
+ session_id = start_new_session()
139
+
140
+ def ingest_website(url):
141
+ return ingest_source(url, True, session_id)
142
+
143
+ def ingest_pdf(file):
144
+ return ingest_source(file.name, False, session_id)
145
+
146
+ def query_ask(q):
147
+ return rag_query(q, session_id)
148
+
149
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="emerald")) as demo:
150
+ gr.Markdown("# πŸ€– Smart RAG App Pro (Gemini + Adaptive PDF + Multi-User Mode)")
151
+
152
+ gr.Markdown(f"πŸ†• **Private Session ID:** `{session_id}` – Your data is isolated and auto-clears on refresh.")
153
+
154
+ with gr.Tab("🌐 Ingest Website"):
155
+ url_in = gr.Textbox(label="Enter Website URL")
156
+ url_btn = gr.Button("Ingest Website")
157
+ url_out = gr.Textbox(label="Status")
158
+ url_btn.click(fn=ingest_website, inputs=url_in, outputs=url_out)
159
+
160
+ with gr.Tab("πŸ“„ Ingest PDF"):
161
+ pdf_in = gr.File(label="Upload PDF")
162
+ pdf_btn = gr.Button("Ingest PDF")
163
+ pdf_out = gr.Textbox(label="Status")
164
+ pdf_btn.click(fn=ingest_pdf, inputs=pdf_in, outputs=pdf_out)
165
+
166
+ with gr.Tab("πŸ’¬ Ask Questions"):
167
+ q_in = gr.Textbox(label="Ask anything from ingested data")
168
+ q_btn = gr.Button("Ask Gemini")
169
+ q_out = gr.Markdown(label="Answer")
170
+ q_btn.click(fn=query_ask, inputs=q_in, outputs=q_out)
171
+
172
+ demo.launch()