LangChain中用JSON文本构建FewShotPromptTemplate触发KeyError问题
问题重现
尝试创建用于总结JSON内容的FewShotPromptTemplate时,无论传入什么输入都会触发KeyError: '\n "name"',但单独调用example_prompt.invoke(examples[0]).to_string()能正常运行。相关代码如下:
from langchain_core.prompts import PromptTemplate, FewShotPromptTemplate json_raw = """{ "name": "Bernd", "type": "Bread" }""" examples = [ { "question": json_raw, "answer": "A file describing a bread.", } ] example_prompt = PromptTemplate.from_template("Input file:\n{question}\n\nOutput file:\n{answer}\n") prompt = FewShotPromptTemplate( examples=examples, example_prompt=example_prompt, suffix="Input file:\n{input}", input_variables=["input"], ) command = prompt.invoke({"input": "asdf"}) print(command)
完整报错信息:
Traceback (most recent call last): File "/Users/jan/meine/ai/bpmnbot/fewshotbug.py", line 20, in <module> command = prompt.invoke({"input": "input"}) File "/Users/jan/meine/ai/bpmnbot/venv/lib/python3.13/site-packages/langchain_core/prompts/base.py", line 208, in invoke return self._call_with_config( ~~~~~~~~~~~~~~~~~~~~~~^ self._format_prompt_with_error_handling, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...<3 lines>... serialized=self._serialized, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ) ^ File "/Users/jan/meine/ai/bpmnbot/venv/lib/python3.13/site-packages/langchain_core/runnables/base.py", line 1925, in _call_with_config context.run( ~~~~~~~~~~~^ call_func_with_variable_args, # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...<4 lines>... **kwargs, ^^^^^^^^^ ), ^ File "/Users/jan/meine/ai/bpmnbot/venv/lib/python3.13/site-packages/langchain_core/runnables/config.py", line 396, in call_func_with_variable_args return func(input, **kwargs) # type: ignore[call-arg] File "/Users/jan/meine/ai/bpmnbot/venv/lib/python3.13/site-packages/langchain_core/prompts/base.py", line 183, in _format_prompt_with_error_handling return self.format_prompt(**_inner_input) ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^ File "/Users/jan/meine/ai/bpmnbot/venv/lib/python3.13/site-packages/langchain_core/prompts/string.py", line 286, in format_prompt return StringPromptValue(text=self.format(**kwargs)) ~~~~~~~~~~~^^^^^^^^^^ File "/Users/jan/meine/ai/bpmnbot/venv/lib/python3.13/site-packages/langchain_core/prompts/few_shot.py", line 197, in format return DEFAULT_FORMATTER_MAPPING[self.template_format](template, **kwargs) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/string.py", line 190, in format return self.vformat(format_string, args, kwargs) ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/jan/meine/ai/bpmnbot/venv/lib/python3.13/site-packages/langchain_core/utils/formatting.py", line 33, in vformat return super().vformat(format_string, args, kwargs) ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/string.py", line 194, in vformat result, _ = self._vformat(format_string, args, kwargs, used_args, 2) ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/string.py", line 234, in _vformat obj, arg_used = self.get_field(field_name, args, kwargs) ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/string.py", line 299, in get_field obj = self.get_value(first, args, kwargs) File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/string.py", line 256, in get_value return kwargs[key] ~~~~~~^^^^^ KeyError: '\n "name"'
原因分析
FewShotPromptTemplate默认使用Python的str.format作为模板格式化方式,示例中json_raw包含JSON语法的{},这些会被str.format误判为需要填充的变量占位符。当FewShotPromptTemplate拼接完所有示例生成最终模板后,JSON里的{"name": "Bernd"}会被解析为需要获取键'\n "name"'的值,但该键不存在于输入变量中,因此触发KeyError。
单独调用example_prompt.invoke(examples[0])时,json_raw是作为{question}变量的填充值传入,此时str.format只会处理模板中定义的{question}和{answer}占位符,不会解析JSON内部的{},所以能正常运行。
解决方案
有两种可行的解决方式:
方式1:切换模板格式为Jinja2
Jinja2模板只会识别{{ }}作为变量占位符,不会解析JSON中的{},只需在创建FewShotPromptTemplate时指定template_format="jinja2"即可:
prompt = FewShotPromptTemplate( examples=examples, example_prompt=example_prompt, suffix="Input file:\n{input}", input_variables=["input"], template_format="jinja2" # 添加这一行 )
方式2:转义JSON中的{}
将JSON里的{替换为{{,}替换为}},让str.format将其视为普通字符:
json_raw = """{{ "name": "Bernd", "type": "Bread" }}"""
推荐使用方式1,无需手动转义,更简洁可靠。
内容的提问来源于stack exchange,提问作者Jan Berndt

