gauravmeena0708/epfo-circulars
0
1# answer_generator.py2 3import logging4from langchain_huggingface import HuggingFaceEndpoint5from langchain_huggingface.chat_models import ChatHuggingFace6from langchain_core.messages import HumanMessage 7import config8 9logger = logging.getLogger(__name__)10logging.basicConfig(level=config.LOG_LEVEL, format=config.LOG_FORMAT)11 12 13def _stream_llm_answer(llm_instance, messages):14 """Iterate the remote stream while keeping provider failures out of the UI."""15 try:16 yield from llm_instance.stream(messages)17 except Exception as e:18 logger.error(f"Error while streaming the Chat LLM response: {e}", exc_info=True)19 provider = getattr(config, "HF_INFERENCE_PROVIDER", "configured")20 yield (21 "The language-model service is temporarily unavailable. "22 f"Verify that the Hugging Face provider '{provider}' is enabled and "23 "that HF_TOKEN has Inference Providers permission."24 )25 26 27def format_prompt(query, retrieved_chunks_data):28 if not retrieved_chunks_data:29 context_str = "No relevant information found in the documents."30 else:31 context_parts = []32 for i, chunk_data in enumerate(retrieved_chunks_data):33 meta = chunk_data.get('metadata', {})34 title = meta.get('title') or "EPFO Document"35 circular_no = meta.get('circular_no') or "N/A"36 source_pdf = meta.get('english_pdf_link') or meta.get('source_pdf', 'N/A')37 page_no = meta.get('page_number', 'N/A')38 source_info = f"[Title: {title} | Identifier: {circular_no} | PDF: {source_pdf} | Page: {page_no}]"39 context_parts.append(f"Source [{i+1}] {source_info}:\n{chunk_data['text']}")40 context_str = "\n\n".join(context_parts)41 42 prompt = f"""You are a helpful and precise assistant specializing in Employees' Provident Fund Organisation (EPFO) rules, circulars, schemes, and manuals.43Answer the user's question based strictly on the context provided below.44Support factual claims with inline source numbers such as [1] or [2], matching the numbered sources below the answer.45Also mention relevant circular numbers, dates, or statutory sections when they are present in the context.46Never invent a source number or cite a source that does not support the claim.47If the provided context does not contain enough information to answer the question, state clearly that the information was not found in the documents.48 49Context from EPFO Documents:50-----------------------51{context_str}52-----------------------53 54Question: {query}55 56Helpful & Grounded Answer:"""57 return prompt58 59 60def get_llm_answer(query, retrieved_chunks_data, llm_instance, stream=False):61 if not query:62 logger.warning("Query is empty. Cannot generate answer.")63 return "No query provided."64 if llm_instance is None:65 logger.error("LLM instance is not provided. Cannot generate answer.")66 return "LLM not available."67 68 prompt_string = format_prompt(query, retrieved_chunks_data) 69 logger.debug(f"Formatted Prompt String for Chat LLM:\n{prompt_string}")70 71 logger.info(f"Sending prompt to Chat LLM for query: '{query[:100]}...'")72 messages = [HumanMessage(content=prompt_string)]73 74 if stream:75 return _stream_llm_answer(llm_instance, messages)76 77 try:78 response_message = llm_instance.invoke(messages)79 logger.info("Received response from Chat LLM.")80 if hasattr(response_message, 'content'):81 return response_message.content82 else:83 logger.error(f"Unexpected response type from Chat LLM: {type(response_message)}. Full response: {response_message}")84 return str(response_message)85 86 except Exception as e:87 logger.error(f"Error during Chat LLM invocation: {e}", exc_info=True)88 return "An error occurred while trying to generate an answer from the language model."89 90 91def initialize_llm(hf_token=None, max_new_tokens=None):92 token = hf_token or config.HF_TOKEN93 if not token:94 logger.error("Hugging Face API token (HF_TOKEN) is not set. LLM cannot be initialized.")95 raise ValueError("HF_TOKEN not found. LLM initialization failed.")96 97 try:98 logger.info(99 f"Initializing Chat LLM via HuggingFaceEndpoint: {config.LLM_REPO_ID}, "100 f"Task: {config.LLM_TASK}"101 )102 kwargs = {103 "repo_id": config.LLM_REPO_ID,104 "task": config.LLM_TASK,105 "temperature": config.LLM_TEMPERATURE,106 "max_new_tokens": max_new_tokens or getattr(config, "LLM_MAX_NEW_TOKENS", 2048),107 "huggingfacehub_api_token": token,108 }109 if getattr(config, "HF_INFERENCE_PROVIDER", None):110 kwargs["provider"] = config.HF_INFERENCE_PROVIDER111 112 endpoint = HuggingFaceEndpoint(**kwargs)113 chat_model = ChatHuggingFace(llm=endpoint)114 logger.info("ChatHuggingFace LLM initialized successfully.")115 return chat_model116 except Exception as e:117 logger.error(f"Failed to initialize Chat LLM: {e}", exc_info=True)118 raise119 120 121if __name__ == '__main__':122 logger.info("Starting Answer Generator test...")123 try:124 llm_service = initialize_llm()125 sample_query = "What is the procedure for joint declaration?"126 sample_context = [{127 "text": "Joint declaration SOP outlines the procedure for member profile correction.",128 "metadata": {"title": "SOP Joint Declaration", "source_pdf": "Circular_JD.pdf", "page_number": "1"}129 }]130 print(get_llm_answer(sample_query, sample_context, llm_service))131 except Exception as e:132 logger.info(f"Test run completed: {e}")133 