Getting Started¶
There are two ways to run the project — pick the row that matches your goal.
| Goal | What you need |
|---|---|
| Just run it (deploy / try it out) | Docker + Docker Compose 24+ — see Option A. Nothing else. |
| Develop / modify code | Python 3.12+, uv, and Docker (for Elasticsearch) — see Option B. |
An LLM API key (KB_LLM__API_KEY) and an embedding key (KB_EMBEDDING__API_KEY)
are optional — the server boots without them and degrades gracefully
(keyword-only search, AI chat disabled). See Configuration.
Option A — Docker Compose (recommended)¶
Everything runs in containers. The only requirement is Docker.
# 1. Clone, then (optionally) add your API keys
cp .env.example .env # edit .env to set KB_LLM__API_KEY / KB_EMBEDDING__API_KEY
# (skip this and the app still runs — keyword-only, AI chat off)
# 2. Build and start the whole stack (ES + IK plugin + API)
docker compose up -d --build # first build ~2-3 min; subsequent starts are instant
Open http://localhost:8000.
| URL | Description |
|---|---|
http://localhost:8000 |
Knowledge Base Search UI |
http://localhost:8000/docs |
Swagger UI / interactive API docs |
http://localhost:8000/redoc |
ReDoc API reference |
http://localhost:9200 |
Elasticsearch (direct) |
Everyday commands:
docker compose logs -f app # follow API logs
docker compose ps # service status + health
docker compose restart app # restart the API (e.g. after editing config/*.csv)
docker compose down # stop everything (keeps ES data + uploads)
docker compose down -v # stop and wipe the Elasticsearch data volume
What the compose stack gives you:
- The
appservice waits for Elasticsearch to be healthy before starting, and reaches it over the internal network (KB_ES__URL=http://elasticsearch:9200is set automatically — no need to configure it). - Persistence: ES data lives in the
es-datanamed volume; uploaded/imported files in./data/uploads; your CSVs andtaxonomy.yamlare bind-mounted from./config, so edits on the host take effect on the nextdocker compose restart app. - API keys are read from
.env(optional). Anything in.envis passed through to the container.
Enabling OCR (scanned PDFs/images)
OCR (PaddleOCR) is left out of the default image to keep it slim (~440 MB). To
bake it in, set the build arg in docker-compose.yml:
# docker-compose.yml → services.app.build.args
INSTALL_OCR: "true" # adds ~1.5-2 GB; models download on first use
then rebuild: docker compose build app && docker compose up -d.
Option B — Local (host Python + ES container)¶
Run the app from source for development; run Elasticsearch in a container.
# 1. Start Elasticsearch only (with the IK analyzer plugin)
docker compose up -d --build elasticsearch
# 2. Install dependencies and run the dev server with autoreload
uv run python -m kb --reload # port from KB_SERVER__PORT (default 8000)
uv run python -m kb --port 8001 --reload # explicit port override
Useful development commands:
uv run pytest tests/unit # unit tests (no infra)
uv run --extra ingest pytest tests/unit # incl. PPTX/PDF extraction tests
uv run --extra ingest --extra ocr pytest tests/unit # incl. OCR (needs libGL)
uv run pytest tests/integration -m integration # needs Docker
uv run ruff check src tests # lint
uv run mypy src # type check
Test fixtures are generated, not committed
PPTX/PDF fixture files are produced on-the-fly by tests/unit/conftest.py from
the seed CSVs — no large binary test assets live in the repo.
Seeding & data¶
On every startup the server clears all documents from every index and reloads
from the CSV files under config/. Additions, edits, and row deletions in the
CSVs all take effect on the next restart. After seeding, restore_imports()
re-indexes any previously imported documents from the kb_import_files tracker
index — so imported files survive the re-seed. See
Architecture → Import Pipeline.
Reading these docs locally¶
This documentation site is built with MkDocs Material. To serve it with live reload, or publish it:
uv sync --extra docs # install mkdocs-material + the i18n plugin
uv run mkdocs serve # live preview at http://127.0.0.1:8000
uv run mkdocs build --strict # build static site into ./site (fails on broken links)
uv run mkdocs gh-deploy # publish to the gh-pages branch (GitHub Pages)
The site is bilingual (English / 中文). Use the language switcher in the header.