Spaces:
Sleeping
Sleeping
| from langchain_community.vectorstores import FAISS | |
| from langchain_huggingface import HuggingFaceEmbeddings | |
| from langchain.memory import ConversationBufferMemory | |
| from langchain_groq import ChatGroq | |
| from langchain.chains import ConversationalRetrievalChain | |
| from langchain.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate | |
| from config import VECTOR_DIR, EMBED_MODEL, GROQ_API_KEY, GROQ_MODEL | |
| # ---- Memory for our rag system---- | |
| memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True) | |
| #we are going to reset memory if new pdf uplaod | |
| def reset_memory(): | |
| """Clear previous conversation memory (use after ingesting a new PDF)""" | |
| memory.clear() | |
| def normalize_question(question: str) -> str: | |
| """ | |
| Ensure the question starts with 'What' if not already starting | |
| with Who/When/Where/Why/How/What/tell me about/summarize. | |
| """ | |
| question = question.strip() | |
| if question == "": | |
| return "What?" | |
| first_word = question.split()[0].lower() | |
| wh_words = ["what", "who", "when", "where", "why", "how","tell me about"] | |
| if first_word not in wh_words: | |
| question = "What " + question[0].lower() + question[1:] if len(question) > 0 else "What?" | |
| return question | |
| def build_chain(): | |
| embeddings = HuggingFaceEmbeddings(model_name=EMBED_MODEL) | |
| vectordb = FAISS.load_local(VECTOR_DIR, embeddings, allow_dangerous_deserialization=True) | |
| retriever = vectordb.as_retriever(search_kwargs={"k": 3}) | |
| llm = ChatGroq(model=GROQ_MODEL, api_key=GROQ_API_KEY, temperature=0.1) | |
| # ---- System + Human Prompt with diverse prompt engineering---- | |
| chat_prompt = ChatPromptTemplate.from_messages([ | |
| #this is a system message | |
| SystemMessagePromptTemplate.from_template( | |
| "You are a highly knowledgeable financial expert assistant. " | |
| "Use the context provided to answer the user question accurately. " | |
| "Always provide the answer in clear, concise sentences. " | |
| "Cite the reference (page number or section title) from the PDF where the information was found. " | |
| "If the answer is not present in the context, say 'The information is not available in the provided document.'" | |
| ), | |
| #this is a human message | |
| HumanMessagePromptTemplate.from_template( | |
| """Context: | |
| {context} | |
| User Question: | |
| {question} | |
| Instructions: | |
| - Answer the question clearly and concisely. | |
| - Always start the answer naturally (What, Who, When, Where, Why, How,tell me about ,summarize) depending on the question. | |
| - Include the reference where the information is found in the format: Reference: page:X or section name. | |
| - If the information is not in the context, state clearly that it is not available. | |
| Answer: | |
| """ | |
| ) | |
| ]) | |
| # this fuction make our orginal chain | |
| chain = ConversationalRetrievalChain.from_llm( | |
| llm=llm, | |
| retriever=retriever, | |
| memory=memory, | |
| combine_docs_chain_kwargs={"prompt": chat_prompt} | |
| ) | |
| return chain | |
| # this method responsible for question answering | |
| def answer(user_question: str) -> str: | |
| """ | |
| Normalize the user's question and ask the RAG chain. | |
| """ | |
| question = normalize_question(user_question) | |
| chain = build_chain() | |
| result = chain.invoke({"question": question}) | |
| return result.get("answer") or result.get("result") or "No answer." | |