Streamlit: AI Web Apps ๐ŸŒ

Class 10Age 14โ€“15Lesson 9 of 12๐Ÿ†“ Free
Student in Kochi showing a Streamlit plant disease classifier app on laptop โ€” uploaded leaf image with disease prediction shown
Watch first - 2-3 minutes

Class 10 Lesson 9 - Streamlit: AI Web Apps

No sign-in needed - English narration - Safe for all school ages

Meet Dev โ€” Class 10, Kochi

Dev's family runs a small coconut farm in Thrissur district. Every monsoon, coconut palms get attacked by pests and fungal diseases. His father shows photos to an agricultural officer who visits once a month โ€” but by then, the disease has spread. Dev thought: "I have a trained CNN model from Lesson 1 that classifies plant diseases. What if farmers could upload a photo from their phone and get an instant answer?"

The problem: building a website needs HTML, CSS, JavaScript. FastAPI from Lesson 8 needs a separate frontend. Dev discovered Streamlit โ€” a Python library that turns a Python script into a full web application. No HTML. No CSS. Just Python. He had a working app in 40 minutes and deployed it online for free.

What is Streamlit?
Python Script โ†’ Web App in Minutes

Streamlit is a Python library that converts a regular Python script into an interactive web application by simply calling functions like st.title(), st.text_input(), and st.image(). Every time a user interacts with a widget (slider, button, file upload), the entire script re-runs from top to bottom and the UI updates.

๐ŸŒฟ Plant Disease Detector
๐Ÿ“ท Upload a leaf image (jpg, png)
Drop files here or click to browse
Analyse Image
โœ… Detected: Coconut Leaf Blight (94.2% confidence)
๐Ÿ’Š Recommended: Copper oxychloride spray, 3g/litre water.

This is what Dev built. The UI above is a static preview of what the Streamlit app looks like.

Core Widgets
Essential Streamlit Functions
import streamlit as st

# Layout
st.title("My AI App")
st.header("Section heading")
st.subheader("Sub-heading")
st.write("Any text, dataframe, chart, dict โ€” all rendered automatically")
st.markdown("**Bold**, *italic*, and `code` formatting supported")

# Input widgets
name = st.text_input("Your name", placeholder="e.g. Priya")
age  = st.number_input("Age", min_value=5, max_value=100, value=15)
lang = st.selectbox("Preferred language", ["English", "Telugu", "Hindi", "Malayalam"])
conf = st.slider("Confidence threshold", min_value=0.0, max_value=1.0, value=0.5)
clicked = st.button("Run prediction")

# File upload
uploaded = st.file_uploader("Upload image", type=["jpg","jpeg","png"])

# Output
st.success("Great job! ๐ŸŽ‰")    # green box
st.warning("Check your input")  # yellow box
st.error("Invalid file")        # red box

# Show image
if uploaded:
    st.image(uploaded, caption="Uploaded image", use_container_width=True)

# Show data and charts
import pandas as pd
df = pd.DataFrame({"Score": [85, 92, 78]}, index=["Run1","Run2","Run3"])
st.dataframe(df)
st.bar_chart(df)
Full App
Plant Disease Classifier โ€” Complete Streamlit App
# plant_disease_app.py
# Run locally: streamlit run plant_disease_app.py
# Deploy free: https://share.streamlit.io

import streamlit as st
import numpy as np
from PIL import Image

# โ”€โ”€ Page config โ”€โ”€
st.set_page_config(
    page_title="Plant Disease Detector",
    page_icon="๐ŸŒฟ",
    layout="centered"
)

# โ”€โ”€ Cache the model โ€” loaded once, not on every re-run โ”€โ”€
@st.cache_resource
def load_model():
    """Load the trained CNN model. Cached so it only loads once."""
    try:
        import tensorflow as tf
        model = tf.keras.models.load_model("plant_disease_model.h5")
        return model
    except Exception:
        return None

# โ”€โ”€ Class labels (matches training dataset order) โ”€โ”€
CLASSES = [
    "Cashew Anthracnose",
    "Cashew Gumosis",
    "Cassava Bacterial Blight",
    "Cassava Brown Spot",
    "Coconut Leaf Blight",
    "Coconut Leaf Rot",
    "Healthy",
    "Maize Leaf Blight",
    "Maize Leaf Spot",
    "Tomato Early Blight"
]

TREATMENTS = {
    "Cashew Anthracnose":      "Spray Mancozeb 75WP (2.5g/L). Remove infected branches.",
    "Cashew Gumosis":          "Apply Bordeaux paste on affected areas. Improve drainage.",
    "Cassava Bacterial Blight":"Remove and burn infected parts. Use disease-free cuttings.",
    "Cassava Brown Spot":      "Apply Carbendazim 50WP (1g/L). Ensure good spacing.",
    "Coconut Leaf Blight":     "Spray Copper oxychloride (3g/L). Improve air circulation.",
    "Coconut Leaf Rot":        "Apply Bordeaux mixture. Remove fallen debris.",
    "Healthy":                 "No treatment needed. Plant is healthy! โœ…",
    "Maize Leaf Blight":       "Spray Propiconazole (1ml/L). Use resistant varieties.",
    "Maize Leaf Spot":         "Apply Zineb 75WP (2g/L). Destroy infected crop residue.",
    "Tomato Early Blight":     "Spray Chlorothalonil 75WP (2g/L). Stake plants well."
}

# โ”€โ”€ App UI โ”€โ”€
st.title("๐ŸŒฟ Plant Disease Detector")
st.markdown("Upload a photo of a plant leaf to identify disease and get treatment advice.")
st.markdown("---")

model = load_model()
if model is None:
    st.warning("โš ๏ธ Model file not found. Running in demo mode with random predictions.")

# Sidebar โ€” settings
with st.sidebar:
    st.header("Settings")
    confidence_threshold = st.slider("Minimum confidence", 0.3, 1.0, 0.6)
    show_top3 = st.checkbox("Show top 3 predictions", value=True)
    st.markdown("---")
    st.markdown("**Supported crops:**")
    st.markdown("Cashew ยท Cassava ยท Coconut ยท Maize ยท Tomato")

# File upload
uploaded_file = st.file_uploader(
    "๐Ÿ“ท Upload a leaf image",
    type=["jpg", "jpeg", "png"],
    help="Take a clear photo of the leaf in good lighting"
)

if uploaded_file is not None:
    # Display uploaded image
    image = Image.open(uploaded_file).convert("RGB")
    col1, col2 = st.columns([1, 1])
    with col1:
        st.image(image, caption="Uploaded leaf", use_container_width=True)

    with col2:
        with st.spinner("Analysing..."):
            # Preprocess for CNN (224ร—224, normalised)
            img_array = np.array(image.resize((224, 224))) / 255.0
            img_array = np.expand_dims(img_array, axis=0)  # (1, 224, 224, 3)

            if model is not None:
                predictions = model.predict(img_array)[0]
            else:
                # Demo mode: fake predictions for illustration
                predictions = np.random.dirichlet(np.ones(len(CLASSES)) * 0.5)

            top_idx  = np.argmax(predictions)
            top_conf = predictions[top_idx]
            top_cls  = CLASSES[top_idx]

        if top_conf >= confidence_threshold:
            if top_cls == "Healthy":
                st.success(f"โœ… **{top_cls}**\n\n{top_conf*100:.1f}% confident")
            else:
                st.error(f"โš ๏ธ **{top_cls}**\n\n{top_conf*100:.1f}% confident")
        else:
            st.warning(f"Low confidence ({top_conf*100:.1f}%). Please upload a clearer photo.")

    # Treatment recommendation
    if top_conf >= confidence_threshold:
        st.markdown("### ๐Ÿ’Š Recommended Treatment")
        treatment = TREATMENTS.get(top_cls, "Consult an agricultural officer.")
        st.info(treatment)

    # Top 3 predictions bar chart
    if show_top3:
        st.markdown("### ๐Ÿ“Š Top 3 Predictions")
        top3_idx   = np.argsort(predictions)[-3:][::-1]
        top3_data  = {CLASSES[i]: float(predictions[i]) for i in top3_idx}
        import pandas as pd
        st.bar_chart(pd.Series(top3_data))

    # Feedback button
    st.markdown("---")
    correct = st.radio("Was this prediction correct?", ["Yes", "No"], horizontal=True)
    if st.button("Submit feedback"):
        st.success("Thank you! Your feedback helps improve the model.")
@st.cache_resource is essential for ML apps. Without it, the model would be reloaded from disk every time ANY widget is interacted with โ€” causing 2โ€“10 second pauses. With the decorator, Streamlit loads the model once and caches it in memory across all re-runs.
Free Deployment
Share Your App with the World
  1. Create a free GitHub account and push your app code + requirements.txt to a public repo. Requirements: streamlit, tensorflow, pillow, numpy
  2. Go to share.streamlit.io and sign in with GitHub
  3. Click "New app", select your repo, set main file as plant_disease_app.py
  4. Click "Deploy" โ€” Streamlit Cloud installs packages and starts your app automatically
  5. Share the public URL (e.g., yourname-plant-detector.streamlit.app) โ€” anyone in the world can use your app from any browser
Model file size: Streamlit Community Cloud has a 1GB limit per app. Large deep learning models (.h5 files) should be stored in a cloud bucket (like Google Drive or S3) and downloaded at startup using gdown or boto3 rather than committed to GitHub.
Dev's outcome: He deployed the app and shared the URL with his father. His father showed it to farmers in their village. Within a week, 12 farmers had uploaded leaf photos. The app correctly identified coconut blight in 9 of them, giving them treatment recommendations 3 weeks before the next agricultural officer visit.

๐Ÿงช Check Your Understanding โ€” Lesson 9 Quiz

1. Streamlit re-runs the entire script whenever:
a) The server clock ticks every second
b) A user interacts with any widget (button click, slider move, file upload) โ€” Streamlit's execution model re-runs the script top-to-bottom and updates the UI with new values
c) The Python file is saved on disk
d) A new user opens the app URL
2. `@st.cache_resource` on the model loading function is important because:
a) It saves the model predictions to a local database for offline use
b) Without it, the model would be re-loaded from disk on every widget interaction โ€” causing multi-second delays. The decorator caches the loaded model object in memory, so it's loaded only once per session.
c) It compresses the model file to save storage space
d) It allows the model to run on GPU automatically
3. `st.columns([1, 1])` creates:
a) A table with 1 row and 1 column
b) Two equal-width side-by-side columns that you can fill independently โ€” useful for showing an image next to prediction results
c) A 1ร—1 pixel invisible container
d) Two buttons placed side by side
4. Streamlit Community Cloud (share.streamlit.io) deploys apps from:
a) A zip file uploaded to the Streamlit website
b) A public GitHub repository โ€” it clones the repo, installs requirements.txt, and runs your app file on a cloud server with a public URL
c) A Docker container that you build and push manually
d) Python code pasted directly into the Streamlit web editor
5. `np.expand_dims(img_array, axis=0)` is used before model.predict() to:
a) Increase the image resolution for better predictions
b) Add a batch dimension โ€” CNN models expect shape (batch_size, height, width, channels), but a single image has shape (height, width, channels). expand_dims converts (224,224,3) to (1,224,224,3).
c) Convert the image from colour to grayscale
d) Normalise pixel values to the range 0โ€“1
6. `st.sidebar` places widgets:
a) Below the main content area
b) In a collapsible panel on the left side of the app โ€” ideal for settings that don't need to be visible by default, keeping the main area clean
c) In a popup modal that appears on button click
d) As floating buttons in the bottom-right corner
7. The difference between `st.success()`, `st.warning()`, and `st.error()` is:
a) They differ in font size only
b) They display coloured message boxes โ€” green (success), yellow (warning), red (error) โ€” providing visual feedback about the state of an operation without any custom CSS
c) st.error() raises a Python exception; the others just print
d) They only work inside @st.cache_resource functions
8. Compared to building a FastAPI backend + separate HTML/JS frontend, Streamlit's main advantage for ML prototyping is:
a) Streamlit apps run 10ร— faster than FastAPI apps
b) You can build a shareable, interactive ML demo entirely in Python โ€” no HTML, CSS, or JavaScript needed. This is much faster for prototyping, though FastAPI is better for production-scale APIs consumed by external apps.
c) Streamlit apps automatically train the ML model on new uploaded data
d) Streamlit apps work offline without any internet connection
โ† Lesson 8: FastAPI Lesson 10: AI for India โ†’