PromptTemplate 示例 JSON 被当成缺失变量
PromptTemplate 把 JSON 花括号当成占位符时,区分字面模板与变量值;核对双花括号、partial_variables 和重复模板化。
提示词里加了一段 JSON 示例,调用 prompt.invoke({"question": question}) 后却报 missing variables,缺少的名字甚至是 "name"。另一种表现是在格式化时出现 Invalid format specifier。这两个症状都可能来自模板中的字面花括号。
下面针对 Python 的 langchain-core 0.3.79、默认 template_format="f-string"。这个名称指模板格式规则,不表示字符串一定写成 Python 的 f"...";普通三引号字符串同样会被模板解析。
看看模板实际识别了哪些变量
下面是容易出错的结构,JSON 的外层花括号也会进入模板解析:
from langchain_core.prompts import PromptTemplate
prompt = PromptTemplate.from_template(
'按这个示例回答:{"name": "茶", "quantity": 2}\n问题:{question}'
)
print(prompt.input_variables)
如果 input_variables 中出现了 JSON 字段片段,问题发生在把提示词送给模型之前。显式声明 input_variables=["question"] 并不能让解析器忽略其余花括号;这个版本会从模板重新推导变量。
也要检查真正缺失的业务变量。模板里确实写了 {context},调用时却只传 question,仍然需要补齐 context。不能看到 missing variables 就把所有占位符都转义。
固定示例可以转义,动态内容作为值传入
对于模板里固定的 JSON,将字面 { 和 } 写成 {{ 和 }},保留业务占位符的单花括号:
prompt = PromptTemplate.from_template(
'按这个示例回答:{{"name": "茶", "quantity": 2}}\n问题:{question}'
)
rendered = prompt.format(question="一杯茶")
print(rendered)
一轮格式化后,示例回到普通 JSON 的单花括号。如果文本还要经过另一层模板,第一轮的结果可能再次被解析。此时应该减少重复模板化,而不是不清楚层数就不断增加花括号。
示例由程序生成,或者内容中本来含有大量花括号时,把整段文本作为变量值更容易维护:
import json
from langchain_core.prompts import PromptTemplate
example = json.dumps({"name": "茶", "quantity": 2}, ensure_ascii=False)
prompt = PromptTemplate.from_template(
"按这个示例回答:{example}\n问题:{question}",
partial_variables={"example": example},
)
rendered = prompt.format(question="一杯茶")
变量值不会在这一次替换中再次扫描成占位符。前提是后续没有把 rendered 又交给 PromptTemplate.from_template(),或转换成新的字符串消息模板。只需要传递已经生成的消息内容时,保留它作为消息内容,不要重新解释成模板。
核对最终文本,而不是只看异常消失
调整后确认 input_variables 只保留真正需要调用方提供的变量;检查渲染结果中的 JSON 示例仍是一对花括号,业务问题已经替换,文本没有遗留未预期的占位符。诊断提示词可能带业务数据,记录时只保留必要片段。
这套规则不直接适用于 Jinja2 或 Mustache,它们有自己的占位符语法。为了绕开花括号而切换模板引擎,会改变整个提示词的解释方式;也不要接收不可信的 Jinja2 模板来解决这个问题。
模板能正常渲染,只说明输入构造已经通过。如果随后返回的 JSON 无法解析,应另外检查生成文本的 JSON 语法和字段约束。


