LangChain 中的输出解析

280 阅读6分钟

在LangChain中,通过实现get_format_instructions、parse 和 parse_with_prompt 这些方法,针对不同的使用场景和目标,设计了各种输出解析器。让我们来逐一认识一下。

  1. 列表解析器(List Parser):这个解析器用于处理模型生成的输出,当需要模型的输出是一个列表的时候使用。例如,如果你询问模型“列出所有鲜花的库存”,模型的回答应该是一个列表。
  2. 日期时间解析器(Datetime Parser):这个解析器用于处理日期和时间相关的输出,确保模型的输出是正确的日期或时间格式。
  3. 枚举解析器(Enum Parser):这个解析器用于处理预定义的一组值,当模型的输出应该是这组预定义值之一时使用。例如,如果你定义了一个问题的答案只能是“是”或“否”,那么枚举解析器可以确保模型的回答是这两个选项之一。
  4. 结构化输出解析器(Structured Output Parser):这个解析器用于处理复杂的、结构化的输出。如果你的应用需要模型生成具有特定结构的复杂回答(例如一份报告、一篇文章等),那么可以使用结构化输出解析器来实现。
  5. Pydantic(JSON)解析器:这个解析器用于处理模型的输出,当模型的输出应该是一个符合特定格式的JSON对象时使用。它使用Pydantic库,这是一个数据验证库,可以用于构建复杂的数据模型,并确保模型的输出符合预期的数据模型。
  6. 自动修复解析器(Auto-Fixing Parser):这个解析器可以自动修复某些常见的模型输出错误。例如,如果模型的输出应该是一段文本,但是模型返回了一段包含语法或拼写错误的文本,自动修复解析器可以自动纠正这些错误。
  7. 重试解析器(RetryWithErrorOutputParser):这个解析器用于在模型的初次输出不符合预期时,尝试修复或重新生成新的输出。例如,如果模型的输出应该是一个日期,但是模型返回了一个字符串,那么重试解析器可以重新提示模型生成正确的日期格式。

上面的各种解析器中,前三种很容易理解,而结构化输出解析器你已经用过了。所以接下来我们重点讲一讲Pydantic(JSON)解析器、自动修复解析器和重试解析器。

Pydantic(JSON)解析器

第一步:创建模型实例

先通过环境变量设置OpenAI API密钥,然后使用LangChain库创建了一个OpenAI的模型实例。这里我们仍然选择了text-davinci-003作为大语言模型。

# ------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,用于存储从模型生成的描述。接下来,通过一个名为FlowerDescription的Pydantic BaseModel类,定义了期望的数据格式(也就是数据的结构)。

# ------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,它可以自动验证输入数据,确保输入数据符合你指定的类型和其他验证条件。

第三步:创建输出解析器

在这一步中,我们创建输出解析器并获取输出格式指示。先使用LangChain库中的PydanticOutputParser创建了输出解析器,该解析器将用于解析模型的输出,以确保其符合FlowerDescription的格式。

# ------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"]}

上面这个输出,这部分是通过output_parser.get_format_instructions()方法生成的,这是Pydantic (JSON) 解析器的核心价值,值得你好好研究研究。同时它也算得上是一个很清晰的提示模板,能够为模型提供良好的指导,描述了模型输出应该符合的格式。(其中description中的中文被转成了UTF-8编码。)

第四步:创建提示模板

我们定义了一个提示模板,该模板将用于为模型生成输入提示。模板中包含了你需要模型填充的变量(如价格和花的种类),以及之前获取的输出格式指示。

第五步:生成提示,传入模型并解析输出

这一步中,你使用你的模型和输入提示(由鲜花种类和价格组成)生成了一个具体鲜花的文案需求(同时带有格式描述),然后传递给大模型,也就是说,提示模板中的 flower 和 price,此时都被具体的花取代了,而且模板中的 {format_instructions},也被替换成了 JSON Schema 中指明的格式信息。