做 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
classPromptTemplate:
def__init__(self,template_str:str,input_variables:list):
self.template_str=template_str
self.input_variables=input_variables
defformat(self,**kwargs):
# 1. 校验参数:确保所有需要的变量都传进来了
missing_vars=[varforvarinself.input_variablesifvarnotinkwargs]
ifmissing_vars:
raiseValueError(f"缺少必要参数:{missing_vars}")
# 2. 生成最终 Prompt
returnself.template_str.format(**kwargs)
# = 定义你的模板 =
TRANSLATE_PROMPT=PromptTemplate(
template_str="你是一个精通{source_lang}和{target_lang}的翻译官。请翻译:{text}",
input_variables=["source_lang","target_lang","text"]
)
在业务代码中调用:
# main.py
fromprompt_libimportTRANSLATE_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 应用才算真正具备了“企业级”的健壮性。