Skip to content

LM 格式强制器#

LM 格式强制器 是一个库,用于强制语言模型的输出格式(JSON Schema、正则表达式等)。与仅仅“建议”LLM遵循期望的输出结构不同,LM 格式强制器实际上可以“强制”LLM输出遵循期望的模式。

image

LM 格式强制器与本地LLM(目前支持 LlamaCPPHuggingfaceLLM 后端)配合工作,仅通过处理LLM的输出logits来操作。这使其能够支持像波束搜索和批处理这样的高级生成方法,而不像其他解决方案那样修改生成循环本身。在LM 格式强制器页面中查看更多详细信息的比较表。

JSON Schema 输出#

在 LlamaIndex 中,我们提供了与 LM 格式强制器的初始集成,以便轻松生成结构化输出(更具体地说是 pydantic 对象)。

例如,如果我们想要生成一张包含以下模式的歌曲专辑:

class Song(BaseModel):
    title: str
    length_seconds: int


class Album(BaseModel):
    name: str
    artist: str
    songs: List[Song]

只需创建一个 LMFormatEnforcerPydanticProgram,指定我们期望的 pydantic 类 Album,并提供一个合适的提示模板即可。

注意:LMFormatEnforcerPydanticProgram 会自动填写提示模板的可选参数{json_schema}中的 pydantic 类的 JSON schema。这有助于LLM自然生成正确的JSON,并减少格式强制器的干扰侵略,提高输出质量。

program = LMFormatEnforcerPydanticProgram(
    output_cls=Album,
    prompt_template_str="生成一个示例专辑,包括艺术家和歌曲列表。以电影 {movie_name} 为灵感。您必须根据以下模式进行回答:\n{json_schema}\n",
    llm=LlamaCPP(),
    verbose=True,
)

现在,我们可以通过调用带有额外用户输入的程序来运行程序。 这里让我们来点恐怖的东西,创建一张以《闪灵》为灵感的专辑。

output = program(movie_name="The Shining")

我们得到了我们的 pydantic 对象:

Album(
    name="The Shining: A Musical Journey Through the Haunted Halls of the Overlook Hotel",
    artist="The Shining Choir",
    songs=[
        Song(title="Redrum", length_seconds=300),
        Song(
            title="All Work and No Play Makes Jack a Dull Boy",
            length_seconds=240,
        ),
        Song(title="Heeeeere's Johnny!", length_seconds=180),
    ],
)

您可以在此笔记本中了解更多详情。

正则表达式输出#

LM 格式强制器还支持正则表达式输出。由于 LlamaIndex 中没有现有的正则表达式抽象,我们将直接使用LLM,在其中注入LM 格式生成器。

regex = r'"Hello, my name is (?P<name>[a-zA-Z]*)\. I was born in (?P<hometown>[a-zA-Z]*). Nice to meet you!"'
prompt = "这是我介绍自己的方式,如果我的名字是约翰,我出生在波士顿:"

llm = LlamaCPP()
regex_parser = lmformatenforcer.RegexParser(regex)
lm_format_enforcer_fn = build_lm_format_enforcer_function(llm, regex_parser)
with activate_lm_format_enforcer(llm, lm_format_enforcer_fn):
    output = llm.complete(prompt)

这将导致LLM生成我们指定的正则表达式格式的输出。我们还可以解析输出以获取命名组:

print(output)
# "Hello, my name is John. I was born in Boston, Nice to meet you!"
print(re.match(regex, output.text).groupdict())
# {'name': 'John', 'hometown': 'Boston'}

请参阅此笔记本以了解更多详情。