# 05. RAG chain to remember interactive

## Chain creation method to remember previous conversations <a href="#chain" id="chain"></a>

Advance knowledge to understand this

* `RunnableWithMessageHistory` : <https://wikidocs.net/235581>

```python
# API KEY A configuration file for managing environment variables
from dotenv import load_dotenv

# API KEY load information
load_dotenv()
```

```
 True 
```

```python
# LangSmith set up tracking. https://smith.langchain.com
# !pip install langchain-teddynote
from langchain_teddynote import logging

# Enter a project name.
logging.langsmith("CH12-RAG")
```

```
 Start tracking LangSmith. 
[Project name] 
CH12-RAG 
```

### One. Add only dialogs to regular Chain <a href="#id-1-chain" id="id-1-chain"></a>

```python
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.chat_history import BaseChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser


# Prompt definition
prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "You are a Question-Answering chatbot. Please provide answers to the questions given.",
        ),
        # Please use chat_history, the key for conversation history, without changing it if possible!
        MessagesPlaceholder(variable_name="chat_history"),
        ("human", "#Question:\n{question}"),  # Use user input as a variable
    ]
)

# llm creation
llm = ChatOpenAI()

# Generate a general chain
chain = prompt | llm | StrOutputParser()
```

Create a chain that records the conversation ( `chain_with_history` )

```python
# A dictionary to store session records.
store = {}


# Function to retrieve session records based on session ID
def get_session_history(session_ids):
    print(f"[Conversation Session ID]: {session_ids}")
    if session_ids not in store:  # If the session ID is not in the store
        # Create a new ChatMessageHistory object and save it to the store.
        store[session_ids] = ChatMessageHistory()
    return store[session_ids]  # Returns the session record for the given session ID.


chain_with_history = RunnableWithMessageHistory(
    chain,
    get_session_history,  # Function to retrieve session records
    input_messages_key="question",  # The user's question goes into the template variable. key
    history_messages_key="chat_history",  # 기록 메시지의 키
)
```

Run the first question

```python
chain_with_history.invoke(
    # Enter your question
    {"question": "My name is Teddy."},
    # Records conversations based on session ID.
    config={"configurable": {"session_id": "abc123"}},
)
```

```
 [Dial SessionID]: abc123
```

```
 'Hello, Teddy. What can I help you with?' 
```

Then run the question

```python
chain_with_history.invoke(
    # Enter your question
    {"question": "What is my name?"},
    # Record conversations based on session ID.
    config={"configurable": {"session_id": "abc123"}},
)
```

```
 [Dial SessionID]: abc123
```

```
 'Your name is Teddy.' 
```

### 2. RAG + RunnableWithMessageHistory <a href="#id-2-rag-runnablewithmessagehistory" id="id-2-rag-runnablewithmessagehistory"></a>

First, create a regular RAG Chain. However, in the six-stage prompt `{chat_history}` Be sure to add

```python
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import PDFPlumberLoader
from langchain_community.vectorstores import FAISS
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from operator import itemgetter

# Step 1: Load the document
loader = PDFPlumberLoader("data/SPRI_AI_Brief_2023년12월호_F.pdf")
docs = loader.load()

# Step 2: Split Documents
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=50)
split_documents = text_splitter.split_documents(docs)

# Step 3: Create an embedding
embeddings = OpenAIEmbeddings()

# Step 4: Create DB and save
# Create a vector store.
vectorstore = FAISS.from_documents(documents=split_documents, embedding=embeddings)

# Step 5: Create a Retriever
# Retrieves and generates information contained in documents.
retriever = vectorstore.as_retriever()

# Step 6: Create Prompt
# Generates a prompt.
prompt = PromptTemplate.from_template(
    """You are an assistant for question-answering tasks. 
Use the following pieces of retrieved context to answer the question. 
If you don't know the answer, just say that you don't know. 
Answer in Korean.

#Previous Chat History:
{chat_history}

#Question: 
{question} 

#Context: 
{context} 

#Answer:"""
)

# Step 7: Create a language model (LLM)
# Create a model (LLM).
llm = ChatOpenAI(model_name="gpt-4o", temperature=0)

# Step 8: Create a Chain
chain = (
    {
        "context": itemgetter("question") | retriever,
        "question": itemgetter("question"),
        "chat_history": itemgetter("chat_history"),
    }
    | prompt
    | llm
    | StrOutputParser()
)
```

Define functions to save the conversation

```python
# A dictionary to store session records.

store = {}


# Function to retrieve session records based on session ID
def get_session_history(session_ids):
    print(f"[Fire Session ID]: {session_ids}")
    if session_ids not in store:  # If the session ID is not in the store
        # Create a new ChatMessageHistory object and save it to the store.
        store[session_ids] = ChatMessageHistory()
    return store[session_ids]  # Returns the session record for the given session ID.


# Create a RAG chain that records conversations
rag_with_history = RunnableWithMessageHistory(
    chain,
    get_session_history,  # Function to retrieve session records
    input_messages_key="question",  # The key that the user's question will go into the template variable.
    history_messages_key="chat_history",  # 기록 메시지의 키
)
```

Run the first question

```python
rag_with_history.invoke(
    # Enter your question
    {"question": "The name of the generative AI created by Samsung Electronics is?"},
    # Records conversations based on session ID.
    config={"configurable": {"session_id": "rag123"}},
)
```

```
 [Dial SessionID]: rag123
```

```
 "The name of the generated AI created by the Samsung is'Samsung Gauss'." 
```

Execute subsequent questions

```python
rag_with_history.invoke(
    # Enter your question
    {"question": "Please translate previous answer into English."},
    # Records conversations based on session ID.
    config={"configurable": {"session_id": "rag123"}},
)
```

```
 [Dial SessionID]: rag123
```

```
 "The name of the generic AI created by Samsung Electronics is'Samsung Gauss'." 
```

<br>
