多语言 RAG 检索生产实战:语言路由、术语保护、跨语言召回与评测
从中英混排、脚本识别、专有名词和精确锚点保护,到多语言 Embedding、BM25、翻译通道、RRF、Rerank、原文引用与分 Cohort 评测,搭建一套可解释、可回放、可治理的生产级多语言 RAG。
多语言 RAG 最常见的错误设计,是把它理解成:
用户用中文提问
→ 翻译成英文
→ 搜索英文文档
→ 再翻译成中文回答这条链路在演示环境里很容易成立,但进入生产后会迅速暴露问题:
- Query 同时包含中文、英文、产品名、错误码、代码和版本号;
- 翻译模型把业务术语改成了“更自然”但错误的表达;
- 中文问题需要同时搜索中文制度、英文 API 文档和数据库字段;
- 同一个缩写在不同部门、产品和地区含义不同;
- 原始问题中的否定、时间、数字和比较关系在改写中丢失;
- 多个语言通道使用了不同的 ACL 或时间过滤;
- 答案是中文,但真正支持它的证据是英文原文;
- 自动生成的中文“引用片段”与英文原文并不完全一致;
- 总体 Recall 看起来不错,却掩盖了中文问英文、音译实体和中英混排等 Cohort 的严重退化。
生产级多语言 RAG 不是一个翻译层,而是一套查询理解、检索路由、索引建模、证据治理和评测系统。
资料快照:本文核查截至 2026-08-06。实现依据优先参考 Elasticsearch 的语言分析器与 ICU Analysis Plugin、Sentence Transformers 多语言训练文档、BGE-M3、MIRACL、mMARCO 与 MTEB 等官方资料或原始论文。不同模型、Tokenizer、语言分析器和托管服务持续更新;生产系统应冻结
language_policy_version、glossary_version、Embedding Model Key、Reranker、索引代际和评测集版本,而不是笼统记录“支持多语言”。
图 1:多语言检索的核心不是把一句话翻译成另一种语言,而是让原始表达、精确锚点、跨语言语义、权限范围和原文证据在整条链路中保持一致。
一句话结论
推荐的生产链路是:
Original Query
→ Language / Script / Query Type Detection
→ Exact Anchor Extraction
→ Versioned Glossary
→ Structured Query Plan
→ Original Lexical + Exact + Translated Lexical + Multilingual Dense
→ Shared ACL / Tenant / Time Filters
→ RRF / Rerank / Dedup
→ Original-language Evidence
→ Answer in User Locale
→ Claim–Evidence Validation
→ Cohort Evaluation and Drift Monitoring其中最重要的原则有五条:
- 翻译只能增加召回通道,不能替换原始 Query。
- 产品名、错误码、版本号、数字、时间、否定和权限范围必须先被保护。
- 所有语言通道必须使用完全相同的 Tenant、ACL、状态和时间过滤。
- Citation 必须回到原始证据;翻译片段只能作为辅助预览。
- 质量必须按语言对、Query 类型、领域和脚本 Cohort 分开评测。
1. 先区分五种“语言”
多语言系统只保存一个 language=zh 字段通常不够。一次请求至少涉及五个不同概念。
| 字段 | 含义 | 示例 |
|---|---|---|
query_language | 用户问题主要使用的语言 | zh-CN |
query_scripts | Query 中实际出现的文字系统 | Han、Latin、Digit |
evidence_language | 证据原文语言 | en-US |
answer_language | 系统应该输出的语言 | zh-CN |
interface_locale | 日期、数字、货币和 UI 展示习惯 | zh-CN |
这五者可以完全不同:
界面:中文
用户问题:中英混排
证据:英文和日文
答案:中文
数字与日期:按中国大陆格式展示此外,还需要单独保存:
source_language
translation_language
translation_provider
translation_version
transliteration_used
glossary_version否则出现坏例时,只能看到“Query 被改写过”,却不知道具体是哪一版词典、翻译模型和语言策略改变了结果。
1.1 BCP 47 语言标签与脚本
语言标签最好使用稳定、可解释的格式,例如:
zh-CN
zh-Hant-TW
en-US
pt-BR
sr-Latn
sr-Cyrl但语言标签不能替代脚本识别。下面这条 Query 的主要语言可能是中文,检索上却同时依赖 Han、Latin、Digit 和符号:
Cursor Auto 模式为什么把 ERR_1205 重试了 3 次?如果系统把整个 Query 归一化成纯中文语义,Cursor、Auto、ERR_1205 和数字 3 都可能被弱化。
2. 多语言 Query 的真实类型
生产 Query 可以按检索行为而不是单一语言分类。
| Query 类型 | 示例 | 主要策略 |
|---|---|---|
| 同语言自然问题 | “RRF 为什么比直接加分稳定?” | 同语言 BM25 + Dense |
| 跨语言问题 | 中文问英文 API 文档 | Original + Translation + Multilingual Dense |
| Code-switch | “PTO 怎么算?” | 术语表 + Exact + 双语言召回 |
| 精确标识符 | ERR_1205、v2.1.0 | Exact / Phrase 优先 |
| 音译或别名 | “库伯内特斯” / Kubernetes | Alias / Transliteration 通道 |
| 多语言比较 | 中文比较两份英文政策 | Multi-query + Evidence Group |
| 时间敏感 | “2026 年新版本有什么变化?” | 时间锚点 + Freshness Filter |
| 多跳问题 | 中文问题跨英文和中文来源 | 分步检索 + Stable ID |
| 无答案 | Query 语言与知识库都没有证据 | 正确拒答或追问 |
| 权限敏感 | 翻译后命中其他租户内容 | 所有通道统一 ACL Hard Gate |
“Query 是中文”并不能决定检索策略。更重要的是:
是否包含 Exact Anchor?
是否需要跨语言?
是否依赖业务术语?
是否需要时间或数值约束?
是否需要多跳?
是否存在权限边界?3. 先保护锚点,再做翻译和改写
下面这些内容不应交给自由生成的 Query Rewrite 随意改写:
- 产品名、组织名、角色名和业务对象 ID;
- API、类名、函数名、字段名和配置键;
- 错误码、工单号、版本号和 Commit SHA;
- URL、域名、文件路径和命令;
- 日期、金额、百分比、比较符和范围;
- 否定词、必须/可选、之前/之后等逻辑约束;
- Tenant、Knowledge Base、ACL 和数据源范围。
例如:
原始 Query:
ERR_1205 在 TDW partition delete 时为什么失败?
危险改写:
为什么数据库删除分区失败?危险改写看起来更自然,但丢失了三个强信号:
ERR_1205
TDW
partition delete正确流程应该是:
原始 Query
→ 提取并冻结 Exact Anchors
→ 识别语言与领域
→ 在不修改 Anchors 的前提下生成检索表达
→ 验证所有强约束仍然存在3.1 Anchor 数据结构
{
"anchors": [
{
"type": "error_code",
"value": "ERR_1205",
"normalized": "ERR_1205",
"must_preserve": true
},
{
"type": "system_name",
"value": "TDW",
"normalized": "TDW",
"must_preserve": true
},
{
"type": "operation",
"value": "partition delete",
"normalized": "partition delete",
"must_preserve": true
}
],
"constraints": {
"negated": false,
"time_range": null,
"numeric_ranges": []
}
}3.2 Anchor Preservation Rate
多语言评测中应单独计算:
Anchor Preservation Rate
=
改写后仍被正确保留的必需 Anchor 数
÷
原始 Query 的必需 Anchor 数对于错误码、版本号、权限范围和高严重度实体,可以设置:
Anchor Preservation Rate = 100%作为 Hard Gate。
4. 术语表不是静态翻译词典
企业知识系统中的术语通常具有领域和时间边界。
PTO
→ HR 场景:paid time off
→ 工程场景:可能完全不是这个含义
回响
→ 通用词:echo
→ 特定作品:固定世界观概念
Auto
→ 普通形容词
→ Cursor 的特定产品模式因此 Glossary Entry 至少需要:
{
"term_id": "term_000184",
"surface_forms": ["PTO", "paid time off", "带薪休假"],
"canonical_term": "paid time off",
"language": "en",
"domain": "hr-policy",
"tenant_id": "tenant_001",
"aliases": ["telecommute leave policy"],
"forbidden_translations": ["production time objective"],
"valid_from": "2026-01-01T00:00:00Z",
"valid_to": null,
"version": 17
}4.1 Glossary 的职责
术语表可以用于:
- Query Rewrite;
- Translation Constraint;
- Exact / Alias Retrieval;
- 实体识别;
- Reranker 输入增强;
- Answer Terminology Consistency;
- Citation Preview 翻译;
- 线上 Drift 诊断。
4.2 不要无限扩展同义词
同义词扩展越多,不代表 Recall 一定越好。它也可能:
- 引入其他领域的同名概念;
- 让 BM25 Query 变得过宽;
- 放大高频但错误的候选;
- 增加 RRF Candidate Inflation;
- 让 Reranker 在大量近义噪声中消耗窗口。
每个扩展词最好带 Purpose:
{
"text": "telecommute paid time off policy",
"purpose": "domain_synonym",
"source": "glossary:v17"
}而不是生成五句看起来差不多的自然语言改写。
5. Structured Query Plan
图 2:翻译或 Semantic Rewrite 之前,先冻结错误码、版本、实体、数字、时间、否定和权限范围;随后生成 Purpose 明确的检索通道。
推荐 Query Planner 输出结构化 JSON,而不是直接输出 Elasticsearch DSL:
{
"query_plan_version": "multilingual-query-plan-v5",
"original_query": "ERR_1205 在 TDW partition delete 时为什么失败?",
"query_language": "zh-CN",
"scripts": ["Han", "Latin", "Digit"],
"answer_language": "zh-CN",
"domain": "data-platform",
"anchors": ["ERR_1205", "TDW", "partition delete"],
"glossary_version": "data-platform@17",
"scope": {
"tenant_id": "tenant_001",
"knowledge_base_ids": ["kb_data_platform"],
"acl_groups": ["employee", "data-team"]
},
"queries": [
{
"id": "q_original",
"text": "ERR_1205 在 TDW partition delete 时为什么失败?",
"language": "zh-CN",
"purpose": "original_lexical"
},
{
"id": "q_exact",
"text": "ERR_1205 TDW partition delete",
"language": "und",
"purpose": "exact_anchor"
},
{
"id": "q_en",
"text": "Why does TDW partition deletion fail with ERR_1205?",
"language": "en",
"purpose": "cross_language_lexical"
},
{
"id": "q_dense",
"text": "TDW 分区删除时出现 ERR_1205 的原因与处理方式",
"language": "zh-CN",
"purpose": "multilingual_dense"
}
],
"validation": {
"anchors_preserved": true,
"scope_unchanged": true,
"translation_drift": "none"
}
}5.1 Planner 不得生成什么
LLM Planner 不得自行生成或放宽:
tenant_id
acl_groups
physical_index
allowed_data_sources
maximum_time_range
sensitive_document_scope这些字段必须由可信的系统组件根据登录态和业务规则编译。
5.2 Fail Closed
出现以下情况时,不应继续执行改写后的 Query:
必需 Anchor 丢失
否定语义改变
时间范围扩大
数值比较符改变
Tenant / ACL 发生变化
翻译结果为空或语言异常
Glossary 冲突未解决合理降级是:
仅使用 Original + Exact Channel而不是让一个疑似漂移的翻译 Query 继续扩大搜索范围。
6. 翻译是召回通道,不是 Query 替代
建议同时保留:
Original Query
Original Lexical Query
Exact Anchor Query
Translated Lexical Query
Multilingual Dense Query原因如下。
6.1 原始 Query 保留精确信号
原始 Query 最容易保留:
- 用户实际措辞;
- 内部黑话;
- 专有名词;
- 拼写错误;
- 原始否定与语气;
- 代码和字段名。
6.2 翻译 Query 扩展目标语言词汇
翻译通道适合发现:
- 英文文档中的标准术语;
- 与中文口语不同的官方产品表达;
- 目标语言的词形变化;
- 没有出现在多语言 Embedding 训练分布中的长尾词。
6.3 Dense Query 提供跨语言语义桥梁
多语言 Embedding 可以把不同语言的相近语义映射到同一个向量空间,但它不等于:
- 所有语言效果一致;
- 所有领域术语都已对齐;
- 数字、代码和错误码都能可靠保留;
- 长文档、多跳和时间约束不需要 Lexical Channel。
因此生产基线通常是:
Exact + Original BM25 + Translated BM25 + Multilingual Dense
→ RRF
→ Multilingual Rerank而不是只选择其中一种。
7. 语言识别不应成为单点故障
短 Query 的语言识别非常不稳定:
PTO?
Auto 为什么慢?
retry policy
回响
v3.2 error建议返回分布和脚本,而不是只返回一个绝对标签:
{
"primary_language": "zh-CN",
"language_candidates": [
{"language": "zh-CN", "probability": 0.72},
{"language": "en", "probability": 0.28}
],
"scripts": {
"Han": 0.42,
"Latin": 0.48,
"Digit": 0.10
},
"code_switching": true,
"low_confidence": false
}7.1 低置信度时怎么做
不要因为语言检测不确定就拒绝检索。可以:
- 保留 Original Query;
- 同时走 Exact 与 ICU / 通用 Analyzer;
- 使用 Multilingual Embedding;
- 减少激进翻译扩展;
- 在 Trace 中标记
language_detection_low_confidence。
7.2 文档语言识别
文档语言最好按 Block 或 Chunk 识别,而不是整篇文档只标一种语言。技术文档常出现:
中文说明
英文标题
代码块
JSON / SQL
英文错误日志
表格字段可以保存:
document_language
block_language
chunk_languages
script_distribution8. Elasticsearch Mapping:原文、语言字段与 Exact 字段并存
一个实用的 Chunk 投影示例:
PUT kb_chunks_v4
{
"mappings": {
"dynamic": "strict",
"properties": {
"tenant_id": {"type": "keyword"},
"knowledge_base_id": {"type": "keyword"},
"knowledge_id": {"type": "keyword"},
"chunk_id": {"type": "keyword"},
"source_revision": {"type": "long"},
"doc_status": {"type": "keyword"},
"acl_groups": {"type": "keyword"},
"source_language": {"type": "keyword"},
"scripts": {"type": "keyword"},
"title": {
"type": "text",
"fields": {
"keyword": {"type": "keyword", "ignore_above": 512}
}
},
"content_original": {
"type": "text",
"fields": {
"zh": {"type": "text", "analyzer": "smartcn"},
"en": {"type": "text", "analyzer": "english"},
"icu": {"type": "text", "analyzer": "icu_analyzer"}
}
},
"exact_tokens": {"type": "keyword"},
"entities": {"type": "keyword"},
"aliases": {"type": "keyword"},
"glossary_terms": {"type": "keyword"},
"embedding_model_key": {"type": "keyword"},
"embedding": {
"type": "dense_vector",
"dims": 1024,
"index": true,
"similarity": "cosine"
}
}
}
}
smartcn、ICU 或其他 Analyzer 是否可用,取决于集群插件和版本。生产 Mapping 必须按真实环境验证;不要把示例 Analyzer 名称直接复制到未安装对应插件的集群。
8.1 为什么保留 content_original
原文是:
- Citation 的事实来源;
- 重新生成不同语言索引投影的输入;
- 翻译错误复盘的基准;
- 重新构建 Embedding 的依据;
- 多语言显示和高亮的来源。
翻译文本和归一化文本都应该是可重建投影,而不是覆盖原文。
8.2 Exact Token 如何产生
可以从内容中提取:
ERR_1205
bge-reranker-v2-m3
index.mapping.total_fields.limit
/api/v1/retrieve
sha256:...
v2.1.0
PTO并写入 exact_tokens。Query 中检测到类似 Anchor 时,额外走 term 或 terms 查询。
8.3 多语言字段不是越多越好
为每种语言复制所有内容会增加:
- 索引大小;
- Mapping 复杂度;
- 写入成本;
- 查询组合;
- 高亮和 Explain 难度。
更合理的策略是:
高流量核心语言
→ 专用 Analyzer Field
长尾语言
→ ICU / 通用字段 + Multilingual Dense
精确标识符
→ Keyword / Exact Field9. 多语言索引与检索架构
图 3:原文、语言专用 Analyzer、Exact Token 与多语言向量承担不同责任;所有检索通道必须共享同一组权限、状态和时间过滤。
10. Language-specific Analyzer 与 ICU
语言 Analyzer 通常包含:
- 语言相关 Tokenization;
- Stopword;
- Stemming / Lemmatization;
- 大小写和字符归一化。
它们适合标准自然语言,但技术知识库还有额外要求:
错误码不能被切坏
版本号不能被去掉
字段名不能被 Stem
URL 和 Path 需要保留
中文与英文相邻时要合理分词10.1 Multi-field
同一份原文可以投影为多个检索视角:
content_original
content_original.zh
content_original.en
content_original.icu
exact_tokensQuery Planner 根据语言和脚本选择字段,而不是对所有字段无差别执行 multi_match。
10.2 何时使用 ICU
ICU Analysis Plugin 可以提供 Unicode 归一化、分词、折叠和转写相关能力,适合处理更广泛的脚本和字符变体。但它不是业务术语表,也不能自动解决:
- 内部缩写;
- 产品别名;
- 同名实体;
- 翻译漂移;
- 权限范围;
- 特定领域的 Token 保护。
ICU 是字符和文本分析基础设施,不是完整多语言检索策略。
11. Multilingual Embedding 的选择
选择多语言 Embedding 时不要只看“支持 100 种语言”。至少评估:
| 维度 | 问题 |
|---|---|
| Language Coverage | 目标语言是否真正有训练和评测覆盖? |
| Cross-lingual Alignment | 中文 Query 与英文 Passage 是否靠近? |
| Monolingual Quality | 同语言检索是否因跨语言对齐而下降? |
| Domain Terms | 内部术语、代码、缩写效果如何? |
| Long Context | 最大长度和截断策略是什么? |
| Similarity | 是否需要 Query / Passage 前缀? |
| Dimension | 存储、内存和 ANN 成本是否可接受? |
| License / Hosting | 是否允许商业和私有部署? |
| Reranker Pair | 是否有匹配的多语言 Reranker? |
11.1 Model Key
建议用完整 Model Key:
provider
+ model_name
+ model_revision
+ endpoint
+ dimension
+ normalization
+ query_template_version
+ passage_template_version例如:
bge-m3|rev-x|endpoint-a|1024|l2|q-v3|p-v2不同 Model Key 的向量不能悄悄混在同一个空间中比较。
11.2 Query 与 Passage 模板
有些模型要求不同前缀:
query: ...
passage: ...模板必须进入:
- Index Manifest;
- Embedding Cache Key;
- Trace;
- Evaluation Run;
- Reindex Plan。
否则模型名称相同,实际向量语义也可能不同。
11.3 多语言 Benchmarks 只是起点
MIRACL、mMARCO 和 MTEB 等基准可以帮助筛选模型,但不能替代自己的数据集。企业内真实问题往往包含:
- 内部产品名;
- 混合语言;
- 错误码和字段名;
- 权限条件;
- 新旧版本;
- 语料中没有答案的问题。
这些分布与公开 Benchmark 相差很大。
12. Exact、BM25 与 Dense 如何融合
多语言系统尤其不适合只用 Dense Retrieval。
12.1 Exact Channel
适合:
ERR_1205
RFC 9111
v2.1.0
GET /v1/users
index.mapping.total_fields.limit示例:
{
"query": {
"bool": {
"filter": [
{"term": {"tenant_id": "tenant_001"}},
{"terms": {"acl_groups": ["employee", "data-team"]}},
{"term": {"doc_status": "active"}}
],
"must": [
{"terms": {"exact_tokens": ["ERR_1205", "TDW"]}}
]
}
}
}12.2 Original-language BM25
保留用户原始词项和本语言表达,尤其适合:
- 直接术语;
- 内部黑话;
- 标题和字段;
- 原文短语;
- 拼写变体。
12.3 Translated-language BM25
发现目标语言中的标准术语和词形,但必须保留:
translation_id
translation_model
translation_version
glossary_version
anchors_preserved12.4 Multilingual Dense
补充语义改写、跨语言和同义表达召回。
12.5 RRF
不同通道分数没有稳定公共尺度,RRF 是可靠基线:
RRF(d) = Σ weight_i / (k + rank_i(d))初期建议先使用等权或非常克制的权重,再按 Language Pair Cohort 调优。
{
"fusion": {
"type": "rrf",
"rank_constant": 60,
"rank_window_size": 100,
"channels": [
"exact",
"original_bm25",
"translated_bm25",
"multilingual_dense"
]
}
}12.6 Candidate Inflation
Multi-query 会迅速放大候选数:
4 个 Query
× 4 条通道
× 每路 Top 100
= 最多 1600 个原始候选需要全局预算:
per_query_limit
per_channel_limit
global_unique_candidate_limit
per_document_limit
rerank_window否则质量提升可能被延迟和成本吞噬。
13. 所有语言通道必须共享 Hard Filter
错误做法:
中文 BM25
→ 带 Tenant / ACL
英文翻译 Query
→ 只按文本搜索
Dense kNN
→ 搜索后再 Post-filter这样会产生跨语言越权通道。
正确做法:
System Scope
AND
User Filters
AND
Doc Status
AND
Temporal Constraints编译成所有召回器共用的 Filter。
{
"hard_filter": {
"tenant_id": "tenant_001",
"acl_groups": ["employee", "data-team"],
"knowledge_base_ids": ["kb_001", "kb_002"],
"doc_status": "active",
"business_as_of": "2026-08-06T00:00:00Z"
}
}翻译模型和 Query Planner 都无权扩大这些范围。
13.1 权限指标
分别监控:
Unauthorized Retrieval Rate
Unauthorized Context Rate
Unauthorized Citation Rate三者都应该是:
max = 014. Multilingual Reranker
第一阶段跨语言召回成功后,Reranker 仍可能失败:
- 训练语言覆盖不足;
- Query 与 Passage 语言组合较少见;
- 业务术语被 Tokenizer 拆坏;
- 长文本截断掉关键句;
- 翻译 Query 与原始 Query 意图略有不同;
- Reranker 更偏好同语言候选。
14.1 Rerank 输入
建议保留:
original_query
selected_query_variant
query_language
passage_language
anchors
passage_original
optional translated preview不要只把翻译后的 Query 和翻译后的 Passage 送入模型,否则无法知道最终排序是否仍然忠于原始问题。
14.2 两种 Pair 策略
策略 A:Original Query × Original Passage
→ 最少人工变换,依赖模型跨语言能力
策略 B:Translated Query × Original Passage
→ 目标语言词项更匹配,但可能继承翻译漂移可以在评测集中按 Language Pair 比较,而不是凭经验选择。
14.3 Reranker 降级
Reranker 超时
→ 回退 RRF
目标语言不支持
→ 使用支持的 Pair 或跳过
输入截断严重
→ 使用 Child Span / Summary + Original Anchor
模型异常
→ 标记 degraded,不返回空结果15. Transliteration、别名与实体
跨语言检索不只有翻译,还包括转写和别名:
Kubernetes
库伯内特斯
k8s
PostgreSQL
Postgres
PG
Elasticsearch
ES建议实体记录:
{
"entity_id": "product:kubernetes",
"canonical_name": "Kubernetes",
"aliases": ["k8s", "库伯内特斯"],
"languages": ["en", "zh-CN"],
"domain": "cloud-native",
"ambiguous": false,
"version": 8
}15.1 自动转写的边界
自动 Transliteration 适合生成召回候选,但不能自动认定两个实体相同。出现歧义时,应:
- 使用领域和上下文消歧;
- 保留多个候选实体;
- 必要时向用户追问;
- 在 Trace 中记录实体链接置信度。
16. 中文检索的特殊问题
中文没有天然空格边界,技术文本又大量混入英文和符号。
需要特别评测:
产品名与中文相邻
中英文之间没有空格
错误码与标点相邻
版本号与汉字相邻
路径、域名和代码块
简体 / 繁体变体示例:
为什么Elasticsearch的index.mapping.total_fields.limit会超?应同时保留:
Elasticsearch
index.mapping.total_fields.limit
字段数限制
mapping explosion16.1 简繁体
简繁转换可以作为辅助归一化,但原文仍需保留。某些专有名词、地区用法和法律文本不能假设自动转换完全等价。
16.2 拼音
拼音通道只适合特定产品体验,例如用户经常用拼音输入中文实体。它可能带来大量同音噪声,不应默认对所有 Query 启用。
17. 代码、API 与配置字段
代码类内容通常“语言无关”,但周围解释是有语言的。
retry_policy
max_retries
HTTP 429
kubectl rollout undo
SELECT ... FOR UPDATE SKIP LOCKED推荐:
- 代码块单独解析;
- 标识符写入 Exact Field;
- 保留大小写敏感原文;
- 自然语言说明进入语言 Analyzer;
- Query 中出现代码时提高 Exact Channel 权重;
- 不让翻译模型翻译函数名和参数名。
17.1 Protected Span
翻译前可以使用占位符:
为什么 <CODE_1> 在返回 <CODE_2> 后没有重试?翻译完成后再恢复:
<CODE_1> = retry_policy
<CODE_2> = HTTP 429并验证占位符数量和顺序没有变化。
18. Answer Language 与 Evidence Language 分离
用户可以用中文阅读英文证据的答案:
Answer Language = zh-CN
Evidence Language = en-US但 Citation 必须指向英文原文,而不是让生成模型伪造一段“像引用”的中文翻译。
18.1 推荐响应结构
{
"answer_language": "zh-CN",
"answer": "删除后的版本信息只会保留有限时间,因此仍需要 Tombstone。",
"claims": [
{
"claim_id": "c1",
"text": "删除后的版本信息只会保留有限时间",
"citation_ids": ["cite_1"]
}
],
"citations": [
{
"citation_id": "cite_1",
"source_language": "en-US",
"original_quote": "Delete operations retain version information for a limited time...",
"translated_preview": "删除操作只在有限时间内保留版本信息……",
"translation_generated": true,
"translation_version": "preview-translate-v4",
"source_revision": 42
}
]
}18.2 翻译预览不是证据本体
UI 可以展示翻译预览,但必须明确:
原文
机器翻译预览
来源标题
更新时间
语言Claim–Evidence Validation 应基于:
- 原始 Evidence;或
- 明确可审计的对齐结果。
不能只验证生成出来的翻译预览与答案是否相似。
18.3 用户可读 Citation
建议允许用户:
- 默认看翻译预览;
- 展开查看原文;
- 跳转到原始段落;
- 查看文档语言和更新时间;
- 看到机器翻译标识;
- 报告翻译或引用错误。
19. Translation Drift 如何检测
翻译漂移可以分为:
| 类型 | 示例 |
|---|---|
| Anchor Loss | ERR_1205 消失 |
| Negation Flip | “不支持”变成“支持” |
| Numeric Drift | 30 天 变成 3 天 |
| Temporal Drift | “之前”变成“之后” |
| Entity Drift | 产品 A 变成通用概念 |
| Scope Drift | 部门范围或数据源范围扩大 |
| Modality Drift | “必须”变成“建议” |
19.1 确定性检查优先
以下检查不需要 LLM Judge:
Exact Anchor 是否出现
数字是否相同
日期是否相同
比较符是否相同
占位符是否完整
Tenant / ACL 是否相同
语言标签是否合法19.2 Semantic Drift Judge
对难以确定性判断的语义,可以使用结构化 Judge:
{
"equivalent_intent": true,
"negation_preserved": true,
"temporal_constraints_preserved": true,
"numeric_constraints_preserved": true,
"entity_constraints_preserved": true,
"missing_constraints": [],
"added_constraints": []
}Judge 必须在人工标注的 Translation Calibration Set 上校准。
20. 缓存键必须包含语言策略版本
多语言链路常见缓存:
Language Detection Cache
Translation Cache
Query Plan Cache
Embedding Cache
Retrieval Cache
Rerank Cache
Answer Cache
Citation Preview Translation CacheKey 至少包含:
original_query_hash
query_language
answer_language
domain
glossary_version
translation_model_key
translation_prompt_version
embedding_model_key
query_plan_version
corpus_revision
permission_scope_hash
business_as_of错误示例:
translate:{query_hash}它忽略了领域、目标语言、词典和模型版本。
20.1 权限不能只存在于 Value
Retrieval、Context 和 Answer Cache 的 Key 必须包含 Effective Permission Scope。即使 Cache Value 中保存 ACL,先命中后再检查也可能造成:
- Timing Side Channel;
- 日志泄露;
- 错误预览;
- 跨租户污染。
21. 多语言 Trace 应该记录什么
{
"request_id": "req_multi_001",
"original_query": "PTO 怎么算?",
"language_detection": {
"primary": "zh-CN",
"scripts": ["Latin", "Han"],
"code_switching": true,
"model_version": "lang-detect-v4"
},
"anchors": ["PTO"],
"glossary": {
"domain": "hr-policy",
"version": 17,
"matched_terms": ["PTO"]
},
"translations": [
{
"id": "tr_1",
"target_language": "en",
"text": "How is paid time off calculated?",
"anchors_preserved": true,
"drift_status": "pass"
}
],
"retrieval": {
"exact": {"count": 12, "latency_ms": 8},
"original_bm25": {"count": 50, "latency_ms": 19},
"translated_bm25": {"count": 50, "latency_ms": 21},
"multilingual_dense": {"count": 80, "latency_ms": 35},
"union_unique_count": 126
},
"fusion": {
"type": "rrf",
"rank_window_size": 100
},
"rerank": {
"model_key": "multilingual-reranker-x",
"input_count": 50,
"output_count": 8
},
"answer_language": "zh-CN",
"citation_languages": ["en-US"],
"degraded": false
}21.1 Candidate 级 Trace
每个候选还应记录:
retrieval_channel
query_variant_id
query_language
passage_language
raw_rank
fused_rank
rerank_rank
anchor_matches
translation_used
selected_for_context
removed_reason否则无法判断跨语言证据在哪一层丢失。
22. 失败与降级矩阵
| 故障 | 推荐降级 | 必须记录 |
|---|---|---|
| Language Detection 低置信度 | Original + Exact + Dense | lang_low_confidence |
| Translation 超时 | 跳过翻译通道 | translated_channel_skipped |
| Anchor 丢失 | 拒绝使用该改写 | anchor_validation_failed |
| Glossary 冲突 | 使用原始 Query 或追问 | glossary_ambiguous |
| Multilingual Embedding 失败 | Original / Translated BM25 | dense_unavailable |
| Reranker 不支持语言对 | 回退 RRF | rerank_language_unsupported |
| Citation Preview 翻译失败 | 展示原文 | preview_translation_failed |
| 权限编译失败 | Fail Closed | scope_resolution_failed |
降级后仍要保证:
Tenant / ACL 不变
原始 Query 可追溯
Citation 指向原文
响应标记 partial / degraded23. 多语言安全边界
23.1 Prompt Injection 跨语言
攻击内容可能使用:
- 低资源语言;
- 混合脚本;
- 同形异义字符;
- Unicode 混淆;
- 机器翻译绕过;
- 代码块或 Base64。
安全策略不能只检测英文关键词。
23.2 Unicode Normalization
归一化有助于检测混淆字符,但不能覆盖所有情况。应同时保存原始文本与归一化文本,并在高风险 Anchor 上记录差异。
23.3 翻译服务的数据边界
把私有 Query 或 Context 发送给外部翻译服务前,需要明确:
- 数据驻留;
- 保留策略;
- 日志策略;
- 租户隔离;
- PII 脱敏;
- 合同和合规边界。
高敏感数据可以采用自托管翻译、只翻译 Query、或完全依赖本地多语言模型。
24. 多语言评测矩阵
图 4:总体平均值会掩盖长尾语言和跨语言失败;门禁应按 Language Pair、Query Type、Domain、Glossary、Model 与 Pipeline Version 分组。
24.1 最小 Cohort
至少覆盖:
zh → zh
en → en
zh → en
en → zh
zh + en code-switch
transliteration / alias
exact ID / error code / version
numeric / temporal constraints
multi-hop across languages
no-answer
permission-sensitive24.2 Eval Case
{
"case_id": "multi_eval_0042",
"question": "远程员工 PTO 怎么算?",
"query_language": "zh-CN",
"scripts": ["Han", "Latin"],
"evidence_languages": ["en-US"],
"answer_language": "zh-CN",
"query_type": "code_switch_cross_language",
"required_anchors": ["PTO"],
"scope": {
"tenant_id": "tenant_001",
"knowledge_base_ids": ["kb_hr"],
"acl_groups": ["employee"]
},
"expected_evidence": [
{
"knowledge_id": "remote_work_policy_2026",
"source_revision": 12,
"language": "en-US"
}
],
"required_claims": [
"说明适用的员工类型",
"说明 PTO 计算口径",
"说明生效日期"
],
"expected_behavior": "answer_with_original_citation",
"severity": "high"
}25. 检索指标
25.1 单路与并集 Recall
Original BM25 Recall@K
Translated BM25 Recall@K
Multilingual Dense Recall@K
Exact Recall@K
Union Recall@K25.2 Unique Relevant Gain
Translated Channel Unique Gain
→ 只有翻译通道找到的正确证据
Dense Unique Gain
→ 只有多语言向量找到的正确证据如果一个通道只增加重复候选,没有独有正确证据,应重新评估其成本。
25.3 Ranking
MRR
NDCG@K
MAP
Rerank Gain25.4 多语言专项指标
Anchor Preservation Rate
Translation Drift Rate
Entity Linking Accuracy
Constraint Preservation Rate
Cross-language Evidence Recall
Original Citation Resolution Rate
Translated Preview Error Rate26. 答案与引用指标
答案质量需要分开评估:
| 指标 | 含义 |
|---|---|
| Answer Correctness | 结论是否正确 |
| Completeness | 必需 Claim 是否覆盖 |
| Faithfulness | Claim 是否由给定 Context 支持 |
| Citation Precision | 引用是否真正支持对应 Claim |
| Citation Recall | 必需 Claim 是否都有有效引用 |
| Terminology Consistency | 是否使用约定业务术语 |
| Original Quote Accuracy | 原文片段是否准确 |
| Translation Preview Quality | 辅助翻译是否忠于原文 |
| Refusal Accuracy | 无证据或无权限时是否正确拒答 |
机器翻译预览质量不能代替 Citation Precision。Citation Precision 的事实对象仍是原始证据。
27. Case-level Diff 与发布门禁
Baseline 与 Candidate 必须在相同 Case 上成对执行:
{
"case_id": "multi_eval_0042",
"baseline": {
"union_recall_at_20": 0.5,
"anchor_preservation": 1.0,
"citation_support": 1.0,
"latency_ms": 420
},
"candidate": {
"union_recall_at_20": 1.0,
"anchor_preservation": 1.0,
"citation_support": 1.0,
"latency_ms": 505
},
"classification": "improved",
"reason": "translated BM25 找回英文政策中的必需证据"
}27.1 Hard Gate
hard_gates:
unauthorized_retrieval_rate:
max: 0
unauthorized_context_rate:
max: 0
unauthorized_citation_rate:
max: 0
required_anchor_preservation_rate:
min: 1.0
invalid_original_citation_rate:
max: 0
critical_cross_language_cases:
pass_rate_min: 1.027.2 Soft Gate
soft_gates:
cross_language_union_recall_at_20:
max_drop: 0.005
multilingual_ndcg_at_10:
max_drop: 0.01
translation_drift_rate:
max: 0.01
p95_latency_ms:
max_increase_ratio: 0.15
cost_per_request:
max_increase_ratio: 0.12平均分上升不能抵消某个高严重度语言对的严重回归。
28. MySQL 数据模型
28.1 Glossary
CREATE TABLE multilingual_glossary_term (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
tenant_id VARCHAR(64) NOT NULL,
domain_key VARCHAR(128) NOT NULL,
term_id VARCHAR(128) NOT NULL,
canonical_term VARCHAR(512) NOT NULL,
language_tag VARCHAR(32) NOT NULL,
surface_forms JSON NOT NULL,
aliases JSON NOT NULL,
forbidden_translations JSON NOT NULL,
version BIGINT NOT NULL,
valid_from DATETIME(6) NOT NULL,
valid_to DATETIME(6) NULL,
updated_at DATETIME(6) NOT NULL,
UNIQUE KEY uk_term_version (tenant_id, domain_key, term_id, version)
);28.2 Query Plan 与 Translation
CREATE TABLE multilingual_query_plan (
request_id VARCHAR(64) PRIMARY KEY,
tenant_id VARCHAR(64) NOT NULL,
original_query TEXT NOT NULL,
query_language VARCHAR(32) NOT NULL,
answer_language VARCHAR(32) NOT NULL,
scripts JSON NOT NULL,
anchors JSON NOT NULL,
glossary_version VARCHAR(128) NOT NULL,
query_plan_version VARCHAR(128) NOT NULL,
scope_hash CHAR(64) NOT NULL,
translations JSON NOT NULL,
validation_result JSON NOT NULL,
created_at DATETIME(6) NOT NULL
);28.3 Citation Preview Translation
CREATE TABLE citation_translation_preview (
citation_id VARCHAR(128) NOT NULL,
source_revision BIGINT NOT NULL,
target_language VARCHAR(32) NOT NULL,
translation_model_key VARCHAR(255) NOT NULL,
glossary_version VARCHAR(128) NOT NULL,
original_text_hash CHAR(64) NOT NULL,
translated_text MEDIUMTEXT NOT NULL,
translated_text_hash CHAR(64) NOT NULL,
created_at DATETIME(6) NOT NULL,
PRIMARY KEY (
citation_id,
source_revision,
target_language,
translation_model_key,
glossary_version
)
);29. Go Query Plan Validator
package multilingual
import (
"errors"
"fmt"
"strings"
)
type Anchor struct {
Type string `json:"type"`
Value string `json:"value"`
MustPreserve bool `json:"must_preserve"`
}
type Scope struct {
TenantID string `json:"tenant_id"`
KnowledgeBaseIDs []string `json:"knowledge_base_ids"`
ACLGroups []string `json:"acl_groups"`
}
type QueryVariant struct {
ID string `json:"id"`
Text string `json:"text"`
Language string `json:"language"`
Purpose string `json:"purpose"`
}
type QueryPlan struct {
OriginalQuery string `json:"original_query"`
Anchors []Anchor `json:"anchors"`
Scope Scope `json:"scope"`
Queries []QueryVariant `json:"queries"`
}
func ValidatePlan(plan QueryPlan, trustedScope Scope) error {
if plan.OriginalQuery == "" {
return errors.New("original query is required")
}
if plan.Scope.TenantID != trustedScope.TenantID {
return errors.New("tenant scope changed")
}
for _, anchor := range plan.Anchors {
if !anchor.MustPreserve {
continue
}
preserved := false
for _, query := range plan.Queries {
if strings.Contains(strings.ToLower(query.Text), strings.ToLower(anchor.Value)) {
preserved = true
break
}
}
if !preserved {
return fmt.Errorf("required anchor %q was lost", anchor.Value)
}
}
return nil
}实际实现还应校验:
- ACL 集合完全一致;
- Knowledge Base 只能收窄不能扩大;
- 时间范围没有扩大;
- Numeric Constraint 没有改变;
- Query 数量和候选预算没有超限;
- Purpose 在白名单内。
30. 延迟与成本预算
多语言检索会增加:
语言识别
术语匹配
翻译
更多检索通道
更大的候选并集
多语言 Rerank
Citation Preview 翻译示例预算:
| 阶段 | P95 示例 |
|---|---|
| Language / Script Detection | 8 ms |
| Anchor + Glossary | 12 ms |
| Translation | 80 ms |
| Query Embedding | 35 ms |
| Parallel Retrieval | 100 ms |
| RRF / Dedup | 8 ms |
| Rerank | 120 ms |
| Context / Citation | 25 ms |
| 总检索链路 | 300–450 ms |
这只是示例。真正预算要根据:
- 翻译服务地域;
- Embedding 部署;
- Query 数量;
- 候选窗口;
- 语言对;
- 并发和缓存;
- Voice / Agent 的端到端 Deadline。
30.1 优化优先级
- Original、Exact、Translation、Dense 并行;
- Language Detection 和 Glossary 本地化;
- 翻译与 Embedding 使用版本化缓存;
- 只对高价值 Query 启用多 Query;
- 限制全局候选和 Rerank Window;
- Citation Preview 延迟生成或按需生成。
31. 常见反模式
反模式一:翻译后完全替换原始 Query
专有名词、错误码和原始限定容易丢失。
反模式二:只有多语言向量检索
代码、版本、数字和精确术语持续产生坏例。
反模式三:所有语言通道使用不同 Filter
这是直接的越权风险。
反模式四:把全文翻译后覆盖原文索引
Citation、修复和重建失去可靠来源。
反模式五:Glossary 没有 Tenant、Domain 和 Version
同名术语会在不同业务中互相污染。
反模式六:Language Detection 输出一个绝对标签
短 Query 和 Code-switching 会被错误路由。
反模式七:只看整体 Recall
长尾语言和跨语言 Cohort 的严重退化被平均值隐藏。
反模式八:Citation 只展示机器翻译
用户无法验证原文,模型也可能引用了翻译错误。
反模式九:Reranker 不按 Language Pair 评测
同语言表现好,不代表跨语言 Pair 表现好。
反模式十:Semantic Cache 忽略语言和术语版本
相似 Query 可能在不同语言、领域和时间下语义不同。
反模式十一:Query Planner 可以生成 ACL
模型不应决定用户能访问哪些内容。
反模式十二:自动翻译所有 Context
成本高、延迟大,并可能增加事实漂移;优先保持原文证据。
32. 分阶段落地路线
P0:可靠基线
- 保存 Original Query;
- 语言与脚本识别;
- Exact Anchor 提取;
- Versioned Glossary;
- Original BM25 + Multilingual Dense;
- 所有通道共享 Hard Filter;
- 原文 Citation;
- zh→zh、zh→en、Code-switch Golden Set;
- Anchor Preservation 与 Unauthorized Hard Gate;
- Trace 记录 Query Variant 和候选来源。
验收标准:
任何跨语言坏例都能判断:
是 Anchor、Translation、BM25、Dense、Fusion、Rerank、Context 还是 Citation 出错。P1:质量与体验
- Translated BM25;
- Domain Glossary Workflow;
- Multilingual Reranker;
- Transliteration / Alias;
- Translation Drift Judge;
- 原文 + 翻译预览 Citation UI;
- 分 Language Pair Dashboard;
- Case-level Paired Diff;
- Query / Translation / Preview Cache。
P2:高级能力
- 多语言 Sparse Retrieval;
- 多跳跨语言 Planning;
- 领域微调 Embedding / Reranker;
- Active Learning;
- Glossary 自动候选与人工审核;
- Translation Quality Estimation;
- 多模态和语音跨语言证据;
- 在线 Shadow / Canary;
- 自动根因分类与 Release Gate 联动。
33. 上线检查清单
- 是否区分 Query、Evidence、Answer 和 Interface Language?
- 是否记录 Script Distribution 和 Code-switching?
- 是否保留 Original Query?
- 产品名、错误码、版本、数字、日期和否定是否被保护?
- Anchor Preservation 是否有 Hard Gate?
- Glossary 是否按 Tenant、Domain 和 Version 管理?
- 翻译 Query 是否只是新增通道,而不是替换原 Query?
- Query Plan 是否结构化并有 Query 数量预算?
- Planner 是否无权改变 Tenant、ACL 和数据源?
- 是否保存原文、语言投影与 Exact Field?
- 核心语言是否有专用 Analyzer?
- 长尾语言是否有 ICU / 通用字段和 Dense 兜底?
- Query / Passage Embedding Template 是否版本化?
- 多 KB 是否验证同一 Embedding 空间?
- Exact、Original BM25、Translated BM25 和 Dense 是否分别可观测?
- 是否计算 Union Recall 与 Unique Relevant Gain?
- 所有召回通道是否使用同一 Hard Filter?
- Multilingual Reranker 是否按 Language Pair 评测?
- Reranker 失败是否回退 RRF?
- Transliteration 和 Alias 是否有实体消歧?
- 代码、API 和配置字段是否禁止翻译?
- Citation 是否回到原始 Evidence?
- 翻译预览是否明确标记为机器生成?
- Claim–Evidence Validation 是否基于原文?
- Translation Drift 是否包含否定、时间、数字和实体?
- Cache Key 是否包含语言、词典、模型和 Scope Version?
- Trace 是否保存 Translation、Query Variant 与 Candidate Channel?
- 是否有 Translation / Embedding / Rerank 降级策略?
- 安全检测是否覆盖混合脚本和多语言 Injection?
- 评测是否覆盖同语言、跨语言、混排、音译、无答案和权限?
- 指标是否按 Language Pair、Domain、Model 和 Pipeline 分组?
- High / Critical Cohort 是否允许被平均分抵消?
- P95、Cost 和 Candidate Inflation 是否在预算内?
- 所有版本是否进入 Release Manifest?
总结
多语言 RAG 的真正挑战不是“模型能不能理解中文和英文”,而是让多个语言和检索通道保持同一个问题、同一个权限范围和同一条证据链:
Original Query
→ 保存用户真实意图
Anchor Protection
→ 保存不可丢失的实体、代码、数字与逻辑约束
Versioned Glossary
→ 让业务术语在正确领域和时间内对齐
Parallel Retrieval
→ Exact、Original Lexical、Translated Lexical 和 Dense 互补
Shared Hard Filter
→ 所有通道使用相同 Tenant、ACL、状态与时间边界
Fusion / Rerank
→ 在候选预算内选择真正可回答的证据
Original Citation
→ 回到用户有权访问的原始来源
Cohort Evaluation
→ 发现平均分掩盖的语言对和长尾失败最重要的工程判断是:
翻译可以帮助系统找到证据,但不能替代用户原始问题;答案可以使用用户熟悉的语言,但引用必须回到原始、版本固定且权限正确的证据。
官方资料与原始论文
- Elasticsearch:Language analyzers
- Elasticsearch:ICU analysis plugin
- Sentence Transformers:Multilingual Models
- BGE M3-Embedding: Multi-Lingual, Multi-Functionality, Multi-Granularity
- MIRACL: A Multilingual Retrieval Dataset Covering 18 Diverse Languages
- mMARCO: A Multilingual Version of the MS MARCO Passage Ranking Dataset
- MTEB: Massive Text Embedding Benchmark
- BCP 47 / RFC 5646: Tags for Identifying Languages
- Query Rewriting 生产实战
- Elasticsearch Hybrid Search 生产实战
- Reranker 生产实战
- Citation Engineering 生产实战
- RAG 评测生产实战
- RAG 可观测性生产实战
讨论
继续讨论这篇笔记
有问题、补充案例或不同观点,可以通过 GitHub Discussions 继续交流。