Analisador de Saída

O modelo de linguagem LLM produz conteúdo no formato de texto, porém, ao desenvolver aplicações de IA, desejamos receber conteúdo formatado, como a conversão dos resultados em objetos alvo, arrays, etc., para facilitar o processamento do programa. Isso requer o analisador de saída fornecido pela LangChain para formatar o conteúdo retornado pelo modelo.

A função do analisador de saída é formatar os resultados retornados pelo modelo de linguagem. Um analisador de saída deve implementar dois métodos necessários:

  • "get_format_instructions": Retorna uma string contendo instruções sobre o formato que o modelo de linguagem deve retornar.
  • "parse": Analisa o conteúdo retornado pelo modelo no formato alvo.

Agora vamos dar uma olhada nos analisadores de saída integrados na LangChain.

Analizador Pydantic

Abaixo está o analisador de saída principal PydanticOutputParser encapsulado pela LangChain. Este analisador é baseado na biblioteca pydantic do Python e é usado para converter o resultado de saída do modelo em objetos Python.

from langchain.output_parsers import PydanticOutputParser
from langchain.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="pergunta para configurar a piada")
    punchline: str = Field(description="resposta para resolver a piada")

    @validator("setup")
    def question_ends_with_question_mark(cls, field):
        if field[-1] != "?":
            raise ValueError("Pergunta mal formulada!")
        return field

parser = PydanticOutputParser(pydantic_object=Joke)

prompt = PromptTemplate(
    template="Responder à consulta do usuário.\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": "Me conte uma piada."})
parser.invoke(output)

Exemplo de resultado retornado:

Joke(setup='Por que o frango atravessou a rua?', punchline='Para chegar ao outro lado!')

Interface LCEL

Interface Executável

O analisador de saída implementa a interface Executável, que é um dos blocos de construção básicos da Linguagem de Expressão LangChain (LCEL). Ele suporta métodos de invocação como invoke, ainvoke, stream, astream, batch, abatch, astream_log, etc.

Aplicação dos Analisadores de Saída no LCEL

O analisador de saída pode aceitar uma string ou BaseMessage como entrada e retornar dados estruturados de qualquer tipo. Podemos construir e invocar uma cadeia de analisadores adicionando o analisador a uma sequência Executável.

chain = prompt | model | parser
chain.invoke({"query": "Me conte uma piada."})

Retorna

Joke(setup='Por que o frango atravessou a rua?', punchline='Para chegar ao outro lado!')

Alguns analisadores podem transmitir objetos de análise parciais, como SimpleJsonOutputParser, enquanto outros não suportam streaming. A saída final depende se o analisador pode construir objetos de análise parciais.

from langchain.output_parsers.json import SimpleJsonOutputParser

json_prompt = PromptTemplate.from_template(
    "Retorne um objeto JSON com uma chave `resposta` que responda à seguinte pergunta: {question}"
)
json_parser = SimpleJsonOutputParser()
json_chain = json_prompt | model | json_parser
list(json_chain.stream({"question": "Quem inventou o microscópio?"}))
[{},
 {'answer': ''},
 {'answer': 'Formiga'},
 {'answer': 'Anton'},
 {'answer': 'Antônio'},
 {'answer': 'Antonie van'},
 {'answer': 'Antonie van Lee'},
 {'answer': 'Antonie van Leeu'},
 {'answer': 'Antonie van Leeuwen'},
 {'answer': 'Antonie van Leeuwenho'},
 {'answer': 'Antonie van Leeuwenhoek'}]

No LCEL, podemos construir fluxos complexos de processamento de dados combinando diferentes analisadores para atender a vários requisitos.