大型语言模型(LLM),例如Google Gemini和OpenAI GPT-4o,在文本生成方面表现出了惊人的能力。然而,在许多实际应用场景中,我们需要的不仅仅是自由格式的文本,而是可以直接嵌入应用程序的结构化数据。本文将深入探讨如何利用Python,通过Gemini API和OpenAI API,从LLM中获取结构化JSON输出,并利用Pydantic模型自动验证数据,从而提升AI应用的可靠性和可维护性。
结构化输出:告别繁琐解析
传统的LLM应用往往返回非结构化的文本,需要开发者自行编写代码进行解析,这不仅耗时耗力,而且容易出错。结构化输出 则改变了这一现状。它允许我们预先定义数据的Schema,让LLM直接返回符合该Schema的JSON格式数据。
举个例子,如果我们想从LLM获取一个菜谱信息,传统的LLM可能会返回类似这样的文本:
这里是一个曲奇饼干的菜谱:...
而使用结构化输出,我们可以让LLM直接返回如下JSON数据:
{
"recipe_name": "巧克力曲奇",
"ingredients": [
"2 杯面粉",
"1 杯糖",
"1 杯巧克力豆"
]
}
这种方法的优势显而易见:
- 避免手动解析:无需编写复杂的正则表达式或字符串处理代码。
- 数据格式可预测:保证数据的一致性,方便后续处理。
- 易于验证:可以使用Pydantic等库进行自动验证,确保数据的质量。
Gemini API:Pydantic加持的结构化JSON输出
Google Gemini API 提供了强大的结构化输出能力,允许开发者通过指定 response_schema
来获得经过 Pydantic 验证的 JSON 输出。这极大地简化了从LLM获取结构化数据的流程。
以下是一个使用 Gemini API 获取曲奇饼干菜谱的示例代码:
from google import genai
from pydantic import BaseModel
from dotenv import load_dotenv
import os
load_dotenv()
api_key = os.getenv("GEMINI_APIKEY")
if not api_key:
raise ValueError("GEMINI_APIKEY environment variable not set")
client = genai.Client(api_key=api_key)
class Recipe(BaseModel):
recipe_name: str
ingredients: list[str]
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="给我一个流行的曲奇饼干菜谱,并包括配料的用量。",
config={
"response_mime_type": "application/json",
"response_schema": Recipe,
},
)
recipe: Recipe = response.parsed
print(f"菜谱名称: {recipe.recipe_name}")
print("配料:")
for ingredient in recipe.ingredients:
print(f"- {ingredient}")
代码解析:
- 定义 Pydantic 模型: 首先,我们使用 Pydantic 定义了一个
Recipe
模型,明确了菜谱的recipe_name
和ingredients
字段,并指定了各自的数据类型。这为 Gemini API 提供了明确的数据结构定义。 - 调用
generate_content()
方法: 在调用generate_content()
方法时,我们将response_mime_type
设置为"application/json"
,并将response_schema
设置为我们定义的Recipe
模型。这告诉 Gemini API 我们期望返回 JSON 格式的数据,并且数据应该符合Recipe
模型的结构。 - 访问
response.parsed
: Gemini API 会自动将返回的 JSON 数据解析为Recipe
类的实例,并赋值给response.parsed
。我们可以直接通过response.parsed
访问结构化数据,无需手动解析。
实际应用案例:
假设你需要构建一个美食推荐App,用户可以输入关键词,App会返回相关的菜谱信息。使用 Gemini API 的 结构化输出 功能,你可以轻松地从LLM获取菜谱名称、配料、制作步骤等信息,并将这些信息直接展示在App界面上,而无需编写复杂的解析代码。
数据案例:
以下是一个可能的返回结果:
{
"recipe_name": "花生酱曲奇",
"ingredients": [
"1 杯奶油花生酱",
"1 杯砂糖",
"1 个鸡蛋"
]
}
OpenAI GPT-4o:新一代结构化输出解析方案
OpenAI 近期也加入了 结构化输出 解析的行列,为开发者提供了另一种便捷的方式来获取结构化数据。与 Gemini API 类似,OpenAI 也支持使用 Pydantic 模型进行数据验证。
以下是使用 OpenAI GPT-4o 获取曲奇饼干菜谱的示例代码:
from openai import OpenAI
from pydantic import BaseModel
from dotenv import load_dotenv
import os
load_dotenv()
api_key = os.getenv("OPENAI_APIKEY")
if not api_key:
raise ValueError("OPENAI_APIKEY environment variable not set")
client = OpenAI(api_key=api_key)
class Recipe(BaseModel):
recipe_name: str
ingredients: list[str]
response = client.responses.parse(
model="gpt-4o-2024-08-06",
input=[
{
"role": "system",
"content": "你是一个乐于助人的助手,可以从用户查询中提取结构化数据。",
},
{
"role": "user",
"content": "给我一个流行的曲奇饼干菜谱,并包括配料的用量。",
},
],
text_format=Recipe,
)
recipe = response.output_parsed
print(f"菜谱名称: {recipe.recipe_name}")
print("配料:")
for ingredient in recipe.ingredients:
print(f"- {ingredient}")
代码解析:
- 定义 Pydantic 模型: 同样,我们首先定义了一个
Recipe
模型,明确了菜谱的结构。 - 调用
client.responses.parse()
方法: 使用client.responses.parse()
方法向 LLM 发送请求,并将text_format
参数设置为我们定义的Recipe
模型。这告诉 OpenAI 我们期望返回符合Recipe
模型的结构化数据。 - 访问
response.output_parsed
: OpenAI 会自动将返回的数据解析为Recipe
类的实例,并赋值给response.output_parsed
。
实际应用案例:
假设你需要构建一个智能客服机器人,它可以回答用户关于电影信息的问题。使用 OpenAI GPT-4o 的 结构化输出 功能,你可以让LLM返回电影名称、导演、演员、上映日期等信息,并将这些信息以结构化的方式展示给用户。
数据案例:
以下是一个可能的返回结果:
{
"recipe_name": "巧克力燕麦曲奇",
"ingredients": [
"1 杯全麦面粉",
"1/2 杯红糖",
"1/2 杯燕麦片",
"1/2 杯巧克力碎片"
]
}
结构化输出的应用场景:无限可能
结构化输出 的应用场景非常广泛,以下是一些典型的例子:
- 构建聊天机器人: 聊天机器人不再局限于简单的文本回复,可以返回结构化的数据,例如产品信息、预订信息等。
- 自动化工作流: 自动化生成菜谱、任务清单、结构化问答等。例如,可以根据用户的输入,自动生成一份包含详细步骤的旅行计划。
- 验证 AI 响应: 使用类型化的 Schema 验证 AI 响应,确保数据的准确性和完整性。
- 减少自定义解析逻辑: 大幅减少编写自定义解析代码的工作量,提高开发效率。
更多实际案例:
- 金融领域: 从新闻报道中提取公司名称、股票代码、财务数据等,用于构建量化交易模型。
- 医疗领域: 从病历记录中提取疾病名称、症状、药物信息等,辅助医生进行诊断和治疗。
- 电商领域: 从商品描述中提取商品名称、品牌、价格、规格等,用于构建商品搜索引擎。
实用技巧:提升结构化输出的质量
在使用 结构化输出 时,以下是一些实用的技巧,可以帮助你提升输出的质量:
- 定义清晰明确的 Pydantic 模型: 模型的定义越清晰,LLM 就越容易生成符合要求的数据。避免使用模糊的字段名称或数据类型,尽量使用具体的、可枚举的值。
- 优雅地处理验证错误: 当 LLM 返回的数据不符合 Pydantic 模型的定义时,会抛出验证错误。你需要编写代码来捕获这些错误,并进行相应的处理,例如向用户提示错误信息,或者使用默认值进行填充。
- 记录原始响应以进行调试: 将 LLM 的原始响应记录下来,可以帮助你分析错误的原因,并改进模型的定义或提示语。
- 及时更新: Gemini 和 OpenAI 的 API 都在不断发展,及时关注官方文档,了解最新的功能和特性。
具体案例:
假设你的 Pydantic 模型定义了一个 age
字段,数据类型为 int
,但是 LLM 返回的 age
值为字符串 "twenty"
,那么 Pydantic 验证会失败。你需要捕获这个错误,并向用户提示 “年龄必须是数字”。
结论:结构化输出引领AI应用新方向
结构化输出 将自然语言转换为清晰的 JSON 数据,为 AI 应用带来了革命性的变化。无论你选择 Google Gemini 还是 OpenAI GPT-4o,都可以通过简单的 Python 代码,将自然语言转化为干净的 JSON 数据。它不仅提高了开发效率,还增强了 AI 应用的可靠性和可维护性。随着 LLM 技术的不断发展, 结构化输出 将在 AI 应用中发挥越来越重要的作用。拥抱结构化输出,将使你的AI应用更加强大、更加智能。
未来展望:
随着大模型技术的不断进步,我们可以期待 结构化输出 功能将更加完善,支持更复杂的数据结构和更灵活的配置选项。未来的 LLM 可能会具备更强的理解能力和推理能力,能够更好地理解用户的意图,并生成更准确、更符合要求的结构化数据。同时,各种开源工具和框架也将不断涌现,为 结构化输出 的应用提供更便捷的支持。让我们共同期待 结构化输出 在 AI 领域带来的更多惊喜。