Build a Chat App with Memory in Streamlit

What You Will Build

A chat interface that:

Why Chat History is Needed

Streamlit reruns the script every time the user interacts.

Without storing messages:

👉 Solution → st.session_state

Step 1: Install Streamlit

Bash

pip install streamlit    

Step 2: Create App File

Create:

Step 3: Full Working Chat App

Python

import streamlit as st
import openai

st.title("Chat App")

# Initialize chat history
if "messages" not in st.session_state:
    st.session_state.messages = []

# Display previous messages
for msg in st.session_state.messages:
    with st.chat_message(msg["role"]):
        st.write(msg["content"])

# Add Clear Chat Button
with st.sidebar:
    if st.button("Clear Chat"):
        st.session_state.messages = []
        st.rerun()

# User input
prompt = st.chat_input("Type your message")

if prompt:
    # Save user message
    st.session_state.messages.append({"role": "user", "content": prompt})

    with st.chat_message("user"):
        st.write(prompt)

    # Bot response
    response = openai.ChatCompletion.create(
        model="gpt-4o-mini",
        messages=st.session_state.messages
    )

    reply = response.choices[0].message.content

    st.session_state.messages.append({"role": "assistant", "content": reply})

    with st.chat_message("assistant"):
        st.write(reply)    

Step 4: Run the App

Bash

streamlit run chat_app.py    

How This Works Internally

Streamlit Execution Model

Every interaction:

Why st.session_state is Critical

Without session state:

User sends message → app reruns → message disappears

With session state:

Message stored → script reruns → messages restored

Understanding Each Component

1️⃣ Initialize Session State

if "messages" not in st.session_state:
    st.session_state.messages = []    

2️⃣ Display Stored Messages

for msg in st.session_state.messages:    

Each message is stored as:

{"role": "user", "content": "Hello"}    

Roles

3️⃣ st.chat_message()

Creates chat bubble UI.

Available roles:

4️⃣ Chat Input Widget

prompt = st.chat_input("Type your message")    

5️⃣ Save Messages

st.session_state.messages.append({...})