singhankur01 commited on
Commit
b38767f
·
verified ·
1 Parent(s): 55c0213

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -117
app.py CHANGED
@@ -1,4 +1,3 @@
1
-
2
  import os
3
  import json
4
  import re
@@ -14,6 +13,7 @@ from bs4 import BeautifulSoup
14
  from fastapi import FastAPI, Depends, HTTPException, Header
15
  from fastapi.responses import JSONResponse
16
 
 
17
  from utils.DocsLoader import load_and_chunk
18
  from utils.Schemas import RunRequest, RunResponse
19
  # from concurrent.futures import ThreadPoolExecutor
@@ -34,10 +34,9 @@ from langchain.prompts import ChatPromptTemplate
34
  # from langchain_nvidia_ai_endpoints.embeddings import NVIDIAEmbeddings
35
  # from langchain_nvidia_ai_endpoints.reranking import NVIDIARerank
36
 
37
- import os
38
  from sentence_transformers import SentenceTransformer
39
 
40
-
41
  MODEL_DIR = os.path.join("/tmp", "e5-large-v2")
42
 
43
  if not os.path.exists(MODEL_DIR):
@@ -53,6 +52,7 @@ load_dotenv()
53
  vector_cache = {}
54
  ml_models = {}
55
  secret = ""
 
56
  landmark_data = {
57
  "Delhi": "Gateway of India", "Mumbai": "India Gate", "Chennai": "Charminar",
58
  "Hyderabad": "Taj Mahal", "Ahmedabad": "Howrah Bridge", "Mysuru": "Golconda Fort",
@@ -69,6 +69,8 @@ landmark_data = {
69
  "Jakarta": "The Shard", "Vienna": "Blue Mosque", "Kathmandu": "Neuschwanstein Castle",
70
  "Los Angeles": "Buckingham Palace"
71
  }
 
 
72
  PRELOAD_URLS = [
73
  "https://hackrx.blob.core.windows.net/assets/Arogya%20Sanjeevani%20Policy%20-%20CIN%20-%20U10200WB1906GOI001713%201.pdf?sv=2023-01-03&st=2025-07-21T08%3A29%3A02Z&se=2025-09-22T08%3A29%3A00Z&sr=b&sp=r&sig=nzrz1K9Iurt%2BBXom%2FB%2BMPTFMFP3PRnIvEsipAX10Ig4%3D",
74
  "https://hackrx.blob.core.windows.net/assets/Super_Splendor_(Feb_2023).pdf?sv=2023-01-03&st=2025-07-21T08%3A10%3A00Z&se=2025-09-22T08%3A10%3A00Z&sr=b&sp=r&sig=vhHrl63YtrEOCsAy%2BpVKr20b3ZUo5HMz1lF9%2BJh6LQ0%3D",
@@ -91,7 +93,6 @@ PRELOAD_URLS = [
91
 
92
  @asynccontextmanager
93
  async def lifespan(app: FastAPI):
94
- # This code runs ONCE when the application starts up
95
  print("🚀 Initializing models and prompt template...")
96
 
97
  try:
@@ -107,11 +108,11 @@ async def lifespan(app: FastAPI):
107
  # raise RuntimeError("CRITICAL: Missing nvidia api key in environment secrets!")
108
 
109
 
110
- # Load models into the shared dictionary
111
  ml_models["embedder"] = HuggingFaceEmbeddings(
112
- # model_name="BAAI/bge-large-en-v1.5", #better but lil slower
113
  model_name="BAAI/bge-base-en-v1.5", #better but lil slower
114
- # model_name="intfloat/e5-large-v2", #lil faster but dont know response is slow
115
  # encode_kwargs={
116
  # "batch_size": 64,
117
  # # "normalize_embeddings": True
@@ -120,15 +121,15 @@ async def lifespan(app: FastAPI):
120
 
121
  )
122
  cross_encoder_model = HuggingFaceCrossEncoder(model_name="BAAI/bge-reranker-base")
123
- # cross_encoder_model = HuggingFaceCrossEncoder(model_name="BAAI/bge-reranker-large")
124
  ml_models["reranker_compressor"] = CrossEncoderReranker(model=cross_encoder_model, top_n=9)
 
125
  ml_models["llm"] = ChatGoogleGenerativeAI(
126
- # model="gemini-1.5-pro",
127
- model="gemini-2.5-flash",
128
  api_key=GOOGLE_API_KEY,
129
- # temperature=0.15,
130
- # max_output_tokens=300
131
  )
 
 
132
  ml_models["prompt_template"] = ChatPromptTemplate.from_template("""
133
  **Role**: You are an expert assistant in insurance, legal compliance, human resources, and contract management and general question answering.
134
 
@@ -173,7 +174,7 @@ Step 3 – **Final Output**:
173
  print("❌ Lifespan error:", str(e))
174
  raise e
175
 
176
- # Preload vectorstores for all URLs
177
  for url in PRELOAD_URLS:
178
  doc_url = str(url)
179
 
@@ -181,7 +182,7 @@ Step 3 – **Final Output**:
181
  print(f"📄 Processing new document: {doc_url}")
182
  chunks = load_and_chunk(doc_url)
183
 
184
- # Build vectorstore & save to cache
185
  vectorstore = await FAISS.afrom_documents(documents=chunks, embedding=ml_models["embedder"])
186
  vector_cache[doc_url] = vectorstore # store in memory cache
187
  print(f"✅ Vectorstore cached for: {doc_url}")
@@ -190,9 +191,9 @@ Step 3 – **Final Output**:
190
  print("🧹 Cleaning up.")
191
  ml_models.clear()
192
  # --- 2. FastAPI App Instance ---
193
- # We pass the lifespan function to the FastAPI constructor
194
  app = FastAPI(title="HackRX RAG Server", lifespan=lifespan)
195
 
 
196
  def store_secret(url: str):
197
  global secret
198
  url_c = url
@@ -207,54 +208,35 @@ def store_secret(url: str):
207
 
208
  # --- 3. API Key Verification ---
209
  TEAM_API_KEY = os.getenv("TEAM_API_KEY")
210
- TEAM_API_KEY2 = os.getenv("TEAM_API_KEY2")
211
 
212
  def verify_api_key(authorization: str = Header(...)):
213
  if not authorization.startswith("Bearer "):
214
  raise HTTPException(status_code=401, detail="Invalid Authorization header format")
215
  token = authorization.split("Bearer ")[1]
216
- if token != TEAM_API_KEY and token != TEAM_API_KEY2 and token != secret:
217
- raise HTTPException(status_code=403, detail="Invalid or missing API key")
218
-
219
-
220
- # --- 4. Parsing Helper ---
221
- def parse_llm_response(content: str) -> str:
222
- try:
223
- # Remove code fences and clean up
224
- content_cleaned = re.sub(r"^```json|```$", "", content.strip(), flags=re.IGNORECASE).strip()
225
- data = json.loads(content_cleaned)
226
-
227
- if isinstance(data, dict):
228
- if "decision" in data:
229
- decision = data.get("decision", "N/A").upper()
230
- amount = data.get("amount", "Not specified")
231
- justification = data.get("justification", "No justification provided.")
232
- return f"Decision: {decision}\nAmount: {amount}\nJustification: {justification}"
233
 
234
- elif "response" in data:
235
- return data["response"]
236
-
237
- return "The response was parsed but didn't match expected structure."
238
-
239
- except json.JSONDecodeError:
240
- return f"Unstructured response:\n{content.strip()}"
241
 
242
- except Exception as e:
243
- return f"An error occurred while processing the response: {str(e)}"
244
 
245
 
246
- # --- 5. Main API Endpoint ---
247
  @app.post("/api/v1/hackrx/run", response_model=RunResponse, dependencies=[Depends(verify_api_key)])
248
  async def run_hackrx(req: RunRequest):
 
249
  doc_url = str(req.documents)
250
  lower_url = doc_url.lower()
 
 
251
  if "get-secret-token" in lower_url:
252
  store_secret(doc_url)
253
  answers = []
254
  return JSONResponse({"answers": answers}, status_code=200)
 
 
 
255
  elif doc_url == "https://hackrx.blob.core.windows.net/hackrx/rounds/FinalRound4SubmissionPDF.pdf?sv=2023-01-03&spr=https&st=2025-08-07T14%3A23%3A48Z&se=2027-08-08T14%3A23%3A00Z&sr=b&sp=r&sig=nMtZ2x9aBvz%2FPjRWboEOZIGB%2FaGfNf5TfBOrhGqSv4M%3D":
256
  try:
257
- # print("Step 1: Querying for the assigned city...")
258
  city_url = "https://register.hackrx.in/submissions/myFavouriteCity"
259
  city_response = requests.get(city_url)
260
  city_response.raise_for_status()
@@ -265,114 +247,101 @@ async def run_hackrx(req: RunRequest):
265
  if not assigned_city:
266
  raise HTTPException(status_code=500, detail="City not found in response")
267
 
268
- print(f"Assigned city is: {assigned_city}")
269
- chk = {"Hyderabad", "Mumbai", "Pune", "London", "Seoul"}
270
- if assigned_city in chk:
271
- base_flight_url = "https://register.hackrx.in/teams/public/flights/"
272
- final_url = base_flight_url + "getFifthCityFlightNumber"
273
- flight_response = requests.get(final_url)
274
- flight_response.raise_for_status()
275
- flight_number = flight_response.json().get("data", {}).get("flightNumber")
276
- answers = []
277
- answers.append(f"Your flight number is {flight_number}")
278
- return JSONResponse({"answers": answers}, status_code=200)
279
- # Step 2: Decode the landmark
280
- # print(f"Step 2: Looking up the landmark for {assigned_city}...")
281
- else:
282
- landmark = landmark_data.get(assigned_city)
283
- if not landmark:
284
- raise HTTPException(status_code=404, detail=f"Landmark for city '{assigned_city}' not found")
285
-
286
- print(f"✅ Landmark found: {landmark}")
287
-
288
- # Step 3: Choose the flight path based on landmark
289
- # print("Step 3: Determining the correct flight path...")
290
- base_flight_url = "https://register.hackrx.in/teams/public/flights/"
291
- if landmark == "Gateway of India":
292
- final_url = base_flight_url + "getFirstCityFlightNumber"
293
- elif landmark == "Taj Mahal":
294
- final_url = base_flight_url + "getSecondCityFlightNumber"
295
- elif landmark == "Eiffel Tower":
296
- final_url = base_flight_url + "getThirdCityFlightNumber"
297
- elif landmark == "Big Ben":
298
- final_url = base_flight_url + "getFourthCityFlightNumber"
299
- else:
300
- final_url = base_flight_url + "getFifthCityFlightNumber"
301
 
302
- # print(f"✅ Correct flight path URL: {final_url}")
303
-
304
- # Step 4: Get the final flight number
305
- # print("Step 4: Getting the final flight number...")
306
- flight_response = requests.get(final_url)
307
- flight_response.raise_for_status()
308
- flight_number = flight_response.json().get("data", {}).get("flightNumber")
309
 
310
- if not flight_number:
311
- raise HTTPException(status_code=500, detail="Flight number not found")
312
 
313
- # print(f"🎉 MISSION COMPLETE! The flight number is: {flight_number}")
314
- answers = []
315
 
316
- answers.append(f"Your flight number is {flight_number}")
317
- return JSONResponse({"answers": answers}, status_code=200)
318
- # return JSONResponse({"solution_flight_number": flight_number}, status_code=200)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  except HTTPException:
320
  raise
321
  except requests.exceptions.RequestException as e:
322
  raise HTTPException(status_code=500, detail=f"An API call failed: {e}")
323
  except Exception as e:
324
  raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {e}")
325
-
326
 
327
  else:
328
  start_time = time.time()
329
- # if(doc_url not in vector_cache):
330
  chunks = load_and_chunk(str(req.documents))
 
331
  if not chunks:
332
  return JSONResponse({"error": "No documents could be processed."}, status_code=400)
 
333
  end_time = time.time() - start_time
 
334
  print(f"chunking done: {end_time}")
335
- # if not chunks:
336
- # return JSONResponse({"error": "No documents could be processed."}, status_code=400)
337
-
338
-
339
  start_time2 = time.time()
340
- # Reuse vectorstore if already cached
341
  if doc_url in vector_cache:
342
  print(f"♻ Using cached vectorstore for: {doc_url}")
343
  vectorstore = vector_cache[doc_url]
 
344
  else:
345
- print(f"📄 Processing new document: {doc_url}")
346
- # Build vectorstore & save to cache
347
  vectorstore = await FAISS.afrom_documents(documents=chunks, embedding=ml_models["embedder"])
348
  vector_cache[doc_url] = vectorstore # store in memory cache
349
- print(f"Vectorstore cached for: {doc_url}")
 
350
  end_time2 = time.time() - start_time2
351
  print(f"vector done: {end_time2}")
352
 
353
- # start_time2 = time.time()
354
- # vectorstore = await FAISS.afrom_documents(
355
- # documents=chunks,
356
- # embedding=ml_models["embedder"]
357
- # )
358
- # end_time2 = time.time() - start_time2
359
- # print(f"vector done: {end_time2}")
360
- # dense_retriever = vectorstore.as_retriever(search_type="mmr",search_kwargs={"k": 8})
361
- dense_retriever = vectorstore.as_retriever(search_type="mmr",search_kwargs={"k": 14 ,"lambda_mult": 0.7} ) # prev 16
362
- # dense_retriever = vectorstore.as_retriever(search_type="similarity" ,search_kwargs={"k": 11} )
363
 
364
 
365
  # Create retrievers using the pre-loaded models from our ml_models dictionary
366
  keyword_retriever = BM25Retriever.from_documents(chunks)
367
  keyword_retriever.k = 9 #prev 11
 
368
  # dense_retriever = Chroma.from_documents(documents=chunks, embedding=ml_models["embedder"]).as_retriever()
 
369
  ensemble_retriever = EnsembleRetriever(retrievers=[keyword_retriever, dense_retriever], weights=[0.3, 0.7],search_kwargs={"k": 14}) #prev 16
370
- ### to make it faster we are now using our built reranker thats why commenting the code below
 
 
 
371
  # compression_retriever = ContextualCompressionRetriever(
372
  # base_retriever=ensemble_retriever, base_compressor=ml_models["reranker_compressor"]
373
  # )
374
 
375
- # Define the RAG chain using pre-loaded components
376
  hybrid_rag_chain = (
377
  {"context": itemgetter("full_query") | ensemble_retriever, "full_query": itemgetter("full_query")}
378
  | ml_models["prompt_template"]
@@ -381,11 +350,9 @@ async def run_hackrx(req: RunRequest):
381
 
382
  tasks = [hybrid_rag_chain.ainvoke({"full_query": q}) for q in req.questions]
383
  results = await asyncio.gather(*tasks)
384
- # answers = [parse_llm_response(result.content) for result in results]
385
  answers = []
386
-
387
  for msg in results:
388
- # Safely access the content field
389
  if hasattr(msg, "content"):
390
  answers.append(msg.content.strip())
391
 
@@ -393,4 +360,4 @@ async def run_hackrx(req: RunRequest):
393
 
394
  @app.get("/", include_in_schema=False)
395
  def root():
396
- return {"message": "API is running. Go to /docs for documentation."}
 
 
1
  import os
2
  import json
3
  import re
 
13
  from fastapi import FastAPI, Depends, HTTPException, Header
14
  from fastapi.responses import JSONResponse
15
 
16
+
17
  from utils.DocsLoader import load_and_chunk
18
  from utils.Schemas import RunRequest, RunResponse
19
  # from concurrent.futures import ThreadPoolExecutor
 
34
  # from langchain_nvidia_ai_endpoints.embeddings import NVIDIAEmbeddings
35
  # from langchain_nvidia_ai_endpoints.reranking import NVIDIARerank
36
 
 
37
  from sentence_transformers import SentenceTransformer
38
 
39
+ #loading the model for SentenceTransformersTokenTextSplitter
40
  MODEL_DIR = os.path.join("/tmp", "e5-large-v2")
41
 
42
  if not os.path.exists(MODEL_DIR):
 
52
  vector_cache = {}
53
  ml_models = {}
54
  secret = ""
55
+
56
  landmark_data = {
57
  "Delhi": "Gateway of India", "Mumbai": "India Gate", "Chennai": "Charminar",
58
  "Hyderabad": "Taj Mahal", "Ahmedabad": "Howrah Bridge", "Mysuru": "Golconda Fort",
 
69
  "Jakarta": "The Shard", "Vienna": "Blue Mosque", "Kathmandu": "Neuschwanstein Castle",
70
  "Los Angeles": "Buckingham Palace"
71
  }
72
+
73
+ # preloading the documents to make faster response as free hf space cpu is slow
74
  PRELOAD_URLS = [
75
  "https://hackrx.blob.core.windows.net/assets/Arogya%20Sanjeevani%20Policy%20-%20CIN%20-%20U10200WB1906GOI001713%201.pdf?sv=2023-01-03&st=2025-07-21T08%3A29%3A02Z&se=2025-09-22T08%3A29%3A00Z&sr=b&sp=r&sig=nzrz1K9Iurt%2BBXom%2FB%2BMPTFMFP3PRnIvEsipAX10Ig4%3D",
76
  "https://hackrx.blob.core.windows.net/assets/Super_Splendor_(Feb_2023).pdf?sv=2023-01-03&st=2025-07-21T08%3A10%3A00Z&se=2025-09-22T08%3A10%3A00Z&sr=b&sp=r&sig=vhHrl63YtrEOCsAy%2BpVKr20b3ZUo5HMz1lF9%2BJh6LQ0%3D",
 
93
 
94
  @asynccontextmanager
95
  async def lifespan(app: FastAPI):
 
96
  print("🚀 Initializing models and prompt template...")
97
 
98
  try:
 
108
  # raise RuntimeError("CRITICAL: Missing nvidia api key in environment secrets!")
109
 
110
 
111
+ # Loading the models into the shared dictionary
112
  ml_models["embedder"] = HuggingFaceEmbeddings(
113
+ # model_name="BAAI/bge-large-en-v1.5", #better but lil more slower
114
  model_name="BAAI/bge-base-en-v1.5", #better but lil slower
115
+ # model_name="intfloat/e5-large-v2",
116
  # encode_kwargs={
117
  # "batch_size": 64,
118
  # # "normalize_embeddings": True
 
121
 
122
  )
123
  cross_encoder_model = HuggingFaceCrossEncoder(model_name="BAAI/bge-reranker-base")
124
+
125
  ml_models["reranker_compressor"] = CrossEncoderReranker(model=cross_encoder_model, top_n=9)
126
+
127
  ml_models["llm"] = ChatGoogleGenerativeAI(
128
+ model="gemini-2.5-flash", #using flash 2.5 as its give better result but slower than lower flash
 
129
  api_key=GOOGLE_API_KEY,
 
 
130
  )
131
+
132
+ # making the prompt (chain of thoughts)
133
  ml_models["prompt_template"] = ChatPromptTemplate.from_template("""
134
  **Role**: You are an expert assistant in insurance, legal compliance, human resources, and contract management and general question answering.
135
 
 
174
  print("❌ Lifespan error:", str(e))
175
  raise e
176
 
177
+ # Preloading vectorstores for all URLs
178
  for url in PRELOAD_URLS:
179
  doc_url = str(url)
180
 
 
182
  print(f"📄 Processing new document: {doc_url}")
183
  chunks = load_and_chunk(doc_url)
184
 
185
+ # Building vectorstore & save to cache
186
  vectorstore = await FAISS.afrom_documents(documents=chunks, embedding=ml_models["embedder"])
187
  vector_cache[doc_url] = vectorstore # store in memory cache
188
  print(f"✅ Vectorstore cached for: {doc_url}")
 
191
  print("🧹 Cleaning up.")
192
  ml_models.clear()
193
  # --- 2. FastAPI App Instance ---
 
194
  app = FastAPI(title="HackRX RAG Server", lifespan=lifespan)
195
 
196
+ # for realtime authorization
197
  def store_secret(url: str):
198
  global secret
199
  url_c = url
 
208
 
209
  # --- 3. API Key Verification ---
210
  TEAM_API_KEY = os.getenv("TEAM_API_KEY")
 
211
 
212
  def verify_api_key(authorization: str = Header(...)):
213
  if not authorization.startswith("Bearer "):
214
  raise HTTPException(status_code=401, detail="Invalid Authorization header format")
215
  token = authorization.split("Bearer ")[1]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
 
217
+ # 1st for initial team token , 2nd for real time token
218
+ if token != TEAM_API_KEY and token != secret:
219
+ raise HTTPException(status_code=403, detail="Invalid or missing API key")
 
 
 
 
220
 
 
 
221
 
222
 
223
+ # --- 4. Main API Endpoint ---
224
  @app.post("/api/v1/hackrx/run", response_model=RunResponse, dependencies=[Depends(verify_api_key)])
225
  async def run_hackrx(req: RunRequest):
226
+
227
  doc_url = str(req.documents)
228
  lower_url = doc_url.lower()
229
+
230
+ # for setting the secret-token in realtime
231
  if "get-secret-token" in lower_url:
232
  store_secret(doc_url)
233
  answers = []
234
  return JSONResponse({"answers": answers}, status_code=200)
235
+
236
+ # for flight problem (trying to bring Sachin ji back to the real world ... he should not have slept!!! because now we are not able to sleep )
237
+
238
  elif doc_url == "https://hackrx.blob.core.windows.net/hackrx/rounds/FinalRound4SubmissionPDF.pdf?sv=2023-01-03&spr=https&st=2025-08-07T14%3A23%3A48Z&se=2027-08-08T14%3A23%3A00Z&sr=b&sp=r&sig=nMtZ2x9aBvz%2FPjRWboEOZIGB%2FaGfNf5TfBOrhGqSv4M%3D":
239
  try:
 
240
  city_url = "https://register.hackrx.in/submissions/myFavouriteCity"
241
  city_response = requests.get(city_url)
242
  city_response.raise_for_status()
 
247
  if not assigned_city:
248
  raise HTTPException(status_code=500, detail="City not found in response")
249
 
250
+ print(f"Assigned city is: {assigned_city}")
251
+
252
+ landmark = landmark_data.get(assigned_city)
253
+
254
+ if not landmark:
255
+ raise HTTPException(status_code=404, detail=f"Landmark for city '{assigned_city}' not found")
256
+
257
+ print(f"Landmark found: {landmark}")
258
+
259
+ base_flight_url = "https://register.hackrx.in/teams/public/flights/"
260
+
261
+ if landmark == "Gateway of India":
262
+ final_url = base_flight_url + "getFirstCityFlightNumber"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
 
264
+ elif landmark == "Taj Mahal":
265
+ final_url = base_flight_url + "getSecondCityFlightNumber"
 
 
 
 
 
266
 
267
+ elif landmark == "Eiffel Tower":
268
+ final_url = base_flight_url + "getThirdCityFlightNumber"
269
 
270
+ elif landmark == "Big Ben":
271
+ final_url = base_flight_url + "getFourthCityFlightNumber"
272
 
273
+ else:
274
+ final_url = base_flight_url + "getFifthCityFlightNumber"
275
+
276
+ flight_response = requests.get(final_url)
277
+ flight_response.raise_for_status()
278
+
279
+ #fetching flight number
280
+ flight_number = flight_response.json().get("data", {}).get("flightNumber")
281
+
282
+ if not flight_number:
283
+ raise HTTPException(status_code=500, detail="Flight number not found")
284
+
285
+ answers = []
286
+ answers.append(f"Your flight number is {flight_number}")
287
+
288
+ return JSONResponse({"answers": answers}, status_code=200)
289
+
290
  except HTTPException:
291
  raise
292
  except requests.exceptions.RequestException as e:
293
  raise HTTPException(status_code=500, detail=f"An API call failed: {e}")
294
  except Exception as e:
295
  raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {e}")
296
+
297
 
298
  else:
299
  start_time = time.time()
 
300
  chunks = load_and_chunk(str(req.documents))
301
+
302
  if not chunks:
303
  return JSONResponse({"error": "No documents could be processed."}, status_code=400)
304
+
305
  end_time = time.time() - start_time
306
+
307
  print(f"chunking done: {end_time}")
308
+
 
 
 
309
  start_time2 = time.time()
310
+ # Reuse vectorstore if already cached
311
  if doc_url in vector_cache:
312
  print(f"♻ Using cached vectorstore for: {doc_url}")
313
  vectorstore = vector_cache[doc_url]
314
+
315
  else:
316
+ print(f"Processing new document: {doc_url}")
317
+ # Build FAISS vectorstore & save to cache
318
  vectorstore = await FAISS.afrom_documents(documents=chunks, embedding=ml_models["embedder"])
319
  vector_cache[doc_url] = vectorstore # store in memory cache
320
+ print(f"Vectorstore cached for: {doc_url}")
321
+
322
  end_time2 = time.time() - start_time2
323
  print(f"vector done: {end_time2}")
324
 
325
+ dense_retriever = vectorstore.as_retriever(search_type="mmr",search_kwargs={"k": 14 ,"lambda_mult": 0.7} ) # prev used 16
326
+ # dense_retriever = vectorstore.as_retriever(search_type="similarity" ,search_kwargs={"k": 11} ) # for full sementic
 
 
 
 
 
 
 
 
327
 
328
 
329
  # Create retrievers using the pre-loaded models from our ml_models dictionary
330
  keyword_retriever = BM25Retriever.from_documents(chunks)
331
  keyword_retriever.k = 9 #prev 11
332
+
333
  # dense_retriever = Chroma.from_documents(documents=chunks, embedding=ml_models["embedder"]).as_retriever()
334
+
335
  ensemble_retriever = EnsembleRetriever(retrievers=[keyword_retriever, dense_retriever], weights=[0.3, 0.7],search_kwargs={"k": 14}) #prev 16
336
+
337
+ # sadly commenting reranker as it take larger time in cpu but is using GPU make use of it
338
+ #Also if using GPU chnage the ensemble retriver in rag chain to compression_retriever
339
+
340
  # compression_retriever = ContextualCompressionRetriever(
341
  # base_retriever=ensemble_retriever, base_compressor=ml_models["reranker_compressor"]
342
  # )
343
 
344
+ # RAG chain
345
  hybrid_rag_chain = (
346
  {"context": itemgetter("full_query") | ensemble_retriever, "full_query": itemgetter("full_query")}
347
  | ml_models["prompt_template"]
 
350
 
351
  tasks = [hybrid_rag_chain.ainvoke({"full_query": q}) for q in req.questions]
352
  results = await asyncio.gather(*tasks)
353
+
354
  answers = []
 
355
  for msg in results:
 
356
  if hasattr(msg, "content"):
357
  answers.append(msg.content.strip())
358
 
 
360
 
361
  @app.get("/", include_in_schema=False)
362
  def root():
363
+ return {"message": "API is running."}