进阶 lmql.ai 2026-10-11 18:10:44 · 33 阅读

第7章 LMQL 中的 Scripted Prompting(脚本化提示)

Scripted Prompting 编程式 LLM 提示,支持控制流。在 LMQL 中,程序不仅仅是静态的文本模板,还包含控制流(如循环、条件判断、函数调用)。这使得动态构建提示成为可能,并允许 LMQL 程序动态响应模型输出。这种脚本化机制是通过组合提示模板、控制流和输出约束来实现的。

转义(Escaping):当需要以字面方式使用 [, ], { 和 } 时,LMQL 要求特殊转义,详见 Escaping。

模板与控制流(Templates and Control Flow) 行李箱清单 假设我们想在度假前生成一份行李箱清单。一种方法是使用以下查询:

# 使用采样解码器
sample(temperature=1.0) 
# 生成一个列表
"去海边(非旅行)时不要忘的一些东西:\n"
"[LIST]"

输出示例:

A list of things not to forget when going to the sea (not travelling): LIST- 一部具备通话、短信或技术服务的手机 - 当地报纸的副本 - 钢笔或手机钥匙扣

在这里,我们指定采样解码器以增加多样性(相较于 argmax,参见 Decoders),然后执行程序,使用一个 [LIST] 变量来生成列表。这种方法效果可能不错,但在实践中不确定模型是否总能生成结构良好的物品列表。此外,我们还需要解析响应以分离各项物品并进一步处理。

简单提示模板 为了解决这个问题,我们可以提供更严格的模板,通过提供多条提示语句(每个物品一条),让模型仅填充 THING 变量:

"去海边(非旅行)时不要忘的一些东西:\n"
"-[THING]" where STOPS_AT(THING, "\n")
"-[THING]" where STOPS_AT(THING, "\n")
"-[THING]" where STOPS_AT(THING, "\n")
"-[THING]" where STOPS_AT(THING, "\n")
"-[THING]" where STOPS_AT(THING, "\n")

输出示例:

A list of things not to forget when going to the sea (not travelling): -THING 一部带 a/r 短信功能的手机 -THING pletter -THING accoon -THING 关于/有关海洋的电影 -THING A 曾到过/进入过 Poconos

请注意,我们在每个 THING 上使用了停止约束,以便当模型输出新行时,确保我们继续遵循提供的模板,而不是让模型输出持续下去。如果没有停止条件,简单的模板填充将无法实现,因为模型将为第一个变量生成多于一个的物品。

带控制流的提示 基于这个提示模板,我们现在可以利用提示中的控制流来进一步处理结果并避免冗余,同时引导文本生成。首先,我们简化查询,使用 for 循环代替重复变量:

"去海边(非旅行)时不要忘的一些东西:\n"
backpack = []
for i in range(5):
   "-[THING]" where STOPS_AT(THING, "\n") 
   backpack.append(THING.strip())
print(backpack)

输出示例:

A list of things not to forget when going to the sea (not travelling): -THING 一双好的蓝色/凝胶 saskaers -THING 一个良好的晒黑器 -THING 一个良好的空气清新剂 -THING 一个洗手的好地方 -THING 一个洗脚的好地方 output: ['A good pair of blue/gel saskaers', 'A good sun tanner', 'A good air freshener', 'A good spot for washing your hands', 'A good spot for washing your feet']

由于我们逐个 THING 解码列表,可以轻松访问各个单独物品,无需考虑解析或验证。我们只是将它们添加到 backpack 物品列表中,然后可以进一步处理。

跨变量约束 现在我们已收集到一份物品列表,甚至可以扩展程序,约束后续部分仅选择 backpack 中的物品:

"去海边(非旅行)时不要忘的一些东西:\n"
backpack = []
for i in range(5):
   "-[THING]" where STOPS_AT(THING, "\n") 
   backpack.append(THING.strip())

"其中最重要的是:[ESSENTIAL_THING]" \
    where ESSENTIAL_THING in backpack

输出示例:

A list of things not to forget when going to the sea (not travelling): ⏎ -THING Sunscreen ⏎ -THING Beach Towels ⏎ -THING Beach Umbrella ⏎ -THING Beach Chairs ⏎ -THING Beach Bag ⏎ The most essential of which is: ESSENTIAL_THING Sunscreen

这有助于引导模型实现完整且一致的推理,从而降低模型自相矛盾的可能性。

转义(Escaping) 在提示字符串内部,字符 [, ], { 和 } 保留用于模板变量,不能直接作为字面量使用。若要作为字面量使用,需分别转义为 [[, ]], {{ 和 }}。除此之外,顶层字符串在 LMQL 中解释为 Python f-string,因此适用 Python 字符串和 f-string 的标准转义规则。例如,若想在提示字符串中使用 JSON 语法,需按以下方式转义花括号和方括号:

argmax 
    """
    Write a summary of Bruno Mars, the singer:
    {{
      "name": "[STRING_VALUE]",
      "age": [INT_VALUE],
      "top_songs": [[
         "[STRING_VALUE]",
         "[STRING_VALUE]"
      ]]
    }}
    """
from
    "openai/text-davinci-003" 
where
    STOPS_BEFORE(STRING_VALUE, '"') and INT(INT_VALUE) and len(TOKENS(INT_VALUE)) < 2

Python 兼容性 除了简单的控制流,LMQL 还支持查询的 prompt 子句中的大多数有效 Python 结构,其中顶层字符串(如 "-[THING]")会被自动解释为模型输入,并按需分配模板变量。更高级用法请参见 Tool Augmentation 章节。

评论 (0)