Most retrieval-augmented generation projects treat documents as text to be split; RAGFlow was built on the conviction that the hard part happens before the first embedding call. Scanned PDFs, multi-column papers, tables spanning pages, contracts with stamps — a naive text extractor mangles all of them, and no amount of clever retrieval fixes garbage chunks. So RAGFlow invested where others didn’t: an OCR stack that detects and reads text visually, a layout analyzer that understands columns and reading order, and template-aware chunking that respects document structure. Apache-2.0-licensed and developed by InfiniFlow, it has grown into one of the most-starred RAG engines on GitHub, and its current main branch tells a second story: the Python backend has been rewritten in Go, with compiled services for ingestion, search, and agents, while the Python SDK and the React UI stay as the friendly outer shell — a production systems project, not a research demo.
The architecture splits into four planes that meet at the HTTP router. The document plane is the deepest: an ingestion service in internal/ingestion/ queues every upload as a tracked task, DeepDoc’s ONNX sessions read pages like a human would, format parsers normalize DOCX and CSV and audio, a delimiter-aware chunker splits the text, and an embedder batches the results into vectors. The index plane abstracts search behind one interface with Elasticsearch, Infinity, OceanBase and more behind it. The agent plane runs visual workflows — a canvas of components from a Begin entry point through LLM calls, categorizers, and browsers — plus a dedicated agentic RAG loop that iterates searches and cites evidence. The API plane binds it all: one Go binary, a REST router, an MCP surface, and metadata in a DAO layer. As always in this series, what follows is an educational tour of published source code.
RAGFlow at a glance: the React app and Python SDK call the Go server, whose router queues uploads into the ingestion service; DeepDoc OCR and the chunker feed the embedder, which writes vectors into the search engine backed by object storage; the canvas runs agent workflows grounded by the agentic RAG loop that queries the same engine.
Reading the overview from left to right:
- The React web app covers datasets, chats, files and agent builders in a Vite-built UI.
- The Python SDK mirrors the REST surface for programmatic use.
- The RAGFlow server wires config, engines, storage and services into one binary.
- The HTTP router registers every route for datasets, documents, chunks, chats and agents.
- The ingestion service executes document tasks with heartbeats and progress tracking.
- The OCR sessions pool ONNX inference for detection and recognition models.
- The chunker splits parsed text under delimiter and size rules.
- The search engine interface hides Elasticsearch, Infinity and other backends behind one contract.
Why You Need This
The first reason is DeepDoc, the document-understanding stack that justifies RAGFlow’s reputation. Under internal/deepdoc/, the ONNX session pool loads computer-vision models once and shares them across workers, with explicit memory management for weights. The text detector runs DBNet-style segmentation to find text boxes on page images; the recognizer reads each cropped box with a CRNN; the table structure recognizer recovers rows and columns from table images so cells survive as cells instead of soup. Above the models, the PDF layout analyzer — nearly eight hundred lines — sorts characters into lines, lines into columns, and regions into reading order, handling the cross-page tables and floating captions that defeat naive extractors. Reading this half teaches what “deep document understanding” actually costs: real vision models, real geometry, and real engineering around ONNX runtime sessions.
The second reason is the document path, which shows what a production ingestion system looks like when written by people who have been burned by batch scripts. The ingestion service — twelve hundred lines — owns the task lifecycle: acknowledgements, heartbeats, progress sinks, redelivery counters, and convergence tests that verify a document reaches a terminal state. Format parsers normalize DOCX, CSV, audio, email and more into text plus structure; the chunker applies preprocessing, delimiter-aware splitting, and postprocessing with test coverage for each stage; and the embedder batches chunks into embedding calls under explicit token limits. Originals and derivatives live in the storage factory, which selects MinIO, S3, OSS, GCS or in-memory blobs from config. It is a complete curriculum in robust data flow: every failure mode you have hit in a document importer has a named, tested mechanism here.
The third reason is the agent and retrieval plane, which turns the corpus from a search box into a reasoning substrate. The workflow side implements a canvas of typed components: the base contract defines inputs, outputs and invocation, the LLM agent component — the largest at sixteen hundred lines — adds tool calling and streaming, and neighbors cover workflow entry, intent-based branching, and headless browsing. The runtime executes the graph with shared context and a retrieval bridge, while the tool registry wires dozens of callable tools from corpus search to sandboxed code execution. The retrieval side goes further: the agentic RAG loop plans multi-step searches, tracks what it has found in an evidence registry, and attaches citations — with prompt templates for queries, keywords, and citation discipline versioned as markdown in rag/prompts/.
The detail view: clients and the API gateway with DAO and config; the document flow from ingestion through OCR sessions, detectors, recognizers, layout analysis, parsers, chunking and embedding; the agent plane from canvas and component base through the LLM node, tool registry, agentic search and the RAG loop with its prompt library; and the index plane of engine clients, shared types and object storage.
Walking the detail diagram, one document is traceable end to end. An upload lands on the router, which queues a task in the ingestion service and stores the original file in object storage. The worker invokes the right reader from the format parsers; a scanned PDF goes through the OCR session pool, where the detector finds text boxes and the recognizer reads them, and the layout analyzer restores reading order. The text flows into the chunker, then the embedder vectorizes the chunks and writes them into the search engine — concretely the Elasticsearch client or the Infinity client, speaking the shared schema of the engine types. Progress reports flow back to the UI the whole way, so the system can show exactly which document is stuck and why.
The second walkthrough is a question rather than a file. A user asks something in chat; the router dispatches to the conversation service; and when agentic retrieval is enabled, the agentic RAG agent begins its loop — generate query variants, search, read the hits, decide whether the evidence suffices, and either iterate or answer with citations. Each step consumes templates from the prompt library: query generation, keyword extraction, cross-language rewriting, citation forcing. The same corpus is reachable from the agent side through the search tool inside a canvas workflow — the design lesson of the whole plane: one retrieval substrate, two consumption styles, scripted workflow graphs for predictable processes and an autonomous loop for open questions. The MCP surface in internal/mcp/ and the Python SDK make the same corpus reachable from third-party tools and scripts.
From Install to Your First Chat
The supported route is Docker Compose: clone the repo, edit docker/.env to set your LLM provider key, and docker compose -f docker/docker-compose.yml up -d brings up the server, Elasticsearch or Infinity, MinIO, Redis and MySQL. The web UI listens on port 80; sign up, create a knowledge base, and drop in PDFs — the document plane takes over, showing per-file parsing progress as it runs. To use the corpus from code, pip install ragflow-sdk, create a client with your base URL and API key, and the SDK’s RAGFlow object exposes datasets, chats, and agents as plain Python objects. Agent building happens in the UI canvas — drag an LLM component, wire it to a retrieval component, add a categorizer for routing — and the resulting graph runs from the API exactly like the built-in chat. For development, the Go services build with standard tooling and the frontend with npm run build.
Honest limits: the Go rewrite is recent enough that much of the documentation, and most third-party tutorials, still describe the older Python architecture, so file references in guides can drift from the tree you are reading. The full stack — OCR models, search engine, vector database, MySQL, Redis, MinIO — is heavy for a laptop, and the DeepDoc vision models add meaningful startup cost and memory. Agentic RAG multiplies LLM calls per question, which is powerful and expensive at the same time. And the dual heritage means some behaviors are configured in YAML, some in the UI, and some in code. None of that changes the verdict: RAGFlow is the deepest open-source treatment of the document side of RAG, and its source is the best available map of what production ingestion actually requires. Enjoyed this post? Never miss out on future posts by following us