LiamKhoaLe commited on
Commit
8828f20
·
1 Parent(s): 5aeecfe

Add application file

Browse files
Files changed (7) hide show
  1. .huggingface.yml +4 -0
  2. Dockerfile +19 -0
  3. app.py +305 -0
  4. clear_mongo.py +48 -0
  5. connect_mongo.py +24 -0
  6. migrate.py +48 -0
  7. requirements.txt +20 -0
.huggingface.yml ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ sdk: docker
2
+ app_file: main.py
3
+ port: 7860
4
+ hardware: cpu-basic
Dockerfile ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11
2
+
3
+ # Create and use a non-root user
4
+ RUN useradd -m -u 1000 user
5
+ USER user
6
+ ENV PATH="/home/user/.local/bin:$PATH"
7
+
8
+ # Set working directory
9
+ WORKDIR /app
10
+
11
+ # Copy and install dependencies
12
+ COPY --chown=user ./requirements.txt requirements.txt
13
+ RUN pip install --no-cache-dir -r requirements.txt
14
+
15
+ # Load environment variables
16
+ ENV ENV_PATH="/app/.env"
17
+
18
+ # Run server with uvicorn
19
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,305 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ==========================
2
+ # Medical Chatbot Backend (Gemini Flash API + RAG) - Local Prebuilt Model with FAISS Index & Data Stored in MongoDB
3
+ # ==========================
4
+ """
5
+ This script loads:
6
+ 1) A FAISS index stored in MongoDB (in the "faiss_index" collection)
7
+ 2) A local SentenceTransformer model (downloaded via snapshot_download)
8
+ 3) QA data (the full dataset of 256916 QA entries) stored in MongoDB (in the "qa_data" collection)
9
+
10
+ If the QA data or FAISS index are not found in MongoDB, the script loads the full dataset from Hugging Face,
11
+ computes embeddings for all QA pairs (concatenating the "Patient" and "Doctor" fields), and stores both the raw QA data
12
+ and the FAISS index in MongoDB.
13
+
14
+ The chatbot instructs Gemini Flash to format its answer using markdown.
15
+ """
16
+
17
+ import os
18
+ import faiss
19
+ import numpy as np
20
+ import gc
21
+ import time
22
+ from fastapi import FastAPI
23
+ from fastapi.responses import HTMLResponse, JSONResponse
24
+ from pathlib import Path
25
+ # import streamlit as st
26
+ # import threading
27
+ # import requests
28
+ from dotenv import load_dotenv
29
+
30
+ # 🔹 Load environment variables from .env
31
+ load_dotenv()
32
+ gemini_flash_api_key = os.getenv("FlashAPI")
33
+ mongo_uri = os.getenv("MONGO_URI")
34
+ index_uri = os.getenv("INDEX_URI")
35
+ # 🔹 Load Streamlit secrets from .toml
36
+ # gemini_flash_api_key = st.secrets["general"]["FlashAPI"]
37
+ # mongo_uri = st.secrets["general"]["MONGO_URI"]
38
+ # index_uri = st.secrets["general"]["INDEX_URI"]
39
+ if not gemini_flash_api_key:
40
+ raise ValueError("❌ Gemini Flash API key (FlashAPI) is missing!")
41
+ # st.error("❌ Gemini Flash API key (FlashAPI) is missing!")
42
+ # st.stop() # Prevent the app from running without necessary API keys
43
+ if not mongo_uri:
44
+ raise ValueError("❌ MongoDB URI (MongoURI) is missing!")
45
+ # st.error("❌ MongoDB URI (MongoURI) is missing!")
46
+ # st.stop() # Prevent the app from running without necessary API keys
47
+ if not index_uri:
48
+ raise ValueError("❌ INDEX_URI for FAISS index cluster is missing!")
49
+ # st.error("❌ INDEX_URI for FAISS index cluster is missing!")
50
+ # st.stop() # Prevent the app from running without necessary API keys
51
+
52
+ # 1. Environment variables to mitigate segmentation faults
53
+ os.environ["OMP_NUM_THREADS"] = "1"
54
+ os.environ["MKL_NUM_THREADS"] = "1"
55
+ os.environ["TOKENIZERS_PARALLELISM"] = "false"
56
+ # 2. Setup local project directory (for model cache)
57
+ project_dir = "./AutoGenRAGMedicalChatbot"
58
+ os.makedirs(project_dir, exist_ok=True)
59
+ huggingface_cache_dir = os.path.join(project_dir, "huggingface_models")
60
+ os.environ["HF_HOME"] = huggingface_cache_dir # Use this folder for HF cache
61
+ # 3. Download (or load from cache) the SentenceTransformer model
62
+ from huggingface_hub import snapshot_download
63
+ print("⏳ Checking or downloading the all-MiniLM-L6-v2 model from huggingface_hub...")
64
+ # st.write("⏳ Checking or downloading the all-MiniLM-L6-v2 model from huggingface_hub...")
65
+ model_loc = snapshot_download(
66
+ repo_id="sentence-transformers/all-MiniLM-L6-v2",
67
+ cache_dir=os.environ["HF_HOME"],
68
+ local_files_only=False
69
+ )
70
+ print(f"✅ Model directory: {model_loc}")
71
+ # st.write(f"✅ Model directory: {model_loc}")
72
+
73
+ from sentence_transformers import SentenceTransformer
74
+ print("📥 **Loading Embedding Model...**")
75
+ # st.write("📥 **Loading Embedding Model...**")
76
+ embedding_model = SentenceTransformer(model_loc, device="cpu")
77
+
78
+ # 🔹 MongoDB Setup
79
+ from pymongo import MongoClient
80
+ # 1. QA client
81
+ client = MongoClient(mongo_uri)
82
+ db = client["MedicalChatbotDB"] # Use your chosen database name
83
+ qa_collection = db["qa_data"]
84
+ # 2. FAISS index client
85
+ iclient = MongoClient(index_uri)
86
+ idb = iclient["MedicalChatbotDB"] # Use your chosen database name
87
+ index_collection = idb["faiss_index_files"]
88
+
89
+ ##---------------------------##
90
+ ## EMBEDDING AND DATA RETRIEVAL
91
+ ##---------------------------##
92
+
93
+ # 🔹 Load or Build QA Data in MongoDB
94
+ print("⏳ Checking MongoDB for existing QA data...")
95
+ # st.write("⏳ Checking MongoDB for existing QA data...")
96
+ if qa_collection.count_documents({}) == 0:
97
+ print("⚠️ QA data not found in MongoDB. Loading dataset from Hugging Face...")
98
+ # st.write("⚠️ QA data not found in MongoDB. Loading dataset from Hugging Face...")
99
+ from datasets import load_dataset
100
+ dataset = load_dataset("ruslanmv/ai-medical-chatbot", cache_dir=huggingface_cache_dir)
101
+ df = dataset["train"].to_pandas()[["Patient", "Doctor"]]
102
+ # Add an index column "i" to preserve order.
103
+ df["i"] = range(len(df))
104
+ qa_data = df.to_dict("records")
105
+ # Insert in batches (e.g., batches of 1000) to avoid document size limits.
106
+ batch_size = 1000
107
+ for i in range(0, len(qa_data), batch_size):
108
+ qa_collection.insert_many(qa_data[i:i+batch_size])
109
+ print(f"📦 QA data stored in MongoDB. Total entries: {len(qa_data)}")
110
+ # st.write(f"📦 QA data stored in MongoDB. Total entries: {len(qa_data)}")
111
+ else:
112
+ print("✅ Loaded existing QA data from MongoDB.")
113
+ # st.write("✅ Loaded existing QA data from MongoDB.")
114
+ # Use an aggregation pipeline with allowDiskUse to sort by "i" without creating an index.
115
+ qa_docs = list(qa_collection.aggregate([
116
+ {"$sort": {"i": 1}},
117
+ {"$project": {"_id": 0}}
118
+ ], allowDiskUse=True))
119
+ qa_data = qa_docs
120
+ print("📦 Total QA entries loaded:", len(qa_data))
121
+ # st.write("📦 Total QA entries loaded:", len(qa_data))
122
+
123
+ # 🔹 Build or Load the FAISS Index from MongoDB using GridFS (on the separate cluster)
124
+ print("⏳ Checking GridFS for existing FAISS index...")
125
+ # st.write("⏳ Checking GridFS for existing FAISS index...")
126
+ import gridfs
127
+ fs = gridfs.GridFS(idb, collection="faiss_index_files") # 'idb' is connected using INDEX_URI
128
+ # 1. Find the FAISS index file by filename.
129
+ existing_file = fs.find_one({"filename": "faiss_index.bin"})
130
+ if existing_file is None:
131
+ print("⚠️ FAISS index not found in GridFS. Building FAISS index from QA data...")
132
+ # st.write("⚠️ FAISS index not found in GridFS. Building FAISS index from QA data...")
133
+ # Compute embeddings for each QA pair by concatenating "Patient" and "Doctor" fields.
134
+ texts = [item.get("Patient", "") + " " + item.get("Doctor", "") for item in qa_data]
135
+ batch_size = 512 # Adjust as needed
136
+ embeddings_list = []
137
+ for i in range(0, len(texts), batch_size):
138
+ batch = texts[i:i+batch_size]
139
+ batch_embeddings = embedding_model.encode(batch, convert_to_numpy=True).astype(np.float32)
140
+ embeddings_list.append(batch_embeddings)
141
+ print(f"Encoded batch {i} to {i + len(batch)}")
142
+ # st.write(f"Encoded batch {i} to {i + len(batch)}")
143
+ embeddings = np.vstack(embeddings_list)
144
+ dim = embeddings.shape[1]
145
+ # Create a FAISS index (using IndexHNSWFlat; or use IVFPQ for compression)
146
+ index = faiss.IndexHNSWFlat(dim, 32)
147
+ index.add(embeddings)
148
+ print("FAISS index built. Total vectors:", index.ntotal)
149
+ # Serialize the index
150
+ index_bytes = faiss.serialize_index(index)
151
+ index_data = np.frombuffer(index_bytes, dtype='uint8').tobytes()
152
+ # Store in GridFS (this bypasses the 16 MB limit)
153
+ file_id = fs.put(index_data, filename="faiss_index.bin")
154
+ print("📦 FAISS index built and stored in GridFS with file_id:", file_id)
155
+ # st.write("📦 FAISS index built and stored in GridFS with file_id:", file_id)
156
+ del embeddings
157
+ gc.collect()
158
+ else:
159
+ print("✅ Found FAISS index in GridFS. Loading...")
160
+ # st.write("✅ Found FAISS index in GridFS. Loading...")
161
+ stored_index_bytes = existing_file.read()
162
+ index_bytes_np = np.frombuffer(stored_index_bytes, dtype='uint8')
163
+ index = faiss.deserialize_index(index_bytes_np)
164
+ print("📦 FAISS index loaded from GridFS successfully!")
165
+ # st.write("📦 FAISS index loaded from GridFS successfully!")
166
+
167
+
168
+ ##---------------------------##
169
+ ## INFERENCE BACK+FRONT END
170
+ ##---------------------------##
171
+
172
+ # 🔹 Prepare Retrieval and Chat Logic
173
+ def retrieve_medical_info(query):
174
+ """Retrieve relevant medical knowledge using the FAISS index."""
175
+ query_embedding = embedding_model.encode([query], convert_to_numpy=True)
176
+ _, idxs = index.search(query_embedding, k=3)
177
+ results = []
178
+ for i in idxs[0]:
179
+ if i < len(qa_data):
180
+ results.append(qa_data[i].get("Doctor", "No answer available."))
181
+ else:
182
+ results.append("No answer available.")
183
+ return results
184
+
185
+ # 🔹 Gemini Flash API Call
186
+ from google import genai
187
+ def gemini_flash_completion(prompt, model, temperature=0.7):
188
+ client_genai = genai.Client(api_key=gemini_flash_api_key)
189
+ try:
190
+ response = client_genai.models.generate_content(model=model, contents=prompt)
191
+ return response.text
192
+ except Exception as e:
193
+ print(f"⚠️ Error calling Gemini API: {e}")
194
+ # st.error(f"⚠️ Error calling Gemini API: {e}")
195
+ return "Error generating response from Gemini."
196
+
197
+ # Define a simple language mapping (modify or add more as needed)
198
+ language_map = {
199
+ "EN": "English",
200
+ "VI": "Vietnamese",
201
+ "ZH": "Chinese"
202
+ }
203
+
204
+ # 🔹 Chatbot Class
205
+ class RAGMedicalChatbot:
206
+ def __init__(self, model_name, retrieve_function):
207
+ self.model_name = model_name
208
+ self.retrieve = retrieve_function
209
+
210
+ def chat(self, user_query, lang="EN"):
211
+ retrieved_info = self.retrieve(user_query)
212
+ knowledge_base = "\n".join(retrieved_info)
213
+ # Construct prompt for Gemini Flash
214
+ prompt = (
215
+ "Please format your answer using markdown. Use **bold** for titles, *italic* for emphasis, "
216
+ "and ensure that headings and paragraphs are clearly separated.\n\n"
217
+ f"Using the following medical knowledge:\n{knowledge_base} \n(trained with 256,916 data entries).\n\n"
218
+ f"Answer the following question in a professional and medically accurate manner:\n{user_query}.\n\n"
219
+ f"Your response answer must be in {lang} language."
220
+ )
221
+ completion = gemini_flash_completion(prompt, model=self.model_name, temperature=0.7)
222
+ return completion.strip()
223
+
224
+ # 🔹 Model Class (change to others if needed)
225
+ chatbot = RAGMedicalChatbot(
226
+ model_name="gemini-2.0-flash",
227
+ retrieve_function=retrieve_medical_info
228
+ )
229
+ print("✅ Medical chatbot is ready! 🤖")
230
+ # st.success("✅ Medical chatbot is ready! 🤖")
231
+
232
+ # 🔹 FastAPI Server
233
+ # from fastapi.staticfiles import StaticFiles
234
+ from fastapi.middleware.cors import CORSMiddleware # Bypassing CORS origin
235
+ app = FastAPI(title="Medical Chatbot")
236
+ # 1. Define the origins
237
+ origins = [
238
+ "http://localhost:5173", # Vite dev server
239
+ "http://localhost:3000", # Another vercel dev server
240
+ "https://medical-chatbot-henna.vercel.app", # ✅ Vercel frontend production URL
241
+
242
+ ]
243
+ # 2. Then add the CORS middleware:
244
+ app.add_middleware(
245
+ CORSMiddleware,
246
+ allow_origins=origins, # or ["*"] to allow all
247
+ allow_credentials=True,
248
+ allow_methods=["*"],
249
+ allow_headers=["*"],
250
+ )
251
+ # (02/03/2025) Move static files UI to Vercel
252
+ # 3. Mount static files (make sure the "static" folder exists and contains your images)
253
+ # app.mount("/static", StaticFiles(directory="static"), name="static")
254
+ # 4. Get statics template route
255
+ # @app.get("/", response_class=HTMLResponse)
256
+ # async def get_home():
257
+ # return HTML_CONTENT
258
+
259
+ # 🔹 Chat route
260
+ @app.post("/chat")
261
+ async def chat_endpoint(data: dict):
262
+ user_query = data.get("query", "")
263
+ lang = data.get("lang", "EN") # Expect a language code from the request
264
+ if not user_query:
265
+ return JSONResponse(content={"response": "No query provided."})
266
+ start_time = time.time()
267
+ response_text = chatbot.chat(user_query, lang) # Pass language selection
268
+ end_time = time.time()
269
+ response_text += f"\n\n(Response time: {end_time - start_time:.2f} seconds)"
270
+ return JSONResponse(content={"response": response_text})
271
+
272
+ # 🔹 Main Execution
273
+ # 1. On Streamlit (free-tier allowance 1GB)
274
+ # 🌐 Start FastAPI server in a separate thread
275
+ # def run_fastapi():
276
+ # import uvicorn
277
+ # uvicorn.run(app, host="0.0.0.0", port=8000)
278
+ # threading.Thread(target=run_fastapi, daemon=True).start()
279
+ # # 🔍 Streamlit UI for Testing
280
+ # st.title("🩺 Medical Chatbot API")
281
+ # st.info("This is a **FastAPI Backend running on Streamlit Cloud**")
282
+ # user_query = st.text_input("Enter your medical question:")
283
+ # selected_lang = st.selectbox("Select Language:", ["English (EN)", "Vietnamese (VI)", "Chinese (ZH)"])
284
+ # if st.button("Ask Doctor Bot"):
285
+ # lang_code = selected_lang.split("(")[-1].strip(")")
286
+ # st.markdown("🤖 **DocBot is thinking...**")
287
+ # # a) API request to FastAPI
288
+ # response = requests.post("http://127.0.0.1:8000/chat", json={"query": user_query, "lang": lang_code})
289
+ # response_json = response.json()
290
+ # # b) Display response
291
+ # st.markdown(response_json["response"])
292
+
293
+ # 2. On Render (free-tier allowance 521MB)
294
+ # if __name__ == "__main__":
295
+ # import uvicorn
296
+ # print("\n🩺 Starting Medical Chatbot FastAPI server...\n")
297
+ # # 🌐 Start app
298
+ # uvicorn.run(app, host="0.0.0.0", port=8000)
299
+
300
+ # 3. On Hugging Face with Gradio (limited API request)
301
+ import gradio as gr
302
+ import uvicorn
303
+ gr.mount_gradio_app(app, gr.Interface(fn=chatbot.chat, inputs=["text", "text"], outputs="text"), path="/gradio")
304
+ if __name__ == "__main__":
305
+ uvicorn.run(app, host="0.0.0.0", port=7860)
clear_mongo.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pymongo import MongoClient
2
+ from dotenv import load_dotenv
3
+ import os
4
+
5
+ # # Load environment variables from .env
6
+ # load_dotenv()
7
+
8
+ ##-------------##
9
+ # FOR QA CLUSTER
10
+ ##-------------##
11
+
12
+ # mongo_uri = os.getenv("MONGO_URI")
13
+ # if not mongo_uri:
14
+ # raise ValueError("❌ MongoDB URI (MongoURI) is missing!")
15
+
16
+ # client = MongoClient(mongo_uri)
17
+ # db = client["MedicalChatbotDB"] # Use the same database name as in your main script
18
+
19
+ # # To drop just the collection storing the FAISS index:
20
+ # db.drop_collection("qa_data")
21
+ # print("Dropped collection 'qa_data' from MedicalChatbotDB.")
22
+
23
+ # # Alternatively, to drop the entire database:
24
+ # client.drop_database("MedicalChatbotDB")
25
+ # print("Dropped database 'MedicalChatbotDB'.")
26
+
27
+
28
+ ##-------------##
29
+ # FOR INDEX CLUSTER
30
+ ##-------------##
31
+
32
+ # Load environment variables from .env
33
+ # load_dotenv()
34
+ # index_uri = os.getenv("INDEX_URI")
35
+ # if not index_uri:
36
+ # raise ValueError("❌ MongoDB URI (IndexURI) is missing!")
37
+
38
+ # iclient = MongoClient(index_uri)
39
+ # idb = iclient["MedicalChatbotDB"] # Use the same database name as in your main script
40
+
41
+ # # To drop just the collection storing the FAISS index:
42
+ # idb.drop_collection("faiss_index_files.files")
43
+ # idb.drop_collection("faiss_index_files.chunks")
44
+ # print("Dropped collection 'faiss_index_files' and chunks from MedicalChatbotDB.")
45
+
46
+ # # Alternatively, to drop the entire database:
47
+ # iclient.drop_database("MedicalChatbotDB")
48
+ # print("Dropped database 'MedicalChatbotDB'.")
connect_mongo.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pymongo import MongoClient
2
+ from dotenv import load_dotenv
3
+ import os
4
+
5
+ # Test MongoDB connection, and list out all collection.
6
+ load_dotenv()
7
+
8
+ # QA Cluster
9
+ mongo_uri = os.getenv("MONGO_URI")
10
+ client = MongoClient(mongo_uri)
11
+ db = client["MedicalChatbotDB"]
12
+ # List all collection
13
+ print("QA Collection: ",db.list_collection_names())
14
+ # Count document QA related
15
+ print("QA count: ", db.qa_data.count_documents({}))
16
+
17
+ # Index Cluster
18
+ index_uri = os.getenv("INDEX_URI")
19
+ iclient = MongoClient(index_uri)
20
+ idb = iclient["MedicalChatbotDB"]
21
+ # List all collection
22
+ print("FAISS Collection: ",idb.list_collection_names())
23
+ # Count document QA related
24
+ print("Index count: ", idb.faiss_index_files.files.count_documents({}))
migrate.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Running this script to split FAISS index collection to the second/different cluster.
2
+ from pymongo import MongoClient
3
+ from dotenv import load_dotenv
4
+ import os
5
+
6
+ # Load environment variables from .env
7
+ load_dotenv()
8
+ # Connection strings (update as needed)
9
+ mongo_uri = os.getenv("MONGO_URI") # QA cluster connection string
10
+ index_uri = os.getenv("INDEX_URI") # FAISS index cluster connection string
11
+
12
+ if not mongo_uri:
13
+ raise ValueError("MONGO_URI is missing!")
14
+ if not index_uri:
15
+ raise ValueError("INDEX_URI is missing!")
16
+
17
+ # Connect to the QA cluster (where FAISS data was accidentally stored)
18
+ qa_client = MongoClient(mongo_uri)
19
+ qa_db = qa_client["MedicalChatbotDB"]
20
+
21
+ # Connect to the FAISS index cluster
22
+ faiss_client = MongoClient(index_uri)
23
+ faiss_db = faiss_client["MedicalChatbotDB"] # Use the same database name if desired
24
+
25
+ # Define the GridFS collections to move.
26
+ # In GridFS, files are stored in two collections: "<bucket>.files" and "<bucket>.chunks".
27
+ source_files = qa_db["faiss_index_files.files"]
28
+ source_chunks = qa_db["faiss_index_files.chunks"]
29
+
30
+ dest_files = faiss_db["faiss_index_files.files"]
31
+ dest_chunks = faiss_db["faiss_index_files.chunks"]
32
+
33
+ print("Moving FAISS index GridFS files...")
34
+
35
+ # Copy documents from the source 'files' collection
36
+ for doc in source_files.find():
37
+ dest_files.insert_one(doc)
38
+
39
+ # Copy documents from the source 'chunks' collection
40
+ for doc in source_chunks.find():
41
+ dest_chunks.insert_one(doc)
42
+
43
+ print("✅ FAISS GridFS collections moved successfully.")
44
+
45
+ # Optionally, drop the old collections from the QA cluster to free up space:
46
+ qa_db.drop_collection("faiss_index_files.files")
47
+ qa_db.drop_collection("faiss_index_files.chunks")
48
+ print("Old FAISS GridFS collections dropped from the QA cluster.")
requirements.txt ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # **Agents**
2
+ google-genai
3
+ huggingface_hub
4
+ # autogen-agentchat # Not using Autogen since not implementing multi-agent yet
5
+ # autogenstudio
6
+ faiss-cpu
7
+ sentence-transformers
8
+ # tiktoken # Not using OpenAI agent
9
+ # chromadb # Not used for RAG pipeline now
10
+ # datasets # Expect to load from Mongo only, no need to fetch dataset from HuggingFace unless re-embedding
11
+ # googletrans # Translate and process multi-language with LLM already
12
+ # **Environment**
13
+ python-dotenv # Not used in Streamlit deployment
14
+ pymongo
15
+ # **Deployment**
16
+ uvicorn
17
+ fastapi
18
+ gradio # On Huggingface deployment with gradio
19
+ # streamlit # On streamlit deployment with daemon
20
+ # requests