Streamlit: Rapid Prototyping
What You'll Build Today
For the past 70 days, you have lived in the terminal. You have built powerful scripts, connected to LLMs, and processed data. But if you wanted to show your work to a friend, a manager, or a client, you had to say, "Okay, open your terminal, install Python, create a virtual environment, run this command..."
That ends today.
Today, you are going to build your first Interactive Web Application. specifically, you will build a functional AI Chat Interface that looks and feels like ChatGPT.
Here is what you will master:
* Streamlit Architecture: You will learn how to turn a Python script into a web app in literally seconds, allowing you to prototype ideas instantly.
* Input Widgets: You will learn how to capture user intent through text boxes, buttons, and sliders without writing a single line of HTML or JavaScript.
* Layouts: You will learn how to organize your screen using sidebars and columns so your app looks professional, not clutterd.
* Session State: You will learn the critical concept of "app memory." This is the difference between a static form and a conversational app that remembers what you just said.
* Caching: You will learn how to make your app fast by preventing it from re-running expensive computations (like loading a heavy AI model) every time a user clicks a button.
The Problem
Let's look at how we have been interacting with our AI models so far.
Imagine you built a great RAG tool that summarizes legal contracts. You send the script to your boss, who is a brilliant lawyer but not a programmer.
The "Terminal" Pain:# main.py
print("Welcome to LegalAI.")
print("Loading models... (this takes 30 seconds)")
# ... huge loading delay ...
print("Model loaded.")
while True:
user_input = input("Enter your legal question (or 'q' to quit): ")
if user_input == 'q':
break
print(f"Processing '{user_input}'...")
# ... logic ...
print("Here is the summary: [Result]")
Your boss calls you: "I clicked the file and a black box appeared and then disappeared. How do I use this?"
You realize you need a user interface (UI). You Google "How to build a web app with Python." You find a tutorial on Flask, HTML, and JavaScript.
The "Web Development" Pain:To make a simple text box and a button using standard web tools, you often need three different files and languages.
HTML (index.html):``html
JavaScript (script.js):
javascript
function sendData() {
const query = document.getElementById("userInput").value;
fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({text: query})
})
.then(response => response.json())
.then(data => {
document.getElementById("response").innerText = data.answer;
});
}
Python (app.py):
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/api/chat', methods=['POST'])
def chat():
data = request.json
# ... logic ...
return jsonify({"answer": "Here is the result"})
This is painful. You are a Data Scientist or AI Engineer, not a Frontend Web Developer. You spend 80% of your time fighting with CSS margins and JavaScript promises, and only 20% on the actual AI logic.
There has to be a way to write pure Python and get a beautiful web app automatically.
Let's Build It
Enter Streamlit. Streamlit is a library that turns data scripts into shareable web apps. It handles all the HTML, CSS, and JavaScript for you.
Step 0: Installation and Setup
First, we need to install the library.
bash
pip install streamlit
bashapp.pyCreate a new file named
. To run a Streamlit app, you don't use thepythoncommand. You use thestreamlitcommand:
streamlit run app.py
`
This will spin up a local server and automatically open your default web browser to
http://localhost:8501.
Step 1: Hello World (The Magic)
Streamlit works on a simple principle: The entire script runs from top to bottom every time the user interacts with the page.
Let's write our first app.
# app.py
import streamlit as st
import time
# Add a title
st.title("My First GenAI App")
# Add text
st.write("Welcome to Day 71. This is a web app built entirely in Python.")
# Simulate a process
st.write("Loading AI model...")
time.sleep(1) # Pretending to work
st.success("Model Loaded!")
Save the file. Look at your browser. You will usually see a "Source file changed" button in the top right. Click "Always rerun." Now, every time you save your file, the web page updates instantly.
Why this matters: You get instant feedback. No restarting servers.
Step 2: Input Widgets
Static text is boring. We need user input. Streamlit provides widgets that look like variables in your code.
Update
app.py:
import streamlit as st
st.title("Echo Bot")
# Text Input
user_name = st.text_input("What is your name?", "Stranger")
# Button
if st.button("Say Hello"):
st.write(f"Hello, {user_name}! Welcome to the bootcamp.")
else:
st.write("Waiting for you to click the button...")
Run this. Type your name and hit Enter. Then click the button.
The "Gotcha": Notice that when you type in the text box and hit enter, the script reruns. When you click the button, the script reruns again. Streamlit is reactive.
Step 3: Layouts (Sidebar and Columns)
Professional apps don't just dump everything in a vertical list. Let's organize our UI. We will put configuration options in a sidebar and use columns for the main display.
import streamlit as st
st.title("AI Configuration Dashboard")
# The Sidebar
with st.sidebar:
st.header("Settings")
model_type = st.selectbox("Choose Model", ["GPT-3.5", "GPT-4", "Claude 2"])
temperature = st.slider("Creativity (Temperature)", 0.0, 1.0, 0.7)
# Main Page Columns
col1, col2 = st.columns(2)
with col1:
st.info(f"Selected Model: {model_type}")
with col2:
st.warning(f"Current Temperature: {temperature}")
st.write("---")
st.write("Chat interface would go here...")
Why this matters: The with st.sidebar: syntax makes it incredibly easy to separate your "inputs" (settings) from your "outputs" (results), which is a standard pattern in AI apps.
Step 4: Session State (The Brain)
This is the most important concept of the day.
Because Streamlit reruns the entire script on every interaction, variables get reset. If you have a list called
messages = [] at the top of your script, it will empty out every time you click a button.
To remember things across reruns (like chat history), we use
st.session_state. It's a dictionary that persists as long as the user has the tab open.
Let's prove it with a counter.
import streamlit as st
st.title("The Memory Test")
# BROKEN COUNTER
count = 0
if st.button("Increment Broken Counter"):
count += 1
st.write(f"Broken Count: {count}")
# This will always show 0 or 1, because count resets to 0 every time.
st.write("---")
# WORKING COUNTER
# 1. Initialize the state if it doesn't exist
if 'my_count' not in st.session_state:
st.session_state.my_count = 0
# 2. Modify the state
if st.button("Increment Working Counter"):
st.session_state.my_count += 1
# 3. Read the state
st.write(f"Working Count: {st.session_state.my_count}")
Why this matters: Without Session State, you cannot build a chat application because the bot would forget the previous message every time you sent a new one.
Step 5: The Chat Interface (Main Project)
Now let's combine everything to build our ChatGPT clone. We will use a "simulated" AI response for now so you can focus on the UI structure, but you can easily swap the
get_response function with your actual OpenAI/LangChain calls from previous days.
import streamlit as st
import time
st.title("Day 71: Streamlit Chat")
# --- 1. Setup Session State for History ---
if "messages" not in st.session_state:
st.session_state.messages = []
# --- 2. Sidebar for Settings ---
with st.sidebar:
st.header("Model Settings")
st.write("This helps simulate different AI behaviors.")
response_delay = st.slider("Response Speed (sec)", 0.1, 2.0, 0.5)
# --- 3. Display Chat History ---
# We loop through the history and display every message
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.write(message["content"])
# --- 4. Handle New User Input ---
# st.chat_input creates the text box at the bottom
if prompt := st.chat_input("What is on your mind?"):
# A. Display User Message
with st.chat_message("user"):
st.write(prompt)
# B. Add User Message to History
st.session_state.messages.append({"role": "user", "content": prompt})
# C. Generate AI Response (Simulated)
with st.chat_message("assistant"):
message_placeholder = st.empty() # Create a placeholder to stream text
full_response = ""
# Simulate thinking logic
simulated_response = f"I heard you say: '{prompt}'. That is interesting!"
# Simulate typing effect
for chunk in simulated_response.split():
full_response += chunk + " "
time.sleep(0.05) # Typing speed
# Add a blinking cursor to show activity
message_placeholder.write(full_response + "▌")
message_placeholder.write(full_response)
# D. Add AI Message to History
st.session_state.messages.append({"role": "assistant", "content": full_response})
Run this code.
You now have a functional chat interface.
It has a history (thanks to session_state).
It has a clean input bar ( chat_input).
It differentiates between User and Assistant ( chat_message).
It even simulates the "streaming" typing effect.
Now You Try
Take the Chat Interface code above and extend it.
The "Clear Chat" Button:
Add a button in the sidebar that, when clicked, wipes the conversation history.
Hint: You need to empty the list in st.session_state.messages.
System Prompt Configuration:
Add a
st.text_area in the sidebar where the user can define the "System Persona" (e.g., "You are a pirate").
Hint: You don't need to change the logic, just store this text in a variable or session state to show you know how to capture multi-line input.
Chat Role Selection:
Add a radio button (
st.radio) that lets you choose if you are chatting as a "User" or "Admin". If "Admin" is selected, show a special st.warning("Admin Mode Active") at the top of the chat.
Challenge Project: The PDF RAG UI
Your challenge is to build a frontend for a "Chat with PDF" tool. We won't connect the vector database today (unless you feel ambitious and want to pull in code from Day 65), but we will build the UI logic for it.
Requirements:
File Uploader: Use st.file_uploader in the sidebar to accept PDF files.
Processing State: When a file is uploaded, show a spinner ( with st.spinner('Processing...'):) that simulates parsing the text.
Conditional Chat: The main chat interface should be disabled or hidden until a file is uploaded.
File Info: Display the name and size of the uploaded file in the sidebar.
Example Flow:
* User opens app -> Sees "Please upload a PDF to begin."
* User uploads
contract.pdf.
* App shows "Processing..." for 2 seconds.
* App shows "File Processed!"
* Chat interface appears. User asks "What is the termination clause?"
Hints:
*
st.file_uploader returns None if no file is present. You can use if uploaded_file is not None: to control your logic flow.
* To hide the chat, you can simply put the entire chat logic block inside that
if statement.
What You Learned
Today you stepped out of the console and into the browser.
* Streamlit Structure: You learned that the script runs top-to-bottom on every interaction.
* Widgets: You used
st.text_input, st.button, st.slider, and st.file_uploader.
* Layout: You organized tools with
st.sidebar and st.columns.
* State Management: You mastered
st.session_state` to give your app a memory.
Why This Matters:
In the real world, AI is a product, not just a script. Streamlit allows you to build "Minimum Viable Products" (MVPs) in hours instead of weeks. It bridges the gap between your Python logic and your end users.
Tomorrow:Streamlit is great for prototypes, but what if you want to build a mobile app or a custom website that talks to your AI? You need an API. Tomorrow, we build the backend engine using FastAPI.