This project demonstrates how to rapidly prototype chatbot applications using two popular Python frameworks: Streamlit and Chainlit. It provides end-to-end demos, a comparison of pros and cons, and practical recommendations for when to choose one framework over the other.
Rapid prototyping is an iterative process of building simple versions of a product, collecting user feedback, and validating assumptions before committing to full-scale development.
- Saves development costs and time-to-market.
- Aligned with Agile and Lean Startup methodologies.
- Especially important for AI applications, where technologies, use cases, and expectations evolve quickly.
In this project, you’ll learn how to build chatbot prototypes that can be tested locally and later adapted for production.
- Streamlit (launched in 2019): General-purpose UI framework for data apps and ML prototypes.
- Chainlit (launched in 2023): Purpose-built for conversational AI prototyping with built-in chatbot UI components.
Both are Python-based and easy to use, but they serve slightly different needs. This repo explores their strengths, trade-offs, and recommendations.
The demos use Ollama to run open-source LLMs locally, specifically Google’s Gemma 2 (2B) model.
This ensures the demos are:
- Easy to set up locally.
- Free of external API costs.
- Flexible for experimentation.
Download Ollama from here. Verify installation:
ollama --versionPull the Gemma 2B model (≈1.7 GB):
ollama pull gemma:2bCheck models:
ollama listInstall uv (a modern Python project manager). Verify:
uv --versionInitialize project:
uv init --bare chatbot-demosIn requirements.txt:
chainlit==2.7.2
ollama==0.5.3
streamlit==1.49.1
Then set up a Python 3.12 virtual environment:
uv venv --python=3.12
source .venv/bin/activate
uv add -r requirements.txtCheck installation:
uv pip listchatbot-demos/
│── llm_client.py # Backend client for LLM interactions
│── streamlit_demo.py # Streamlit-based chatbot UI
│── chainlit_demo.py # Chainlit-based chatbot UI
│── requirements.txt # Dependencies
│── pyproject.toml # uv project config
We implement a decoupled backend class (LLMClient) to handle:
- Choosing LLM providers
- Executing calls
- Adding retrieval-augmented generation (RAG)
- Logging conversation history
This abstraction keeps the UI code (Streamlit or Chainlit) clean and modular.
Example (in llm_client.py):
import logging
class LLMClient:
def __init__(self, model="gemma:2b"):
self.model = model
logging.basicConfig(level=logging.INFO)
def query(self, prompt: str) -> str:
# Example call to Ollama
import subprocess
result = subprocess.run(
["ollama", "run", self.model, prompt],
capture_output=True, text=True
)
return result.stdout.strip()streamlit run streamlit_demo.pychainlit run chainlit_demo.py| Feature | Streamlit | Chainlit |
|---|---|---|
| Primary use case | General ML/data app prototyping | Conversational AI prototyping |
| UI components | Rich, customizable widgets | Chat-first, built-in messaging UI |
| Learning curve | Very low (simple Python scripts) | Low (chatbot-oriented API) |
| Community | Larger, more mature | Growing, focused on chatbots |
| Flexibility | High (not chatbot-specific) | Optimized for chat interactions |
-
Use Streamlit if:
- You need a general-purpose prototype with custom UI elements.
- The chatbot is part of a larger ML/data product.
-
Use Chainlit if:
- You’re building a chatbot-first application.
- You want a plug-and-play conversation interface.
- Swap local LLMs (Gemma) for cloud APIs (OpenAI, Anthropic, Google).
- Add retrieval-augmented generation (RAG).
- Deploy on AWS / GCP / Azure.
MIT License. See LICENSE for details.
- Simanga Mchunu