Parser di Output

Il modello di lingua LLM restituisce contenuto in formato testuale, ma durante lo sviluppo di applicazioni di intelligenza artificiale vogliamo ricevere contenuti formattati, come ad esempio convertire i risultati in oggetti di destinazione, array, ecc., per facilitare l'elaborazione del programma. Questo richiede l'utilizzo del parser di output fornito da LangChain per formattare il contenuto restituito dal modello.

La funzione del parser di output è quella di formattare i risultati restituiti dal modello di lingua. Un parser di output deve implementare due metodi necessari:

  • "get_format_instructions": Restituisce una stringa contenente istruzioni su quale formato il modello di lingua dovrebbe restituire.
  • "parse": Analizza il contenuto restituito dal modello nel formato di destinazione.

Ora diamo un'occhiata ai parser di output integrati in LangChain.

Parser Pydantic

Di seguito è riportato il parser di output principale PydanticOutputParser incapsulato da LangChain. Questo parser si basa sulla libreria Python pydantic ed è utilizzato per convertire il risultato di output del modello in oggetti 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="domanda per inserire uno scherzo")
    punchline: str = Field(description="risposta per risolvere lo scherzo")

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

parser = PydanticOutputParser(pydantic_object=Joke)

prompt = PromptTemplate(
    template="Rispondi alla richiesta dell'utente.\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": "Raccontami una barzelletta."})
parser.invoke(output)

Esempio di risultato restituito:

Joke(setup='Perché la gallina ha attraversato la strada?', punchline='Per arrivare dall\'altro lato!')

Interfaccia LCEL

Interfaccia eseguibile

Il parser di output implementa l'interfaccia Runnable, che è uno dei blocchi di costruzione di base del Linguaggio di Espressione LangChain (LCEL). Supporta metodi di invocazione come invoke, ainvoke, stream, astream, batch, abatch, astream_log, ecc.

Applicazione dei Parser di Output in LCEL

Il parser di output può accettare una stringa o un BaseMessage come input e restituire dati strutturati di qualsiasi tipo. Possiamo costruire e invocare una catena di parser aggiungendo il parser a una sequenza eseguibile.

chain = prompt | model | parser
chain.invoke({"query": "Raccontami una barzelletta."})

Risultato

Joke(setup='Perché la gallina ha attraversato la strada?', punchline='Per arrivare dall'altro lato!')

Alcuni parser possono analizzare parzialmente oggetti di analisi, come SimpleJsonOutputParser, mentre altri non supportano lo streaming. Il risultato finale dipende dalla capacità del parser di costruire oggetti di analisi parziali.

from langchain.output_parsers.json import SimpleJsonOutputParser

json_prompt = PromptTemplate.from_template(
    "Restituisci un oggetto JSON con una chiave `risposta` che risponde alla seguente domanda: {question}"
)
json_parser = SimpleJsonOutputParser()
json_chain = json_prompt | model | json_parser
list(json_chain.stream({"question": "Chi ha inventato il microscopio?"}))
[{},
 {'answer': ''},
 {'answer': 'Formica'},
 {'answer': 'Anton'},
 {'answer': 'Antonio'},
 {'answer': 'Antonio van'},
 {'answer': 'Antonio van Lee'},
 {'answer': 'Antonio van Leeu'},
 {'answer': 'Antonio van Leeuwen'},
 {'answer': 'Antonio van Leeuwenho'},
 {'answer': 'Antonio van Leeuwenhoek'}]

In LCEL, possiamo costruire flussi di elaborazione dei dati complessi combinando diversi parser per soddisfare varie esigenze.