Esempi di riferimento

Spesso la qualità delle estrazioni può essere migliorata fornendo esempi di riferimento alla LLM.

Suggerimento: Sebbene questo tutorial si concentri su come utilizzare gli esempi con un modello chiamato strumento, questa tecnica è generalmente applicabile e funzionerà anche con tecniche basate su JSON o prompt.

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "Sei un algoritmo di estrazione esperto. "
            "Estrai solo informazioni rilevanti dal testo. "
            "Se non conosci il valore di un attributo richiesto per l'estrazione, restituisci null per il valore dell'attributo.",
        ),
        MessagesPlaceholder("esempi"),  # <-- ESEMPI!
        ("umano", "{testo}"),
    ]
)

Prova il modello:

from langchain_core.messages import (
    MessaggioUmano,
)

prompt.invoke(
    {"testo": "questo è del testo", "esempi": [MessaggioUmano(contenuto="testing 1 2 3")]}
)
ChatPromptValue(messaggi=[MessaggioDiSistema(contenuto="Sei un algoritmo di estrazione esperto. Estrai solo informazioni rilevanti dal testo. Se non conosci il valore di un attributo richiesto per l'estrazione, restituisci null per il valore dell'attributo."), MessaggioUmano(contenuto='testing 1 2 3'), MessaggioUmano(contenuto='questo è del testo')])

Definire lo schema

Utilizziamo nuovamente lo schema della persona dalla guida rapida.

from typing import List, Optional

from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_openai import ChatOpenAI


class Persona(BaseModel):
    """Informazioni su una persona."""


    nome: Optional[str] = Field(..., description="Il nome della persona")
    colore_capelli: Optional[str] = Field(
        ..., description="Il colore degli occhi della persona, se noto"
    )
    altezza_in_metri: Optional[str] = Field(..., description="Altezza in METRI")

class Dati(BaseModel):
    """Dati estratti sulle persone."""

    persone: List[Persona]

Definire esempi di riferimento

Gli esempi possono essere definiti come un elenco di coppie input-output.

Ogni esempio contiene un testo di input e un output che mostra cosa dovrebbe essere estratto dal testo.

info

Questo è un po' dettagliato, quindi sentiti libero di ignorare se non lo capisci!

Il formato dell'esempio deve corrispondere all'API utilizzata (ad es., chiamata dello strumento o modalità JSON, ecc.).

Qui, gli esempi formattati corrisponderanno al formato previsto per l'API di chiamata dello strumento poiché è quello che stiamo usando.

import uuid
from typing import Dict, List, TypedDict

from langchain_core.messages import (
    AIMessage,
    BaseMessage,
    HumanMessage,
    SystemMessage,
    ToolMessage,
)
from langchain_core.pydantic_v1 import BaseModel, Field


class Example(TypedDict):
    """Una rappresentazione di un esempio composto da input di testo e chiamate di strumenti attesi.

    Per l'estrazione, le chiamate degli strumenti sono rappresentate come istanze di un modello pydantic.
    """

    input: str  # Questo è il testo dell'esempio
    tool_calls: List[BaseModel]  # Istanze del modello pydantic che dovrebbero essere estratte


def tool_example_to_messages(example: Example) -> List[BaseMessage]:
    """Convertire un esempio in una lista di messaggi che possono essere inseriti in un LLM.

    Questo codice è un adattatore che converte il nostro esempio in una lista di messaggi
    che possono essere inseriti in un modello di chat.

    La lista di messaggi per esempio corrisponde a:

    1) HumanMessage: contiene il contenuto da cui estrarre il contenuto.
    2) AIMessage: contiene le informazioni estratte dal modello
    3) ToolMessage: contiene conferma al modello che il modello ha richiesto uno strumento correttamente.

    Il ToolMessage è richiesto perché alcuni dei modelli di chat sono iperottimizzati per gli agenti
    piuttosto che per un caso di utilizzo di estrazione.
    """
    messages: List[BaseMessage] = [HumanMessage(content=example["input"])]
    openai_tool_calls = []
    for tool_call in example["tool_calls"]:
        openai_tool_calls.append(
            {
                "id": str(uuid.uuid4()),
                "type": "function",
                "function": {
                    "name": tool_call.__class__.__name__,
                    "arguments": tool_call.json(),
                },
            }
        )
    messages.append(
        AIMessage(content="", additional_kwargs={"tool_calls": openai_tool_calls})
    )
    tool_outputs = example.get("tool_outputs") or [
        "Hai chiamato correttamente questo strumento."
    ] * len(openai_tool_calls)
    for output, tool_call in zip(tool_outputs, openai_tool_calls):
        messages.append(ToolMessage(content=output, tool_call_id=tool_call["id"]))
    return messages

Ora definiamo i nostri esempi e poi li convertiamo nel formato del messaggio.

esempi = [
    (
        "L'oceano è vasto e blu. È più profondo di 20.000 piedi. Ci sono molti pesci al suo interno.",
        Persona(nome=None, altezza_in_metri=None, colore_dei_capelli=None),
    ),
    (
        "Fiona ha viaggiato lontano dalla Francia verso la Spagna.",
        Persona(nome="Fiona", altezza_in_metri=None, colore_dei_capelli=None),
    ),
]


messaggi = []

for testo, chiamata_strumento in esempi:
    messaggi.extend(
        tool_example_to_messages({"input": testo, "tool_calls": [chiamata_strumento]})
    )

Proviamo il prompt

prompt.invoke({"testo": "questo è un po' di testo", "esempi": messaggi})
ChatPromptValue(messages=[SystemMessage(content="Sei un algoritmo di estrazione esperto. Estrai solo informazioni rilevanti dal testo. Se non conosci il valore di un attributo richiesto per l'estrazione, restituisci null per il valore dell'attributo."), HumanMessage(content="L'oceano è vasto e blu. È profondo più di 20.000 piedi. Ci sono molti pesci."), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'c75e57cc-8212-4959-81e9-9477b0b79126', 'type': 'function', 'function': {'name': 'Person', 'arguments': '{"name": null, "hair_color": null, "height_in_meters": null}'}}]}), ToolMessage(content='Hai chiamato correttamente questo strumento.', tool_call_id='c75e57cc-8212-4959-81e9-9477b0b79126'), HumanMessage(content='Fiona ha viaggiato lontano dalla Francia verso la Spagna.'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': '69da50b5-e427-44be-b396-1e56d821c6b0', 'type': 'function', 'function': {'name': 'Person', 'arguments': '{"name": "Fiona", "hair_color": null, "height_in_meters": null}'}}]}), ToolMessage(content='Hai chiamato correttamente questo strumento.', tool_call_id='69da50b5-e427-44be-b396-1e56d821c6b0'), HumanMessage(content='questo è un po\' di testo')])

Creare un estrattore

Qui, creeremo un estrattore utilizzando gpt-4.

llm = ChatOpenAI(
    model="gpt-4-0125-preview",
    temperature=0,
)


runnable = prompt | llm.with_structured_output(
    schema=Data,
    method="function_calling",
    include_raw=False,
)
/Users/harrisonchase/workplace/langchain/libs/core/langchain_core/_api/beta_decorator.py:86: LangChainBetaWarning: La funzione `with_structured_output` è in versione beta. Attualmente è in fase di sviluppo, quindi l'API potrebbe subire modifiche.
  warn_beta(

Senza esempi

Si noti che nonostante stiamo utilizzando gpt-4, sta fallendo con un caso di test molto semplice!

for _ in range(5):
    text = "Il sistema solare è grande, ma la terra ha solo 1 luna."
    print(runnable.invoke({"text": text, "esempi": []}))
persone=[]
persone=[Persona(nome='terra', colore_dei_capelli=None, altezza_in_metri=None)]
persone=[Persona(nome='terra', colore_dei_capelli=None, altezza_in_metri=None)]
persone=[]
persone=[]

Con esempi

Gli esempi di riferimento aiutano a risolvere il fallimento!

for _ in range(5):
    text = "Il sistema solare è grande, ma la terra ha solo 1 luna."
    print(runnable.invoke({"text": text, "esempi": messaggi}))
persone=[]
persone=[]
persone=[]
persone=[]
persone=[]
runnable.invoke(
    {
        "text": "Mi chiamo Harrison. I miei capelli sono neri.",
        "esempi": messaggi,
    }
)
Data(persone=[Persona(nome='Harrison', colore_dei_capelli='neri', altezza_in_metri=None)])