打造定制输出解析器:简单步骤实现复杂任务

72 阅读2分钟

引言

在处理自然语言生成(NLG)模型的输出时,有时我们需要将其结构化为自定义格式。这篇文章将教你如何创建自定义输出解析器,通过简单的步骤实现复杂任务。我们将探讨两种主要方法,并讨论它们各自的优点和挑战。

主要内容

使用 Runnable Lambda 和 Generator

最推荐的解析方式是利用 Runnable LambdaRunnable 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:
    """解析AI消息,反转大小写"""
    return ai_message.content.swapcase()

# 将模型与解析器链式连接
chain = model | parse
chain.invoke("hello")  # 输出 'hELLO!'

注意: 使用 | 语法时,LCEL 会自动将函数升级为 RunnableLambda

流式解析器

对于需要流式处理的任务,我们可以实现一个接收输入可迭代对象并流式返回结果的解析器。

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

# 流式打印输出
for chunk in chain.stream("tell me about yourself in one sentence"):
    print(chunk, end="|", flush=True)
# 输出: i|'M| cLAUDE|,| AN| ai| ASSISTANT| CREATED| BY| aN|THROP|IC| TO| BE| HELPFUL|,| HARMLESS|,| AND| HONEST|.

继承基础解析类

虽然我们不推荐此方法,因为它较为复杂,但在某些情况下可能需要自定义复杂行为。

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

class BooleanOutputParser(BaseOutputParser[bool]):
    """自定义布尔解析器。"""
    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()

常见问题和解决方案

  • 流式解析无法正常工作:确保解析器接受可迭代对象并在可能时返回结果。
  • 解析失败时引发异常:可以使用 OutputParserException 来一致地处理解析错误。

总结和进一步学习资源

本文介绍了如何创建自定义输出解析器的两种方法,帮助开发者根据需要选择合适的方案。想了解更多信息和详细文档,可以查看以下资源:

参考资料

  • LangChain Core Documentation
  • LangChain Anthropic Integration Guide

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

---END---