news 2026/9/11 19:13:09

LlamaIndex × Guidance 集成实战:用约束式结构化输出生成 Pydantic 对象并加固子问题查询引擎

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LlamaIndex × Guidance 集成实战:用约束式结构化输出生成 Pydantic 对象并加固子问题查询引擎

LlamaIndex × Guidance 集成实战:用约束式结构化输出生成 Pydantic 对象并加固子问题查询引擎

【免费下载链接】llama_indexLlamaIndex is the document processing platform for AI项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index

本篇技术指南围绕 LlamaIndex 官方社区集成文档 guidance.md 展开,系统讲解如何将微软开源的 Guidance 语言嵌入 LlamaIndex,利用其"强制约束"能力让 LLM 直接产出符合 JSON Schema / Pydantic 模型的结构化对象,并把这一能力注入SubQuestionQueryEngine的中间环节以提升子问题生成的鲁棒性。读完本文,你将掌握GuidancePydanticProgram的完整用法、handlebars 模板转换原理,以及GuidanceQuestionGenerator的接入方式。

为什么需要 Guidance:从"建议结构"到"强制结构"

常规的 LLM 结构化输出做法是在提示词里"请求"模型输出一段 JSON,再交给解析器处理。这种模式有两个隐患:一是模型可能产出畸形 JSON(例如缺少括号、字段错位),二是解析失败时整个链路报错,需要重试或容错逻辑。

Guidance 提供了一条不同的路径:它把生成(generation)、提示(prompting)和逻辑控制(logical control)交织进同一个连续流程,与语言模型实际逐 token 处理文本的方式对齐。最关键的是,它可以强制LLM 输出遵循指定 schema 的结构,而不是仅仅"建议"——模型只需专注于内容本身,语法层面的错误被彻底排除,输出解析问题因此完全消失。

这种能力对参数量较小、训练语料中源代码数据不足的弱模型尤其有价值:它们难以稳定地生成格式良好、层级正确的结构化输出,而 Guidance 的约束机制恰好弥补了这一短板。

GuidancePydanticProgram:一行代码生成 Pydantic 对象

LlamaIndex 将 Guidance 的约束能力封装为GuidancePydanticProgram,用于直接产出 Pydantic 对象。该实现位于 program/guidance/base.py,继承自核心库中的BaseLLMFunctionProgram(见 llm_prompt_program.py),其单元测试 test_program_guidance.py 验证了类的继承关系。

定义目标 schema

假设我们要生成一张"专辑",包含歌名与时长,schema 如下:

from pydantic import BaseModel from typing import List class Song(BaseModel): title: str length_seconds: int class Album(BaseModel): name: str artist: str songs: List[Song]

注意 handlebars 模板约定

Guidance 使用 handlebars 风格模板:双花括号{{}}用于变量替换,单花括号{}表示字面花括号——这与 Python format string 的约定恰好相反(Python 中单花括号是变量占位符,双花括号才是转义后的字面括号)。

好在 LlamaIndex 提供了convert_to_handlebars工具函数(位于 guidance_utils.py),可把 Python format string 风格的提示模板一键转换为 Guidance 的 handlebars 模板。该函数的转换逻辑是:先将双花括号替换为临时占位符,再把所有单花括号翻倍,最后把占位符还原为单花括号,从而完成两种约定之间的互转。

创建并运行程序

from llama_index.program.guidance import GuidancePydanticProgram from guidance.llms import OpenAI as GuidanceOpenAI program = GuidancePydanticProgram( output_cls=Album, prompt_template_str="Generate an example album, with an artist and a list of songs. Using the movie {{movie_name}} as inspiration", guidance_llm=GuidanceOpenAI("text-davinci-003"), verbose=True, )

然后像调用函数一样传入额外输入运行程序:

output = program(movie_name="The Shining")

得到的就是一个结构完整的AlbumPydantic 对象:

Album( name="The Shining", artist="Jack Torrance", songs=[ Song(title="All Work and No Play", length_seconds=180), Song(title="The Overlook Hotel", length_seconds=240), Song(title="The Shining", length_seconds=210), ], )

说明:GuidancePydanticProgram内部通过user()/assistant()会话块包裹提示并追加gen(stop=".")生成调用;执行完成后,会用parse_pydantic_from_guidance_program从返回文本中提取最后一个 markdown 格式的 JSON 代码块,再经model_validate反序列化为目标 Pydantic 对象。由于当前 Guidance 版本尚不支持从Program.variables直接提取嵌套对象,源码中对此采用了"解析最终文本"的临时方案(注释中已明确标注),详情见 guidance_utils.py。

参数要点与 from_defaults 入口

  • output_cls:目标 Pydantic 模型类,决定强制输出的 schema;
  • prompt_template_str:handlebars 风格的提示模板,其中的{{变量}}会在调用时以关键字参数传入;
  • guidance_llm:Guidance 侧的 LLM 实例,例如GuidanceOpenAI("text-davinci-003");若未提供,源码中会默认回退到OpenAI("gpt-3.5-turbo")
  • verbose:是否打印原始输出,便于调试。

此外还提供了from_defaults类方法,允许以promptPromptTemplate对象)或prompt_template_str二选一的方式初始化;两者都传或都不传会抛出ValueError。完整的可交互示例见 guidance_pydantic_program.ipynb。

底层:JSON Schema 到 Guidance 模板的自动转换

在 guidance_utils.py 中,json_schema_to_guidance_output_template负责把 Pydantic 模型的 JSON Schema 递归转换为 Guidance 约束模板:

  • object类型:输出字面{...}结构,逐字段展开;
  • array类型:使用{{#geneach ...}}循环块,配合stop=']'与可选的max_iterations(对应 schema 的max_items)控制列表长度,元素间用{{#unless @first}}, {{/unless}}插入逗号;
  • string类型:使用{{gen 'key' stop='"'}}生成带结束符约束的字符串;
  • integer/number类型:默认同样以stop='"'约束,可开启use_pattern_controlpattern='[0-9\.]'限定数字字符;
  • boolean类型:使用{{#select 'key'}}True{{or}}False{{/select}}强制二选一。

该实现基于微软 guidance 仓库的 jsonformer 思路,并扩展支持了嵌套 Pydantic 模型(通过$ref解析到$defs)。这也解释了为何弱模型也能稳定输出层级正确的 JSON——语法路径已被模板锁死。

用 Guidance 加固 SubQuestionQueryEngine 的子问题生成

LlamaIndex 提供了一系列高级查询引擎,其中不少依赖中间步骤的结构化输出。若中间响应结构不稳定,后续解析就会失败。Guidance 正好可以在此处发挥价值:确保中间响应具备预期结构,从而可被可靠地解析为结构化对象

集成文档给出了一个典型实践:实现GuidanceQuestionGenerator并替换SubQuestionQueryEngine默认的问题生成器。其源码位于 question_gen/guidance/base.py,对应单元测试见 test_question_gen_guidance_generator.py。

from llama_index.question_gen.guidance import GuidanceQuestionGenerator from guidance.llms import OpenAI as GuidanceOpenAI # 定义基于 guidance 的问题生成器 question_gen = GuidanceQuestionGenerator.from_defaults( guidance_llm=GuidanceOpenAI("text-davinci-003"), verbose=False ) # 定义查询引擎工具 query_engine_tools = ... # 构建子问题查询引擎 s_engine = SubQuestionQueryEngine.from_defaults( question_gen=question_gen, # 使用上面定义的 guidance 版 question_gen query_engine_tools=query_engine_tools, )

内部实现剖析

GuidanceQuestionGenerator继承自核心库的BaseQuestionGenerator,其from_defaults内部以SubQuestionListoutput_cls构建了一个GuidancePydanticProgram,并使用默认子问题提示模板:

DEFAULT_GUIDANCE_SUB_QUESTION_PROMPT_TMPL = convert_to_handlebars( DEFAULT_SUB_QUESTION_PROMPT_TMPL )

核心的generate方法会把工具列表序列化为 JSON 文本(build_tools_text,见 prompts.py),连同用户查询一起作为关键字参数传入程序,最终返回List[SubQuestion]。默认提示模板DEFAULT_SUB_QUESTION_PROMPT_TMPL(同样位于 prompts.py)要求模型"Given a user question, and a list of tools, output a list of relevant sub-questions in json markdown",并通过 Uber/Lyft 财务对比的示例引导输出{"items": [...]}结构。

值得注意的限制:agenerate方法目前仅同步转发到generate,源码注释明确说明"guidance does not support async calls"(见 base.py),因此异步场景下仍需走同步路径。

交互式完整示例见 guidance_sub_question.ipynb。

安装与依赖

两个集成分别打包为独立发行包,对应pyproject.toml如下:

  • llama-index-program-guidance:提供GuidancePydanticProgram,依赖guidance>=0.1.16,<0.2llama-index-core>=0.13.0,<0.15,要求 Python>=3.10,<4.0
  • llama-index-question-gen-guidance:提供GuidanceQuestionGenerator,额外依赖llama-index-program-guidance>=0.4.0,<0.5

安装命令示例:

pip install llama-index-program-guidance llama-index-question-gen-guidance guidance

两个包的[tool.llamahub]配置分别声明了import_pathllama_index.program.guidancellama_index.question_gen.guidance,与上文代码中的导入路径一一对应。API 参考文档也可在 program/guidance.md 与 question_gen/guidance.md 中查阅。

小结

通过本文你可以看到一条清晰的集成链路:

  1. 约束式结构化输出GuidancePydanticProgram把 Pydantic 模型转换为 Guidance 模板,强制 LLM 输出合法 JSON,从而彻底消除解析失败风险,尤其适合弱模型场景;
  2. 模板兼容层convert_to_handlebars解决了 Python format string 与 handlebars 模板约定的差异,让既有提示模板可以无缝迁移;
  3. 中间环节加固GuidanceQuestionGenerator复用同一套约束机制,让SubQuestionQueryEngine的子问题生成结构稳定、可解析,提升整条查询链路的鲁棒性。

需要动手验证时,推荐直接运行仓库中的两个 notebook——guidance_pydantic_program.ipynb 与 guidance_sub_question.ipynb,并结合上述源码路径理解每一步的底层行为。

【免费下载链接】llama_indexLlamaIndex is the document processing platform for AI项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 19:10:15

如何用 Packer 构建 DigitalOcean 快照并发布 Appsmith One-Click 新版本

如何用 Packer 构建 DigitalOcean 快照并发布 Appsmith One-Click 新版本 【免费下载链接】appsmith Platform to build admin panels, internal tools, and dashboards. Integrates with 25 databases and any API. 项目地址: https://gitcode.com/GitHub_Trending/ap/appsm…

作者头像 李华
网站建设 2026/9/11 19:08:24

【滚雪球学数学建模】第21节·复杂问题抽象与模型设计

🎓 本文收录于《滚雪球学数学建模》系列专栏 数学建模真正的难点,往往不在于掌握某一个公式或算法,而在于面对实际问题时,能否完成从 问题分析 → 模型构建 → 算法求解 → 结果验证 → 论文表达 的完整闭环。 本专栏正是围绕这一目标打造:从零基础出发,通过“滚雪球式”…

作者头像 李华
网站建设 2026/9/11 19:02:03

如何用单文件替代 Armoury Crate:G-Helper 完整使用指南

如何用单文件替代 Armoury Crate&#xff1a;G-Helper 完整使用指南 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbook, …

作者头像 李华
网站建设 2026/9/11 19:01:58

【JAVA毕设源码分享】基于 SpringBoot 框架的河南文化旅游网站的设计与实现 基于 SpringBoot 的河南文旅服务平台(程序+文档+代码讲解+一条龙定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/9/11 19:01:39

2026 下半年 AI 产品的数据指标会往哪走

摘要&#xff1a;AI 行业正在集体告别"先爽后算账"的阶段——装机量、月活这些"爽指标"不再能说服投资人&#xff0c;留存、使用深度、单位经济成为新焦点。本文基于近期行业数据与报告&#xff0c;梳理 2026 下半年 AI 产品数据指标的三次迁移&#xff0c…

作者头像 李华
网站建设 2026/9/11 19:00:40

考研调剂公告怎么读?从长春工业大学样本看调剂全流程与避坑指南

每年二三月&#xff0c;考研初试成绩公布后的这段时间&#xff0c;很多学生的手机都会一刻不停刷着各类调剂信息。如果你恰好看到了“长春工业大学2025年硕士研究生招生调剂公告&#xff08;一&#xff09;”这样一条标题&#xff0c;第一反应可能是赶紧点进去找有没有自己的专…

作者头像 李华