Dosu LogoDosu Logo
Ask
Join our Discord
ragflowPublic
InfiniFlow
Documentsragflow
Retrieval Pipeline
Retrieval Pipeline
Type
Topic
Status
Published
Created
Jul 23, 2026
Updated
Jul 23, 2026
Created by
Dosu Bot
Updated by
Dosu Bot

Retrieval Pipeline#

Overview#

RAGFlow's retrieval pipeline has five distinct entry points, but they all converge on a single engine: Dealer.retrieval() in rag/nlp/search.py. Each entry point applies its own query preprocessing before calling into Dealer, and each shares the same reranking and scoring logic downstream.

Chat completions (dialog_service.async_chat) ──┐
Standalone REST (/api/v1/retrieval) ──┤
Dify endpoint (/api/v1/dify/retrieval) ──┼──► Dealer.retrieval() ──► ranked chunks
Agent Retrieval tool (agent/tools/retrieval.py) ──┤
Agentic RAG (RAGTools in agentic_rag.py) ──┘

The Go backend (internal/service/nlp/reranker.go) implements a parallel reranking layer that mirrors the Python Dealer logic, used when requests route through the Go service path.

For BM25/KNN scoring mechanics and backend-level search (Infinity, Elasticsearch, OceanBase), see Hybrid Search and Retrieval.

Entry Points#

Chat Completions#

The chat completion path preprocesses queries inside async_chat() in api/db/services/dialog_service.py. The preprocessing sequence is: strip ##<digits>$$ variable substitution markers → optional multi-turn question refinement via full_question() → cross-language expansion → metadata filtering → optional keyword extraction. Agentic chat routes through rag_agent(), which instantiates RAGTools .

Standalone REST (/api/v1/retrieval)#

retrieval_test() in chunk_api.py handles this endpoint. The call sequence: auth + embedding model resolution → cross-language expansion (if cross_languages) → keyword extraction (if keyword=true) → metadata pre-filter resolving doc_ids → Dealer.retrieval() → optional ToC enhancement → child-chunk expansion → optional KG injection. See Retrieval API for full parameter documentation.

Dify Endpoint (/api/v1/dify/retrieval)#

dify_retrieval_api.py accepts Dify's schema (knowledge_id, retrieval_setting). When metadata_condition is present, operator names are normalized by convert_conditions() (e.g. "is" → "=", "not is" → "≠"), then meta_filter resolves a doc_ids whitelist. If no documents match, a sentinel value ("-999") is passed so retrieval returns zero results rather than bypassing the filter .

Agent Retrieval Tool#

agent/tools/retrieval.py is the Retrieval canvas component. Its _retrieve_kb() method applies: variable reference resolution via get_input_elements_from_text() → string_format() → "user:" prefix stripping → apply_meta_data_filter() for meta_data_filter conditions → cross-language expansion → Dealer.retrieval(). Dataset IDs can be literals or {{cpn_id@var}} references that resolve to KB names or IDs at runtime .

Agentic RAG (RAGTools)#

RAGTools in rag/advanced_rag/agentic_rag.py drives the agentic search graph. Its formalize() method uses an LLM call to rewrite the last user message into a standalone question and extract keywords — distinct from the simpler prefix stripping used in other paths. Retrieved results accumulate in a per-request search_cache to avoid duplicate backend calls within one turn .

Query Preprocessing Transformations#

Each entry point applies a subset of these transforms before calling Dealer.retrieval():

Variable substitution. Two patterns coexist. The agent path resolves {{cpn_id@var}} references via get_input_elements_from_text() and string_format(). The chat path strips ##<digits>$$ markers inline before passing the message to the retrieval call.

"user:" prefix stripping. The agent Retrieval tool runs re.sub(r"^user[::\s]*", "", query, flags=re.IGNORECASE) to remove prefixes that a previous LLM step may have prepended to the query.

Cross-language expansion. cross_languages() in rag/prompts/generator.py takes the query and a list of target language codes, calls the tenant's LLM with a translation prompt, and returns the original query concatenated with the translated variants — all fed together into a single retrieval call. Invoked in the chat path, the REST endpoint , and the agent Retrieval tool .

Metadata filtering. apply_meta_data_filter() accepts three modes:

  • auto — generates filter conditions from the query using an LLM via gen_meta_filter()
  • semi_auto — same but restricted to user-specified metadata keys
  • manual — uses explicit conditions with optional {{var}} value substitution

The filter produces a doc_ids whitelist passed to Dealer.retrieval(). When no documents match, the sentinel "-999" ensures zero results rather than unfiltered fallback . Operator normalization for the Dify path is handled by convert_conditions().

Keyword extraction. When keyword=true (REST endpoint) or the chat prompt config enables it, the tenant's chat LLM extracts keywords from the query and appends them to the query string before retrieval.

Reranker Score Normalization#

After Dealer.retrieval() fetches candidate chunks, it applies one of three reranking paths (see Hybrid Search and Retrieval for the full scoring formula). The key cross-cutting concern is that reranker providers emit scores on incompatible scales — Cohere/Jina/Voyage return calibrated [0, 1] relevance scores, while NVIDIA returns unbounded, often negative logits. Both Python and Go enforce the same normalization contract before blending reranker output with token similarity.

Python: rag/llm/rerank_model.py#

Base.similarity() is the single public entry point for every reranker provider. It calls the provider-specific _compute_rank(), then applies _normalize_rank():

  1. If all scores are already in [0, 1] → return unchanged (preserves calibrated providers' absolute magnitudes)
  2. If the score spread (max − min) is < 1e-3 → clamp per-element to [0, 1] (avoids collapsing a spreadless batch to zero)
  3. Otherwise → min-max rescale onto [0, 1]

rerank_by_model() in search.py relies on this guarantee when blending: tkweight * tksim + vtweight * vtsim, where vtsim is the normalized reranker output.

Go: internal/service/nlp/reranker.go#

NormalizeRerankScores() mirrors _normalize_rank exactly with the same three-case logic. It is called inside RerankByModel() after the model scores arrive, before the tkWeight * tsim + vtWeight * modelSim blend.

The Go package also provides:

  • RerankWithKNN() — two-pass ES approach (first pass retrieves, second KNN-only pass recovers cosine scores filtered to the candidate set)
  • RerankStandard() — ES path without an external reranker; calls HybridSimilarity() locally with stored chunk vectors
  • RerankInfinityFallback() — extracts the Infinity-provided fusion score (tries multiple field name variants: SCORE, score, _score, similarity(), etc.)

Token weighting is consistent across Python and Go: content_ltks + title_tks × 2 + important_kwd × 5 + question_tks × 6 .

Key Source Files#

FilePurpose
rag/nlp/search.pyDealer class — core retrieval + reranking engine
rag/llm/rerank_model.pyBase.similarity() / _normalize_rank() — Python score normalization
internal/service/nlp/reranker.goGo reranking: NormalizeRerankScores, RerankByModel, RerankWithKNN, RerankStandard, RerankInfinityFallback
agent/tools/retrieval.pyAgent Retrieval tool — variable resolution, prefix stripping, metadata filtering
agent/component/base.pyComponentBase — variable_ref_patt, get_input_elements_from_text(), string_format()
api/apps/restful_apis/chunk_api.py/api/v1/retrieval handler (retrieval_test())
api/apps/restful_apis/dify_retrieval_api.pyDify-compatible endpoint with operator normalization
common/metadata_utils.pyapply_meta_data_filter(), meta_filter(), convert_conditions()
rag/advanced_rag/agentic_rag.pyRAGTools — agentic search graph, formalize(), per-request cache
Documents
Agent Import and DSL Compatibility
Agent Retrieval
API Authorization
Ascend Inference Pipeline
Authentication
Canvas Architecture
Chat Assistant Configuration
Chat Completion API
Chunk Metadata Extraction
Chunker Pipeline
Compilation Template Management
Component Variable Propagation
Connection and Resource Management
Connector Architecture
Connector Document Sync
Conversation Session Management
What is the complete API flow for building a frontend UI with RAGFlow, covering dialogs, conversations, message history, streaming responses, and deletion?
Database Migrations
Dataflow Pipeline Execution
Dataset Access Control
Dataset Configuration UI
Dataset Parsing Mode
DeepDoc Module
Dify External Knowledge Integration
Docker Build Configuration
Document Parsing Pipeline
Elasticsearch Index Management
Encrypted Storage
GPU and Accelerator Support
Hybrid Search and Retrieval
Infinity Database Stability
Internal Compilation Artifact Indexing
Keyword Extraction
Knowledge Compilation Pipeline
Knowledge Graph
Knowledge Graph Retrieval
Knowledge Graph Visualization
Layout Element Overlap Detection
LLM Driver Integration
LLM Provider Integration
MCP Server Integration
Metadata Filtering
MinerU Configuration and Provider Resolution
Model Provider Architecture
Model Selection UI
Model Thinking and Reasoning
Multi-Backend Object Storage
OCR Backend and Model Loading
Parser Configuration
Parser Output Lifecycle
Parser-Chunk Contract
Picture Chunker Media Processing
Pipeline Canvas Architecture
Python Dependency Management
RAGFlow Python SDK
Redis Cache Architecture
Retrieval API
Retrieval Pipeline
SSRF Protection
Table Column Field Normalization
Table Structure Parsing
Task Cancellation
Tenant Model Resolution
Text2SQL
TSR Coordinate System Alignment