核心模块(Modules)
模型 I/O(ModelIO)
输出解析器(OutputParsers)
快速开始(QuickStart)

快速入门

语言模型输出文本。但很多时候你可能想得到比纯文本更结构化的信息。这就是输出解析器发挥作用的地方。

输出解析器是帮助结构化语言模型响应的类。一个输出解析器必须实现两个主要方法:

  • “获取格式说明”(Get format instructions):一个返回字符串的方法,该字符串包含关于语言模型输出应如何格式化的说明。
  • “解析”(Parse):一个接收字符串(假定是语言模型的响应)并将其解析为某种结构的方法。

然后是可选的一个:

  • “带提示解析”(Parse with prompt):一个接收字符串(假定是语言模型的响应)和提示(假定是生成该响应的提示)并将其解析为某种结构的方法。提供提示主要是因为 OutputParser 可能想以某种方式重试或修正输出,并且需要来自提示的信息来完成这件事。

入门

下面我们介绍输出解析器的主要类型,即 PydanticOutputParser。

from langchain.output_parsers import PydanticOutputParser
from langchain_core.prompts import PromptTemplate
from langchain_core.pydantic_v1 import BaseModel, Field, validator
from langchain_openai import OpenAI
 
model = OpenAI(model_name="gpt-3.5-turbo-instruct", temperature=0.0)
 
 
# 定义你想要的数据结构。
class Joke(BaseModel):
    setup: str = Field(description="question to set up a joke")
    punchline: str = Field(description="answer to resolve the joke")
 
    # 你可以用 Pydantic 轻松添加自定义校验逻辑。
    @validator("setup")
    def question_ends_with_question_mark(cls, field):
        if field[-1] != "?":
            raise ValueError("Badly formed question!")
        return field
 
 
# 设置解析器 + 把说明注入提示模板。
parser = PydanticOutputParser(pydantic_object=Joke)
 
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_and_model = prompt | model
output = prompt_and_model.invoke({"query": "Tell me a joke."})
parser.invoke(output)
Joke(setup='Why did the chicken cross the road?', punchline='To get to the other side!')

LCEL

输出解析器实现了 Runnable 接口,它是 LangChain 表达式语言(LCEL) 的基本构建块。这意味着它们支持 invoke、ainvoke、stream、astream、batch、abatch、astream_log 调用。

输出解析器接受字符串或 BaseMessage 作为输入,并可以返回任意类型。

parser.invoke(output)
Joke(setup='Why did the chicken cross the road?', punchline='To get to the other side!')

除了手动调用解析器,我们也可以直接把它加入我们的 Runnable 序列:

chain = prompt | model | parser
chain.invoke({"query": "Tell me a joke."})
Joke(setup='Why did the chicken cross the road?', punchline='To get to the other side!')

虽然所有解析器都支持流式接口,但只有某些解析器可以流式输出部分解析的对象,因为这高度依赖于输出类型。无法构造部分对象的解析器将只产出完整解析后的输出。

例如 SimpleJsonOutputParser 可以流式输出部分结果:

from langchain.output_parsers.json import SimpleJsonOutputParser
 
json_prompt = PromptTemplate.from_template(
    "Return a JSON object with an `answer` key that answers the following question: {question}"
)
json_parser = SimpleJsonOutputParser()
json_chain = json_prompt | model | json_parser
list(json_chain.stream({"question": "Who invented the microscope?"}))
[{},
 {'answer': ''},
 {'answer': 'Ant'},
 {'answer': 'Anton'},
 {'answer': 'Antonie'},
 {'answer': 'Antonie van'},
 {'answer': 'Antonie van Lee'},
 {'answer': 'Antonie van Leeu'},
 {'answer': 'Antonie van Leeuwen'},
 {'answer': 'Antonie van Leeuwenho'},
 {'answer': 'Antonie van Leeuwenhoek'}]

而 PydanticOutputParser 不能:

list(chain.stream({"query": "Tell me a joke."}))
[Joke(setup='Why did the chicken cross the road?', punchline='To get to the other side!')]