我们之前说了如何对LangChain中的大模型进行输入提示

也说了如何使用自己的大模型进行调用

接下来我们需要讲解针对模型的输出,进行格式化的工具-输出解释器

输出解析器是专门格式化响应的类,其中包含两个核心方法

  1. get_format_instructions: 返回一个字符串,需要传递给大模型,用于提示大模型如何生成回答
  2. parse,根据字符串解析为特定的格式

当然还可以有可选方法,parse_with_prompt 根据一个字符串和一个提示解析为特定格式,可以由上下文知道该如何解析。

而在LangChain中,其官方提供的输出解析器,主要有

列表解析器,解析为一个列表的时候使用

日期时间解析器,解析为一个正确的时间或者日期

枚举解析器,用于解析为一组预先定义的值,比如一个问题的答案只能是是或者否,就可以利用枚举解析器

结构化输出解析器,用于处理复杂的,结构化的输出。

Pydantic解析器,JSON解析器,用于输出一个特定格式的Python对象

自动修复解析器,可以自动修复一些特定的模型输出错误

重试解析器,类似上面的自动修复解析器,只不过更加灵活。

前面的还好,尤其是结构化输出解析器,我们还用过。我们重点讲解下后三种解析器

Pydantic 解析器,自动修复解析器,重试解析器

对于Pydantic解析器

其有独特的特典,比如数据校验,在向Pydantic的代表的对象赋值的时候,会自动进行数据验证和数据转换,以及支持将类转换为JSON

这里首先声明一个Python的类,其要求继承pydantic的BaseModel,并且利用Field包裹字段。

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=”为什么要这样写这个文案”)

然后就是根据这个类创建一个输出解析器

from langchain.output_parsers import PydanticOutputParser

output_parser = PydanticOutputParser(pydantic_object=FlowerDescription)

并从其中获取到输出格式指示

format_instructions = output_parser.get_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”: “u9c9cu82b1u7684u79cdu7c7b”, “type”: “string”}, “price”: {“title”: “Price”, “description”: “u9c9cu82b1u7684u4ef7u683c”, “type”: “integer”}, “description”: {“title”: “Description”, “description”: “u9c9cu82b1u7684u63cfu8ff0u6587u6848”, “type”: “string”}, “reason”: {“title”: “Reason”, “description”: “u4e3au4ec0u4e48u8981u8fd9u6837u5199u8fd9u4e2au6587u6848”, “type”: “string”}}, “required”: [“flower_type”, “price”, “description”, “reason”]}

之后就是利用这个提示去创建模板,并让大模型输出我们想要的格式

prompt_template = “””您是一位专业的鲜花店文案撰写员。

对于售价为 {price} 元的 {flower} ,您能提供一个吸引人的简短中文描述吗?

{format_instructions}”””

# 根据模板创建提示,同时在提示中加入输出解析器的说明

prompt = PromptTemplate.from_template(prompt_template,

partial_variables={“format_instructions”: format_instructions})

input = prompt.format(flower=”玫瑰”, price=50)

output = model(input)

parsed_output = output_parser.parse(output)

parsed_output_dict = parsed_output.dict()

我们利用一个parser来进行了解析,解析为了FlowerDescription的实例。

{‘flower_type’: ‘Rose’, ‘price’: 50, ‘description’: ‘玫瑰是最浪漫的花,它具有柔和的粉红色,有着浓浓的爱意,价格实惠,50元就可以拥有一束玫瑰。’, ‘reason’: ‘玫瑰代表着爱情,是最浪漫的礼物,以实惠的价格,可以让您尽情体验爱的浪漫。’}’

这就是Pydantic解析器的使用。

之后是自动修复解析器的实战

其自动解析器,主要是根据常见的错误信息,自动修复一下,从而获取到正确的答案。

关于使用,我们可以拿一个手动触发的问题来查看。

class Flower(BaseModel):

name: str = Field(description=”name of a flower”)

colors: List[str] = Field(description=”the colors of this flower”)

parser = PydanticOutputParser(pydantic_object=Flower)

new_parser = OutputFixingParser.from_llm(parser=parser, llm=ChatOpenAI())

result = new_parser.parse( “{‘name’: ‘康乃馨’, ‘colors’: [‘粉红色’,’白色’,’红色’,’紫色’,’黄色’]}”)

result = new_parser.parse(misformatted)

上面我们给pydantic传递的字符串是单引号包裹的,而其期待的是双引号包裹.

对于这种小问题,自动修复解析器自动就把问题修复好了,也没再去调取大模型的API。

重试解析器 RetryWithErrorOutputParser解析器

简单的格式修复,出错不只是格式,比如输出不完整,这种是无法自身进行修复的。

这时候就需要重试解析器,帮助我们再次触发大模型能力

这里我们看下代码

首先是利用一个Pydantic类来创建一个格式化解析器

class Action(BaseModel):

action: str = Field(description=”action to take”)

action_input: str = Field(description=”input to the action”)

# 使用Pydantic格式Action来初始化一个输出解析器

from langchain.output_parsers import PydanticOutputParser

parser = PydanticOutputParser(pydantic_object=Action)

# 定义一个提示模板,它将用于向模型提问

from langchain.prompts import PromptTemplate

prompt = PromptTemplate(

template=”Answer the user query.\n{format_instructions}\n{query}\n”,

input_variables=[“query”],

partial_variables={“format_instructions”: parser.get_format_instructions()},

)

prompt_value = prompt.format_prompt(query=”What are the colors of Orchid?”)

这时候

我们在创建一个RetryWithErrorOutputParser,尝试获取一个正确的输出答案

retry_parser = RetryWithErrorOutputParser.from_llm(

parser=parser, llm=OpenAI(temperature=0)

)

parse_result = retry_parser.parse_with_prompt(‘{“action”: “search”}’, prompt_value)

这时候会发现得到的parse_result的结果为

‘{“action”: “search”,”action_input”:”colors of Orchid”}’

从而解决了问题

总结一下,我们说了结构化解析器和自动修复解析器,以及重试解析器

结构化解析器更偏向日常输出,而自动修复解析器,重试解析器则更加偏向于对parser的修复

发表评论

邮箱地址不会被公开。 必填项已用*标注