前言

在LangChain 0.2中,提示词模板的输出解析器(Output Parser)是用于将生成模型(如GPT-3、GPT-4)输出的文本转换为结构化数据的组件。它们在构建更复杂和精确的自然语言处理应用时非常有用。

一、什么是输出解析器

输出解析器是一个类或函数,用于处理生成模型的输出。它接受生成的文本并将其转换为所需的结构化格式,例如JSON、字典、列表或特定的对象。这使得生成的文本可以更方便地进行后续处理和分析。

二、为什么需要输出解析器
  1. 结构化数据:生成模型的输出通常是非结构化的文本。输出解析器可以将这些文本转换为结构化的数据格式,使其更易于处理和分析。
  2. 自动化处理:通过将生成的文本解析为结构化数据,可以更容易地进行自动化处理,例如存储、搜索和计算。
  3. 减少错误:通过预定义的解析规则,可以减少人工解析文本时可能出现的错误。
  4. 增强可读性:结构化的数据通常比纯文本更易于理解和使用。
三、代码示例

以下是一些具体的输出解析器及其代码示例:

1. CommaSeparatedListOutputParser

这个解析器将逗号分隔的文本转换为列表。

from langchain.output_parsers import CommaSeparatedListOutputParser  
  
# 创建解析器实例  
parser = CommaSeparatedListOutputParser()  
  
# 解析文本  
text = "apple, banana, cherry"  
parsed_output = parser.parse(text)  
  
print(parsed_output)  
# 输出: ['apple', 'banana', 'cherry']
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
2. DatetimeOutputParser

这个解析器将文本解析为日期时间对象。

from langchain.output_parsers import DatetimeOutputParser  
from datetime import datetime  
  
# 创建解析器实例  
class CustomDatetimeOutputParser(DatetimeOutputParser):  
    def parse(self, text: str) -> datetime:  
        try:  
            # 自定义日期时间格式  
            return datetime.strptime(text, "%Y-%m-%d %H:%M:%S")  
        except ValueError as e:  
            raise OutputParserException(f"Could not parse datetime string: {text}") from e  
  
# 使用自定义解析器  
parser = CustomDatetimeOutputParser()  
  
# 解析文本  
text = "2024-08-04 03:35:29"  
parsed_output = parser.parse(text)  
  
print(parsed_output)  
# 输出: 2024-08-04 03:35:29
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
3. EnumOutputParser

这个解析器将文本解析为枚举类型。

from enum import Enum  
  
# 定义枚举类  
class Fruit(Enum):  
    APPLE = "apple"  
    BANANA = "banana"  
    CHERRY = "cherry"  
  
# 自定义 EnumOutputParser  
class CustomEnumOutputParser:  
    def __init__(self, enum_cls):  
        self.enum_cls = enum_cls  
  
    def parse(self, text: str):  
        try:  
            return self.enum_cls(text)  
        except ValueError:  
            raise ValueError(f"Could not parse enum string: {text}")  
  
# 创建解析器实例  
parser = CustomEnumOutputParser(Fruit)  
  
# 解析文本  
text = "apple"  
parsed_output = parser.parse(text)  
  
print(parsed_output)  
# 输出: Fruit.APPLE
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
4. XMLOutputParser

这个解析器将XML格式的文本解析为字典。

from langchain.output_parsers import XMLOutputParser  
  
# 创建解析器实例  
parser = XMLOutputParser()  
  
# 解析文本  
text = "<fruit><name>apple</name><color>red</color></fruit>"  
parsed_output = parser.parse(text)  
  
print(parsed_output)  
# 输出: {'fruit': {'name': 'apple', 'color': 'red'}}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
5. StructuredOutputParser

这个解析器将结构化的文本解析为字典。

from pydantic import BaseModel  
from langchain.output_parsers import StructuredOutputParser  
from typing import List  
  
# 定义你的数据模型  
class FruitModel(BaseModel):  
    name: str  
    color: str  
  
# 创建 response_schemas 列表  
response_schemas = [  
    {  
        "name": "name",  
        "type": "string",  
        "description": "The name of the fruit"  
    },  
    {  
        "name": "color",  
        "type": "string",  
        "description": "The color of the fruit"  
    }  
]  
  
# 初始化 StructuredOutputParser  
parser = StructuredOutputParser(response_schemas=response_schemas)  
  
# 解析示例文本  
text = '{"name": "apple", "color": "red"}'  
parsed_output = parser.parse(text)  
  
print(parsed_output)  
# 输出: {'name': 'apple', 'color': 'red'}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
6. PydanticOutputParser

这个解析器将文本解析为Pydantic模型对象。

from pydantic import BaseModel  
from langchain.output_parsers import PydanticOutputParser  
  
# 定义 Pydantic 模型  
class FruitModel(BaseModel):  
    name: str  
    color: str  
  
# 初始化 PydanticOutputParser  
parser = PydanticOutputParser(pydantic_object=FruitModel)  
  
# 解析示例文本  
text = '{"name": "apple", "color": "red"}'  
parsed_output = parser.parse(text)  
  
print(parsed_output)  
# 输出: name='apple' color='red'
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
7. OutputFixingParser

这个解析器用于修复生成的输出,使其符合预期格式。

from pydantic import BaseModel  
from langchain.output_parsers import PydanticOutputParser, OutputFixingParser  
  
# 定义 Pydantic 模型  
class FruitModel(BaseModel):  
    name: str  
    color: str  
  
# 初始化 PydanticOutputParser  
pydantic_parser = PydanticOutputParser(pydantic_object=FruitModel)  
  
# 定义一个简单的修复函数  
def fix_output(output: dict) -> dict:  
    # 这里可以添加修复逻辑,例如填充缺失字段或修正数据格式  
    return output  
  
# 初始化 OutputFixingParser  
output_fixing_parser = OutputFixingParser(parser=pydantic_parser, fix_output=fix_output)  
  
# 解析示例文本  
text = '{"name": "apple", "color": "red"}'  
parsed_output = output_fixing_parser.parse(text)  
  
print(parsed_output)  
# 输出: name='apple' color='red'
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
8. RetryWithErrorOutputParser

这个解析器在出现错误时重试解析。

from langchain.output_parsers import RetryWithErrorOutputParser  
  
# 定义解析器和重试逻辑  
class SimpleParser:  
    def parse(self, text):  
        if text == "error":  
            raise ValueError("Parsing error")  
        return text  
  
# 创建解析器实例  
parser = RetryWithErrorOutputParser(SimpleParser(), max_retries=3)  
  
# 解析文本  
text = "error"  
try:  
    parsed_output = parser.parse(text)  
except ValueError as e:  
    print(e)  
  
# 输出: Parsing error
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

这些预定义的解析器类提供了多种常见的解析需求,用户可以根据具体情况选择合适的解析器。如果这些预定义的解析器不能满足需求,用户还可以继承BaseOutputParser类,定义自己的解析逻辑。

最后

感谢你们的阅读和喜欢,我收藏了很多技术干货,可以共享给喜欢我文章的朋友们,如果你肯花时间沉下心去学习,它们一定能帮到你。

因为这个行业不同于其他行业,知识体系实在是过于庞大,知识更新也非常快。作为一个普通人,无法全部学完,所以我们在提升技术的时候,首先需要明确一个目标,然后制定好完整的计划,同时找到好的学习方法,这样才能更快的提升自己。