LangChain 中的输出解析器
输出解析器是一种专用于处理和构建语言模型响应的类。
一个基本的输出解析器类通常需要实现两个核心方法。
- get_format_instructions:这个方法需要返回一个字符串,用于指导如何格式化语言模型的输出,告诉它应该如何组织并构建它的回答。
- parse:这个方法接收一个字符串并将其解析为特定的数据结构或格式。这一步通常用于确保模型的输出符合我们的预期,并且能够以我们需要的形式进行后续处理。
LangChain的各种输出解析器
LangChain通过get_format_instructions、parse 和 parse_with_prompt 这些方法实现了针对不同的使用场景和目标的输出解析
- 列表解析器(List Parser):这个解析器用于处理模型生成的输出,当需要模型的输出是一个列表的时候使用。
- 日期时间解析器(Datetime Parser):这个解析器用于处理日期和时间相关的输出,确保模型的输出是正确的日期或时间格式。
- 枚举解析器(Enum Parser):这个解析器用于处理预定义的一组值,当模型的输出应该是这组预定义值之一时使用。
- 结构化输出解析器(Structured Output Parser):这个解析器用于处理复杂的、结构化的输出。
- Pydantic(JSON)解析器:这个解析器用于处理模型的输出,当模型的输出应该是一个符合特定格式的JSON对象时使用。它使用Pydantic库,这是一个数据验证库,可以用于构建复杂的数据模型,并确保模型的输出符合预期的数据模型。
- 自动修复解析器(Auto-Fixing Parser):这个解析器可以自动修复某些常见的模型输出错误。
- 重试解析器(RetryWithErrorOutputParser):这个解析器用于在模型的初次输出不符合预期时,尝试修复或重新生成新的输出。
Pydantic(JSON)解析器实战
第一步:创建模型实例
先通过环境变量设置OpenAI API密钥,然后使用LangChain库创建了一个OpenAI的模型实例。
# ------Part 1
# 设置OpenAI API密钥
import os
os.environ["OPENAI_API_KEY"] = '你的OpenAI API Key'
# 创建模型实例
from langchain import OpenAI
model = OpenAI(model_name='gpt-3.5-turbo-instruct')
第二步:定义输出数据的格式
先创建了一个空的DataFrame,用于存储从模型生成的描述。
# ------Part 2
# 创建一个空的DataFrame用于存储结果
import pandas as pd
df = pd.DataFrame(columns=["flower_type", "price", "description", "reason"])
# 数据准备
flowers = ["玫瑰", "百合", "康乃馨"]
prices = ["50", "30", "20"]
# 定义我们想要接收的数据格式
from pydantic import BaseModel, Field
class FlowerDescription(BaseModel):
flower_type: str = Field(description="鲜花的种类")
price: int = Field(description="鲜花的价格")
description: str = Field(description="鲜花的描述文案")
reason: str = Field(description="为什么要这样写这个文案")
在这里我们用到了负责数据格式验证的Pydantic库来创建带有类型注解的类FlowerDescription,它可以自动验证输入数据。
Pydantic有这样几个特点。
- 数据验证:当你向Pydantic类赋值时,它会自动进行数据验证。
- 数据转换:Pydantic不仅进行数据验证,还可以进行数据转换。
- 易于使用:创建一个Pydantic类就像定义一个普通的Python类一样简单。
- JSON支持:Pydantic类可以很容易地从JSON数据创建,并可以将类的数据转换为JSON格式。
第三步:创建输出解析器
在这一步中,我们创建输出解析器并获取输出格式指示。先使用LangChain库中的PydanticOutputParser创建了输出解析器,该解析器将用于解析模型的输出,以确保其符合FlowerDescription的格式。然后,使用解析器的get_format_instructions方法获取了输出格式的指示。
# ------Part 3
# 创建输出解析器
from langchain.output_parsers import PydanticOutputParser
output_parser = PydanticOutputParser(pydantic_object=FlowerDescription)
# 获取输出格式指示
format_instructions = output_parser.get_format_instructions()
# 打印提示
print("输出格式:",format_instructions)
程序输出如下:
输出格式: The output should be formatted as a JSON instance that conforms to the JSON schema below.
As an example, for the schema {"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]}}
the object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema. The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.
Here is the output schema:
{"properties": {"flower_type": {"title": "Flower Type", "description": "\u9c9c\u82b1\u7684\u79cd\u7c7b", "type": "string"}, "price": {"title": "Price", "description": "\u9c9c\u82b1\u7684\u4ef7\u683c", "type": "integer"}, "description": {"title": "Description", "description": "\u9c9c\u82b1\u7684\u63cf\u8ff0\u6587\u6848", "type": "string"}, "reason": {"title": "Reason", "description": "\u4e3a\u4ec0\u4e48\u8981\u8fd9\u6837\u5199\u8fd9\u4e2a\u6587\u6848", "type": "string"}}, "required": ["flower_type", "price", "description", "reason"]}
第四步:创建提示模板
# ------Part 4
# 创建提示模板
from langchain import PromptTemplate
prompt_template = """您是一位专业的鲜花店文案撰写员。
对于售价为 {price} 元的 {flower} ,您能提供一个吸引人的简短中文描述吗?
{format_instructions}"""
# 根据模板创建提示,同时在提示中加入输出解析器的说明
prompt = PromptTemplate.from_template(prompt_template,
partial_variables={"format_instructions": format_instructions})
# 打印提示
print("提示:", prompt)
输出:
提示:
input_variables=['flower', 'price']
output_parser=None
partial_variables={'format_instructions': 'The output should be formatted as a JSON instance that conforms to the JSON schema below.\n\n
As an example, for the schema {
"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}},
"required": ["foo"]}}\n
the object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema.
The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.\n\n
Here is the output schema:\n```\n
{"properties": {
"flower_type": {"title": "Flower Type", "description": "\u9c9c\u82b1\u7684\u79cd\u7c7b", "type": "string"},
"price": {"title": "Price", "description": "\u9c9c\u82b1\u7684\u4ef7\u683c", "type": "integer"},
"description": {"title": "Description", "description": "\u9c9c\u82b1\u7684\u63cf\u8ff0\u6587\u6848", "type": "string"},
"reason": {"title": "Reason", "description": "\u4e3a\u4ec0\u4e48\u8981\u8fd9\u6837\u5199\u8fd9\u4e2a\u6587\u6848", "type": "string"}},
"required": ["flower_type", "price", "description", "reason"]}\n```'}
template='您是一位专业的鲜花店文案撰写员。
\n对于售价为 {price} 元的 {flower} ,您能提供一个吸引人的简短中文描述吗?\n
{format_instructions}'
template_format='f-string'
validate_template=True
以上就是包含了format_instructions信息的提示模板。
结构化解析器和Pydantic解析器都可以从大模型中获取输出,而结构化解析器更适合简单的文本响应,Pydantic解析器则适用于复杂数据。
自动修复解析器主要适用于纠正小的格式错误。
重试解析器则可以处理更复杂的问题,包括格式错误和内容缺失。