题目:AI 应用里的 Prompt 通常由「模板 + 变量」渲染后再发给大模型。渲染环节的常见事故是:变量漏传导致 {{price}} 原样发给模型(模型会照着占位符输出),或者多传了模板里根本没有的变量(说明模板被改了但调用方没同步)。
请实现 render_prompt(template, variables),返回三元组 (rendered, missing, extra):
-
template:字符串,占位符写作{{key}},key由字母、数字、下划线组成,大括号内侧允许有空格,如{{ key }}; -
rendered:把能在variables中找到的占位符替换成对应值(值统一用str()转换)后的字符串;找不到的占位符原样保留(保留原始写法); -
missing:模板中出现、但variables里没有的 key,按首次出现顺序去重; -
extra:variables中提供、但模板从未使用的 key,按字典序升序; - 不满足 key 规则的写法(如
{abc}、{{!!}}、未闭合的{{x)一律不算占位符,原样输出; - 替换后的值内部即使含有
{{y}}这类形态,也不允许被二次替换。
代码框架:
def render_prompt(template: str, variables: dict) -> tuple:
"""渲染 Prompt 模板并检测占位符异常。
Args:
template: 含 {{key}} 占位符的模板字符串。
variables: 变量字典。
Returns:
(rendered, missing, extra)
rendered: 渲染结果,未命中的占位符原样保留。
missing: 模板用到但没传值的 key,按首次出现顺序去重。
extra: 传了但模板没用到的 key,按字典序升序。
"""
pass
断言用例:
assert render_prompt("你好 {{name}},欢迎回来", {"name": "小明"}) == \
("你好 小明,欢迎回来", [], [])
assert render_prompt("{{ a }}买{{b}}元", {"a": "苹果"}) == \
("苹果买{{b}}元", ["b"], [])
assert render_prompt("{{m}}-{{n}}-{{m}}", {}) == \
("{{m}}-{{n}}-{{m}}", ["m", "n"], [])
assert render_prompt("plain text", {"b": 2, "a": 1}) == \
("plain text", [], ["a", "b"])
assert render_prompt("价格 {{price}} 元", {"price": 0}) == \
("价格 0 元", [], [])
assert render_prompt("{abc} {{d}}", {"d": "x"}) == \
("{abc} x", [], [])
assert render_prompt("{{n}}", {"n": "a\\b{c}"}) == \
("a\\b{c}", [], [])
# 关键:值里的 {{y}} 不能被二次替换
assert render_prompt("{{x}}{{y}}", {"x": "{{y}}", "y": "V"}) == \
("{{y}}V", [], [])