Coding standards¶
Style and architectural rules for Eagle-RAG backend and frontend. Machine-readable agent rules: AGENTS.md.
Python¶
| Setting | Value |
|---|---|
| Version | ≥ 3.12 (requires-python in pyproject.toml) |
| Package manager | uv — uv sync, uv run … |
| Linter | Ruff — E, F, I, W, UP; line length 100 |
| Formatter | Ruff format (same line length) |
| Type checker | mypy on package eagle_rag only |
Import and module style¶
- Use
from __future__ import annotationsin library modules. - Prefer explicit
__all__on public modules when exporting a stable API. - Lazy-import heavy deps inside functions when needed to keep API startup fast (pattern in
health.py, retrievers). - Avoid circular imports:
telemetrymust not importapioringest.
Type hints¶
- Public functions and methods are typed; use
Anysparingly at boundaries (Celery, LlamaIndex). - mypy runs with
ignore_missing_imports = true— still type your own code.
Error handling¶
- API routes: raise
HTTPExceptionwith cleardetail; do not leak stack traces to clients. - Probes and admin: degrade gracefully (empty lists,
status=down) instead of 503 unless inspect truly cannot run. - Celery tasks: use
@with_retryorretry_on_failure; never swallow exceptions that should dead-letter.
Comments¶
- English only in code comments and docstrings.
- Do not restate the code (
# increment iforbidden). - No
TODO,FIXME, or personal notes in committed code. - Explain non-obvious business rules (e.g. scope filter OR semantics, fail-closed Knowhere).
Docstrings — Google style¶
Use Google convention for modules, classes, and public functions.
def get_queue_backlog_series(limit: int = 20) -> list[dict[str, Any]]:
"""Query the most recent ``queue_size`` samples and reshape them into a time series.
Returns ``list[{"sampled_at": iso_str, "knowhere": float, ...}]`` sorted by
``sampled_at`` ASC.
Args:
limit: Maximum number of timestamp buckets to return.
Returns:
Time series rows; empty list when no samples exist.
"""
Rules:
- Triple-quoted
"""on the line afterdef/class. Args,Returns,Raisessections when applicable.- Use double backticks for inline code references in docstrings.
- Module docstring at top of file summarises purpose (see
eagle_rag/api/health.py).
API layer¶
- Routers live under
eagle_rag/api/; schemas undereagle_rag/api/schemas/. - Every route declares
response_model=. - Multi-tenant endpoints accept
kb_namewith fallback tosettings.kb_name. - No authentication layer (intranet deployment) — do not add API keys to core routes without project decision.
Schemas¶
- Pydantic v2 models; use
Field(description=...)for OpenAPI clarity. ScopeSelectionand similar shared types belong inschemas/query.pyorcommon.py.- JSONB-backed dicts:
dict[str, Any] | Noneon API models matching SQLModel.
Database¶
- ORM: SQLModel in
eagle_rag/db/models/. - Migrations: Alembic only —
task db:migrate. - Never run
CREATE TABLEfrom stores or startup hooks.
PostgreSQL JSONB — sessions.scope_filter¶
Why JSONB
- Scope selection is structured but evolves (
kb_names,document_ids,tags) without wide nullable columns. - PostgreSQL JSONB supports indexing (GIN) if we add path indexes later; current queries load by
session_id. - API serialises
ScopeSelectionPydantic model →model_dump()→ JSONB; OR semantics applied at query time inrouter_engine._resolve_scope_filter.
Contributor rules
- Keep keys stable:
kb_names,document_ids,tags(lists). - Empty filter →
Nonein DB, not{}. - Do not store Milvus expressions raw in JSONB — store user selections only.
Celery tasks¶
- Register in
celery_app.includeandsettings.yamltask_routes. - Default decorator:
@with_retry(name="…", queue="…")fromdead_letter.py. - Pass
kb_name,document_id,job_idin kwargs for tracing and audit. - Dispatch cross-service with
send_task_with_trace. acks_late=True— tasks must tolerate redelivery; make writes idempotent.
Queue concurrency defaults (settings.yaml):
| Queue | Concurrency | Rationale |
|---|---|---|
router_queue |
4 | Fast routing |
knowhere_queue |
8 | HTTP-bound |
pixelrag_queue |
1 | Memory-bound visual encoder |
Telemetry¶
Instrument long operations:
from eagle_rag.telemetry import trace_span, get_ai_logger
ai_logger = get_ai_logger(__name__)
with trace_span("operation_name"):
ai_logger.info("event_name", field=value)
- Ops messages →
get_logger(loguru). - Analytics events →
get_ai_logger(JSONL). - LLM calls →
set_llm_span_attributesfor OpenTelemetry GenAI semantics.
See OpenTelemetry Python docs and GenAI conventions.
Frontend (TypeScript)¶
| Tool | Command |
|---|---|
| Runtime | Bun |
| Framework | Next.js 16, React 19 |
| Lint / format | Biome — bun run lint, bun run format |
| UI | HeroUI v3, Tailwind v4 |
| i18n | next-intl — maintain messages/en.json and messages/zh.json |
- Light theme only — no dark-mode-first styling.
- Prefer server/client component split per Next.js conventions in existing pages.
- API types: align with OpenAPI or hand-maintained types in
lib/— no Python codegen in repo today.
Configuration¶
- All tunables in
eagle_rag/settings.yamlwith${ENV:-default}. - Secrets only via environment /
.env(gitignored). - Boolean YAML literals (
true/false) for non-env flags to avoid string injection (seeknowhere.parsing_params.ocr_enabled).
AGENTS.md constraints and rationale¶
| Constraint | Rationale |
|---|---|
| Knowhere external HTTP | Heavy semantic parsing out-of-process; official SDK + job API; independent release cycle in docker/knowhere-self-hosted/ |
| PixelRAG library only | Eliminates pixelrag-serve ops burden; vectors go straight to Milvus eagle_visual; Chrome + torch isolated on worker-pixelrag |
| No FAISS / pixelrag-serve | Visual ANN and scalar filters live in Milvus; ingest must not call removed PixelRAG server APIs |
| DeepSeek + Qwen only | Single vendor stack for LLM/VLM/embed/rerank; reduces adapter surface and key management |
| No finance hardcoding | kb_name multi-tenant product — domain logic belongs in KB content, not code branches |
source_type metadata only |
Routing uses format + PDF probe; prevents misleading routes from filename keywords |
| Four fusion anchor fields | Links visual tiles to Knowhere skeleton for citation and parent-document retrieval |
scope_filter OR union |
Users expect broader recall when selecting multiple tags/KBs/docs |
| Attachments lazy parse, no Milvus | Ephemeral chat context — different lifecycle from KB ingest |
| MCP tools registry | TOOL_DEFINITIONS keeps HTTP /mcp/tools and FastMCP in sync |
| No proactive docs | Avoid doc drift unless behaviour changes |
Full matrix: AGENTS.md.
Removed patterns — do not reintroduce¶
| Removed | Replacement |
|---|---|
| LibreOffice | Knowhere native Office parsing |
| pixelrag-serve | pixelrag_render + pixelrag_embed in worker |
| FAISS | Milvus eagle_visual |
| OpenAI / Cohere adapters | DashScope + DeepSeek via LlamaIndex packages |
File organisation¶
- One primary concern per module (e.g.
admin/metrics.pyfor queue sampling only). - Keep routers thin — delegate to stores, engines, adapters.
- Tests mirror
eagle_ragpackage names intests/test_<area>_*.py.
Pre-commit habit¶
Before push: