from qdrant_client import QdrantClient from qdrant_client.http import models from app.core.config import QDRANT_PATH, RERANK_MODEL_NAME, get_embeddings, COLLECTION_NAME _rerank_model = None _qdrant_client = None def get_rerank_model(): global _rerank_model if _rerank_model is None: from sentence_transformers import CrossEncoder _rerank_model = CrossEncoder(RERANK_MODEL_NAME, device='cpu') return _rerank_model def get_qdrant_client(): global _qdrant_client if _qdrant_client is None: _qdrant_client = QdrantClient(path=QDRANT_PATH) return _qdrant_client def hybrid_retrieval(routing_result: dict): queries = routing_result.get("queries", []) target_col = COLLECTION_NAME client = get_qdrant_client() embeddings = get_embeddings() all_docs_content = [] for q in queries: query_vector = embeddings.embed_query(q) try: search_result = client.query_points( collection_name=target_col, query=query_vector, using="dense", limit=3 ).points for point in search_result: content = point.payload.get('page_content', '') if content: all_docs_content.append(content) except Exception as e: import traceback traceback.print_exc() unique_contexts = [] seen = set() for text in all_docs_content: if text not in seen: unique_contexts.append(text) seen.add(text) return "\n\n---\n\n".join(unique_contexts) def apply_post_retrieval_rerank(user_query: str, retrieved_texts: str, top_n: int = 3): doc_list = retrieved_texts.split("\n\n---\n\n") doc_list = [d for d in doc_list if d.strip()] if not doc_list: return "Không tìm thấy ngữ cảnh phù hợp." rerank_model = get_rerank_model() pairs = [[user_query, doc] for doc in doc_list] scores = rerank_model.predict(pairs) # Xử lý trường hợp model trả về mảng 2 chiều (logits cho [irrelevant, relevant]) if len(scores.shape) > 1 and scores.shape[1] > 1: scores = scores[:, 1] elif len(scores.shape) > 1 and scores.shape[1] == 1: scores = scores.flatten() scored_docs = sorted(zip(scores.tolist(), doc_list), key=lambda x: x[0], reverse=True) final_docs = [doc for score, doc in scored_docs[:top_n]] return "\n\n---\n\n".join(final_docs)