"""
A script for retrieval-based question answering using the langchain library.

This script demonstrates how to integrate a retrieval system with a chat model for answering questions.
It utilizes Chroma for retrieval of relevant information and ChatOpenAI for 
generating answers based on the retrieved content. 
The RedundantFilterRetriever is used for efficient retrieval, 
filtering out redundant information and focusing on the most relevant content.
This setup is ideal for answering questions with context from a specific knowledge base.

Features:
- Initialize ChatOpenAI for language model-based interactions.
- Use OpenAI embeddings for document retrieval.
- Load a Chroma database for document retrieval based on embeddings.
- Use RedundantFilterRetriever for enhanced retrieval efficiency.
- Set up a RetrievalQA chain combining the chat model and the retriever.
- Answer a specific question using the RetrievalQA chain.

Usage:
Run the script to ask a question about the English language and get an answer based on 
retrieved content from the Chroma database and processed through the RedundantFilterRetriever.
"""

import langchain
from dotenv import load_dotenv
from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores.chroma import Chroma
from mod_05_redundant_filter_retriever import RedundantFilterRetriever

langchain.debug = True

load_dotenv()

# Initialize a ChatOpenAI instance for language model interactions.
chat = ChatOpenAI()

# Initialize OpenAI embeddings for document retrieval.
embeddings = OpenAIEmbeddings()

# Load a Chroma database for document retrieval.
db = Chroma(persist_directory="emb", embedding_function=embeddings)

# Initialize the RedundantFilterRetriever with OpenAI embeddings and Chroma database.
# This retriever filters out redundant information, focusing on the most relevant content.
retriever = RedundantFilterRetriever(embeddings=embeddings, chroma=db)

# Configure the RetrievalQA chain with the chat model and the enhanced retriever.
# This chain combines the capabilities of ChatOpenAI and
# RedundantFilterRetriever for efficient question answering.
# https://python.langchain.com/docs/modules/chains/document/
chain = RetrievalQA.from_chain_type(llm=chat, retriever=retriever, chain_type="stuff")

# Run the chain to answer a question based on retrieved content.
result = chain.run("What is an interesting fact about the English language?")
print(result)

langchain.embeddings.OpenAIEmbeddings langchain.vectorstores.chroma.Chroma langchain.chains.RetrievalQA.from_chain_type langchain.chat_models.ChatOpenAI
[((1459, 1472), 'dotenv.load_dotenv', 'load_dotenv', ([], {}), '()\n', (1470, 1472), False, 'from dotenv import load_dotenv\n'), ((1549, 1561), 'langchain.chat_models.ChatOpenAI', 'ChatOpenAI', ([], {}), '()\n', (1559, 1561), False, 'from langchain.chat_models import ChatOpenAI\n'), ((1631, 1649), 'langchain.embeddings.OpenAIEmbeddings', 'OpenAIEmbeddings', ([], {}), '()\n', (1647, 1649), False, 'from langchain.embeddings import OpenAIEmbeddings\n'), ((1705, 1767), 'langchain.vectorstores.chroma.Chroma', 'Chroma', ([], {'persist_directory': '"""emb"""', 'embedding_function': 'embeddings'}), "(persist_directory='emb', embedding_function=embeddings)\n", (1711, 1767), False, 'from langchain.vectorstores.chroma import Chroma\n'), ((1958, 2016), 'mod_05_redundant_filter_retriever.RedundantFilterRetriever', 'RedundantFilterRetriever', ([], {'embeddings': 'embeddings', 'chroma': 'db'}), '(embeddings=embeddings, chroma=db)\n', (1982, 2016), False, 'from mod_05_redundant_filter_retriever import RedundantFilterRetriever\n'), ((2287, 2365), 'langchain.chains.RetrievalQA.from_chain_type', 'RetrievalQA.from_chain_type', ([], {'llm': 'chat', 'retriever': 'retriever', 'chain_type': '"""stuff"""'}), "(llm=chat, retriever=retriever, chain_type='stuff')\n", (2314, 2365), False, 'from langchain.chains import RetrievalQA\n')]