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)])