FastAPI service that exposes REST + SSE APIs and runs an embedded ARQ background worker for file parsing.
| Path | Responsibility |
|---|---|
| routes/ | API route layer: auth / project / file / session / chat / settings |
| agent/ | Chat core: chat_agent as the main agent, citation_parser for block-level citations, prompts, and callable agent tools |
| services/ | Domain services: embedding_service / vector_service for standalone Milvus / mineru_client for PDFs / segment_service / summary_service / vlm_client / export_service |
| models/ | SQLAlchemy ORM models: project / file / segment / block / session / message / image / settings |
| workers/ | ARQ background tasks for async file parsing, chunking, and vectorization after upload |
| packages/kosong/ | Built-in agent reasoning framework for LLM providers, tool calling, and streaming |
| dependencies/ | FastAPI dependencies such as auth for JWT |
| schemas/ | Pydantic request and response schemas |
main.py |
Entry point: the lifespan hook initializes the DB, Redis, and embedded ARQ worker |
config.py |
Configuration loading: database first, then environment fallback |
database.py |
SQLAlchemy engine and session setup |
- Runtime settings such as LLM keys, base URLs, and Embedding mode are stored in the SQLite
settingstable. config.load_settings(db)loads settings into memory at startup, and frontend Settings changes refresh them immediately..envis only used as the initial default source. Priority: DB > env > hardcoded default.
| Variable | Default | Description |
|---|---|---|
LOCAL_NOTEBOOK_DATA_DIR |
./local-notebook-data injected by docker-compose |
Data directory in Docker mode |
DATABASE_URL |
sqlite+aiosqlite:///./local_notebook.db |
SQLAlchemy DSN, replaceable with PostgreSQL |
MILVUS_URI |
http://localhost:19530 |
Standalone Milvus gRPC endpoint |
UPLOAD_DIR |
./uploads |
Uploaded file directory |
REDIS_URL |
redis://localhost:6379 |
Required by the ARQ worker |
SECRET_KEY |
change-me-in-production |
JWT signing secret, must be changed in production |
ACCESS_TOKEN_EXPIRE_MINUTES |
10080 (7 days) |
JWT lifetime |
WORKER_MAX_JOBS |
4 |
ARQ concurrency |
PORT |
8000 |
uvicorn listen port |
Milvus collection names and IVF_PQ index parameters are data-layout constants in services/vector_service.py, not environment variables. Changing them requires a vector-store migration or a full re-index.
Requires Python 3.12+ plus two external services: Redis and Standalone Milvus. Standalone Milvus depends on etcd and minio, so it uses three containers in total.
The simplest setup is to let docker-compose start only the dependencies, then run the Python backend directly on the host:
# 1. Start Redis and the Milvus stack from the project root
docker compose up -d redis etcd minio milvus
# 2. Install backend dependencies
cd backend
pip install -r requirements.txt
# 3. Configure environment variables
export LOCAL_NOTEBOOK_DATA_DIR="$(cd .. && pwd)/local-notebook-data"
export REDIS_URL=redis://localhost:6379
export MILVUS_URI=http://localhost:19530
export DATABASE_URL=sqlite+aiosqlite:///${LOCAL_NOTEBOOK_DATA_DIR}/local_notebook.db
export UPLOAD_DIR=${LOCAL_NOTEBOOK_DATA_DIR}/uploads
export SECRET_KEY=$(openssl rand -hex 32)
mkdir -p "${UPLOAD_DIR}"
# 4. Run the backend
python main.py # default: http://localhost:8000The Redis container exposes 6379, and the Milvus container exposes 19530, so the same docker-compose infra can be used by either the Docker backend or the host Python backend.
If you do not want to use Docker at all, you must install and run all services manually:
- Redis:
brew install redis && redis-serveron macOS, or install it for your OS. - Standalone Milvus + etcd + minio: these are more complex to run as separate processes. Using
docker compose up -d redis etcd minio milvusis recommended.
Health checks:
curl http://localhost:8000/health
curl http://localhost:8000/health/redis- File upload ->
routes/file_routes.pywrites toUPLOAD_DIR-> job is queued in ARQ. - Background parsing ->
workers/parsers/calls MinerU for PDFs or FunASR for audio -> chunks withsegment_service-> vectorizes withembedding_service-> writes vectors into shared Milvus collections withvector_service. - Chat ->
routes/chat_routes.pystreams SSE ->agent/chat_agent.pyreasons ->agent/citation_parser.pyparses citations -> the frontend receives streamed output.