Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -25,9 +25,9 @@ from sklearn.metrics.pairwise import cosine_similarity
|
|
| 25 |
import numpy as np
|
| 26 |
|
| 27 |
### to make it faster we are now using our built reranker thats why commenting the imports below
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
from langchain.prompts import PromptTemplate
|
| 32 |
|
| 33 |
|
|
@@ -53,9 +53,9 @@ async def lifespan(app: FastAPI):
|
|
| 53 |
# Load models into the shared dictionary
|
| 54 |
ml_models["embedder"] = HuggingFaceEmbeddings(model_name="BAAI/bge-base-en-v1.5")
|
| 55 |
### to make it faster we are now using our built reranker thats why commenting the code below
|
| 56 |
-
|
| 57 |
# cross_encoder_model = HuggingFaceCrossEncoder(model_name="BAAI/bge-reranker-large")
|
| 58 |
-
|
| 59 |
ml_models["llm"] = ChatGoogleGenerativeAI(model="gemini-2.0-flash", api_key=GOOGLE_API_KEY)
|
| 60 |
ml_models["prompt_template"] = PromptTemplate.from_template("""
|
| 61 |
You are an expert decision maker Assistant in the domain such as insurance, legal compliance, human resources, and contract management.
|
|
@@ -172,21 +172,21 @@ async def run_hackrx(req: RunRequest):
|
|
| 172 |
# dense_retriever = Chroma.from_documents(documents=chunks, embedding=ml_models["embedder"]).as_retriever()
|
| 173 |
ensemble_retriever = EnsembleRetriever(retrievers=[keyword_retriever, dense_retriever], weights=[0.4, 0.6])
|
| 174 |
### to make it faster we are now using our built reranker thats why commenting the code below
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
|
| 179 |
|
| 180 |
# Define the RAG chain using pre-loaded components
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
|
| 187 |
######## OUR SELF RERANKER ######################################################################
|
| 188 |
#Embed all questions at once
|
| 189 |
-
question_embeddings = ml_models["embedder"].embed_documents(req.questions)
|
| 190 |
|
| 191 |
# For each question, retrieve and rerank with cosine
|
| 192 |
# retrieved_chunks_all = []
|
|
@@ -204,66 +204,66 @@ async def run_hackrx(req: RunRequest):
|
|
| 204 |
# # Join for context
|
| 205 |
# joined_context = "\n\n".join(top_chunks)
|
| 206 |
# retrieved_chunks_all.append(joined_context)
|
| 207 |
-
def mmr_select(query_embedding, doc_embeddings, k=6, lambda_mult=0.6):
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
|
| 211 |
|
| 212 |
-
|
| 213 |
-
|
| 214 |
|
| 215 |
-
|
| 216 |
-
|
| 217 |
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
|
| 235 |
-
|
| 236 |
-
async def async_retrieve_and_rerank(question: str, q_idx: int):
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
)
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
# Retrieve and rerank all in parallel
|
| 252 |
-
retrieved_chunks_all = await asyncio.gather(
|
| 253 |
-
|
| 254 |
-
)
|
| 255 |
|
| 256 |
####################################################################################################################
|
| 257 |
|
| 258 |
-
tasks = []
|
| 259 |
-
for i in range(len(req.questions)):
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
tasks.append(ml_models["llm"].ainvoke(ml_models["prompt_template"].format_prompt(**prompt_input)))
|
| 265 |
-
# tasks = [hybrid_rag_chain.ainvoke({"full_query": q}) for q in req.questions]
|
| 266 |
-
results = await asyncio.gather(*tasks)
|
| 267 |
# answers = []
|
| 268 |
|
| 269 |
# for msg in results:
|
|
@@ -271,6 +271,8 @@ async def run_hackrx(req: RunRequest):
|
|
| 271 |
# if hasattr(msg, "content"):
|
| 272 |
# answers.append(msg.content.strip())
|
| 273 |
# # Extract the content from each result and parse it
|
|
|
|
|
|
|
| 274 |
answers = [parse_llm_response(result.content) for result in results]
|
| 275 |
|
| 276 |
return JSONResponse({"answers": answers}, status_code=200)
|
|
|
|
| 25 |
import numpy as np
|
| 26 |
|
| 27 |
### to make it faster we are now using our built reranker thats why commenting the imports below
|
| 28 |
+
from langchain.retrievers import ContextualCompressionRetriever
|
| 29 |
+
from langchain.retrievers.document_compressors import CrossEncoderReranker
|
| 30 |
+
from langchain_community.cross_encoders import HuggingFaceCrossEncoder
|
| 31 |
from langchain.prompts import PromptTemplate
|
| 32 |
|
| 33 |
|
|
|
|
| 53 |
# Load models into the shared dictionary
|
| 54 |
ml_models["embedder"] = HuggingFaceEmbeddings(model_name="BAAI/bge-base-en-v1.5")
|
| 55 |
### to make it faster we are now using our built reranker thats why commenting the code below
|
| 56 |
+
cross_encoder_model = HuggingFaceCrossEncoder(model_name="BAAI/bge-reranker-base")
|
| 57 |
# cross_encoder_model = HuggingFaceCrossEncoder(model_name="BAAI/bge-reranker-large")
|
| 58 |
+
ml_models["reranker_compressor"] = CrossEncoderReranker(model=cross_encoder_model, top_n=5)
|
| 59 |
ml_models["llm"] = ChatGoogleGenerativeAI(model="gemini-2.0-flash", api_key=GOOGLE_API_KEY)
|
| 60 |
ml_models["prompt_template"] = PromptTemplate.from_template("""
|
| 61 |
You are an expert decision maker Assistant in the domain such as insurance, legal compliance, human resources, and contract management.
|
|
|
|
| 172 |
# dense_retriever = Chroma.from_documents(documents=chunks, embedding=ml_models["embedder"]).as_retriever()
|
| 173 |
ensemble_retriever = EnsembleRetriever(retrievers=[keyword_retriever, dense_retriever], weights=[0.4, 0.6])
|
| 174 |
### to make it faster we are now using our built reranker thats why commenting the code below
|
| 175 |
+
compression_retriever = ContextualCompressionRetriever(
|
| 176 |
+
base_retriever=ensemble_retriever, base_compressor=ml_models["reranker_compressor"]
|
| 177 |
+
)
|
| 178 |
|
| 179 |
|
| 180 |
# Define the RAG chain using pre-loaded components
|
| 181 |
+
hybrid_rag_chain = (
|
| 182 |
+
{"context": itemgetter("full_query") | compression_retriever, "full_query": itemgetter("full_query")}
|
| 183 |
+
| ml_models["prompt_template"]
|
| 184 |
+
| ml_models["llm"]
|
| 185 |
+
)
|
| 186 |
|
| 187 |
######## OUR SELF RERANKER ######################################################################
|
| 188 |
#Embed all questions at once
|
| 189 |
+
# question_embeddings = ml_models["embedder"].embed_documents(req.questions)
|
| 190 |
|
| 191 |
# For each question, retrieve and rerank with cosine
|
| 192 |
# retrieved_chunks_all = []
|
|
|
|
| 204 |
# # Join for context
|
| 205 |
# joined_context = "\n\n".join(top_chunks)
|
| 206 |
# retrieved_chunks_all.append(joined_context)
|
| 207 |
+
# def mmr_select(query_embedding, doc_embeddings, k=6, lambda_mult=0.6):
|
| 208 |
+
# selected = []
|
| 209 |
+
# candidates = list(range(len(doc_embeddings)))
|
| 210 |
+
# doc_embeddings = np.array(doc_embeddings)
|
| 211 |
|
| 212 |
+
# # Convert query_embedding to 2D
|
| 213 |
+
# query_embedding = np.array(query_embedding).reshape(1, -1)
|
| 214 |
|
| 215 |
+
# # Compute similarity between query and all documents
|
| 216 |
+
# query_doc_sims = cosine_similarity(query_embedding, doc_embeddings)[0]
|
| 217 |
|
| 218 |
+
# for _ in range(k):
|
| 219 |
+
# mmr_score = []
|
| 220 |
+
# for idx in candidates:
|
| 221 |
+
# if not selected:
|
| 222 |
+
# diversity = 0
|
| 223 |
+
# else:
|
| 224 |
+
# selected_embeddings = doc_embeddings[selected]
|
| 225 |
+
# diversity = max(cosine_similarity(
|
| 226 |
+
# doc_embeddings[idx].reshape(1, -1),
|
| 227 |
+
# selected_embeddings
|
| 228 |
+
# )[0])
|
| 229 |
+
# score = lambda_mult * query_doc_sims[idx] - (1 - lambda_mult) * diversity
|
| 230 |
+
# mmr_score.append(score)
|
| 231 |
+
# selected_idx = candidates[np.argmax(mmr_score)]
|
| 232 |
+
# selected.append(selected_idx)
|
| 233 |
+
# candidates.remove(selected_idx)
|
| 234 |
|
| 235 |
+
# return selected
|
| 236 |
+
# async def async_retrieve_and_rerank(question: str, q_idx: int):
|
| 237 |
+
# docs = await ensemble_retriever.ainvoke(question)
|
| 238 |
+
# doc_texts = [doc.page_content for doc in docs]
|
| 239 |
+
# doc_embeddings = ml_models["embedder"].embed_documents(doc_texts)
|
| 240 |
+
# # sims = cosine_similarity([question_embeddings[q_idx]], doc_embeddings)[0]
|
| 241 |
+
# query_embedding = question_embeddings[q_idx]
|
| 242 |
+
# selected_indices = mmr_select(
|
| 243 |
+
# query_embedding=query_embedding,
|
| 244 |
+
# doc_embeddings=doc_embeddings,
|
| 245 |
+
# k=6,
|
| 246 |
+
# lambda_mult=0.6,
|
| 247 |
+
# )
|
| 248 |
+
# # top_indices = np.argsort(sims)[-top_k:][::-1]
|
| 249 |
+
# top_chunks = [doc_texts[j] for j in selected_indices]
|
| 250 |
+
# return "\n\n".join(top_chunks)
|
| 251 |
+
# # Retrieve and rerank all in parallel
|
| 252 |
+
# retrieved_chunks_all = await asyncio.gather(
|
| 253 |
+
# *[async_retrieve_and_rerank(q, i) for i, q in enumerate(req.questions)]
|
| 254 |
+
# )
|
| 255 |
|
| 256 |
####################################################################################################################
|
| 257 |
|
| 258 |
+
# tasks = []
|
| 259 |
+
# for i in range(len(req.questions)):
|
| 260 |
+
# prompt_input = {
|
| 261 |
+
# "full_query": req.questions[i],
|
| 262 |
+
# "context": retrieved_chunks_all[i]
|
| 263 |
+
# }
|
| 264 |
+
# tasks.append(ml_models["llm"].ainvoke(ml_models["prompt_template"].format_prompt(**prompt_input)))
|
| 265 |
+
# # tasks = [hybrid_rag_chain.ainvoke({"full_query": q}) for q in req.questions]
|
| 266 |
+
# results = await asyncio.gather(*tasks)
|
| 267 |
# answers = []
|
| 268 |
|
| 269 |
# for msg in results:
|
|
|
|
| 271 |
# if hasattr(msg, "content"):
|
| 272 |
# answers.append(msg.content.strip())
|
| 273 |
# # Extract the content from each result and parse it
|
| 274 |
+
tasks = [hybrid_rag_chain.ainvoke({"full_query": q}) for q in req.questions]
|
| 275 |
+
results = await asyncio.gather(*tasks)
|
| 276 |
answers = [parse_llm_response(result.content) for result in results]
|
| 277 |
|
| 278 |
return JSONResponse({"answers": answers}, status_code=200)
|