多语言 AI 应用——中英文混合场景的工程挑战
多语言 AI 应用——中英文混合场景的工程挑战
适读人群:做出海产品或双语AI应用的工程师 | 阅读时长:约13分钟 | 核心价值:掌握中英文混合场景的实际工程挑战和解决策略
去年我在一个面向全球用户的 SaaS 产品里做 AI 功能,这个产品国内有中文用户,海外主要是英文用户。
最开始我想得很简单:就是把 Prompt 翻译成英文再提供一个英文版本,知识库做两份,一份中文一份英文,根据用户语言选择对应的版本。
上线一个月之后,各种问题就来了。
有中文用户用英文提问的(他们可能更习惯用英文输入技术问题),有英文用户问的问题,答案只在中文文档里有。最夸张的一次,同一段内容,中文知识库和英文知识库里的版本对不上——产品经理更新了中文版但忘了同步英文版,AI 给两类用户的回答自相矛盾。
这才让我意识到多语言 AI 应用的工程挑战远比「做两套」复杂得多。
挑战一:Embedding 模型的跨语言能力差异
这是基础设施层面的问题,很多人没想清楚。
单语言 Embedding 模型的限制
如果你的 Embedding 模型是专为单一语言优化的(比如纯英文的 text-embedding-ada-002 早期版本,或者某些中文专用模型),那它生成的向量空间是语言隔离的。
什么意思?同一个概念「机器学习」和「machine learning」,在单语言 Embedding 模型里对应的向量会相距很远——它们在语义上是等价的,但在向量空间里是陌生人。
用户用中文问「机器学习怎么入门」,如果知识库里只有英文文档,即使内容完全对应,也召回不到。
现代多语言模型的现状
OpenAI 的 text-embedding-3-small 和 text-embedding-3-large 在多语言对齐上做得还不错——同一语义的中英文表达,在向量空间里距离较近。我自己测过,「机器学习」和「machine learning」的余弦相似度大约在 0.82-0.87 之间(具体数字跟文本上下文有关)。
但有一些场景下跨语言召回仍然不稳定:
- 专业术语翻译有多个版本(比如「Retrieval-Augmented Generation」在中文里有「检索增强生成」「RAG」「检索式增强」等多种叫法)
- 文化相关的概念(一个词在中英文里的内涵不同)
- 代码和技术文档(通常中英文混杂)
更可靠的方案:BGE M3 / multilingual-e5
如果你的场景跨语言召回非常关键,考虑专门为多语言设计的 Embedding 模型:
BAAI/bge-m3:对中英文对齐优化得很好,开源,支持本地部署intfloat/multilingual-e5-large:多语言,适合需要跨语言语义搜索的场景
我们在那个双语产品里最终换成了 BGE M3,跨语言召回率比 text-embedding-3-small 提升了大约 12%(基于我们自己构建的跨语言测试集)。
挑战二:Prompt 语言对效果的影响
这个问题我在实验之前以为不重要,测了之后有点惊讶。
结论先说:用模型擅长的语言写 Prompt,效果更好;用目标输出的语言写 Prompt,输出更稳定。
用英文 Prompt 还是中文 Prompt?
我们做过对比实验:同一个任务,分别用中文 Prompt 和英文 Prompt,测试在中文和英文两个场景下的效果。
测试任务:从中文产品文档中提取关键信息,要求以结构化 JSON 输出。
测试结果(50个样本):
中文文档+中文Prompt 中文文档+英文Prompt
JSON格式正确率 91.8% 88.2%
关键信息抽取准确率 89.4% 86.8%
平均延迟 1.8s 1.7s
英文文档+中文Prompt 英文文档+英文Prompt
JSON格式正确率 87.2% 93.4%
关键信息抽取准确率 83.6% 91.2%
平均延迟 1.9s 1.7s规律很清楚:Prompt 语言最好和文档内容语言一致。中文文档用中文 Prompt,英文文档用英文 Prompt。
但这带来了一个新问题:你需要维护两套 Prompt,而且要保持功能上的一致性。
我的实用解决方案
对于格式指令(输出 JSON、字段名等),统一用英文——因为 JSON 本身是英文格式,字段名、结构描述用英文更一致,不容易出现中英文混合的格式问题。
对于语义指令(解释任务要求、描述业务规则),跟随文档语言——中文文档用中文解释,英文文档用英文解释。
# 双语 Prompt 模板设计
def build_extraction_prompt(doc_language: str, document: str) -> str:
# 格式要求部分统一用英文(JSON 格式更稳定)
format_instruction = """
Output a JSON object with these fields:
- title: string
- summary: string (1-2 sentences)
- key_points: array of strings
- category: string (one of: technical, business, general)
Respond with valid JSON only, no markdown.
"""
# 任务描述跟随文档语言
if doc_language == "zh":
task_description = f"请从以下文档中提取关键信息:\n\n{document}"
else:
task_description = f"Extract key information from the following document:\n\n{document}"
return task_description + "\n\n" + format_instruction挑战三:多语言知识库的索引策略
这是我们踩坑最多的地方。说几个主要的方案和它们各自的问题。
方案A:完全分离的双语知识库
中文文档建一个索引,英文文档建另一个索引。用户用中文提问就查中文索引,用英文提问就查英文索引。
问题:
- 语言识别错误会导致查错库(特别是中英混合的提问)
- 信息孤岛:答案在另一个语言库里查不到
- 内容同步是噩梦:两个库要分别维护,容易不一致
方案B:统一向量空间(单索引)
所有文档(不管中英文)放进同一个索引,用支持跨语言的 Embedding 模型。
问题:
- 如果 Embedding 模型的跨语言对齐不好,中英文语义相似的内容可能距离很远
- 单一 Embedding 模型对某种语言的表现可能不如专用模型
这是我们现在用的方案,搭配 BGE M3,整体表现可以接受。
方案C:双语翻译 + 统一索引
每篇文档都翻译成另一种语言,然后原文和译文都存进同一个索引。这样无论用哪种语言提问,都能找到对应的内容。
问题:
- 存储翻译版本需要额外费用(翻译 API + 存储)
- 知识库大小翻倍
- 原文更新时译文可能来不及同步
方案D:查询翻译
在检索时,把用户的 Query 翻译成另一种语言,同时查两种语言,融合结果再排序。
def multilingual_search(query: str, vectorstore, top_k: int = 5) -> list:
"""
跨语言检索:同时用原始 Query 和翻译后的 Query 检索,融合结果
"""
# 检测查询语言
detected_lang = detect_language(query)
# 翻译成另一种语言
if detected_lang == "zh":
translated_query = translate_zh_to_en(query)
else:
translated_query = translate_en_to_zh(query)
# 双查询检索
results_original = vectorstore.similarity_search_with_score(query, k=top_k * 2)
results_translated = vectorstore.similarity_search_with_score(translated_query, k=top_k * 2)
# 融合去重(基于文档ID)
seen_ids = set()
merged_results = []
# 原始查询结果权重更高
for doc, score in results_original:
doc_id = doc.metadata["doc_id"]
if doc_id not in seen_ids:
merged_results.append((doc, score * 1.1)) # 原始语言轻微加权
seen_ids.add(doc_id)
for doc, score in results_translated:
doc_id = doc.metadata["doc_id"]
if doc_id not in seen_ids:
merged_results.append((doc, score))
seen_ids.add(doc_id)
# 按分数排序,取 top_k
merged_results.sort(key=lambda x: x[1], reverse=True)
return [doc for doc, score in merged_results[:top_k]]查询翻译的好处是知识库不需要存两份,但每次检索有额外的翻译 API 调用成本。
挑战四:输出语言控制
AI 输出的语言有时候会「飘」——上下文里有中文,输出却变成英文了,或者反过来。
这在中英混合的技术文档场景里特别常见,因为技术内容本身就是中英混排的。
我们加了一个明确的语言控制指令:
def build_qa_prompt(user_query: str, context: str, output_language: str) -> str:
language_instruction = {
"zh": "请用中文回答。即使参考文档是英文,也必须用中文输出答案。",
"en": "Answer in English only. Even if the reference documents are in Chinese, respond in English.",
"auto": "请用和用户提问相同的语言回答。"
}.get(output_language, "请用和用户提问相同的语言回答。")
return f"""你是一个智能问答助手。请基于以下参考文档回答用户的问题。
{language_instruction}
参考文档:
{context}
用户问题:{user_query}
回答:"""对于 auto 模式(跟随用户提问语言),有时候语言识别不准,特别是短句和专业术语混合的情况。我们最终给用户加了一个语言偏好设置,让用户明确指定,减少了这类问题。
我们最终的双语架构
经过几个月的演进,我们的最终方案是:
Embedding 层:BGE M3,统一向量空间,支持中英文跨语言语义对齐。
知识库:单一索引,每个文档存储语言标签(lang: "zh" | "en" | "mixed")。
检索层:语言感知检索——主要召回和用户 Query 语言匹配的文档,但如果相关分数足够高(> 0.85),跨语言文档也会被召回。
Prompt 层:双语 Prompt 模板,格式指令统一用英文,语义指令跟随查询语言。
输出层:明确指定输出语言(基于用户偏好设置,不靠自动判断)。
这个方案上线后,跨语言查询的满意度提升了明显,「找不到相关信息」的投诉也降了很多。
多语言 AI 应用确实比单语言复杂,但核心工程挑战是可以拆解的:Embedding 的跨语言对齐、Prompt 语言策略、知识库的统一 vs 分离、输出语言控制。把这几个问题一个一个想清楚,可以少踩很多坑。
