Streamlit Tutorial: Build and Deploy AI Apps with Python in Minutes
Streamlit tutorial — build interactive AI web apps, dashboards, and data tools with pure Python in minutes, no frontend experience required. Deploy free to Streamlit Community Cloud.
Get more content like this on Telegram!
Daily AI tips, notes & resources — free
Streamlit Tutorial: Build and Deploy AI Apps with Python in Minutes
The first AI application I shipped to non-technical users was a Streamlit app. I'd spent two weeks building a FastAPI + React version that worked but required constant frontend debugging. The Streamlit version took a day and was easier for users to understand.
Streamlit trades customization for speed-to-working-demo. For data scientists and ML engineers who want to ship something people can actually use, without becoming frontend developers, it's the right tool.
This tutorial covers building a complete AI-powered app — a document Q&A chatbot — from scratch to deployment.
Installation and First App
# pip install streamlit
# first_app.py
import streamlit as st
st.title("My First Streamlit App")
st.write("Hello, World!")
# Basic widgets
name = st.text_input("What's your name?")
if name:
st.success(f"Hello, {name}!")
age = st.slider("How old are you?", 1, 100, 25)
st.write(f"You are {age} years old")
# Run: streamlit run first_app.py
streamlit run first_app.py
# Opens http://localhost:8501 in your browser
Core Components
import streamlit as st
import pandas as pd
import numpy as np
# Page configuration (must be first st. call)
st.set_page_config(
page_title="AI Dashboard",
page_icon="🤖",
layout="wide", # or "centered"
initial_sidebar_state="expanded"
)
# Text elements
st.title("Dashboard")
st.header("Section Header")
st.subheader("Subsection")
st.write("Regular text or any Python object")
st.markdown("**Bold**, *italic*, [link](https://example.com)")
st.code("print('Hello world')", language="python")
st.latex(r"\sum_{i=1}^{n} x_i")
# Sidebar
with st.sidebar:
st.header("Settings")
model = st.selectbox("AI Model", ["gpt-4o-mini", "gpt-4o"])
temperature = st.slider("Temperature", 0.0, 2.0, 0.7)
max_tokens = st.number_input("Max tokens", 100, 2000, 500)
# Columns layout
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Users", "1,234", "+12%")
with col2:
st.metric("Revenue", "$4,560", "-2%")
with col3:
st.metric("Queries", "8,901", "+34%")
# Input widgets
text = st.text_input("Enter text")
area = st.text_area("Long text", height=200)
file = st.file_uploader("Upload file", type=["pdf", "txt", "csv"])
option = st.selectbox("Choose", ["Option A", "Option B", "Option C"])
multi = st.multiselect("Multi-select", ["A", "B", "C", "D"])
button_clicked = st.button("Submit")
# Display data
df = pd.DataFrame(np.random.randn(10, 3), columns=["A", "B", "C"])
st.dataframe(df) # Interactive table
st.table(df.head(3)) # Static table
# Charts
st.line_chart(df)
st.bar_chart(df)
import plotly.express as px
fig = px.scatter(df, x="A", y="B", title="Scatter Plot")
st.plotly_chart(fig, use_container_width=True)
# Status messages
st.success("Operation completed!")
st.error("Something went wrong.")
st.warning("This is a warning.")
st.info("Informational message.")
# Progress and spinners
with st.spinner("Processing..."):
import time
time.sleep(2)
st.success("Done!")
progress = st.progress(0)
for i in range(100):
progress.progress(i + 1)
time.sleep(0.01)
Session State and Conversation Memory
import streamlit as st
st.title("Counter Example")
# Initialize state
if "count" not in st.session_state:
st.session_state.count = 0
if "history" not in st.session_state:
st.session_state.history = []
# Buttons that modify state
col1, col2, col3 = st.columns(3)
with col1:
if st.button("Increment"):
st.session_state.count += 1
st.session_state.history.append(f"+1 → {st.session_state.count}")
with col2:
if st.button("Decrement"):
st.session_state.count -= 1
st.session_state.history.append(f"-1 → {st.session_state.count}")
with col3:
if st.button("Reset"):
st.session_state.count = 0
st.session_state.history = []
st.metric("Count", st.session_state.count)
st.write("History:", st.session_state.history)
Complete AI Chatbot
# chatbot.py
import streamlit as st
from openai import OpenAI
st.set_page_config(page_title="AI Chat", page_icon="💬", layout="centered")
st.title("AI Chatbot")
client = OpenAI()
# Sidebar settings
with st.sidebar:
st.header("Settings")
system_prompt = st.text_area(
"System Prompt",
"You are a helpful AI assistant.",
height=100
)
model = st.selectbox("Model", ["gpt-4o-mini", "gpt-4o"])
temperature = st.slider("Temperature", 0.0, 2.0, 0.7, 0.1)
if st.button("Clear Conversation"):
st.session_state.messages = []
st.rerun()
st.divider()
if st.session_state.get("messages"):
st.write(f"Messages: {len(st.session_state.messages)}")
# Initialize chat history
if "messages" not in st.session_state:
st.session_state.messages = []
# Display existing messages
for msg in st.session_state.messages:
with st.chat_message(msg["role"]):
st.markdown(msg["content"])
# Chat input
if prompt := st.chat_input("Message"):
# Display user message
with st.chat_message("user"):
st.markdown(prompt)
st.session_state.messages.append({"role": "user", "content": prompt})
# Build API messages
api_messages = [{"role": "system", "content": system_prompt}]
api_messages.extend(st.session_state.messages)
# Stream AI response
with st.chat_message("assistant"):
full_response = st.write_stream(
client.chat.completions.create(
model=model,
messages=api_messages,
temperature=temperature,
stream=True
)
)
st.session_state.messages.append({"role": "assistant", "content": full_response})
Document Q&A App with File Upload
# document_qa.py
import streamlit as st
from openai import OpenAI
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
import tempfile, os
st.set_page_config(page_title="Document Q&A", page_icon="📄")
st.title("Document Q&A")
st.caption("Upload a PDF and ask questions about it")
client = OpenAI()
# File upload section
uploaded_file = st.file_uploader("Upload PDF", type="pdf")
if uploaded_file and "vectorstore" not in st.session_state:
with st.spinner("Processing document..."):
# Save to temp file (PyPDFLoader needs a file path)
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
tmp.write(uploaded_file.getvalue())
tmp_path = tmp.name
# Load and chunk
loader = PyPDFLoader(tmp_path)
docs = loader.load()
splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
chunks = splitter.split_documents(docs)
# Create vector store
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
st.session_state.vectorstore = Chroma.from_documents(chunks, embeddings)
os.unlink(tmp_path) # Clean up temp file
st.success(f"Processed {len(docs)} pages, {len(chunks)} chunks")
# Chat interface (only show after document is loaded)
if "vectorstore" in st.session_state:
if "messages" not in st.session_state:
st.session_state.messages = []
# Display messages
for msg in st.session_state.messages:
with st.chat_message(msg["role"]):
st.markdown(msg["content"])
if question := st.chat_input("Ask about the document..."):
with st.chat_message("user"):
st.markdown(question)
st.session_state.messages.append({"role": "user", "content": question})
# Retrieve relevant chunks
docs = st.session_state.vectorstore.similarity_search(question, k=3)
context = "\n\n".join(d.page_content for d in docs)
with st.chat_message("assistant"):
response = st.write_stream(
client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "system",
"content": f"Answer based only on this context:\n{context}\n\n"
"If the answer isn't in the context, say so."
},
{"role": "user", "content": question}
],
stream=True
)
)
st.session_state.messages.append({"role": "assistant", "content": response})
with st.expander("View sources"):
for i, doc in enumerate(docs):
st.write(f"**Chunk {i+1}** (Page {doc.metadata.get('page', 'N/A')})")
st.text(doc.page_content[:300] + "...")
else:
st.info("Please upload a PDF to start asking questions.")
Deploying to Streamlit Community Cloud
# 1. Create requirements.txt
pip freeze > requirements.txt
# Or manually list only needed packages:
# streamlit
# openai
# langchain
# langchain-openai
# langchain-community
# chromadb
# 2. Create .streamlit/secrets.toml (local only, never commit)
[default]
OPENAI_API_KEY = "sk-..."
# 3. Access secrets in code
import streamlit as st
client = OpenAI(api_key=st.secrets["OPENAI_API_KEY"])
# 4. Push to GitHub
# 5. Deploy at share.streamlit.io
# - Connect GitHub repo
# - Select main file (chatbot.py)
# - Add secrets in the Settings > Secrets section
# Free tier: unlimited public apps
Conclusion
Streamlit is the fastest path from Python code to a working web interface. For AI applications where the goal is demonstrating a concept or building an internal tool, it's hard to beat.
The workflow that works: build with Streamlit, ship to Streamlit Community Cloud for free, gather feedback, then migrate to FastAPI + frontend if you need performance or design control. Many internal tools never need that migration.
For the AI components that power these Streamlit apps, see our OpenAI API integration guide and LangChain tutorial.
Frequently Asked Questions
What is Streamlit and what can I build with it?
A Python library that turns scripts into interactive web apps — no HTML/CSS/JS needed. Build AI chatbots, data dashboards, ML demos, document analyzers. Not ideal for complex custom UIs or consumer-facing products needing fine-grained design.
How does Streamlit session state work?
The entire script reruns on every user interaction. st.session_state is a dictionary that persists across reruns for one user session. Store conversation history, uploaded data, and preferences here. Each user gets their own session state.
How do I add streaming responses to a Streamlit chatbot?
Use st.write_stream() with a generator that yields text chunks. For OpenAI: set stream=True, iterate over chunks, yield content. The text appears word-by-word like ChatGPT.
Can Streamlit handle multiple users in production?
Yes, each user session is a separate thread. Works for tens to hundreds of simultaneous users. Never use global variables — always use st.session_state. Deploy to Streamlit Community Cloud (free, auto-scaling) or containerize for larger scale.
What are the alternatives to Streamlit for AI apps?
Gradio for ML model demos. Chainlit for chat-specific applications (less code for chat features). Panel for complex layouts. FastAPI + React for full control. Choose Streamlit for quick prototypes, Chainlit for chat, Gradio for model showcases.
Frequently Asked Questions
AiTechWorlds Team
✓ Verified WriterThe AiTechWorlds team is passionate about AI, technology, and education. We create high-quality, research-backed content to help you learn, grow, and succeed in the modern digital world.
Related Articles
AI API Cost Management: How to Cut LLM Costs by 80% Without Losing Quality
AI API cost management — practical strategies to reduce OpenAI, Claude, and Gemini API costs by 80% using model selection, caching, RAG, prompt optimization, and batch processing.
Build an AI Chatbot with Python: Complete Guide from Scratch to Deployment
Build an AI chatbot with Python — complete tutorial from OpenAI API integration to conversation memory, streaming responses, and deploying a production-ready chatbot application.
Build a Personal AI Assistant: Complete Python Project with Memory and Tools
Build a personal AI assistant in Python with persistent memory, web search, file access, and calendar integration — a complete project from architecture to working prototype.
CrewAI Tutorial: Build Multi-Agent AI Systems That Work Together
CrewAI tutorial — build multi-agent AI systems where specialized agents collaborate to complete complex tasks, with practical Python examples for research, coding, and content workflows.