Verwenden von Referenzbeispielen
Die Qualität der Extraktionen kann oft verbessert werden, indem Referenzbeispiele für das LLM bereitgestellt werden.
Tipp: Während sich dieses Tutorial darauf konzentriert, wie man Beispiele mit einem Model-aufrufenden Tool verwendet, ist diese Technik im Allgemeinen anwendbar und funktioniert auch mit JSON-basierten oder promptbasierten Techniken.
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"Du bist ein Experte für Extraktionsalgorithmus. "
"Extrahiere nur relevante Informationen aus dem Text. "
"Wenn du den Wert eines Attributs, das extrahiert werden soll, nicht kennst, gib für den Wert des Attributs null zurück.",
),
MessagesPlaceholder("examples"), # <-- BEISPIELE!
("human", "{text}"),
]
)
Teste die Vorlage:
from langchain_core.messages import (
HumanMessage,
)
prompt.invoke(
{"text": "Das ist ein Text", "examples": [HumanMessage(content="Test 1 2 3")]}
)
ChatPromptValue(messages=[SystemMessage(content="Du bist ein Experte für Extraktionsalgorithmus. Extrahiere nur relevante Informationen aus dem Text. Wenn du den Wert eines Attributs, das extrahiert werden soll, nicht kennst, gib für den Wert des Attributs null zurück."), HumanMessage(content='Test 1 2 3'), HumanMessage(content='Das ist ein Text')])
Schema definieren
Lassen Sie uns das Personenschema aus dem Schnellstart wiederverwenden.
from typing import List, Optional
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_openai import ChatOpenAI
class Person(BaseModel):
"""Informationen über eine Person."""
name: Optional[str] = Field(..., description="Der Name der Person")
hair_color: Optional[str] = Field(
..., description="Die Haarfarbe der Person, falls bekannt"
)
height_in_meters: Optional[str] = Field(..., description="Höhe in Metern")
class Data(BaseModel):
"""Extrahierte Daten über Personen."""
people: List[Person]
Definition von Referenzbeispielen
Beispiele können als Liste von Eingabe-Ausgabe-Paaren definiert werden.
Jedes Beispiel enthält einen Beispiel-"input"-Text und eine Beispiel-"output"-Anzeige, die zeigt, was aus dem Text extrahiert werden soll.
Info
Das ist etwas spezifisch, also ignoriere es gerne, wenn du das nicht verstehst!
Das Format des Beispiels muss zum verwendeten API-Format passen (z. B. Tool-Aufruf oder JSON-Modus usw.).
Hier werden die formatierten Beispiele dem erwarteten Format für den Aufruf der Tool-API entsprechen, da dies das ist, was wir verwenden.
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 Beispiel(TypedDict):
"""Eine Darstellung eines Beispiels, bestehend aus Texteingabe und erwarteten Tool-Aufrufen.
Für die Extraktion werden die Tool-Aufrufe als Instanzen des pydantischen Modells dargestellt.
"""
input: str # Dies ist der Beispieltext
tool_calls: List[BaseModel] # Instanzen des pydantischen Modells, die extrahiert werden sollen
def tool_beispiel_zu_nachrichten(beispiel: Beispiel) -> List[BaseMessage]:
"""Wandle ein Beispiel in eine Liste von Nachrichten um, die einem LLM zugeführt werden können.
Dieser Code ist ein Adapter, der unser Beispiel in eine Liste von Nachrichten umwandelt,
die einem Chat-Modell zugeführt werden können.
Die Liste von Nachrichten pro Beispiel entspricht:
1) HumanMessage: enthält den Inhalt, aus dem der Inhalt extrahiert werden soll.
2) AIMessage: enthält die extrahierten Informationen aus dem Modell
3) ToolMessage: enthält eine Bestätigung an das Modell, dass das Modell einen Tool-Aufruf korrekt angefordert hat.
Die ToolMessage ist erforderlich, da einige der Chat-Modelle hyperoptimiert für Agenten sind
und nicht für einen Extraktions-Anwendungsfall.
"""
nachrichten: List[BaseMessage] = [HumanMessage(content=beispiel["input"])]
openai_tool_calls = []
for tool_call in beispiel["tool_calls"]:
openai_tool_calls.append(
{
"id": str(uuid.uuid4()),
"type": "function",
"function": {
"name": tool_call.__class__.__name__,
"arguments": tool_call.json(),
},
}
)
nachrichten.append(
AIMessage(content="", additional_kwargs={"tool_calls": openai_tool_calls})
)
tool_outputs = beispiel.get("tool_outputs") or [
"Du hast dieses Tool korrekt aufgerufen."
] * len(openai_tool_calls)
for output, tool_call in zip(tool_outputs, openai_tool_calls):
nachrichten.append(ToolMessage(content=output, tool_call_id=tool_call["id"]))
return nachrichten
Als Nächstes definieren wir unsere Beispiele und wandeln sie dann in das Nachrichtenformat um.
beispiele = [
(
"Der Ozean ist weit und blau. Er ist mehr als 20.000 Fuß tief. Es gibt viele Fische darin.",
Person(name=None, height_in_meters=None, hair_color=None),
),
(
"Fiona reiste weit von Frankreich nach Spanien.",
Person(name="Fiona", height_in_meters=None, hair_color=None),
),
]
nachrichten = []
for text, tool_call in beispiele:
nachrichten.extend(
tool_beispiel_zu_nachrichten({"input": text, "tool_calls": [tool_call]})
)
Lassen Sie uns den Prompt testen
prompt.invoke({"text": "das ist etwas Text", "beispiele": nachrichten})
ChatPromptValue(messages=[SystemMessage(content="Du bist ein Experte für Extraktionsalgorithmen. Extrahiere nur relevante Informationen aus dem Text. Wenn du den Wert eines gefragten Attributes nicht kennst, gib für den Attributwert null zurück."), HumanMessage(content="Der Ozean ist weit und blau. Er ist mehr als 20.000 Fuß tief. Es gibt viele Fische darin."), 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='Du hast dieses Tool korrekt aufgerufen.', tool_call_id='c75e57cc-8212-4959-81e9-9477b0b79126'), HumanMessage(content='Fiona reiste weit weg von Frankreich nach Spanien.'), 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='Du hast dieses Tool korrekt aufgerufen.', tool_call_id='69da50b5-e427-44be-b396-1e56d821c6b0'), HumanMessage(content='Das ist ein bisschen Text')])
Erstelle einen Extraktor
Hier werden wir einen Extraktor mit gpt-4 erstellen.
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: Die Funktion `with_structured_output` befindet sich im Beta-Stadium. Sie wird aktiv weiterentwickelt, daher kann sich die API ändern.
warn_beta(
Ohne Beispiele
Beachte, dass selbst bei Verwendung von gpt-4 die Ausführung bei einem sehr einfachen Testfall scheitert!
for _ in range(5):
text = "Das Sonnensystem ist groß, aber die Erde hat nur 1 Mond."
print(runnable.invoke({"text": text, "examples": []}))
people=[]
people=[Person(name='earth', hair_color=None, height_in_meters=None)]
people=[Person(name='earth', hair_color=None, height_in_meters=None)]
people=[]
people=[]
Mit Beispielen
Referenzbeispiele helfen, das Problem zu beheben!
for _ in range(5):
text = "Das Sonnensystem ist groß, aber die Erde hat nur 1 Mond."
print(runnable.invoke({"text": text, "examples": messages}))
people=[]
people=[]
people=[]
people=[]
people=[]
runnable.invoke(
{
"text": "Ich heiße Harrison. Mein Haar ist schwarz.",
"examples": messages,
}
)
Data(people=[Person(name='Harrison', hair_color='schwarz', height_in_meters=None)])