> ## Documentation Index
> Fetch the complete documentation index at: https://genai.codewithsiva.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Chat Bot

> Build a stateful chatbot with memory using LangGraph

In this section, we will see how to design a stateful chatbot with memory that can recall previous conversational details.

## Objectives

1. Understand state persistence and message accumulation.
2. Build a looping dialogue agent that appends interactions.
3. Maintain contextual conversation state.

## Agent II: Memory Agent

#### Goal

Build a stateful chatbot that remembers conversation history and appends responses back to the message list.

#### Sample Input

Sequential inputs:

1. `{"messages": [HumanMessage(content="Hi, my name is Satish.")]}`
2. `{"messages": [HumanMessage(content="What is my name?")]}` (including history)

#### Sample Output

1. `"Hello Satish! Nice to meet you."`
2. `"Your name is Satish."`

#### Plan

1. Define the `AgentState` schema containing `messages` (a list of messages, using both HumanMessage and AIMessage).
2. Create the `process` node function that invokes the LLM with the full message history and appends the result to `messages`.
3. Build the graph, compile it, and invoke it sequentially to see it remember previous details.

### Code Implementation

#### 1. Define the State Schema

We define a schema `AgentState` with a list of messages:

```python theme={null}
from typing import TypedDict, Union
from langchain_core.messages import HumanMessage, AIMessage

class AgentState(TypedDict):
    messages: list[Union[HumanMessage, AIMessage]]
```

#### 2. Define the Node Function

The node function invokes the model with the entire message history and appends the model's response back into the state:

```python theme={null}
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4o")

def process(state: AgentState) -> AgentState:
    response = llm.invoke(state["messages"])
    state["messages"].append(AIMessage(content=response.content))
    print(f"\nAI: {response.content}")
    return state
```

#### 3. Build and Compile the Graph

```python theme={null}
from langgraph.graph import StateGraph, START, END

graph = StateGraph(AgentState)
graph.add_node("chatbot", process)

graph.add_edge(START, "chatbot")
graph.add_edge("chatbot", END) 

app = graph.compile()
```

#### 4. Invoke the Agent

We invoke the compiled agent sequentially:

```python theme={null}
state = {"messages": []}
state["messages"].append(HumanMessage(content="Hi, my name is Satish."))
state = app.invoke(state)

state["messages"].append(HumanMessage(content="What is my name?"))
app.invoke(state)
```

## Exercise: Math Tutor Memory Agent 🧮

#### Goal

Build a Math Tutor chatbot that remembers the user's name and guides them through math questions, keeping conversation context.

#### Sample Input

Sequential inputs:

1. `"Hi, I am Rahul. I need help with arithmetic."`
2. `"What is my name and what subject did I ask for help with?"`

#### Sample Output

1. `"Hello Rahul! I'd be happy to help you with arithmetic. What is your first question?"`
2. `"Your name is Rahul, and you asked for help with arithmetic."`

#### Plan

1. Create a `TypedDict` for the list of conversation messages.
2. Write `tutor_node` that binds a math system message instruction, runs the LLM on the chat list, and appends the response.
3. Register the tutor node, set entry/finish points, compile the graph.
4. Test with sequential questions to confirm memory retention.

<Accordion title="Solution">
  ```python theme={null}
  from typing import TypedDict, Union
  from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
  from langchain_openai import ChatOpenAI
  from langgraph.graph import StateGraph, START, END

  # 1. State Schema
  class AgentState(TypedDict):
      messages: list[Union[HumanMessage, AIMessage]]

  llm = ChatOpenAI(model="gpt-4o")

  # 2. Node Function
  def tutor_node(state: AgentState) -> AgentState:
      sys = SystemMessage(content="You are an encouraging math tutor bot. Remember the user's name and preferences.")
      response = llm.invoke([sys] + state["messages"])
      state["messages"].append(AIMessage(content=response.content))
      print(f"\nTutor: {response.content}")
      return state

  # 3. Create Graph
  graph = StateGraph(AgentState)
  graph.add_node("tutor", tutor_node)
  graph.add_edge(START, "tutor")
  graph.add_edge("tutor", END)
  app = graph.compile()

  # 4. Invoke sequentially
  state = {"messages": []}
  state["messages"].append(HumanMessage(content="Hi, I am Rahul. I need help with arithmetic."))
  state = app.invoke(state)

  state["messages"].append(HumanMessage(content="What is my name and what subject did I ask for help with?"))
  app.invoke(state)
  ```
</Accordion>

## Practice & Exercises

To reinforce what you've learned in this section, practice with the interactive notebook:

<CardGroup cols={1}>
  <Card title="Practice & Exercises" icon="laptop-code">
    Practice building stateful chatbots, accumulating messages, and persisting conversation history.

    [💻 VS Code](vscode://file/Users/sivaprasad/Downloads/GenAI%20With%20Python/public/notebooks/langgraph/Chat_Bot.ipynb) | [🚀 Colab](https://colab.research.google.com/github/prasad230776/genai-course/blob/master/public/notebooks/langgraph/Chat_Bot.ipynb) | <a href="/public/notebooks/langgraph/Chat_Bot.ipynb" download>📥 Download</a>
  </Card>
</CardGroup>
