import streamlit as st from transformers import pipeline from similarity_search import get_relevant_context # Import function from similarity_search.py from bs4 import BeautifulSoup # For stripping HTML/XML tags import spacy # Import spaCy for NLP tasks # Load the spaCy model (make sure to download it first via 'python -m spacy download en_core_web_sm') nlp = spacy.load("en_core_web_sm") # Load the Roberta model for question answering def load_qa_model(): print("Loading QA model...") try: qa_model = pipeline("question-answering", model="deepset/roberta-base-squad2") print("QA model loaded.") return qa_model except Exception as e: print(f"Error loading QA model: {e}") raise RuntimeError("Failed to load the QA model.") # Function to clean the context text (remove HTML tags and optional stop words) def clean_text(context, remove_stop_words=False): # Remove HTML/XML tags clean_context = BeautifulSoup(context, "html.parser").get_text() if remove_stop_words: stop_words = set(["the", "a", "an", "of", "and", "to", "in", "for", "on", "at", "by", "with", "about", "as", "from"]) clean_context = " ".join([word for word in clean_context.split() if word.lower() not in stop_words]) return clean_context # Function to extract proper nouns or pronouns from the question for context retrieval def extract_topic_from_question(question): # Process the text with spaCy doc = nlp(question) # Define pronouns to exclude manually if necessary excluded_pronouns = ['I', 'you', 'he', 'she', 'it', 'they', 'we', 'them', 'this', 'that', 'these', 'those'] # Extract proper nouns (PROPN) and pronouns (PRON), but exclude certain pronouns and stopwords proper_nouns_or_pronouns = [ token.text for token in doc if ( token.pos_ == 'PROPN' or token.pos_ == 'PRON') and token.text.lower() not in excluded_pronouns and not token.is_stop ] # If no proper nouns or pronouns are found, remove stopwords and return whatever is left if not proper_nouns_or_pronouns: remaining_tokens = [ token.text for token in doc if not token.is_stop # Just remove stopwords, keep all other tokens ] return " ".join(remaining_tokens) # Otherwise, return the proper nouns or pronouns return " ".join(proper_nouns_or_pronouns) # Inside the answer_question_with_context function, add debugging statements: def answer_question_with_context(question, qa_model): try: print(question) # Extract topic from question (proper nouns or pronouns) topic = extract_topic_from_question(question) print(f"Extracted topic (proper nouns or pronouns): {topic}" if topic else "No proper nouns or pronouns extracted.") # Retrieve relevant context based on the extracted topic context = get_relevant_context(question, topic) print(f"Retrieved Context: {context}") # Debug: Show context result if not context.strip(): return "No context found for answering.", "" # Clean the context context = clean_text(context, remove_stop_words=True) # Use the QA model to extract an answer from the context result = qa_model(question=question, context=context) return result.get('answer', 'No answer found.'), context except Exception as e: print(f"Error during question answering: {e}") # Debug: Log error in terminal return f"Error during question answering: {e}", "" # Streamlit UI def main(): st.title("RAG Question Answering with Context Retrieval") st.markdown("**Dataset Used:** _google_natural_questions_answerability_ ", unsafe_allow_html=True) # User input for the question question = st.text_input("Enter your question:", "What is the capital of Italy?") # Default question # Display a log update log = st.empty() # Button to get the answer if st.button("Get Answer"): if not question: st.error("Please provide a question.") else: try: # Display a loading spinner and log message for the QA model log.text("Loading QA model...") with st.spinner("Loading QA model... Please wait."): # Try loading the QA model qa_model = load_qa_model() # Display log message for context retrieval log.text("Retrieving context...") with st.spinner("Retrieving context..."): answer, context = answer_question_with_context(question, qa_model) if not context.strip(): # If context is empty, let the user enter the context manually st.warning("I couldn't find any relevant context for this question. Please enter it below:") context = st.text_area("Enter your context here:", "", height=200, max_chars=1000) if not context.strip(): context = "I couldn't find any relevant context, and you didn't provide one either. Maybe next time!" # Display the answer and context st.subheader("Answer:") st.write(answer) # Show the final answer # Display the context st.subheader("Context Used for Answering:") st.text_area("Context:", context, height=200, max_chars=1000, key="context_input", disabled=False) # Editable context box except Exception as e: st.error(f"An error occurred: {e}") log.text(f"Error: {e}") # Log error in place # Display information about the application st.markdown(""" ### About the Application This is a **Retrieval-Augmented Generation (RAG)** application that answers questions by dynamically retrieving context from a dataset. Here's how it works: 1. **Dynamic Topic Extraction**: The application analyzes the user's question and extracts key topics (such as proper nouns or pronouns) to understand the context of the query. 2. **Context Retrieval**: Based on the extracted topic, the app searches for the most relevant documents (a few hundred) in the dataset. 3. **Answer Generation**: Using the retrieved context, an AI model (like RoBERTa) is used to generate the most accurate answer possible. The model combines the context with its internal knowledge to provide a robust and informed response. 4. **Customization**: If the application doesn't find enough relevant context automatically, you can manually input additional context to improve the answer. The application leverages **Roberta-based question-answering models** to generate answers based on the context retrieved. This helps provide more accurate, context-specific answers compared to traditional approaches that rely solely on pre-trained model knowledge. **Dataset Used**: The application dynamically pulls relevant documents from a dataset google_natural_questions_answerability, helping answer user questions more effectively. """) # Display Buy Me a Coffee button st.markdown("""

If you find this project useful, consider buying me a coffee to support further development! ☕️

Buy Me a Coffee
""", unsafe_allow_html=True) if __name__ == "__main__": main()