ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

多语言 Prompt 模板系统:mini-rag 用 TemplateParser 实现中英文无缝切换

多语言 Prompt 模板系统:mini-rag 用 TemplateParser 实现中英文无缝切换

【免费下载链接】mini-rag

An Educational Project (step by step) to teach how to build a production-ready app for RAG application.

项目地址:https://gitcode.com/gh_mirrors/mi/mini-rag
点击查看免费下载

mini-rag 是一个手把手教你构建生产级 RAG 应用的教育项目,它内置的多语言 Prompt 模板系统值得一提:仅靠一个类 TemplateParser,就把 RAG 用到的全部 Prompt 拆分为按语言组织的模板文件,同一套问答流程只需修改一行配置,就能在英文、中文等语言之间无缝切换。本文带你拆解这套设计,并演示如何三步扩展一种新语言。

mini-rag 是什么:RAG 应用的完整教学项目

一句话定位:mini-rag 是一个最小化的 RAG(检索增强生成)问答系统实现,配合一套分步视频教程讲解整个代码库。项目结构非常清晰:

  • 🚀 FastAPI 提供 REST 接口(main.py)
  • 📦 Celery + RabbitMQ 处理文件解析、向量索引等异步任务(celery_app.py)
  • 🔌 LLM 与 VectorDB 均采用工厂模式,Provider 可自由替换
  • 🗂️ Prompt 统一收口在 templates/ 目录,按语言隔离

读完这个项目,你拿到的不只是一个能跑的 RAG Demo,而是一套生产级应用的完整设计思路。

为什么 RAG 应用需要多语言 Prompt 模板

RAG 问答分三步:检索相关文档 → 组装完整 Prompt → 调用 LLM 生成答案。mini-rag 把这套流程放在 NLPController.py 的answer_rag_question中:

  1. 调用search_vector_db_collection从向量库检索 Top-N 相关文本块
  2. 用三类模板拼装完整 Prompt:system_prompt(角色设定)、document_prompt(逐篇文档)、footer_prompt(提问与作答格式)
  3. 交给 LLM 生成最终答案

如果 Prompt 被写死成英文,当阿拉伯语用户提问时,模型就难以用用户的语言作答。所以 mini-rag 把所有 Prompt 文本放进"按语言分目录的模板文件",只留$doc_num、$chunk_text、$query等占位符,运行时再填充真实内容。

模板文件长什么样:按语言目录组织

所有 Prompt 模板位于src/stores/llm/templates/locales/下,目前项目内置英文和阿拉伯语两种:

templates/ └── locales/ ├── en/rag.py # 英文模板 └── ar/rag.py # 阿拉伯文模板

以英文版 en/rag.py 为例,每个文件就是几个string.Template对象:

system_prompt = Template("You are an assistant to generate a response for the user. ...") document_prompt = Template("## Document No: $doc_num\n### Content: $chunk_text") footer_prompt = Template("## Question:\n$query\n## Answer:")

阿拉伯文版 ar/rag.py 中是完全同构的三个变量,只是文案换成了阿拉伯语。这正是无缝切换的关键:业务代码依赖的是"变量名",而不是"哪种语言的文案"。

TemplateParser 核心机制解析

全部魔法都藏在 template_parser.py 这一个文件里,核心有三点。

1)语言校验与自动回退

构造时接收language(当前语言)与default_language(回退语言,默认en)两个参数。set_language方法(#L13-L21)会先做目录存在性检查:

  • 传了language但locales/{language}目录不存在 → 静默回退到默认语言
  • 语言为None→ 直接使用默认语言

这意味着无论配置文件里怎么填,系统都不会崩溃,只会优雅降级。

2)动态按需加载模块

get(group, key, vars)被调用时,通过__import__动态导入对应模块(#L23-L43):

module = __import__(f"stores.llm.templates.locales.{language}.{group}", fromlist=[group]) return getattr(module, key).substitute(vars)

两个细节值得品味:

  • 按需加载:用到哪组模板才加载哪组,不会一次性载入所有语言包
  • substitute替换:这是string.Template的原生能力,$doc_num等占位符在运行时被替换为真实值

3)分组级回退:第二重保险

若当前语言下缺少某个分组文件(比如某语言只翻译了部分模块),get会自动回退到默认语言的同名文件(#L29-L31)。"语言级回退 + 分组级回退"双重保险,保证即使翻译不完整,系统也依然完整可用。

配置如何驱动语言无缝切换

语言参数来自配置文件 config.py:

PRIMARY_LANG: str = "en" # 业务使用的当前语言 DEFAULT_LANG: str = "en" # 回退使用的默认语言

项目里有两处入口初始化 TemplateParser,保证前后端行为一致:

  • API 端:FastAPI 启动时创建(main.py#L46-L49)
  • 异步任务端:Celery 的get_setup_utils中创建(celery_app.py#L40-L43)

实例被注入NLPController后,answer_rag_question组装 Prompt 只需三行:

system_prompt = self.template_parser.get("rag", "system_prompt") document_prompt = self.template_parser.get("rag", "document_prompt", {"doc_num": i, "chunk_text": ...}) footer_prompt = self.template_parser.get("rag", "footer_prompt", {"query": query})

想把整个系统切换到阿拉伯语,只需把环境配置里的PRIMARY_LANG改掉,一行 Python 代码都不用动。

三步给系统添加中文支持

这套设计最迷人的地方在于:新增一种语言完全不用改代码。

  1. 新建目录src/stores/llm/templates/locales/zh/
  2. 复制 en/rag.py,将三个模板翻译成中文,保持变量名(system_prompt、document_prompt、footer_prompt)和占位符($doc_num、$chunk_text、$query)不变
  3. 配置PRIMARY_LANG=zh

服务重启后,整个问答流程即输出中文。若某组模板尚未翻译,TemplateParser 会自动回退到默认语言,服务不会中断。

总结:小模块背后的设计智慧

📌 TemplateParser 只有四十多行代码,却体现了生产级应用的几个通用最佳实践:

  • 配置优于代码:语言切换只是一个配置项的事
  • 优雅降级:双层回退保证缺翻译时系统"降级"而不是"崩溃"
  • 按需加载:__import__动态导入,避免加载无用模板
  • 结构同构:所有语言使用同一套变量名与占位符,业务代码对语言完全无感知

如果你想系统学习如何构建 RAG 应用,建议完整阅读 项目 README,这套多语言 Prompt 模板模块就是"把简单的事做好"的绝佳范例。

【免费下载链接】mini-rag

An Educational Project (step by step) to teach how to build a production-ready app for RAG application.

项目地址:https://gitcode.com/gh_mirrors/mi/mini-rag
点击查看免费下载

相关推荐

上一篇:用架构决策记录(ADR)落地 AWS 云基础设施选型:从决策到治理的完整实战指南
下一篇:Psalm TypeDoesNotContainNull 错误解析:在静态分析中识别不可能成立的 null 判断

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进