Spaces:
Sleeping
Sleeping
| from langchain_core.runnables import RunnablePassthrough | |
| from langchain_core.output_parsers import StrOutputParser | |
| from langchain_core.prompts import ChatPromptTemplate | |
| from app.core.retriever import hybrid_retriever | |
| from app.core.reranker import document_reranker | |
| from app.core.generator import llm_generator | |
| from app.core.cache import semantic_cache | |
| from app.core.memory import conversation_memory | |
| from app.utils.prompts import get_rag_template, get_conversation_template, get_system_prompt | |
| from app.utils.logger import logger | |
| from app.config import config | |
| from typing import AsyncIterator | |
| class RAGPipeline: | |
| def __init__(self): | |
| self.retriever = hybrid_retriever | |
| self.reranker = document_reranker | |
| self.generator = llm_generator | |
| self.cache = semantic_cache | |
| self.memory = conversation_memory | |
| self.use_cache = config["rag"]["cache"]["enabled"] | |
| self.use_reranking = config["rag"]["retrieval"]["rerank"] | |
| self.top_k = config["rag"]["retrieval"]["top_k"] | |
| logger.info("RAG Pipeline initialized") | |
| def _format_context(self, documents: list) -> str: | |
| """Format retrieved documents into context string.""" | |
| context_parts = [] | |
| for i, doc in enumerate(documents, 1): | |
| context_parts.append(f"[{i}] {doc.page_content}") | |
| return "\n\n".join(context_parts) | |
| async def _retrieve_and_rerank(self, query: str) -> list: | |
| """Retrieve and optionally rerank documents.""" | |
| # Retrieve documents | |
| documents = await self.retriever.ainvoke(query) | |
| if not documents: | |
| logger.warning("No documents retrieved") | |
| return [] | |
| logger.info(f"Retrieved {len(documents)} documents") | |
| # Rerank if enabled | |
| if self.use_reranking: | |
| documents = self.reranker.rerank(query, documents, top_k=self.top_k) | |
| logger.info(f"Reranked to top {len(documents)} documents") | |
| return documents[:self.top_k] | |
| async def generate( | |
| self, | |
| query: str, | |
| session_id: str = None, | |
| use_context: bool = True | |
| ) -> str: | |
| """Generate response for query with optional RAG context.""" | |
| # Check cache first | |
| if self.use_cache: | |
| cached_response = await self.cache.get(query, use_context) | |
| if cached_response: | |
| logger.info("Cache hit") | |
| return cached_response | |
| # Get conversation history if session provided | |
| history = [] | |
| if session_id: | |
| history = self.memory.get_messages(session_id) | |
| # Retrieve and rerank documents if context needed | |
| context = "" | |
| if use_context: | |
| documents = await self._retrieve_and_rerank(query) | |
| if documents: | |
| context = self._format_context(documents) | |
| # Build prompt | |
| if context: | |
| template = get_rag_template() | |
| prompt = template.format(context=context, question=query) | |
| else: | |
| template = get_conversation_template() | |
| prompt = template.format(question=query) | |
| # Generate response | |
| system_prompt = get_system_prompt() | |
| response = await self.generator.agenerate(prompt, system_prompt) | |
| # Save to memory if session provided | |
| if session_id: | |
| self.memory.add_message(session_id, "user", query) | |
| self.memory.add_message(session_id, "assistant", response) | |
| # Cache the response | |
| if self.use_cache: | |
| await self.cache.set(query, response, use_context) | |
| logger.info("Response generated successfully") | |
| return response | |
| async def stream( | |
| self, | |
| query: str, | |
| session_id: str = None, | |
| use_context: bool = True | |
| ) -> AsyncIterator[str]: | |
| """Stream response for query with optional RAG context.""" | |
| # Check cache first | |
| if self.use_cache: | |
| cached_response = await self.cache.get(query, use_context) | |
| if cached_response: | |
| logger.info("Cache hit - streaming cached response") | |
| yield cached_response | |
| return | |
| # Get conversation history if session provided | |
| history = [] | |
| if session_id: | |
| history = self.memory.get_messages(session_id) | |
| # Retrieve and rerank documents if context needed | |
| context = "" | |
| if use_context: | |
| documents = await self._retrieve_and_rerank(query) | |
| if documents: | |
| context = self._format_context(documents) | |
| # Build prompt | |
| if context: | |
| template = get_rag_template() | |
| prompt = template.format(context=context, question=query) | |
| else: | |
| template = get_conversation_template() | |
| prompt = template.format(question=query) | |
| # Stream response | |
| system_prompt = get_system_prompt() | |
| full_response = "" | |
| async for chunk in self.generator.stream(prompt, system_prompt): | |
| full_response += chunk | |
| yield chunk | |
| # Save to memory if session provided | |
| if session_id: | |
| self.memory.add_message(session_id, "user", query) | |
| self.memory.add_message(session_id, "assistant", full_response) | |
| # Cache the full response | |
| if self.use_cache: | |
| await self.cache.set(query, full_response, use_context) | |
| logger.info("Response streamed successfully") | |
| rag_pipeline = RAGPipeline() | |