主题
结构化这件事,输出只是其中一面,另一面是输入:许多提示词指南与最佳实践确实会推荐一些技巧,比如把输入提示词用 XML 标签包裹起来,以增强 LLM 对输入的理解。
LlamaIndex 让你可以原生地把输入组织成 XML 片段,底层借助 banks 与 Jinja(请确保安装的是 llama-index>=0.12.34)。
单独使用结构化输入
下面是一个把结构化输入与 Pydantic 模型搭配使用的简单例子:
from pydantic import BaseModel
from llama_index.core.prompts import RichPromptTemplate
from llama_index.llms.openai import OpenAI
from typing import Dict
template_str = "Please extract from the following XML code the contact details of the user:\n\n```xml\n{{ user | to_xml }}\n```\n\n"
prompt = RichPromptTemplate(template_str)
class User(BaseModel):
name: str
surname: str
age: int
email: str
phone: str
social_accounts: Dict[str, str]
user = User(
name="John",
surname="Doe",
age=30,
email="john.doe@example.com",
phone="123-456-7890",
social_accounts={"bluesky": "john.doe", "instagram": "johndoe1234"},
)
## check how the prompt would look like
prompt.format(user=user)
llm = OpenAI()
response = llm.chat(prompt.format_messages(user=user))
print(response.message.content)可以看到,要启用结构化输出,需要使用一个 Jinja 表达式(用 包裹),并施加 to_xml 过滤器(过滤运算符是 |)。
结构化输入与结构化输出的结合
把结构化输入和结构化输出结合起来,能显著提升 LLM 输出的一致性(也就是可靠性)。
下面这段代码演示了如何两者并用:
from pydantic import Field
from typing import Optional
class SocialAccounts(BaseModel):
instagram: Optional[str] = Field(default=None)
bluesky: Optional[str] = Field(default=None)
x: Optional[str] = Field(default=None)
mastodon: Optional[str] = Field(default=None)
class ContactDetails(BaseModel):
email: str
phone: str
social_accounts: SocialAccounts
sllm = llm.as_structured_llm(ContactDetails)
structured_response = await sllm.achat(prompt.format_messages(user=user))
print(structured_response.raw.email)
print(structured_response.raw.phone)
print(structured_response.raw.social_accounts.instagram)
print(structured_response.raw.social_accounts.bluesky)想更深入了解结构化输入,请看这份示例 notebook。