Streamlit + AI Guide
Build an AI Chatbot with Streamlit & OpenAI
A working chatbot with streaming responses, chat history, and free deployment — in under 50 lines.
Last updated: October 2026 · Tested with Streamlit 1.40+ and OpenAI SDK 1.x
Quick answer: Install streamlit and openai, store your API key in .streamlit/secrets.toml, use st.chat_message() and st.chat_input() for the UI, store messages in st.session_state, and stream responses with st.write_stream(). Deploy for free on Streamlit Cloud.
Install Dependencies
pip install streamlit openai
Create your project folder and a requirements.txt:
mkdir streamlit-chatbot
cd streamlit-chatbot
echo "streamlit
openai" > requirements.txt
touch app.py
Store Your API Key Securely
Never hardcode API keys. Create .streamlit/secrets.toml:
# .streamlit/secrets.toml
OPENAI_API_KEY = "sk-your-key-here"
Important: Add .streamlit/secrets.toml to your .gitignore. Never commit secrets to GitHub. Streamlit Cloud has a separate secrets manager for deployment.
Build the Chatbot (Full Code)
Here's the complete working app.py:
import streamlit as st
from openai import OpenAI
# Setup
st.set_page_config(page_title="AI Chatbot", page_icon="🤖")
client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"])
st.title("🤖 AI Chatbot")
st.caption("Powered by Streamlit + OpenAI")
# Initialize chat history
if "messages" not in st.session_state:
st.session_state.messages = [
{"role": "system", "content": "You are a helpful assistant."}
]
# Display existing messages
for msg in st.session_state.messages:
if msg["role"] != "system":
with st.chat_message(msg["role"]):
st.markdown(msg["content"])
# Handle new input
if prompt := st.chat_input("Ask me anything..."):
# Add user message
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
# Get AI response (streamed)
with st.chat_message("assistant"):
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=st.session_state.messages,
stream=True,
)
response = st.write_stream(
chunk.choices[0].delta.content or ""
for chunk in stream
)
# Save assistant message
st.session_state.messages.append(
{"role": "assistant", "content": response}
)
Run it:
streamlit run app.py
That's a complete, working AI chatbot with streaming and history. Let's break it down.
Understanding the Key Parts
Session state: Streamlit reruns the script on every interaction. To keep the conversation alive, we store it in st.session_state.messages:
if "messages" not in st.session_state:
st.session_state.messages = [
{"role": "system", "content": "You are a helpful assistant."}
]
Chat UI: st.chat_message renders a bubble with an avatar. st.chat_input shows the input box at the bottom:
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
st.markdown(response)
Streaming: st.write_stream() displays chunks as they arrive, like ChatGPT:
response = st.write_stream(
chunk.choices[0].delta.content or ""
for chunk in stream
)
Add a Sidebar with Controls
Give users control over the model and reset:
with st.sidebar:
st.header("Settings")
model = st.selectbox(
"Model",
["gpt-4o-mini", "gpt-4o", "gpt-3.5-turbo"]
)
temperature = st.slider(
"Temperature", 0.0, 1.0, 0.7, 0.1
)
if st.button("Clear chat"):
st.session_state.messages = [
{"role": "system", "content": "You are a helpful assistant."}
]
st.rerun()
Pass model and temperature to the API call. This instantly makes your app feel professional.
Deploy to Streamlit Cloud (Free)
- Push your code to a GitHub repo (make sure secrets aren't committed).
- Go to
share.streamlit.ioand connect your repo. - In the Streamlit Cloud dashboard, go to Settings → Secrets.
- Paste your
OPENAI_API_KEYin TOML format. - Click Deploy.
You now have a live AI chatbot with a public URL — hosted for free.
💡 Cost tip: Use gpt-4o-mini as the default. It's 10–20x cheaper than GPT-4o and more than capable for most chatbot use cases.
🚀 Enhancements to Try Next
- Add RAG: Let the chatbot answer questions from your own PDFs or docs. 👉 See our What is RAG guide.
- Add file uploads: Let users upload images or documents for analysis.
- Swap models: Use Anthropic Claude or Google Gemini by changing one import.
- Add authentication: Restrict access with a login screen.
- Cache responses: Add
@st.cache_datafor repeated prompts.
🛡️ Best Practices
- Never hardcode API keys — use
st.secrets. - Limit chat history length to control token costs (e.g., last 20 messages).
- Use
gpt-4o-minifor development and prototyping. - Add rate limiting to prevent abuse if the app is public.
- Show a typing indicator or use streaming — perception of speed matters.
- Test prompts with different system messages to control the bot's personality.
Security: If your app is public, anyone can run up your OpenAI bill. Add authentication (Streamlit has built-in OIDC support) before sharing widely.
❓ Frequently Asked Questions
Can I build an AI chatbot with Streamlit?
Yes. Streamlit has built-in chat components (st.chat_message, st.chat_input) that make building an AI chatbot straightforward. Combined with the OpenAI API, you can build a working chatbot in under 50 lines of code.
Do I need an OpenAI API key for a Streamlit chatbot?
Yes. You need an OpenAI API key to call GPT models. You can also use alternatives like Anthropic Claude or Google Gemini by swapping the API client. Store the key in .streamlit/secrets.toml for security.
How do I keep chat history in Streamlit?
Store the conversation in st.session_state as a list of message dicts. Each rerun reads the list and renders all previous messages. This keeps the conversation persistent across user interactions.
How do I stream AI responses in Streamlit?
Use st.write_stream() with a generator that yields tokens from the OpenAI streaming API. This displays responses word by word, like ChatGPT. It dramatically improves perceived responsiveness.
How much does it cost to run an AI chatbot?
Costs depend on usage. With GPT-4o-mini, a typical chatbot conversation costs fractions of a cent per exchange. Streaming, chat history, and rate limiting help control costs. Free tiers on OpenAI are available for testing.