Day 71 of 80

Streamlit: Rapid Prototyping

Phase 8: Deployment & UI

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


Create a new file named app.py. To run a Streamlit app, you don't use the python command. You use the streamlit command:

bash

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.