Hybrid RAG system with a FastAPI backend and Vue 3 frontend. The backend exposes a LlamaIndex Knowledge Graph query engine over HTTPS, called by a Kotlin LangGraph4j agent as a tool. Neo4j is the graph store, pgvector handles vector embeddings, and Celery processes ingestion and deletion asynchronously. The UI provides document upload with interactive knowledge graph visualization, a query interface with retrieval mode selection, and document management.
- Framework: FastAPI + Uvicorn
- Validation: Pydantic + Pydantic-Settings
- Logging: Structlog (JSON in prod, console in debug)
- KG Engine: LlamaIndex (KnowledgeGraphIndex)
- Graph Store: Neo4j (via llama-index-graph-stores-neo4j)
- Vector Store: PostgreSQL + pgvector (dual retrieval: KG + vector)
- Task Queue: Celery + Redis
- Build: Poetry 2.3+
- Linting: Ruff
- Type Checking: mypy (strict mode)
- Testing: pytest + pytest-asyncio + httpx
- Framework: Vue 3 + TypeScript (Composition API,
<script setup>) - Build: Vite + pnpm
- Styling: Tailwind CSS + shadcn-vue
- State: Pinia
- Routing: Vue Router 4
- Graph Visualization: Cytoscape.js
- Linting: ESLint (flat config) with eslint-plugin-vue + typescript-eslint
services/query-engine/ # Backend
app/
├── api/v1/ # API route handlers
├── connectors/ # Document source connectors (GCS)
├── core/ # Config (Pydantic Settings), logging, errors, middleware
├── models/ # Pydantic request/response schemas (CamelModel base)
├── services/ # Business logic (KnowledgeGraphService, IngestionPipeline)
└── worker/ # Celery app, background tasks
tests/ # Pytest test suite
ui/ # Frontend
src/
├── components/ # Reusable components (layout, graph, upload, ui)
├── composables/ # Composition API hooks
├── layouts/ # Page layouts
├── router/ # Vue Router config
├── services/ # API client
├── stores/ # Pinia state
├── types/ # TypeScript interfaces
└── views/ # Page views (QueryView, UploadView)
All commands run from services/query-engine/.
# Install dependencies
poetry install
# Run development server
poetry run uvicorn app.main:app --reload
# Run tests
poetry run pytest
# Lint
poetry run ruff check .
# Format
poetry run ruff format .
# Type check
poetry run mypy .
# Run Celery worker
poetry run celery -A app.worker.celery_app:celery_app worker --loglevel=info
# Integration tests (requires Docker)
poetry run pytest tests/integration/ -m integration -vAll commands run from ui/.
# Install dependencies
pnpm install
# Run dev server
pnpm dev
# Type check + production build
pnpm build
# Lint
pnpm lint- Line length: 100 characters
- Type hints: Required on all functions (strict mypy)
- Modern Python syntax: Use
list[str]notList[str], etc. - Imports: Always at the top of the file, sorted by isort (via ruff). No inline imports unless absolutely necessary.
- API routes: Use
APIRouter, grouped underapi/v1/ - Models: Inherit from
CamelModel(inapp/models/__init__.py), notBaseModeldirectly. JSON serialization is camelCase for the Kotlin agent; Python code stays snake_case. Useby_alias=Truewhen callingmodel_dump()manually. - Config: Environment variables loaded via Pydantic-Settings from
.env - Logging: Use structlog, not
print()or stdlibloggingdirectly - Docstrings: PEP 257 — all public modules, classes, functions, and methods must have docstrings. Use triple double quotes. One-line for simple cases, multi-line with summary + blank line + description for complex ones.
- Components in
src/components/ui/are auto-generated by shadcn-vue and excluded from linting — do not edit directly - Composition API only — use
<script setup lang="ts">, no Options API - Import paths: Use
@/alias (maps tosrc/)
- Tests live in
tests/mirroring the app structure - Use
pytest-asynciowith modeauto - Use
httpx.AsyncClientwithASGITransportfor endpoint tests - Fixtures defined in
tests/conftest.py conftest.pysetsCELERY_BROKER_URL=""at import time to force in-memory rate limiter storage — no Redis or Docker required to run tests