跪拜 Guibai
← All articles
Backend

A FastAPI Monolith Runs an Enterprise Knowledge Base with RAG, KAG, and 9 MySQL Databases

By 苏三说技术 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

A single Python process runs the same enterprise knowledge platform that Java microservices serve, at identical API paths over shared databases, so any team weighing FastAPI against Spring Cloud gets a concrete cost and complexity comparison. The four-tier LLM fallback, the hybrid RRF search, and the PDF-to-Markdown pipeline are directly reusable, and the twin-backend setup shows Python can coexist with Java on one schema rather than replace it.

Summary

An enterprise knowledge base backend packs ten business modules into one FastAPI process. A gateway middleware handles auth, CORS, and logging; document, file, search, statistics, graph, foundation, user auth, and AI apps each own their own MySQL database, and common infrastructure manages connection pools across nine MySQL databases, Redis, Elasticsearch, MongoDB, and Neo4j. Every external call runs through async/await drivers, so a single uvicorn process carries the workload the Java counterpart spreads across eight microservices.

Document management runs the full lifecycle from creation through review, approval, publish, and archive, with version snapshots, inline comments, and an audit workflow. Uploaded PDF, DOCX, and XLSX files convert to Markdown automatically, and Markdown exports to a styled PDF. Search merges Elasticsearch BM25 full-text with semantic vector retrieval via Reciprocal Rank Fusion. The AI layer answers questions with a RAG pipeline backed by a four-tier model fallback, and KAG augments generation with entity relations from the Neo4j knowledge graph; responses stream over SSE. A 4-tier degradation chain runs primary model to retry to backup to a fallback response.

The same system also ships as a Java Spring Cloud backend. The two share one schema and expose API-identical endpoints, so the front end switches between them by changing the API address. Python wins on deployment simplicity, sub-5-second cold start, and 200-500MB memory against 30s+ and 4GB+ for Java, while video transcoding and PPTX parsing remain on the Python roadmap.

Takeaways
— Nine MySQL databases, each scoped to a business module, are managed by a DatabaseManager singleton with async pools configured at pool_size=10 and max_overflow=20.
— The whole backend runs as one FastAPI process; business modules are isolated via APIRouter under an apps/ directory.
— All external I/O is async: asyncmy for MySQL, hiredis for Redis, Motor for MongoDB, the async ES client, aio-pika for RabbitMQ, and aioboto3 for S3.
— PDF, DOCX, and XLSX uploads convert to Markdown via pymupdf, python-docx, and openpyxl respectively, with tables, styles, and images preserved.
— Markdown exports to styled PDF through weasyprint, including heading hierarchy, code blocks, tables, and S3-sourced images.
— Search runs Elasticsearch BM25 full-text plus vector embedding retrieval in parallel, merged by Reciprocal Rank Fusion.
— The RAG pipeline is chunk → embed → hybrid retrieve → re-rank → LLM generate, asynchronous end to end.
— A 4-tier AI fallback keeps services available: primary model → retry → backup model → fallback response.
— KAG enhances generation by drawing entity relations from the Neo4j knowledge graph.
— Auth uses dual JWT tokens (2-hour access, 7-day refresh, HS256) and BCrypt password hashes, with a three-tier RBAC model.
— A Java Spring Cloud twin exposes about 197 endpoints; both backends share the identical database schema and run side by side, with the front end switching API address.
— Python cold-starts in under 5 seconds and uses 200-500MB memory; the Java version takes 30s+ and 4GB+, running eight separate services.
— Video transcoding and PPTX parsing exist in the Java backend but are marked planned in the Python version.
— Startup involves docker compose for infrastructure, a SQL script to create the 9 databases, uv sync, alembic upgrade, then uvicorn on port 8080.
Conclusions

The striking choice is twin backend implementations: Python and Java share one database schema and identical API paths, so a front end swaps runtimes just by changing an address.

The four-tier model fallback treats LLM calls as best-effort dependencies with retry and a canned answer, a pragmatic production stance rather than assuming model providers stay reliable.

The monolith-versus-microservices tradeoff gets quantified instead of asserted: sub-5-second start and 200-500MB memory against 30s+ and 4GB+, with the Python side candidly listing video and PPTX as missing.

Concepts & terms
RAG
Retrieval-Augmented Generation: chunks documents, embeds them, retrieves relevant pieces, and feeds them to an LLM to ground answers in source material.
KAG
Knowledge-Augmented Generation: augments RAG by drawing structured entity relations from a knowledge graph into the generation step.
Module-based monolith
A single-process application split internally by business domain, here into apps/ modules, that can later be split into microservices along those boundaries.
RRF
Reciprocal Rank Fusion: an algorithm that merges multiple ranked result lists into one combined ranking.
BM25
A classic keyword ranking function used in full-text search to score documents by term frequency and inverse document frequency.
Snowflake ID
A 64-bit distributed unique ID generator combining timestamp, datacenter, and sequence, here with clock-rollback tolerance.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗