Five RAG Open-Source Projects in 2026: What Actually Stands Up and What's Outdated
Five Major RAG Open-Source Projects Deeply Compared: Dify, RAGFlow, FastGPT, AnythingLLM, LightRAG
All data as of 2026-10-30, star counts verified via GitHub API / shields.io, issue IDs are clickable for verification.
Origin: My own project
tiered-rag-service(a Chinese PDF Q&A service with tiered access control) reached a halfway point, and I wanted to know my real position in the ecosystem, so I tore down these five benchmarks one by one. After doing so, I found that many widely circulated "consensus" points are already outdated — including three in my own notes and one description of my own project. All corrections are in the appendix at the end.
First, what my project is, so the comparison has a reference point
In one sentence: FastAPI + LangChain Chinese PDF Q&A service with hybrid retrieval (BM25/jieba + bge vectors) → cross-encoder rerank → compiles a separate retrieval engine per access tier.
| Item | Actual value (source-verified) |
|---|---|
| Stack | Python 3.11+ · LangChain 1.4.5 · FastAPI 0.162 · Chroma 1.5.9 · sentence-transformers 6.2 · Redis · Gradio 6.30 · Docker Compose |
| Chunking | RecursiveCharacterTextSplitter, chunk_size=800 / overlap=20, delimiters \n\n / 。 / ! / ? |
| Recall | BM25 (jieba tokenizer) top-20 + Chroma vector top-20, EnsembleRetriever weights 0.5/0.5 |
| Rerank | bge-reranker-v2-m3 cross-encoder, compress to top-3 |
| Generation | qwen-plus (embeddings use bge-small-zh-v1.5) |
| Isolation | Tiered order (TIERED_RAG_LEVELS, default public,secret, tier N reads 0..N), each tier has its own BM25 corpus + Chroma {"level":{"$in":[...]}} filter |
| Quality | 45 unit tests (run in 0.4s, no model/Redis/keys required) · 10 ADRs · CI static checks |
Its most valuable part isn't the pipeline itself, but that I tested it and it knocked down my own assumptions (data in Section 5 and the appendix). This also set my judgment criteria for looking at these five projects: no complexity without evidence.
One Chart for Positioning
These five projects are not in the same track at all; ranking them outright makes no sense. Spread them across two axes: abstraction level (underlying framework ↔ ready-to-use product) and retrieval paradigm (vector matching ↔ structural understanding).
| Project | Stars | Positioning | Tech stack | License | Minimum config |
|---|---|---|---|---|---|
| Dify | 160k | LLM application operating system, workflow + agent orchestration platform | Python 3.13 / Flask + Next.js | Modified Apache 2.0 with additional terms | 2C / 4G |
| RAGFlow | 93k | Deep document understanding RAG engine (ceiling of parsing capability) | Go (rewritten in 1.0) | Apache 2.0 | 4C / 16G |
| AnythingLLM | 68k | Local-first private ChatGPT, desktop double-click to use | Node/Express + React/Vite | MIT (most permissive) | Single-machine desktop |
| LightRAG | 40k | Knowledge-graph-enhanced RAG for multi-hop relational reasoning | Python | MIT | Depends on LLM, not machine |
| FastGPT | 30k | Lightweight visual knowledge-base Q&A, tunable RAG pipeline | Next.js 16 / TS 6 / MongoDB | Apache 2.0 + additional terms | 2C / 4G |
Two facts that get corrected at first glance:
- Dify isn't ~100k, it's 160k. It has almost quadrupled in two years and is already the de facto standard of this track.
- RAGFlow's core is already Go. Since v1.0.0-rc1 it was a complete rewrite; the repository language composition is 71.2% Go, and "Python + React" belongs to the v0.x era. This matters because it changes how you do secondary development (details below).
1. Dify: The Most Platform-Vertical, but RAG Is Just One Submodule
What It Actually Is
The backend api/ is Flask 3.1.3 + Celery + gunicorn/gevent, running Python ~3.13; the frontend web/ is Next.js/React. What's truly notable is the architectural evolution:
- The workflow execution engine has been extracted into a standalone library
langgenius/graphon— a Python graph execution engine specifically for agentic workflows, with 1.18.0 locking the dependency. - The plugin runtime is a standalone Go sidecar
dify-plugin-daemon; plugins are installed from marketplace.dify.ai, with types including model / tool / agent-strategy / datasource / trigger / bundle. - Vector stores support 30
VECTOR_STOREoptions (Weaviate default, plus qdrant/milvus/pgvector/opensearch/tidb). - The monorepo now contains
dify-agent,dify-agent-runtime,cli,skills,e2e— what it's building is not RAG, it's an "LLM application operating system."
The license is Apache 2.0 modified with two extra conditions: no multi-tenant/multi-workspace service without a commercial license, and the web/ LOGO and copyright info must not be removed. Internal private deployment is fine; selling SaaS requires negotiation.
RAG Pipeline: This Is Where I Need to Correct Things
Dify's current chunking modes are exactly General and Parent-child; the old "Automatic/Custom" labels are gone from the current docs. Parent-child chunking has existed since v0.15.0 (2024-12): match on the small child chunk, return the parent chunk.
On the retrieval side: High-Quality / Economical, then vector / full-text / hybrid, hybrid gives a weight slider or a Rerank model; TopK default is 3, score threshold default is 0.5. On 2025-09-23 they added Knowledge Pipeline (visual ETL), and in 2026-02 v1.12.0 added Summary Index — LLM generates a summary for each chunk, vectorizes it separately, and uses it as an additional recall path; both General and Parent-child can configure it.
Comparing to my own defaults is interesting: I use rerank_top_n=3, Dify's TopK default is also 3; but Dify has something I haven't built — score threshold 0.5, i.e., below confidence it doesn't feed. I unconditionally stuff the top-3 into the Prompt.
That Famous Issue: #31510
My original narrative was "Parent-child chunking is a gap in Dify, the issue was Not planned, and I implemented it." After verification, every sentence of that needs rewriting.
#31510 is real, titled "Upgrade RAG Indexing Architecture to address 'Context Fragmentation' (Moving beyond Naive RAG)", opened 2026-01-26, with the example being this: the title "Project Alpha Specifications" and body "The maximum voltage is 5V" are split apart, breaking retrieval. The author suggests using LangChain's ParentDocumentRetriever. On 2026-03-14 it was auto-closed by dosubot with state_reason: not_planned.
But the key is: this issue complains about the overall "naive RAG indexing architecture," while Dify has already had Parent-child mode. It was marked not_planned not because the official team denies the pain point, but because the symptom already has a ready-made switch and doesn't warrant refactoring the indexing layer.
So the correct statement is not "I solved a problem Dify hadn't solved," but "Dify has had Parent-child chunking for two years, and my own formal version doesn't use that structure." Why not, see point 6 below.
Real Pain Points (All First-Hand Issues)
- #16178: Excel parsing over 10MB takes 30+ minutes; chunking loads serially. Also marked NOT_PLANNED.
- #27291: Upgrading 1.9.1 → 1.9.2 directly broke existing Weaviate knowledge bases; users forced to rebuild index or downgrade.
- #32297: During migration, Redis lock TTL is only 60 seconds; large databases lose the lock mid-upgrade.
- #33725: After v1.13.x moved execution to Celery workers, workflows finish without getting output; workaround is
CELERY_WORKER_CONCURRENCY=10. - #20768: Parent-child mode eats whitespace inside child chunks — Parent-child chunking itself has pitfalls; it's not a silver bullet.
- #44923: Loop/iteration node single-step debugging loses checkpoints; still open as of 2026-10-28.
Platform complexity grows faster than single-machine capacity. Official minimum is 2C/4G, but the 1.18.0 (2026-10-23) upgrade notes mention: Agent Backend and runtime must upgrade together, sandbox now requires a new auth token, PASSWORD_PEPPER must be kept, and the KnowledgeFS image is amd64-only. That means "it can start," not "it works well."
Evolution Pace (Feel How Fast It Is)
Knowledge Pipeline 2025-09-23 → 1.11.2 2025-12-25 → Summary Index 1.12.0 2026-02 → Human-in-the-loop 1.13.0 → Agent × Skills 1.14.0 ("Workflows Become a Team Asset") → E2B sandbox 1.17.0 → New Agent standalone app 2026-08-27 → 1.18.0 2026-10-23 (Agent Output Routes, .ifpkg portable apps, nested workflow trace drill-down, difyctl CLI).
1.18.0 also added Agent Knowledge Base (Beta): a standalone knowledge-fs compose profile and separate database, with retrieval depth options of Fast / Deep / Research. Not yet on cloud.
Three Concrete Lessons for tiered-rag-service
- Borrow the Summary Index. A batch process generates chunk summaries, a separate table serves as one recall path. It can address the "cross-paragraph synthesis" issue I measured — in
docs/evaluation.md's stratified sampling table, the expected conclusion for that category is "both approaches fail, exposing chunk strategy problems." - Add a score threshold. I unconditionally stack top-3; Dify defaults to a 0.5 threshold. My library has out-of-scope test items like "What time does the cafeteria open," but I only rely on the Prompt's "strictly no common sense" instruction — using retrieval confidence is more reliable than prompt engineering, which is the same philosophy as my permission design.
- Watch out for that #20768. Parent-child chunking can break child chunk text integrity. Any "smarter-looking" chunking strategy has its own bug surface; it's not a free upgrade.
2. RAGFlow: Making "Document Parsing" Industrial-Grade, at the Cost of Rewriting the Whole Team
Who Made It, Current Status
InfiniFlow (Shanghai), founded 2023-08, co-founder Zhang Yingfeng. Apache 2.0, pure open-source license, the cleanest of the five besides AnythingLLM / LightRAG.
The last Python version is v0.27.2 (2026-09-10); v1.0.0-rc3 released 2026-10-30 — today. rc1 is the full Go rewrite, with an irreversible database migration; the official upgrade path is a long chain: v0.22.1 → v0.25.6 → v0.26.4 → v0.27.2 → v1.0.0-rc1, and Tag-type datasets do not auto-migrate.
DeepDoc: Its True Moat
This is the only irreplaceable part of RAGFlow. Verified details:
- DLA (layout analysis) + OCR + TSR (table structure recognition) run in-process inside the Go service using ONNX Runtime, models at
internal/rag/res/deepdoc. v1.0 explicitly states "DeepDoc currently supports CPU environments only" — no GPU needed, better than most people assume. - 10 layout categories: Text / Title / Figure(+caption) / Table(+caption) / Header / Footer / Reference / Equation. There's a YOLOv10 variant, and an optional VLM pipeline since v0.18.0.
- OCR is self-trained
det.onnx+rec.onnx(CTC decoding), weights on HuggingFaceInfiniFlow/deepdoc. Whether it derives from PaddleOCR runtime, the official team hasn't said; I can't verify, so I'm leaving it open. - TSR outputs 5 labels: Column / Row / Column header / Projected row header / Spanning cell, with automatic table rotation correction. The name "TSRNet" circulating online could not be verified in the current repository.
- Parsers now go beyond DeepDoc: DeepDOC (default) / Naive / Docling / OpenDataLoader / TCADP / MonkeyOCRv2 / MinerU / Mistral OCR / PaddleOCR-VL — it's absorbing the open-source ecosystem itself.
- 12 built-in chunking templates: General, Q&A, Manual, Table, Paper, Book, Laws, Presentation, Picture, One, Audio, Email. The resume and tag templates existed in v0.27; I didn't see them in v1.0 docs (this is an inference).
- Formats: PDF, spreadsheets, images, emails, Markdown, plain text and code, HTML, DOC, DOCX, PPTX, audio. No video.
Infinity: Why They Built Their Own Database, and Why They Still Don't Use It
Infinity is the same company's AI-native database, supporting dense + sparse + tensor + full-text four-index hybrids, with built-in ColBERT reranking. Official numbers: vector search 0.1ms/15K QPS, full-text 1ms/12K QPS @33M documents, single binary deployment.
But here's a counterintuitive fact: Elasticsearch is still the default. docker-compose-base.yml clearly says DOC_ENGINE=${DOC_ENGINE:-elasticsearch}, with Infinity only an optional profile, locked to v0.7.4-x64-v3. The community has voiced dissatisfaction over this (#7917). Also, engines cannot migrate libraries: #8038 requests ES → Infinity migration with no implementer, and #8624 reports Infinity data loss.
How Heavy Is the Architecture, Really
I broke down the compose and counted. Always-on services: minio (image is actually pgsty/silo), kvrocks, nats. Profile-gated: es01, mysql, clickhouse, infinity, opensearch01/oceanbase/seekdb/serenedb/vastbase, tei-cpu|gpu, kibana, jaeger, sandbox-executor-manager. The application container ragflow-cpu internally hosts Go API 9380 / Admin 9381 / MCP 9382, wrapped with nginx.
Official hard requirements: 4 cores / 16GB / 50GB disk, Docker ≥ 24, Compose ≥ 2.26.1, single-container MEM_LIMIT defaults to ~8GB, and with ES you need vm.max_map_count ≥ 262144. GPU not required. The Go backend doesn't support macOS.
My old note said "feeding a cow to drink a glass of milk"; after seeing the compose, I think that was underselling it. For comparison, tiered-rag-service's compose has only api + redis.
Two Big Moves in 2026
- v0.20.0 (2025-08-04): Agent and Workflow merged into one, full MCP support.
- v0.27.0 (2026-08-19): Launched Knowledge Compilation (Wiki / Graph / Tree / PageIndex / Mindmap / Timeline / Skills — seven precompiled artifacts), Agentic RAG split into Low / Medium / High / Ultra four tiers, and simultaneously removed GraphRAG and RAPTOR from the UI. This change caused a storm (#16337, #14617, #16874). Even the project most aggressive about graph augmentation pulled graphs off the product surface — that signal is worth chewing on.
- Others: v0.21 introduced the ingestion pipeline canvas + TOC long-context, v0.23–0.25 worked on Memory, v0.26.3 added SoMark OCR.
Real Pain Points
Parsing hangs/slowness is the biggest category: #9466 (19 comments, just fixed 2026-10-26), #7165, #7576, #6664. Memory: #7995, #21177 (goroutine leak, fix in #19456). Executor deadlock #11464. A long list of chunking bugs: #18552, #20776, #21344. Go rewrite missing features: #15240, #20453. GPU silently falling back to CPU: #14565.
Lessons for tiered-rag-service
First, correct myself: I don't have pdfplumber or regex table parsing. src/tiered_rag/indexer.py only uses pypdf's page.extract_text(), and pdfplumber isn't in the dependency list. Also, my known limitation #4 states plainly: scanned PDFs produce no output; if text extraction yields nothing, it returns empty.
So what RAGFlow teaches me isn't "I should also add OCR," but the dividing-line design: I currently hardcode regex-based header/footer cleaning in text_cleaning.py (strip_repeating_layout, with config options TIERED_RAG_HEADER_PATTERN / FOOTER_PATTERN). That approach is right — it proves "cleaning rules must be externalized as config" rather than hardcoded. But my capability ceiling is "recognize repeated lines," while RAGFlow uses trained layout models. The real dividing line is characters per page: if pypdf extracts near 0, it should clearly error "this is a scanned document, this service doesn't handle it," rather than quietly returning empty text and making users think the knowledge base is broken. I currently return {"message": "未能提取到文本"} — honest, but not enough; it should be an observable failure classification.
As for whether to run persistent OCR for this: No. I have measured evidence against all "unverified complexity": reranking blows retrieval P50 from 15ms to 3306ms (about 220x), and on my 3-question eval set, quality differences are completely indistinguishable. RAGFlow's 16GB memory for DeepDoc is justified (it serves scanned documents and complex tables); I don't have that reason, so I should wait.
3. FastGPT: Lightweight and Controllable RAG Pipeline, but Chinese Full-Text Search Is Its Unavoidable Weak Link
Basics
Made by labring — the same people behind Sealos, Laf, AI Proxy. Latest release v4.17.2 (2026-10-09), main is already at 4.17.3.
Verified the stack via pnpm-workspace.yaml and package.json: Next.js 16.3.6, React 18, TypeScript ^6.0.3, Chakra UI v2, pnpm + turbo monorepo, Node ^22.23.4, mongoose ^8.22.1, pg ^8.10, @zilliz/milvus2-sdk-node, @node-rs/jieba.
Storage split is straightforward: MongoDB stores everything except vectors, vectors go in PostgreSQL/Milvus/OceanBase/SeekDB. Compose services: fastgpt-app, mongo, vector store, s3, sandbox-proxy, and AI Proxy is mandatory as of v4.17.0.
Resource requirements verified at concrete levels: PgVector/SeekDB minimum 2C4G, recommended 2C8G; 1 million vectors needs 4C8G (recommended 4C16G); 5 million needs 8C32G (recommended 16C64G); Milvus minimum 2C8G, recommended 4C16G. So "2 cores 4GB" only holds at toy scale.
License: The Easiest Footgun
The agreement is literally named "FastGPT Open Source License" (Apache 2.0 + additional terms), and the GitHub page shows that name directly. Official docs quote:
"FastGPT may be used for commercial purposes, such as serving as a 'backend-as-a-service' for other applications... However, when the following conditions are met, you must contact the author for a commercial license." "Multi-tenant SaaS service: Unless explicitly authorized in writing by FastGPT, you may not use fastgpt.io's source code to operate a multi-tenant SaaS service similar to fastgpt.io." "LOGO and copyright notice: ...The FastGPT console's LOGO or copyright information must not be removed or modified."
And one many people miss: the contributor terms say "the producer has the right to adjust the open-source license to a more restrictive or more permissive form." The licensor reserves the right to tighten. Think carefully before using it as a long-term commercial base.
(A side note: Dify's additional terms are almost identical. Everyone in this track who wants to do SaaS has put the same lock on. )
RAG Pipeline: I Tore Through the v4.17.0 Source Code to Enumerate
This area changed a lot; most old tutorials circulating online are obsolete. The current real enums in packages/global/core/dataset/constants.ts:
- Dataset modes:
chunk | qa | imageParse | backup | template - Chunk setting modes:
auto | custom | intelligent(intelligent is an external "smart chunking" service) - Split mode
DataChunkSplitMode:paragraph | size | char, withminSize / forceChunk / maxSizethree trigger thresholds
Note: the "split by heading / by special symbols / regex split" UI modes in old tutorials are no longer in the 4.17 enums. If you're still reciting that interview answer, the answer is outdated.
On the retrieval side (workflow/template/system/datasetSearch.ts): embedding | fullTextRecall | mixedRecall, scoring methods embedding | fullText | reRank | rrf. Defaults: similarity threshold 0.4, datasetMaxTokens 5000, vector weight 0.5, rerank disabled by default, rerank weight 0.5. Tag filtering isPro: true — this feature is commercial-only.
Full-Text Search: FastGPT's Most Solid Technical Debt
Implementation is MongoDB $text + jieba tokenization. True BM25 only exists with Milvus ≥ 2.5.16 (added in v4.16.2). Official docs say: "PG/OceanBase/SeekDB/openGauss full-text search still goes through MongoDB $text."
So if you use pgvector (the most common deployment choice), your full-text search depends on Mongo's text index; switching databases doesn't escape it.
Real issues from this:
- #2791 (2024-09): Searching "Shanghai Jiao Tong University" returns "Shanghai", "Jiao", "Tong", "University" as separate words — Mongo
$texthas no phrase matching, the classic lexical retrieval failure. - #5182 (2025-07): pg 40 million vectors + Mongo 14 million rows of full-text, query timeout.
- #6749 (2026-04): Mongo full-text query too large; users requested a config option to disable the tokenizer request.
- #3695 (2025-02): After upgrade, reports
text index required for $text query— searched before index was built. - #4301 (2025-03): 73 records retrieval hangs, next-server memory exhausted, container restarts.
- #1896: Mongo space not reclaimed, wasting 7.9GB.
- #4197 / #3731: pgvector HNSW
ef_searchdefault values cause recall loss.
Upgrade pain: The official migration doc from 4.0 to 4.17.3 is about 150 pages long, and it says "before upgrading to V4.17.0, first upgrade to V4.16.x and run all leftover migration scripts."
Orchestration Capability
Documented 20 nodes: ai_chat, content_extract, coreferenceResolution (coreference resolution), custom_feedback, dataset_search, document_parsing, form_input, http, knowledge_base_search_merge, loop, loop_run, parallel_run, question_classify, reply, sandbox-v2, text_editor, tfswitch, tool, user-selection, variable_update. MCP serves as both client (v4.9.6+) and server-side publishing. OpenAI-compatible /v1/chat/completions and /v1/responses.
Recent: v4.17.2 added knowledge-base data pre-storage + training chain refactor + directory-constrained retrieval; v4.17.1 added permission snapshots, knowledge-base tags, OFD parsing (for domestic Chinese scenarios); v4.17.0 added SSO (LDAP/DingTalk), Agent V2 TTS, mandatory AI Proxy. v4.13.2 (2025-10) is marked "no longer maintained."
Lessons for tiered-rag-service
First, we hit the same wall with jieba, but I hit it more cheaply. On my side it's BM25Retriever.from_documents(docs, preprocess_func=jieba.lcut) — rank-bm25 splits on spaces by default, which for Chinese means splitting on whole sentences, so the tokenizer must be passed explicitly. FastGPT uses jieba too (@node-rs/jieba), but underneath it connects to Mongo $text, leading to #2791 where "Shanghai Jiao Tong University" gets torn into three separate words. My BM25 is a real lexical scorer, not a bag-of-words union. This is worth narrating carefully, but with restraint: I'm not smarter than FastGPT; it's the same wall with different landings, and I haven't proven I'm better with recall@k — those 3 questions in my eval set have no discriminative power.
Second, it taught me that "default off" is a form of courage. FastGPT's datasetSearchUsingReRank defaults to false. I used to think that was a lack of optimization; now I've changed my view: my own measurement shows reranking balloons retrieval P50 by 220x with no measurable quality difference. So "default off" is an honest default. I currently hardcode rerank_top_n=3 into the default config; I should revisit that.
Third, rrf as a separate scoring option is worth stealing. I currently only use EnsembleRetriever's weighted fusion, and my own README warns: "fusing two candidate rankings can't treat BM25 raw scores and vector similarities as directly additive across the same dimension." Since the essence is fusing rankings, why not make RRF an explicit optional strategy? It has no manually tuned weight hyperparameter, which fits my embarrassing situation where "weights 0.5/0.5 are still empirical" (the ablation matrix C/D rows in docs/evaluation.md are answering exactly this).
Fourth, coreference resolution shouldn't be just a pronoun table. FastGPT made it a standalone workflow node. My D-003 is if not history or not any(p in question for p in _PRONOUNS) — I already wrote in my own docs that it has problems: elliptical questions without pronouns may still depend on history, and questions containing "this" or "that" don't necessarily need rewriting. The eval plan's item "construct 30 follow-ups requiring rewriting but not containing table pronouns, to measure the rewrite miss rate" targets exactly this.
4. AnythingLLM: Most Successful at Product Delivery, but the RAG Core Is Deliberately Thin
Basics
67,747★ / 7,623 forks, MIT — the most permissive for secondary development among the five (tied with LightRAG). pushed_at is today. v1.19.0 released 2026-10-26, roughly one release per month.
Yarn monorepo, three packages:
server/(anything-llm-serverv1.19.0): Express 4.21 + Prisma 5.3.1/SQLite,langchainlocked at 0.1.36,@lancedb/lancedb0.15.0,@modelcontextprotocol/sdk^1.24.3, with swagger.frontend/: React 18.2 + Vite 4.3 + Tailwind 3.3 + i18next (about 30 languages).collector/: standalone Express collection service (port 8888), parsers cover docx/mbox/pdf/audio/wav; extended loaders include RepoLoader (GitHub/GitLab), Confluence, DrupalWiki, ObsidianVault, PaperlessNgx, WebsiteDepth, YouTube subtitles.
embed and browser-extension are git submodules.
Desktop Version: Local-First's Real Landing Form
Electron-packaged, macOS Intel + Apple Silicon, Windows x64 + ARM64, Linux x64/ARM64 (AppImage, officially labeled "limited").
Official docs call the desktop version "single-player". In the feature table, multi-user, user management, workspace permissions, password protection, embedding components, white-label, browser access — desktop all ❌, Docker all ✅. Desktop "Network discovery" only exposes the API to 0.0.0.0; browser access returns 404 directly.
A note to flag: the repository Mintplex-Labs/anythingllm-desktop now returns 404, and the desktop repo isn't findable under the org; installers go through cdn.anythingllm.com, and the main repo only has a stale desktop branch (package.json stuck at v0.2.0). If you want to read desktop source for packaging patterns, the path has changed — I couldn't fully verify this.
Local Models: Lemonade Is the Biggest Change of 2026
Lemonade is AMD's open-source llama.cpp server (lemonade-sdk/lemonade). Timeline: v1.11.1 added it as a provider → v1.18.0 (2026-10-13) made it the desktop default engine, replacing the previously bundled Ollama → v1.19.0 brought it into Docker (-e ENABLE_BUILT_IN_LLM=true).
Going from "user must install Ollama themselves" to "engine bundled" completes the double-click-to-use loop. Vector stores: LanceDB (default), PGVector, Chroma/ChromaCloud, Milvus, Zilliz, Pinecone, Qdrant, Weaviate, Astra. (SingleStore, which appears in some online tutorials, is no longer present in code, README, or docs.)
RAG Core: Thin to a Surprise
Tokenizer is only LangChain's RecursiveCharacterTextSplitter; docs say "currently the only splitting strategy". Default chunk = 1000 characters (note: characters, not tokens), overlap = 20. Adjustable, but only applies to re-embedded documents and is bounded by the embedding model's limits.
Retrieval knobs are only: Max Context Snippets (docs suggest 4–6), similarity threshold (default 20%, Low .25 / Med .50 / High .75), document pinning (inject a full document into the prompt, bypassing RAG), and session-level attachment full-text since v1.8.5. Rerank ("Accuracy Optimized") is only supported by LanceDB, and uses a fixed Xenova/ms-marco-MiniLM-L-6-v2, adding +100–500ms.
Three conversation modes: Agent (default for new workspaces after v1.11.1, renamed from "Auto" in v1.13.0), Chat, Query.
"Deep customization is limited" is true, backed by issues: #3941 (asking for rerank support outside LanceDB), #2146 (asking for semantic chunking, 9 upvotes, not implemented), #3198, #5413. Vector store is also system-level config, can't be chosen per workspace.
Other pain points: #3700 multi-user memory growth, #3515 desktop idle at 40% CPU, #3367 document page very slow with 20k files, #5712 "embedding brutally slow", #6199 silent data loss / orphan vectors, #4443 hardcoded 5-minute Ollama timeout, #5025 (11 upvotes) asks for desktop to be a thin client to server. Desktop upgrade is overwrite install (data retained), but v1.18's engine swap deletes old Ollama models.
What They've Been Working On in 2025–2026
MCP (only the client's Tools capability; no Resources/Prompts/Sampling), Agent Skills + Community Hub + Intelligent Tool Selection (v1.12.0, claims up to 80% token savings), file-system & document-generation agents, Telegram bot, Model Router, scheduled tasks, Automatic Memories, Agent Surveys (all v1.13.0), image generation (v1.16.0), Meeting Assistant (v1.19.0, has /v1/meeting-assistant/start|stop|search API), AnythingLLM Mobile (Android, on-device inference, open-source), live document sync (beta).
Lessons for tiered-rag-service
AnythingLLM is the only one of the five that treats "delivery" as the core problem. Its RAG core is even thinner than mine — only one splitter, 1000-character cut, rerank only on LanceDB — yet it has 68k stars. That alone says: in open-source product propagation, "runs out of the box, no config, good privacy" matters far more than "5 points higher recall."
Here I need to be honest with myself: my tiered-rag-service does have two more layers in retrieval (BM25 fusion + cross-encoder rerank), but my README's known limitation #2 says "evaluation is only small-sample process verification, no production-grade metrics." I have no right to claim my pipeline is better, because on those 3 questions, pure vector and hybrid+rerank both give context precision/recall of 1.0.
Two concrete things to borrow:
- Document pinning. It acknowledges a simple fact: retrieval has a failure rate; below the threshold, don't pretend — just stuff the user-specified full text into the prompt. My threshold filters long documents that users actually know they're asking about. This is the other half of the answer to my "out-of-scope questions should be refused" test item — besides refusal, give users an escape hatch: "I know where it is, don't retrieve."
/healthzalready exists, but learn to complete the delivery experience. I already have Dockerfile + docker-compose + CI (better than I thought from the material), but what truly blocks others from reproducing is the README line: "first launch downloads bge-small-zh-v1.5 and bge-reranker-v2-m3 (~1.2GB)." Any 1.2GB initial download is a real wall for anything meant to run on someone else's machine; I need to provide a pre-packaged or optional downscale solution.
What I won't copy: Electron. #3515's idle 40% CPU is something users complain about in issues; I don't want to carry that.
5. LightRAG: The Cost-Performance King of Graph Augmentation, but That "10x" Is Fake
Basics
HKUDS (HKU Data Science), 40,438★ / 5,844 forks, MIT, Python, [EMNLP 2025] paper, created 2024-10-02, pushed yesterday. Comparison target microsoft/graphrag: 36,496★, MIT, current pyproject.toml version 3.3.0.
LightRAG has caught up to and overtaken Microsoft's GraphRAG — in two years, that itself is evidence its approach has been validated.
Two-Level Retrieval: Verified, There Are Actually Five Modes
Low-level (local) handles specific entities and their relationships; high-level (global) handles macro topics and cross-document associations. The README now lists five: local / global / hybrid / naive / mix, default is mix (local + global + naive fused). The WebUI type definition also has a sixth bypass. Also, since 2025-08, hybrid queries have reranker enabled by default.
(My note's "four modes" was old 2024 information.)
Incremental update is its most elegant design: index cost is only total_tokens / chunk_size LLM calls, new documents only extract their own chunk batch, no full rebuild. When deleting documents, affected entity relationships are rebuilt from the LLM response cache (added 2025-08) — saving re-extraction.
I appreciate the honest storage disclaimers: default backends JsonKVStorage / NanoVectorDBStorage / NetworkXStorage / JsonDocStatusStorage, and the README explicitly says these are "not suitable for production" because they eat memory. Production options: PostgreSQL (officially recommended; one database can cover all four storage types), MongoDB, OpenSearch (2026-03), Neo4j, Memgraph, Milvus, Qdrant, Faiss, Chroma, Redis, Apache AGE, Gremlin, TiDB.
"Indexing Speed ~10x Faster" — I Checked, It's False
I must call this out, because I wrote it in my own notes too.
I searched the full text of arXiv 2410.05779v3: 10x, ten times, order of magnitude, times faster — zero hits. The paper's §4.5 (Legal dataset) gives formulas, not multiples: retrieval tokens 610 × 1,000 vs <100; retrieval API calls 610,000 / C_max vs 1; incremental update 1,399 × 2 × 5,000 tokens vs T_extract.
That "10x" comes from third-party marketing blogs (e.g., ragdollai.io writing "10x faster queries at 90% lower cost"). And "10x faster indexing" is actually a claim belonging to another project, E²GraphRAG, mistakenly attributed to LightRAG.
What's more worth saying: in the LightRAG paper's own table, on the Mix dataset it loses to GraphRAG (Overall 49.6% vs 50.4%). It wins on Agriculture / CS / Legal (54.8 / 52.0 / 52.8). This isn't "all-around dominance," it's "more cost-effective in most scenarios."
Real Pain Points
- Entity deduplication only matches by exact name → lots of duplicate nodes and disconnected subgraphs. The paper has 0 occurrences of
entity resolutionandduplicate. External academic patches exist (DEG-RAG, arXiv 2510.14271). - Hallucinated generic entities (junk nodes like "related person" / "a certain department") — issue #191 (2024-11-01) has been open since then, unresolved.
- Manual cleanup:
POST /graph/entities/mergeendpoint does exist (merges duplicate/misspelled entities), but the built-in WebUI client only calls/graph/entity/edit(withallowMerge) and/graph/label/list(returnsmerge_candidates), and does not call that merge endpoint. My note that "WebUI has a merge button" had the right direction but wrong details. - LLM call volume: after extraction, there are entity merge and relationship merge phases. README requires the extraction model to be non-thinking and warns that models with throughput below ~50 tok/s will time out (actual timeout = configured value × 2).
- High model capability requirements: README explicitly admits "higher capability requirements for LLMs than traditional RAG," and calls Qwen3-30B-A3B-Instruct "a reasonable lower bound." If you want to run a 7B model for graph augmentation, don't expect quality.
- Chinese:
SUMMARY_LANGUAGEsupports Chinese (default English), recursive splitting handles CJK punctuation, WebUI has zh/zh_TW interface and README-zh. But all paper benchmarks are English UltraDomain datasets; there is no public quantitative data for Chinese quality. That's "supported," not "validated."
Key 2026 Moves
RAG-Anything (24,310★, released 2025-06) merged into LightRAG in 2026-05; multimodal parsing (via MinerU / Docling) is now a feature of LightRAG, not a separate choice. Same family: MiniRAG (2,026★, ACL 2026, focused on small-model scenarios), VideoRAG (3,496★, KDD'2026, video). AnyGraph is unrelated (that's a 231★ graph foundation model project, stalled since 2024-09; don't mix it up).
GraphRAG's unique capability is Leiden community detection + bottom-up hierarchical community reports, which is the foundation of global search. LightRAG deliberately cuts community reports to trade for cost and speed — that's the real difference between the two, not speed.
Lessons for tiered-rag-service
First, "incremental cost" is the only hard metric for whether a graph approach can land. LightRAG compresses cost to chunk count × 1 call, uses cache for deletion rollback, which makes graphs discussable at my scale. This also solves a real technical debt of mine: my known limitation #3 says "every upload rebuilds BM25 fully, O(N) and gets slower as library grows." LightRAG's incremental thinking gives me a reference — in the Roadmap, the item "BM25 index persistence, avoid full rebuild" should be prioritized ahead of citation tracing.
Second, and most important: three pieces of evidence point to the same thing — in this scenario, graphs still lose to a well-tuned hybrid retrieval on ROI. RAGFlow removed GraphRAG from its UI; LightRAG requires 30B-class models for quality guarantees; entity dedup is exact string match only. I'm not adopting graphs.
Third, this project taught me "how to evaluate something I haven't built." My original narrative was "I solved Dify's Not planned pain point with parent-child splitting." The reality:
- I've only done parent-child splitting in a learning prototype (
D:\python_project\Langchainn\RAG进阶\6+父子文档切块.py, child 200 / parent 1000, metadata storesparent_text); the productionindexer.pyis single-layer 800/20, with no parent field; - And Dify has had Parent-child for two years; the feature itself isn't scarce.
So what I can honestly claim is not "I did chunking others haven't," but: "Others claim their retrieval pipelines are better, but I measured reranking's 220x latency cost and 'no difference on 3 questions,' and used that to question my own defaults." That's worth far more than parent-child splitting, and it's the part I actually did and have data for.
6. Horizontal Comparison: The Six Dimensions That Actually Matter
Document Parsing
| Parsing capability | Chinese adaptation | Pluggable | |
|---|---|---|---|
| Dify | Weak (Excel 10MB+ takes 30 min, #16178) | Average | Has Knowledge Pipeline |
| RAGFlow | Ceiling (DLA+OCR+TSR, in-process ONNX, CPU-capable) | Good | 9 parsers swappable |
| FastGPT | Passable (v4.17.1 added OFD) | Good | Limited |
| AnythingLLM | Collector complete but mostly plain-text oriented | Average | collector as separate process |
| LightRAG | Since 2026-05, merged MinerU/Docling multimodal | No benchmarks | — |
| tiered-rag-service | pypdf single-layer text extraction, scanned returns empty | Regex header/footer cleaning + CJK soft-line-join | Rules externalized as env, parser not swappable |
Chunking Strategies
- Dify: General + Parent-child (since 2024-12), plus Summary Index as an additional recall path.
- RAGFlow: 12 templates chunk by document type; this is the most engineered approach to "chunking."
- FastGPT:
paragraph / size / char+ external intelligent service; old "by heading/regex" no longer in enum. - AnythingLLM: Only recursive character splitter, 1000 chars / overlap 20.
- LightRAG: Chunk is just a carrier before entity extraction; chunking method doesn't matter, the graph matters.
- Mine: single-layer 800 / overlap 20, custom delimiters for Chinese punctuation. Same structure as AnythingLLM, just different parameters.
Retrieval Pipeline
| Full-text implementation | Hybrid retrieval | Rerank | Confidence threshold | |
|---|---|---|---|---|
| Dify | Depends on chosen vector store (30 options, Weaviate default) | Weight slider / rerank model (choose one) | Default off, TopK=3 | 0.5 (yes) |
| RAGFlow | ES (default) or Infinity (built-in ColBERT) | Strong, multi-path fusion | Infinity built-in | Yes |
| FastGPT | Mongo $text + jieba; true BM25 only on Milvus |
Weighted / rerank / RRF | Default off | 0.4 (yes) |
| AnythingLLM | Threshold + pinning | No weight adjustment | LanceDB only, fixed model | Default 20% (yes) |
| LightRAG | Graph traversal + vectors | local/global/hybrid/mix (default) | Hybrid default on since 2025-08 | — |
| Mine | True BM25 (rank-bm25 + jieba), not $text |
EnsembleRetriever 0.5/0.5, top-20 each | bge-reranker-v2-m3, top-3 | None (to add) |
All four platforms have a confidence threshold; only mine doesn't. This is the cheapest and most urgent fix from this research.
Permission Model (I'm Only Writing What I Verified, Not Making "Only I Have This" Claims)
What I verified: Dify has metadata filtering and an external knowledge-base API; FastGPT has knowledge-base tag filtering but isPro: true (paid feature); AnythingLLM's multi-user/workspace access management exists only in Docker version; RAGFlow and LightRAG's permission granularity I did not individually verify.
So I can only say: among these five, the access control I can confirm is at the "can this user open this KB/workspace" layer, and filtering capability is often tied to the commercial edition; while tiered-rag-service takes a different path — classification levels as chunk metadata, and at startup and each ingestion, compiles a search engine per tier (tier-specific BM25 corpus + Chroma {"level":{"$in":[...]}}), so lower-tier candidate sets physically cannot contain higher-tier chunks. At the same time, I must be clear about the other half: the tier is declared in the request body, with no real authentication (ADR D-010), so it proves "the retrieval layer can do data isolation," not "the system can resist privilege escalation."
I'm not writing "only I have this," because I haven't verified the full capability matrix of the other four.
Orchestration and Agent
Dify ≫ FastGPT > RAGFlow > AnythingLLM ≫ LightRAG (the latter isn't in this track). My project is deliberately not an Agent — the Roadmap's last item is "wrap the retriever as a tool and let an agent decide when to retrieve."
Deployment Weight (The Most Exaggerated Gap)
AnythingLLM desktop → double-click, zero config
tiered-rag-service → pip install -r requirements.txt + docker compose up -d redis (first model download ~1.2GB)
LightRAG default → pip install + one API key (but production needs Postgres/Neo4j)
FastGPT → 2C4G minimum, Milvus 2C8G, vectors scale up 4C8G ~ 16C64G
Dify → nominal 2C4G, actual 7 services + Go sidecar, 1.18 needs Agent runtime
RAGFlow → 4C / 16G / 50G hard requirement, 3 middleware always-on, no macOS
License (First Red Line for Product-Making)
| License | Can you build SaaS on it? | |
|---|---|---|
| AnythingLLM, LightRAG, Mine | MIT | Yes, no extra conditions |
| RAGFlow | Apache 2.0 | Yes, pure open source |
| Dify | Apache 2.0 + addendum | Multi-tenant needs commercial license, LOGO must stay |
| FastGPT | Apache 2.0 + addendum | Multi-tenant needs written authorization, LOGO must stay, and license reserves right to tighten |
| GraphRAG | MIT | Yes |
My project is MIT, which counts as a real advantage in selection: things others have to consider because of license, I don't.
7. Selection Decisions
- Need a "everything" application platform, have operations team, don't mind extra terms → Dify. The 160k-star ecosystem dividend is real; the risk of upgrade breaking your KB is also real.
- Poor document quality, many scans, complex tables, and you can spare 16GB RAM → RAGFlow; no competitor at the parsing level. But v1.0's Go rewrite migration is irreversible; if you board now, either stay on v0.27.2 or accept rc risk.
- Personal project / small team / quick demo → FastGPT (Chinese scenarios + tunable RAG pipeline, but pgvector users must accept Mongo full-text accuracy) or AnythingLLM (MIT, lightest deployment, but the RAG core is thin enough you'll need to modify it).
- Problem essence is "how are A and B related" / "cross-document synthesis" → LightRAG. Prerequisite: can afford a 30B-class model, and accept entity dedup you'll need to add yourself.
- Just Q&A, no analysis → plain vector + BM25 + rerank. Graph is over-engineering; RAGFlow itself pulled GraphRAG from its UI.
8. Three Things These Five Projects Taught Me
One: The bottleneck is in front of retrieval, and inside retrieval. RAGFlow's 93k stars prove: for real enterprise documents, parsing quality brings recall gains an order of magnitude larger than tuning retrieval parameters — garbage in, garbage out; no matter how accurate vectors are, they can't save a missed table. My own measurement proves the other end: when I quantified the bottleneck, it wasn't in model calls; it was in retrieval and reranking (after cache hits, the remaining 3369ms has 3361ms in retrieval+rerank, 99.8%). Together the two directions say the same sentence: optimization budget belongs in the data pipeline, not on the generation side.
Two: "Platformization" is interest-bearing debt. Every capability Dify adds brings another sidecar; RAGFlow had to change languages because of excessive state, leaving a 5-hop migration path; FastGPT has a 150-page migration doc. These three are telling me the same thing in the same way. What's most valuable about my project now is "only api + redis"; that advantage has a shelf life. So what I need to defend isn't "never add dependencies," but "any new state must be deletable and rebuildable, and rebuild time must be acceptable" — this constraint directly explains why BM25 full rebuild (limitation 3) is still tolerable now, but would be intolerable at thousand-level chunks.
Three: Star count on open-source projects measures delivery friction, not algorithmic sophistication. AnythingLLM has one splitter, 1000-char cut, rerank only on LanceDB, and an issue asking for semantic chunking has sat unopened for three years — it's 68k stars, higher than projects with deeper retrieval pipelines. Users want "no server setup, data stays local, double-click works."
I initially resisted this conclusion because it contradicts my self-narrative completely. But my own data supports it: on 3 questions, I can't measure any quality advantage of hybrid+rerank over pure vector, yet I pay 220x retrieval latency. If "smarter" isn't supported by measurement, it's just more expensive. That is probably the most uncomfortable and most useful takeaway from this research.
9. Next Steps for tiered-rag-service
Sorted by "evidence strength ÷ implementation cost," the first four are directly added from this research:
- Add score threshold (from Dify default 0.5 / FastGPT 0.4 / AnythingLLM 20%) — all four platforms have it, only I don't. This is the cheapest fix this round, and it directly improves the "out-of-scope questions should be refused" test item.
- Re-evaluate
rerank_top_ndefault (from FastGPTdatasetSearchUsingReRank=false) — I have 220x latency measurement, and with default-on I can't show quality benefit; this default is wrong. Either change the default or expand the eval set to prove it. - BM25 index persistence (incremental idea from LightRAG's
total_tokens/chunk_sizecost model) — solves known limitation 3, and keeps the "delete and rebuild" constraint alive. - Document pinning (from AnythingLLM) — acknowledge retrieval has failure rate; give users an escape hatch bypassing retrieval.
- RRF as optional fusion strategy (from FastGPT's scoring enum) — removes the embarrassment of "0.5/0.5 is empirical" and lets the ablation matrix D row run too.
- Summary Index as one recall path (from Dify v1.12.0) — for the "cross-paragraph synthesis" class in the eval set; this is the only chunk-side change with expected benefit.
- Expand eval set to 30+ questions, add noise documents, change judge model (this is last, but it's the premise for the first six) — my own written pass criterion is "hybrid retrieval recall@3 ≥ pure vector +10 percentage points, otherwise admit parameters aren't tuned or corpus isn't suitable." Measure first, then talk about optimization order.
Explicitly not doing: knowledge graphs, microservices, message queues, standalone object storage, Electron client, persistent OCR.
Appendix A: Six Circulating Claims This Research Overturned
| Claim | Verified result |
|---|---|
| "Dify has no parent-child chunking; the issue was Not planned" | Two layers. #31510 was indeed auto-closed by dosubot with not_planned on 2026-03-14; but Dify has had Parent-child since v0.15.0 (2024-12), and what was rejected was "refactor indexing architecture," not "do parent-child chunking." |
| "LightRAG indexes 10x faster than GraphRAG" | False. The paper has no such multiple; "10x" comes from third-party blogs; "10x faster indexing" is originally a claim by E²GraphRAG. And in the paper's table, LightRAG loses to GraphRAG on the Mix dataset (49.6% vs 50.4%). |
| "RAGFlow is Python + React" | v1.0 is rewritten in Go, Go is 71.2% of the repo language. Last Python version is v0.27.2 (2026-09-10). |
| "FastGPT supports heading/regex splitting" | No longer exists in v4.17 enum; now it's paragraph / size / char. |
| "AnythingLLM supports SingleStore" | Gone from code, README, and docs. |
| "LightRAG has four query modes" | Five, and the default is the new mix. |
Appendix B: Items I Could Not Verify or That Remain Uncertain
Whether RAGFlow's OCR derives from PaddleOCR runtime; whether the TSR model is called TSRNet; whether v1.0 really removed resume/tag templates; why AnythingLLM's desktop source repo is 404 and its exact packaging method; the claim "2026-02 FastGPT releases Memory API" appears only in a search snippet; any first-party indexing speed multiple from LightRAG; GraphRAG's "4–6 LLM calls per chunk"; FastGPT's exact company registration name (secondary sources inconsistent); Dify's plugin marketplace total; and the complete permission capability matrix of the other four projects (so the permission section in Section 6 only writes verified parts). GitHub API hit rate limits this time; some star counts are taken from shields.io live badges (precision to thousand).
Data timestamp: 2026-10-30. This track changes every three months; re-verify release notes before citing.