A simple, self-hosted ChatGPT-style application with Streamlit frontend and FastAPI backend. Local model inference (Transformers or llama.cpp) on CPU/GPU, with SQLite persistence for multi-turn chat history and session metadata.
-
Streamlit UI with:
- Sidebar conversation list & New Chat button
- Model & compute-mode selectors (auto/cpu/gpu)
- Single Load/Unload toggle button per chat
- Chat transcript display with timestamps, tokens, and throughput (TPS)
- URL-based
chat_idfor deep linking & hard-refresh resiliency
-
FastAPI backend with:
/status(global or per-chat) to retrieve loaded state & last-used model/chatsto list all conversations and their metadata/historyto fetch full transcript for a chat/load&/unloadto manage model memory per chat/chatto handle multi-turn context, truncation, inference, and performance metrics/docsfor interactive API documentation (Swagger UI)- UTF-8 logging and SQLite persistence of every message and session
-
ModelManager to dynamically load/unload models from
/modelsfolder:- Auto-detects GGUF (llama.cpp) vs. Transformers
- Supports CPU/GPU/auto modes with fallback
- Frees GPU VRAM on unload
-
SQLite for durable storage of:
- Message history (
chat_history.db) - Session metadata (last-used model & device)
- Message history (
mini-chatgpt-app/
├── backend/
│ ├── logging_config.py # Python logging setup
│ ├── db.py # SQLAlchemy models & SQLite setup
│ ├── model_loader.py # Dynamic model load/unload
│ └── main.py # FastAPI application
├── frontend/
│ └── app.py # Streamlit application
├── models/ # Place your model folders here
│ └── Qwen2.5-Math-1.5B/ # Example model checkpoint
├── logs/ # UTF-8 safe log files per chat
├── chat_history.db # SQLite database file
├── requirements.txt # Python dependencies
└── README.md # This documentation
-
Clone the repo and
cdinto it:git clone <your-repo-url> mini-chatgpt-app cd mini-chatgpt-app
-
Create & activate a Python venv:
python -m venv venv source venv/bin/activate # Linux/macOS venv\\Scripts\\activate # Windows
-
Install dependencies:
pip install -r requirements.txt
-
Download a model (e.g. Qwen2.5-Math-1.5B) into
models/:git lfs install cd models git clone https://huggingface.co/Qwen/Qwen2.5-Math-1.5B cd ..
-
Clone an example model from Hugging Face into
models/:cd models git lfs install git clone https://huggingface.co/cognitivecomputations/Dolphin3.0-Qwen2.5-1.5B cd ..
-
Run the backend:
uvicorn backend.main:app --reload --host 0.0.0.0 --port 8000
-
Run the frontend:
streamlit run frontend/app.py
-
Open http://localhost:8501 in your browser.
| Schema | Fields |
|---|---|
| LoadRequest | chat_id, model, device |
| UnloadRequest | chat_id, model, device |
| ChatRequest | chat_id, message |
| ChatResponse | response, tokens, time_s, tps |
| StatusResponse | loaded, model?, device? |
| ChatMeta | chat_id, title, model?, device? |
| ChatMessage | sender, text, timestamp |
- Returns last-loaded state & model/device for a chat, or global fallback if no
chat_id.
- Returns list of all chats with their
chat_id, a truncated first message astitle, and last-used model/device.
- Returns full message history of
<chat_id>in chronological order.
- Description: FastAPI's automatically generated interactive documentation (Swagger UI) for all endpoints.
- URL: http://localhost:8000/docs
- Body:
LoadRequest - Action: Loads model into memory and persists
(model, device)forchat_id. - Response:
{status, chat_id, model, device, load_time_s}
- Body:
UnloadRequest - Action: Unloads model from memory for
chat_id(DB retains metadata). - Response:
{status, chat_id, model, device}
- Body:
ChatRequest - Action: Runs one chat turn with context from SQLite, persists messages, returns
ChatResponse.
- Persistent Storage: All messages and session choices are stored in SQLite (
chat_history.db). - Context Window: On each
/chat, the backend loads full history, concatenates into a prompt, truncates to the model’smax_position_embeddings, then runs inference. - Model Management: Use
/load//unloadto control GPU/CPU memory. The Streamlit UI reflects loaded state and last-used model per-chat.
- Empty dropdown? Ensure your model folder (e.g.
models/Qwen2.5-Math-1.5B) exists. - GPU not detected? Confirm
torch.cuda.is_available()and install the CUDA-enabled torch wheel. - Encoding errors? Logs and DB use UTF-8; please check your system locale.
Enjoy your self-hosted LLM Chat! 🎉