Dosu LogoDosu Logo
Ask
Join our Discord
ragflowPublic
InfiniFlow
Documentsragflow
Multilingual Search Tokenization
Multilingual Search Tokenization
Type
Topic
Status
Published
Created
Jul 17, 2026
Updated
Jul 17, 2026
Created by
Dosu Bot
Updated by
Dosu Bot

Multilingual Search Tokenization#

RAGFlow's BM25 index uses language-aware tokenization to produce accurate stems and tokens for non-English knowledge bases. Without this, the default English Porter stemmer leaves non-English words un-stemmed or incorrectly reduced, degrading BM25 recall. The system threads a language parameter from the KB configuration through the entire chunking pipeline into the core tokenizer.


Architecture#

The tokenization stack has two layers:

  1. rag/nlp/rag_tokenizer.py — A thin Python wrapper around infinity.rag_tokenizer.RagTokenizer . When the Infinity document engine is active, tokenize() and fine_grained_tokenize() pass through to the Infinity SDK; otherwise they delegate to the parent class. The set_language() method — which selects the appropriate Snowball stemmer — is provided by the Infinity SDK parent class, not defined in this file .

  2. rag/nlp/__init__.py — Higher-level functions that call set_language() before tokenizing and propagate the language keyword argument throughout:

    • tokenize(d, txt, eng, language="English") — sets language on the tokenizer singleton, then populates content_ltks (coarse) and content_sm_ltks (fine-grained).
    • tokenize_chunks(..., language="English") — iterates chunks and delegates to tokenize().
    • tokenize_table(..., language="English") — also adjusts row delimiters: Chinese and Japanese use ";" instead of ";" .
    • tokenize_chunks_with_images() and doc_tokenize_chunks_with_images() mirror the same pattern.

All defaults are "English", preserving backward compatibility for existing KBs .


Language Parameter Threading#

rag/svr/task_executor.py is the entry point where the KB language field is picked up and propagated:

  • build_chunks() calls rag_tokenizer.tokenizer.set_language(task["language"]) at line 422 before tokenizing chunks, and also passes lang=task_language to the chunker .
  • run_dataflow() calls set_language(task.get("language", "English")) at line 771.
  • run_raptor_for_kb() calls set_language(row.get("language", "English")) at line 1042.
  • do_handle_task() calls set_language(task_language) at line 1406.

All 14 parser modules under rag/app/ (audio, book, email, laws, manual, naive, one, paper, picture, presentation, qa, resume, table, tag) were updated to pass language=lang into the tokenization calls as part of PR #14140 .


Supported Languages#

The KB language selector (LanguageList in web/src/constants/common.ts) exposes 16 languages:

Display NameNative Name
EnglishEnglish
Chinese简体中文
Traditional Chinese繁體中文
RussianРусский
IndonesianBahasa Indonesia
SpanishEspañol
VietnameseTiếng việt
Japanese日本語
Portuguese BRPortuguês BR
GermanDeutsch
FrenchFrançais
ItalianItaliano
BulgarianБългарски
Arabicالعربية
TurkishTürkçe
DutchNederlands

The NLTK Snowball stemmer (bundled with NLTK, no new dependency) is selected by set_language() for the 16 languages that have a Snowball mapping. Languages without a mapping (Chinese, Japanese, Korean, etc.) fall back to the Porter stemmer — this is acceptable because those languages use character-based tokenization anyway .

The cross-language search form (web/src/components/cross-language-form-field.tsx) exposes a curated subset of 11 languages: English, Chinese, Spanish, French, German, Japanese, Korean, Vietnamese, Arabic, Turkish, and Dutch.


RTL Text Support (Arabic, Hebrew, etc.)#

RTL language support has a nuanced history tracked in issue #4675. The core problem was in DeepDoc OCR: it did not correctly handle RTL text extraction from PDFs, causing Arabic/Hebrew chunks to appear in LTR order — breaking both chunk display and downstream BM25 retrieval .

  • Workaround (still valid for OCR-heavy PDFs): Convert the PDF to .docx first (e.g., via Microsoft Word), then upload the .docx. The DOCX parser preserves Arabic character order correctly .
  • Current status: Issue #4675 was closed as RTL support was added. If problems persist with the latest version, open a new issue with a sample file and logs.

Arabic is included in LanguageList and LanguageMap and the cross-language form field . The BM25 tokenizer path is configured for Arabic; the historical limitation was specific to OCR-based PDF extraction.


Key Source Files#

FilePurpose
rag/nlp/rag_tokenizer.pyTokenizer wrapper; delegates set_language() to Infinity SDK
rag/nlp/__init__.pytokenize(), tokenize_chunks(), tokenize_table() — language parameter entrypoints
rag/svr/task_executor.pyReads KB language, calls set_language(), drives chunking pipeline
web/src/constants/common.tsLanguageList / LanguageMap — 16 supported languages in UI
web/src/components/cross-language-form-field.tsxCross-language search language picker (11 languages)
PR #14140Introduced language-aware Snowball stemmer and Dutch support
Documents
Agent Import and DSL Compatibility
Agent Prompt Processing
Agent Retrieval
API Authorization
API Error Codes
Ascend Inference Pipeline
Authentication
Azure OpenAI Integration
Canvas Architecture
Chat Assistant Configuration
Chat Completion API
Chrome for Testing ARM64 Support
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 Model Distribution
DeepDoc Model Path Resolution
DeepDoc Module
Dify External Knowledge Integration
Docker Build Configuration
Document Parsing Pipeline
Elasticsearch Index Management
Embedding Pipeline
Embedding Vector Validation
Encrypted Storage
Figure Description Language Propagation
Frontend Build and Deployment
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 Configuration and Selection
LLM Driver Integration
LLM Provider Integration
MCP Server Integration
Media Context Configuration
Metadata Filtering
MinerU Configuration and Provider Resolution
MinerU PDF Parsing
Model Provider Architecture
Model Selection UI
Model Thinking and Reasoning
Multi-Architecture Docker Support
Multi-Backend Object Storage
Multi-Page Table and Element Handling
Multilingual Search Tokenization
Native Library Build and Linking
OCR Backend and Model Loading
Parser Configuration
Parser Output Lifecycle
Parser-Chunk Contract
PDF Chunk Position Rendering
Picture Chunker Media Processing
Pipeline Canvas Architecture
Provider Configuration Persistence
Provider Model Discovery
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