如何自定义输出解析器:实现自己的解析器

112 阅读2分钟

引言

在使用人工智能模型时,常常需要将模型的输出解析为特定的格式。尽管很多情况下内置的解析器已经足够,但在某些情境中,自定义输出解析器能够更好地满足特定需求。这篇文章将介绍如何创建自定义输出解析器,涵盖的内容包括通过可运行Lambda和生成器实现解析,以及继承基础类解析器。我们的目标是帮助开发者更好地理解这些方法,并提供可操作的代码示例。

主要内容

使用Runnable Lambda和Runnable Generator

我们推荐使用Runnable Lambda和Runnable Generator来实现解析。这种方法简单且高效。以下是一个简单的解析器示例,它将模型输出的字母大小写反转。

from typing import Iterable
from langchain_anthropic.chat_models import ChatAnthropic
from langchain_core.messages import AIMessage, AIMessageChunk

# 初始化模型
model = ChatAnthropic(model_name="claude-2.1")

# 定义解析函数
def parse(ai_message: AIMessage) -> str:
    """Parse the AI message."""
    return ai_message.content.swapcase()

# 组合模型和解析器
chain = model | parse
chain.invoke("hello")  # 输出: 'hELLO!'

流式解析

如果需要处理流式数据,解析器可以接受输入的可迭代对象,并在结果可用时即时输出。

from langchain_core.runnables import RunnableGenerator

# 定义流式解析器
def streaming_parse(chunks: Iterable[AIMessageChunk]) -> Iterable[str]:
    for chunk in chunks:
        yield chunk.content.swapcase()

streaming_parse = RunnableGenerator(streaming_parse)

# 组合流式模型和解析器
chain = model | streaming_parse
chain.invoke("hello")  # 输出: 'hELLO!'

继承解析基类

虽然我们不建议这样做,因为它通常需要写更多的代码而没有显著的好处,但可以通过继承BaseOutputParser来创建自定义解析器。

from langchain_core.exceptions import OutputParserException
from langchain_core.output_parsers import BaseOutputParser

# 自定义布尔解析器
class BooleanOutputParser(BaseOutputParser[bool]):
    """Custom boolean parser."""
    true_val: str = "YES"
    false_val: str = "NO"

    def parse(self, text: str) -> bool:
        cleaned_text = text.strip().upper()
        if cleaned_text not in (self.true_val.upper(), self.false_val.upper()):
            raise OutputParserException(
                f"BooleanOutputParser expected output value to either be "
                f"{self.true_val} or {self.false_val} (case-insensitive). "
                f"Received {cleaned_text}."
            )
        return cleaned_text == self.true_val.upper()

parser = BooleanOutputParser()
parser.invoke("YES")  # 输出: True

常见问题和解决方案

  • 流式数据解析不正常工作? 如果解析器聚合输入,则流式解析将不起作用。通过接受输入的迭代对象并即时输出结果来解决。

  • 解析异常未处理? 使用OutputParserException可以在解析失败时抛出一致的异常。

总结和进一步学习资源

通过这篇文章,你学会了如何使用Runnable Lambda和Generator以及继承基类来创建自定义输出解析器。这些方法能够帮助你在不同的使用场景中解析模型输出,希望这些示例能够为你提供启发。

参考资料

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力! ---END---