Skip to content
LlamaIndex 文档版本 跟随上游 源快照 7bf84614 更新于 2026-10-15

结构化预测(Structured Prediction)让你对「应用如何调用 LLM、如何使用 Pydantic」有更细粒度的控制。我们仍然沿用同一个 Invoice 类,像上一个示例那样加载 PDF,也照旧使用 OpenAI。区别是不再创建结构化 LLM,而是直接对 LLM 调用 structured_predict——这是每个 LLM 类都有的方法。

structured_predict 接受一个 Pydantic 类和一个提示词模板作为参数,并以关键字参数的形式传入模板里用到的各个变量。

from llama_index.core.prompts import PromptTemplate

prompt = PromptTemplate(
    "Extract an invoice from the following text. If you cannot find an invoice ID, use the company name '{company_name}' and the date as the invoice ID: {text}"
)

response = llm.structured_predict(
    Invoice, prompt, text=text, company_name="Uber"
)

可以看到,这让我们得以在 Pydantic 不足以把数据解析正确时,往提示词里追加额外的指引。这种情况下的响应对象就是那个 Pydantic 对象本身。需要的话我们可以把结果取成 JSON:

json_output = response.model_dump_json()
print(json.dumps(json.loads(json_output), indent=2))
{
    "invoice_id": "Uber-2024-10-10",
    "date": "2024-10-10T19:49:00",
    "line_items": [
        {"item_name": "Trip fare", "price": 12.18},
        {"item_name": "Access for All Fee", "price": 0.1},
        ...,
    ],
}

structured_predict 针对不同的使用场景还提供了若干变体,包括异步(astructured_predict)与流式(stream_structured_predict、astream_structured_predict)。

底层机制

取决于你用的是哪个 LLM,structured_predict 会由下面两个类之一来负责调用 LLM 并解析输出。

FunctionCallingProgram

如果你使用的 LLM 具备函数调用 API,FunctionCallingProgram 会:

  • 把 Pydantic 对象转换成一个工具
  • 提示 LLM,并强制它使用这个工具
  • 返回生成的那个 Pydantic 对象

这通常是更可靠的方式,只要可用就会被优先采用。但有些 LLM 只支持文本,它们会走另一种方式。

LLMTextCompletionProgram

如果 LLM 只支持文本,LLMTextCompletionProgram 会:

  • 把 Pydantic schema 输出成 JSON
  • 把 schema 和数据一起发给 LLM,并在提示词里要求它按符合 schema 的形式作答
  • 对 Pydantic 对象调用 model_validate_json(),传入 LLM 返回的原始文本

这种方式可靠性明显更低,但胜在所有文本型 LLM 都支持。

直接调用预测类

实践中 structured_predict 对任何 LLM 都应该工作良好,但如果你需要更底层的控制,可以直接调用 FunctionCallingProgram 和 LLMTextCompletionProgram,并进一步定制其中的行为:

textCompletion = LLMTextCompletionProgram.from_defaults(
    output_cls=Invoice,
    llm=llm,
    prompt=PromptTemplate(
        "Extract an invoice from the following text. If you cannot find an invoice ID, use the company name '{company_name}' and the date as the invoice ID: {text}"
    ),
)

output = textCompletion(company_name="Uber", text=text)

上面的写法等价于对没有函数调用 API 的 LLM 调用 structured_predict,并且同样返回一个 Pydantic 对象。不过,你可以通过继承 PydanticOutputParser 来定制输出解析方式:

from llama_index.core.output_parsers import PydanticOutputParser

class MyOutputParser(PydanticOutputParser):
    def get_pydantic_object(self, text: str):
        # do something more clever than this
        return self.output_parser.model_validate_json(text)

textCompletion = LLMTextCompletionProgram.from_defaults(
    llm=llm,
    prompt=PromptTemplate(
        "Extract an invoice from the following text. If you cannot find an invoice ID, use the company name '{company_name}' and the date as the invoice ID: {text}"
    ),
    output_parser=MyOutputParser(output_cls=Invoice),
)

当你用的 LLM 能力较弱、需要在解析上帮它一把时,这招很有用。

最后一节我们会再看更底层的结构化数据抽取调用,包括在同一次调用里抽取多种结构。

BytesRouter 是社区翻译站点,所有译文仅供参考,一切以官方英文原文为准。