做 AI 应用开发,你是不是经常写出这样的代码:
# 这是一个悲伤的故事
response = client.chat.completions.create(
messages=[
{"role": "user", "content": f"请把这段话翻译成{target_lang},风格要{style}一些:{user_input}"}
]
)
这就是所谓的“硬编码(Hard-coding)”。
在 Demo 阶段,这没问题。
但当你的项目膨胀到几千行代码,拥有 50 个不同的功能点时,这种散落在各个 .py 文件角落里的 f-string,就是一场维护灾难。
业务说:“所有的翻译都要加一句‘保持原意’。” —— 你得去代码里搜一遍,改 10 个地方。你想做 A/B 测试,对比两个 Prompt 的效果,发现要改动核心逻辑代码。Prompt 不是字符串,Prompt 是代码逻辑的一部分。
我们需要用软件工程的思维来治理它。
今天,我们来聊聊如何从零构建一个 Python f-string 风格的动态模板库,让你的 Prompt 管理井井有条。
01 为什么要“模板化”?
模板化(Templating)的核心价值在于“解耦(Decoupling)”。
我们要把 Prompt 的内容(What) 和 代码的逻辑(How) 彻底分开。
一个优秀的 Prompt 库应该具备三个特征:
集中管理: 所有的 Prompt 都在一个文件夹或文件里,像 API 接口文档一样清晰。参数校验: 缺参数?多参数?在调用 LLM 扣费之前,程序就该报错。动态复用: 同样一段“安全过滤规则”,应该能被 10 个不同的 Agent 复用,而不是复制粘贴 10 次。02 基础版:封装 PromptTemplate 类
虽然 LangChain 提供了现成的 PromptTemplate,但它太重了。其实我们自己写一个轻量级的类,只需要 10 行代码。
我们利用 Python 强大的 string.Formatter 或简单的 f-string 逻辑。
实战代码:
# prompt_lib.py
class PromptTemplate:
def __init__(self, template_str: str, input_variables: list):
self.template_str = template_str
self.input_variables = input_variables
def format(self, **kwargs):
# 1. 校验参数:确保所有需要的变量都传进来了
missing_vars = [var for var in self.input_variables if var not in kwargs]
if missing_vars:
raise ValueError(f"缺少必要参数: {missing_vars}")
# 2. 生成最终 Prompt
return self.template_str.format(**kwargs)
# = 定义你的模板 =
TRANSLATE_PROMPT = PromptTemplate(
template_str="你是一个精通{source_lang}和{target_lang}的翻译官。请翻译:{text}",
input_variables=["source_lang", "target_lang", "text"]
)
在业务代码中调用:
# main.py
from prompt_lib import TRANSLATE_PROMPT
# 调用起来非常清晰,且自带参数检查
final_prompt = TRANSLATE_PROMPT.format(
source_lang="中文",
target_lang="英文",
text="你好,世界"
)
print(final_prompt)
这看起来简单,但它带来了一个巨大的好处:你的 IDE 甚至可以利用 Type Hinting 提示你需要传什么参数。
03 进阶版:组件化(Partials)与复用
Prompt 开发中最痛的点是“重复”。
比如,你所有的 Agent 都需要遵守一套“企业安全红线”。你不想在每个 Prompt 里都写这 500 字。
这时候,我们需要引入“组件化”思维(在 LangChain 中叫 PartialPrompt)。
我们可以把 Prompt 拆分为 Base Template(基座) 和 Variable Template(变量)。
实战逻辑:
# 1. 定义公共组件
SAFETY_INSTRUCTION = """
【安全规范】
1. 严禁讨论政治敏感话题。
2. 严禁输出个人隐私数据。
"""
# 2. 定义业务 Prompt
CODE_GENERATION_STR = """
{safety_rules}
你是一个 Python 专家。请帮我写一个函数:{user_req}
"""
# 3. 预填(柯里化)
# 我们在应用初始化时,就先把安全规范填进去
safe_code_prompt = PromptTemplate(
template_str=CODE_GENERATION_STR,
input_variables=["safety_rules", "user_req"]
)
# 业务代码调用时,只需要传 user_req,不需要关心 safety_rules
final_prompt = safe_code_prompt.format(
safety_rules=SAFETY_INSTRUCTION, # 这里可以自动注入
user_req="写个爬虫"
)
通过这种方式,一旦老板说要修改“安全规范”,你只需要改 SAFETY_INSTRUCTION 这一个变量,全公司所有的 Agent 都会自动生效。
04 终极版:使用 YAML/JSON 做配置化管理
当 Prompt 变得非常长(几千字)时,放在 Python 代码里会显得很乱。
最佳实践是将 Prompt 抽离为独立的 YAML 或 JSON 文件。
目录结构建议:
/project_root
/prompts
/chat
customer_service.yaml
tech_support.yaml
/agent
data_analyst.yaml
common.yaml (公共组件)
customer_service.yaml 内容:
_type: prompt
input_variables: ["user_name", "query"]
template: |
你是一个客服。
当前用户:{user_name}
请回答:{query}
在代码中,写一个加载器(Loader)去读取这些文件。这样做的好处是:Prompt 的修改不需要重新部署代码(甚至可以在后台配置中心热更新)。
05 产品视角的思考:Prompt 也是资产
对于技术团队来说,建立 Prompt Template 库不仅仅是为了代码整洁,更是为了资产沉淀。
版本控制(Versioning): 你可以有 v1_sales_prompt 和 v2_sales_prompt,通过 A/B 测试看哪个转化率高。团队协作: 资深的 Prompt 工程师负责维护 YAML 文件,初级后端工程师只负责写 Python 代码调用 format(),互不干扰。写在最后
不要让你的 Prompt 成为“魔法字符串(Magic Strings)”。
它们是这个 AI 时代最重要的源代码。
给它们穿上 Class 的外衣,加上 Type 的约束,放进 YAML 的保险箱。
当你把 Prompt 当作代码来管理,而不是当作文本来处理时,你的 AI 应用才算真正具备了“企业级”的健壮性。