Local chatbot built with FastAPI, LangGraph, Ollama, SQLite, and a small TypeScript frontend.
- Creates and persists conversations in SQLite
- Streams assistant output to the browser with Server-Sent Events
- Stores LangGraph checkpoints separately from app data
- Lets you rename and delete conversations
- Resumes conversation state by reusing the conversation ID as the LangGraph
thread_id
- FastAPI
- LangGraph
- LangChain Core
- LangChain Ollama
- SQLAlchemy
- SQLite
- Jinja2 templates
- TypeScript compiled to browser ESM in
static/js - Plain CSS
.
|-- main.py # FastAPI app and HTTP routes
|-- graph.py # LangGraph definition and Ollama integration
|-- chat_service.py # Chat helpers
|-- conversation_service.py # Conversation and message persistence
|-- database.py # SQLAlchemy engine, session, and base
|-- models.py # SQLAlchemy models
|-- init_db.py # Creates SQLite tables
|-- chatbot.py # Simple CLI smoke-test entrypoint
|-- data/
| |-- app.db # App data: conversations and messages
| `-- checkpoints.db # LangGraph checkpoint storage
|-- templates/
| |-- index.html # Main page
| `-- generation_service.py # Background token generation for SSE
|-- static/
| |-- css/
| | `-- styles.css
| |-- ts/ # TypeScript source
| `-- js/ # Compiled browser JavaScript
|-- pyproject.toml
|-- package.json
`-- tsconfig.json
- The browser creates or selects a conversation.
- A user message is saved to
data/app.db. - The backend starts a background generation task.
- LangGraph loads checkpoint state for that conversation from
data/checkpoints.db. - Tokens are streamed back to the browser over SSE.
- The completed assistant response is saved to the application database.
The app keeps two kinds of persistence:
app.dbstores conversation metadata and message history for the UI.checkpoints.dbstores LangGraph execution state for resumable memory.
- Python 3.13+
- Node.js, for compiling the TypeScript frontend
- Ollama running locally
- The model configured in graph.py:
llama3.1:8b
uv syncuv run python init_db.pynpm install
npm run buildollama pull llama3.1:8b
ollama serveuv run python main.pyThen open http://127.0.0.1:8000.
- The frontend is not using Vite.
tsconfig.jsoncompilesstatic/tsdirectly intostatic/js. package.jsonis only used to manage the TypeScript toolchain.- chatbot.py provides a small CLI loop for backend testing without the browser.