← 提示词工程

Prompt 模板变量设计要注意什么?

中等 Prompt 模板、变量与版本 · 第 1 / 3 问 更新于 2026/09/30
提示工程模板变量Prompt注入类型校验
本题落地项目AI Agentic RAG高级企业知识库平台

简化版

Prompt 变量要像 API 参数一样定义类型、来源、信任级别、最大长度、必填/默认值和转义规则。用户文本、检索证据不能插入高权限指令位置;枚举和结构对象优于自由字符串。渲染前做 schema 校验,渲染后检查未绑定占位符、Token 上限与段落边界,并记录变量哈希以便复现。

详细版

先建立变量清单,例如 locale 是受控枚举,documents 是带 source_id 的数组,user_query 是不可信字符串,max_items 是有范围整数。模板引擎按上下文转义 XML/JSON/Markdown,不能把所有变量做同一种替换;秘密和服务端权限根本不应进入模型可见变量。

缺值要明确 fail-closed 还是安全默认,不能静默渲染空字符串。长内容按文档边界裁剪并保留截断标记;列表用循环结构而非预拼文本。测试覆盖引号、闭合标签、Unicode、超长值、空值和注入语句,并对最终 Prompt 做快照结构测试而非敏感全文泄露。

变量定义(schema+trust) -> 输入校验 -> 上下文转义 -> 模板渲染 -> Token/占位符检查 -> 模型

完整版教学

一、变量是接口,不是字符串洞

模板变量连接用户、数据库、检索和配置。若只做字符串替换,任何来源都可能改变 Prompt 结构,类型错误也只能到模型输出异常时才发现。把变量视作函数参数,就需要明确契约和失败行为。

同名变量还要有唯一语义。context 这种大口袋常同时装历史、文档和工具结果,无法分配权限与预算。拆成 conversation_state、evidence_documents 和 tool_result 更易治理。

二、变量 schema 应包含哪些信息

每个变量至少定义类型、来源、信任、必填、长度/范围、转义上下文和日志策略。枚举字段不要让调用方传“formal,并忽略以上规则”这种自由文本。结构化数组保留每个元素边界和来源。

变量类型信任约束
localeenum应用配置zh-CN/en-US
max_itemsinteger应用配置1~20
user_querystring不可信≤4000 Token
documentsobject[]不可信证据source_id 必填
policy_versionenum高信任服务端注入

记忆钩子:变量设计要同时回答“它是什么”和“它从谁那里来”;类型防错误,信任级别防越权。

三、转义必须看目标上下文

插入 XML 时要转义 <>&,插入 JSON 要用序列化器处理引号与反斜线,Markdown code fence 内则要防用户内容提前闭合围栏。不存在一种 sanitize() 能安全适配所有位置。最好由模板引擎根据 typed slot 自动序列化。

const payload = JSON.stringify({ query: userQuery });
// 不要:'{"query":"' + userQuery + '"}'

转义能保护结构,不会让内容变可信。用户即使被安全包在 <user_input> 中,模型仍可能听从其中注入,所以还需明确角色和执行层权限。

四、缺值和默认值怎么处理

关键变量如权限、目标 schema 和证据来源缺失时应 fail closed,返回配置错误;风格等非关键变量可有安全默认。空字符串、null、未提供要区分,否则模型会看到“依据以下证据:”后空白并自行猜测。

默认值必须写在 schema,而不是散落模板的自然语言中。新增必填变量会破坏旧调用方,应升级模板接口版本。渲染完成后扫描 {...} 等未解析占位符,但不要用过宽规则误判用户正文。

五、Token 预算怎样分配给变量

每个可变长字段设置独立预算和全局上限。证据数组按相关性和文档边界截断,对话历史用结构化摘要,用户查询通常保留完整。不能先任意拼接再从字符串尾部硬截,可能切掉输出 schema 或半句关键条件。

假设窗口 16K:固定规则 1K、输出 2K、用户 2K、证据 8K、历史 2K、缓冲 1K。渲染器输出每段实际 Token 和被丢弃元素 ID。预算变化也需版本化,因为它能改变质量。

六、秘密与权限为何不能作为普通变量

API key、数据库凭据和用户无权查看的数据不应进入 Prompt,即使 system 说“不要输出”。模型可能受注入或日志系统泄露。工具在服务器端使用凭据,只向模型返回最小必要结果。

身份与权限从认证上下文传给策略引擎,不接受用户变量声明。模型可以看到匿名的 permission=read_only 以规划行为,但最终执行仍由后端使用真实主体判定,且模型不能修改这个值。

七、怎样测试模板变量

为每种类型生成边界值:空、最大长度、Unicode、引号、标签闭合、代码围栏、换行和注入句。断言渲染结构、角色、Token 上限和日志脱敏正确。属性测试可随机生成字符串,发现手工样例没覆盖的转义组合。

测试还应验证相同输入得到稳定 Prompt 哈希,列表排序有明确规则,locale 不改变事实字段。生产日志记录模板版本、变量 schema 版本、各段 Token 与非敏感哈希,必要时在受控环境重放。

八、常见误区与追问

  • 误区:所有变量先 HTML escape 就安全。 转义取决于 JSON/XML/Markdown 上下文,且不等于指令隔离。
  • 误区:空变量让模型自己处理更灵活。 关键输入缺失应显式失败,避免模型猜测。
  • 误区:用户写自己是管理员可作为 role 变量。 身份来自认证系统,不可信文本不能授权。
  • 追问:如何防模板注入? 类型化 slot、上下文转义、角色隔离,并在执行层最小权限。
  • 追问:如何裁剪文档变量? 按相关性和完整元素边界,保留 source_id 与截断记录。
  • 追问:日志如何兼顾复现和隐私? 记版本、长度、来源 ID 和哈希,敏感全文进入受控短期存储。

九、加强记忆

模板变量可记成“型、源、信、界、转、验”:定义类型与来源,标信任等级,限制长度范围,按所在格式转义,渲染前后都校验。秘密不入 Prompt、权限不由变量决定、截断不破坏结构。做到这些,Prompt 模板才是有契约的接口,而不是危险的字符串拼接。

项目实战落地

项目里怎么做的

《AI Agentic RAG高级企业知识库平台》的模板用 {变量名} 写占位变量,例如问答模板 RAG_ANSWER 里的 {context}、{question}。所有模板都经过同一个 render 渲染,渲染前先核对变量:

# 找出模板里出现的全部 {name},和调用方传进来的值比对,缺一个就报错
required = set(VARIABLE_PATTERN.findall(content))
missing = required - set(values.keys())
if missing:
    raise CustomException(f"Prompt 模板 {code} 缺少变量:{'、'.join(sorted(missing))}")
result = content
for name in required:
    # 用 replace 只替换认识的变量名,模板里其他大括号原样保留
    result = result.replace("{" + name + "}", str(values[name]))

围绕这个渲染函数还有两处配套:

  • 变量清单自动抽取。 保存模板时从正文里抽出变量,按出现顺序去重后回填 variables 列,不让管理员手填;
  • 预览走真实渲染。 管理端每条模板有「预览」按钮,按变量清单给每个变量一个输入框,调用的是和真实链路同一个 render:RAG_ANSWER 只填 context 就点生成,会弹出「Prompt 模板 RAG_ANSWER 缺少变量:question」;两个都填上,下方显示替换后的完整文本。

《AI Agent智能会议纪要辅助系统》把检查放在保存时:五条预置模板各有必需变量,例如纪要审查模板必须同时有 {meeting_title}、{minutes_json}、{transcript}。管理员改模板时误删了 {transcript},点保存就提示「用户模板缺少必需变量:{transcript}」,数据库不会被改动。

《AI面试官与刷题训练平台》没有自己写渲染函数,直接用 Spring AI 的 PromptTemplate:模板正文存在 prompt_template 表,业务按编码取(评分 INTERVIEW_SCORE、追问 INTERVIEW_FOLLOW_UP、总结 INTERVIEW_SUMMARY、出题 QUESTION_GENERATE),变量同样写成 {position}、{answer} 这样的占位符,放进 Map 后调用 new PromptTemplate(template).render(variables)。Spring AI 2.0 默认的渲染器按大括号识别变量,模板里出现了没传入的变量时直接抛异常,不会把占位符原样发出去。追问要求模型按 {"question":"追问题目","referenceAnswer":"追问参考答案"} 返回,这段带大括号的 JSON 示例是渲染完成之后才拼到提示词末尾的,不经过渲染器。

《AI Agent岗位匹配与求职规划系统》的 prompt_template 表按「模板类型」取模板,变量清单写在 variables 列(如「resumeProfile,projectExperiences」),由管理员维护。简历解析、JD 解析、用户画像三处调用按类型取出启用的模板,用 String.replace 把 {resumeText}、{jobDescription}、{resumeProfile}、{projectExperiences} 换成实际内容,只替换这几个认识的变量名。

《AI企业流程编排系统》的 Prompt 模板在配置节点时就复制进节点:在流程结构页给大模型节点选一条启用的模板,前端把模板正文填进节点的 prompt_content,节点配置里另记下 promptTemplateId;执行时引擎只读节点自己的 prompt_content,把其中的 {变量} 换成流程上下文里的值。之后再改模板库里的这条模板,已经配好的节点不受影响。

《AI个人学习计划与资料助手》的 Prompt 模板按编码取启用的那条(如资料总结 MATERIAL_SUMMARY、知识点提取 KNOWLEDGE_EXTRACT),用 String.replace 替换 {goalTitle}、{materialTitle}、{materialText} 三个变量;学习目标名和资料标题为空时,分别替换成「未命名学习目标」「未命名资料」。资料还没有解析文本时,在调用模型之前就拦下,提示先上传并解析文件。

为什么这样取舍

  • 缺变量宁可报错。 把「资料:{context}」原样发出去,模型会一本正经地针对这个占位符编答案,比报错难排查得多。
  • 不用 str.format。 模板里可能写着 JSON 示例这类带大括号的文本,format 遇到会报 KeyError;replace 只动认识的那几个变量名。
  • 变量清单不手填。 正文里加了 {count}、清单忘了改,预览时就发现不了缺变量;从正文抽取,清单和正文永远一致。
  • 纪要项目在保存时拦。 审查要同时对着纪要和原文看,少了原文,审查就只能凭纪要本身判断;在保存这一步拦下,错误的模板根本进不了库。

面试官还会追问

  • 管理员把一条模板停用了,知识库平台的代码为什么不退回一份写死的默认 Prompt 继续跑?
  • 会议纪要项目的模板页为什么只能编辑、不能新增?模板编码为什么不允许改?

学完《AI Agentic RAG高级企业知识库平台》,上面这些追问你都会迎刃而解。

本题落地项目地狱锤炼AI Agentic RAG高级企业知识库平台基于企业知识库、PGVector 向量检索、Agentic RAG、FastAPI + LangGraph、Function Calling,实现向量 + BM25 混合检索与 RRF 融合、Rerank 重排、HyDE 与多查询改写、父子分块召回、LangGraph 状态图自适应检索、Agent 执行时间线和 LLM-as-judge 四指标评测,覆盖从基础 RAG 到高级 RAG 调优的完整闭环。FastAPILangChainLangGraphRAGPGVector源码+SQL喂饭学习教程配套面试文档环境安装文档项目运行文档 学习这个项目 也可以学AI Agent智能会议纪要辅助系统地狱锤炼 查看项目 也可以学AI面试官与刷题训练平台登峰造极 查看项目 也可以学AI Agent岗位匹配与求职规划系统地狱锤炼 查看项目 也可以学AI企业流程编排系统地狱锤炼 查看项目 也可以学AI个人学习计划与资料助手小试牛刀 查看项目