结构化预测
结构化预测让您能够更精细地控制应用程序如何调用大语言模型并使用Pydantic。我们将使用相同的Invoice类,按照之前示例的方式加载PDF文件,并像之前一样使用OpenAI。与创建结构化大语言模型不同,我们将直接在大语言模型上调用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
Section titled “FunctionCallingProgram”如果您正在使用的LLM具有函数调用API,FunctionCallingProgram将会
- 将 Pydantic 对象转换为工具
- 在提示大型语言模型的同时强制其使用此工具
- 返回生成的Pydantic对象
这通常是一种更可靠的方法,如果可用将优先使用。然而,某些LLM仅支持文本模式,它们将采用另一种方法。
LLMTextCompletionProgram
Section titled “LLMTextCompletionProgram”如果LLM仅支持文本,LLMTextCompletionProgram将会
- 将 Pydantic 模式输出为 JSON
- 将模式和数据发送给LLM,并附带提示指令,要求其以符合模式的形式进行响应
- 在Pydantic对象上调用
model_validate_json(),传入从LLM返回的原始文本
这种方法明显可靠性较低,但所有基于文本的大型语言模型都支持。
实际上,structured_predict 应该适用于任何大型语言模型,但如果您需要更底层的控制,可以直接调用 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完全相同,并会像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,这将非常有用。
在最后一节中,我们将探讨更低级别的结构化数据提取调用,包括在同一调用中提取多个结构。