LangChain-Nachrichtentypen
In LangChain werden alle Konversationen durch Message-Objekte geleitet. Das Verständnis des Zwecks der verschiedenen Nachrichtentypen ist die Grundlage für das Schreiben von Agenten.
Vier Kern-Nachrichtentypen
LangChain definiert vier Kern-Nachrichtentypen, die unterschiedlichen Rollen in einer Konversation entsprechen:
| Type | Rolle | Beschreibung | Typischer Inhalt |
|---|---|---|---|
| HumanMessage | Benutzer | Vom Benutzer gesendete Nachricht | "Wie ist das Wetter heute?" |
| AIMessage | KI-Assistent | Antwort des Modells, kann tool_calls enthalten | "Heute ist es sonnig in Hangzhou, 25°C" |
| SystemMessage | System | Systemanweisung, die die Rolle und die Verhaltensregeln der KI definiert | "Du bist ein professioneller Wetterassistent" |
| ToolMessage | Tool | Ergebnis nach der Tool-Ausführung zurückgeben | "Sonnig, 25°C, Luftfeuchtigkeit 60%" |
HumanMessage — Benutzernachricht
HumanMessage stellt eine vom Benutzer an die KI gesendete Nachricht dar. Sie ist der häufigste Nachrichtentyp und der Ausgangspunkt einer Konversation.
Beispiel
from langchain.chat_models import init_chat_model
# Eine Benutzernachricht erstellen
msg = HumanMessage(content="Was ist Python?")
print(f"Typ: {msg.type}") # human
print(f"Inhalt: {msg.content}") # Was ist Python?
print(f"Rolle: {msg.role}") # user
# Nachrichtenliste erstellen (repräsentiert den Verlauf einer mehrstufigen Konversation)
messages = [
HumanMessage(content="Hallo"),
HumanMessage(content="Welche Kurse bietet Example an?"),
HumanMessage(content="Ist der Python-Kurs für Anfänger ohne Vorkenntnisse geeignet?"),
]
model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)
response = model.invoke(messages)
print(f"\n"Modellantwort: {response.content}")
Ausgabe:
Type: human Content: What is Python? Role: user Model reply: Python is a high-level, interpreted programming language known for its clear and readable syntax, widely used across many fields. Its rich ecosystem and beginner-friendly design make it an excellent choice for those starting from zero.
Schnelle Erstellungsmethoden für HumanMessage
Beim Erstellen von Nachrichtenlisten können Sie Tupel oder Dictionaries als Kurzformen verwenden:
Beispiel
# Methode 1: Standardkonstruktion
msg1 = HumanMessage(content="Hello")
# Methode 2: Tupel-Kurzform (role, content)
msg2 = ("user", "Hello")
msg3 = ("human", "Hello")
# Methode 3: Dictionary-Kurzform
msg4 = {"role": "user", "content": "Hello"}
# Alle vier Methoden sind äquivalent und werden intern im Agent in HumanMessage umgewandelt.
print(type(msg1)) # <class 'langchain_core.messages.human.HumanMessage'>
AIMessage — KI-Antwort
AIMessage repräsentiert die Antwort des Modells. Anders als gewöhnlicher Text kann AIMessagetool_calls(Anfragen für Tool-Aufrufe) enthalten.
Beispiel
# Normale KI-Antwort (kein Tool-Aufruf)
ai_msg = AIMessage(content="Example is a programming learning platform")
# KI-Antwort, die einen Tool-Aufruf enthält
ai_with_tools = AIMessage(
content="", # Beim Aufrufen eines Tools ist content normalerweise leer
tool_calls=[
{
"name": "get_weather",
"args": {"city": "Hangzhou"},
"id": "call_abc123",
"type": "tool_call",
}
]
)
print("=== Normale KI-Nachricht ===")
print(f"Inhalt: {ai_msg.content}")
print(f"Tool-Aufrufe: {ai_msg.tool_calls}") # []
print("\n"=== KI-Nachricht mit Tool-Aufruf ===")
print(f"Inhalt: {ai_with_tools.content}")
print(f"Tool-Aufrufe: {ai_with_tools.tool_calls}")
# [{'name': 'get_weather', 'args': {'city': 'Hangzhou'}, ...}]
Zusätzliche Informationen für AIMessage
Beispiel
model = init_chat_model("deepseek:deepseek-v4-flash")
response = model.invoke("Stelle Python vor")
# AIMessage enthält umfangreiche Metadaten
print(f"Inhalt: {response.content}")
print(f"Nachrichten-ID: {response.id}")
print(f"Modellname: {response.response_metadata.get('model_name')}")
print(f"Finish-Grund: {response.response_metadata.get('finish_reason')}")
# usage_metadata enthält Token-Nutzungsinformationen
if response.usage_metadata:
print(f"Eingabe-Token: {response.usage_metadata.get('input_tokens')}")
print(f"Ausgabe-Token: {response.usage_metadata.get('output_tokens')}")
print(f"Gesamt-Token: {response.usage_metadata.get('total_tokens')}")
Ausgabe:
Content: Example is a free programming learning platform for beginners... Message ID: msg_abc123def456 Model name: deepseek-v4-flash Finish reason: stop Input tokens: 19 Output tokens: 47 Total tokens: 66
SystemMessage — Systemanweisung
SystemMessage wird verwendet, um das Verhalten, die Rolle und die Einschränkungen der KI festzulegen. Sie wird am Anfang der Nachrichtenliste platziert und steuert, wie das Modell antwortet.
Beispiel
from langchain.chat_models import init_chat_model
model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0.7)
# Antwort ohne Systemanweisung
messages_no_system = [HumanMessage(content="Stelle Python vor")]
response = model.invoke(messages_no_system)
print(f"Keine Systemanweisung: {response.content[:80]}...")
# Antwort mit einer Systemanweisung
messages_with_system = [
SystemMessage(content="Du bist ein Blogger im Xiaohongshu-Stil; Antworten sollen lebhaft sein, Emojis verwenden und Themen-Tags enthalten."),
HumanMessage(content="Stelle Python vor")
]
response = model.invoke(messages_with_system)
print(f"\n"Mit Systemanweisung: {response.content}")
Ausgabe:
Without system prompt: Example is an online programming learning platform for beginners, offering rich tutorials and examples... With system prompt: Amazing site! Recommending Example to every beginner who wants to learn programming! Comprehensive free tutorials covering everything from HTML to Python! Plenty of examples and quick to get started - a perfect entry point for programming novices! #ProgrammingLearning #FreeTutorials #ZeroBasics #Example
ToolMessage — Tool-Rückgabeergebnis
ToolMessage enthält das Ergebnis, das nach der Tool-Ausführung zurückgegeben wird. Es muss dem entsprechenden tool_call zugeordnet sein.
Beispiel
from langchain.chat_models import init_chat_model
# Simuliere eine vollständige Runde einer Tool-Aufruf-Konversation
messages = [
HumanMessage(content="Wie ist das Wetter in Hangzhou?"),
# Das Modell fordert den Aufruf eines Tools an
AIMessage(
content="",
tool_calls=[
{"name": "get_weather", "args": {"city": "Hangzhou"},
"id": "call_abc", "type": "tool_call"}
]
),
# Tool-Rückgabeergebnis (muss tool_call_id enthalten, die der obigen id entspricht)
ToolMessage(
content="Sonnig, 25°C, Luftfeuchtigkeit 60%",
tool_call_id="call_abc", # Entspricht der id von tool_call
name="get_weather", # Tool-Name
),
]
model = init_chat_model("deepseek:deepseek-v4-flash")
response = model.invoke(messages)
print(f"Modellantwort basierend auf Tool-Ergebnis: {response.content}")
Ausgabe:
Model reply based on tool result: Hangzhou is sunny today, 25 C, humidity 60%, great for outdoor activities.
ToolMessage's tool_call_id muss genau mit der id von tool_call in der AIMessage übereinstimmen. Wenn sie nicht übereinstimmen, kann das Modell das Tool-Ergebnis ignorieren oder verwirrendes Verhalten erzeugen.
AIMessageChunk — Nachrichten-Chunk für Streaming-Ausgabe
Wenn Sie stream() für Streaming-Ausgabe verwenden, ist jeder eintreffende Chunk ein AIMessageChunk und keine vollständige AIMessage:
Beispiel
model = init_chat_model("deepseek:deepseek-v4-flash")
print("Streaming-Ausgabeprozess:")
# stream() gibt einen AIMessageChunk-Iterator zurück
for chunk in model.stream("Stelle Python in einem Satz vor"):
# Jeder Chunk ist ein kleines Stück Text
print(chunk.content, end="", flush=True)
print() # Zeilenumbruch
Ausgabe:
Streaming output: Example is a free online learning platform for programming beginners, offering rich tutorials and examples.
Schnellreferenztabelle für Nachrichtentypen
| Nachrichtentyp | type-Attribut | role-Attribut | Schlüsselfelder | Wann zu verwenden |
|---|---|---|---|---|
| HumanMessage | human | user | content | Benutzereingabe |
| AIMessage | ai | assistant | content, tool_calls, usage_metadata | Modellantwort |
| AIMessageChunk | ai | assistant | content (Delta) | Streaming-Ausgabe-Chunk |
| SystemMessage | system | system | content | KI-Rolle festlegen |
| ToolMessage | tool | tool | content, tool_call_id, name | Tool-Ausführungsergebnis |
ContentBlock — Strukturierter Nachrichteninhalt
Bisher waren die Nachrichteninhalte, die wir verwendet haben, einfache Zeichenketten. In Wirklichkeit kann der Inhalt jeder Nachricht jedoch aus mehrerenContentBlock(Inhaltsblöcken) bestehen, die eine Liste bilden.
Die drei häufigsten Arten von Inhaltsblöcken:
| Type | Beschreibung | Zweck |
|---|---|---|
| PlainTextContentBlock | Reiner Textinhalt | Gewöhnliche Textnachricht |
| ImageContentBlock | Bildinhalt (base64 oder URL) | Bildeingabe für multimodale Modelle |
| ToolCall | Tool-Aufruf-Anfrage | KI-Anfragen zum Aufruf eines Tools |
Beispiel
from langchain.messages import PlainTextContentBlock, ImageContentBlock
# Nachrichten mit Inhaltsblöcken erstellen
# content kann eine einfache Zeichenkette sein (einfaches Szenario)
simple_msg = HumanMessage(content=Hallo)
# content kann auch eine Liste von ContentBlock sein (komplexes Szenario)
complex_msg = HumanMessage(content=[
PlainTextContentBlock(text="Was ist auf diesem Bild?"),
# Das Bild kann eine URL oder base64-Kodierung sein
ImageContentBlock(
url="https://example.com/photo.jpg"
),
])
print(f"Inhaltstyp der einfachen Nachricht: {type(simple_msg.content)}")
# Ausgabe: <class 'str'>
print(f"Inhaltstyp der komplexen Nachricht: {type(complex_msg.content)}")
# Ausgabe: <class 'list'>
print(f"Anzahl der Inhaltsblöcke: {len(complex_msg.content)}")
# Ausgabe: 2
Wenn Sie nur reinen Text senden müssen, können Sie direkt eine Zeichenkette übergeben, und LangChain verarbeitet sie automatisch. Nur wenn Sie Text und Bilder in einer einzigen Nachricht mischen müssen, müssen Sie manuell eine ContentBlock-Liste erstellen.
Multimodale Nachrichten — Das Modell Bilder "sehen" lassen
Wenn Ihr Modell multimodale Eingaben unterstützt (z. B. GPT-4o, Claude 3+), können Sie es Bildinhalte analysieren lassen:
Beispiel
from pathlib import Path
from langchain.messages import HumanMessage
from langchain.chat_models import init_chat_model
# Lokales Bild als Base64 kodieren
def encode_image(image_path: str) -> str:
Bilddatei einlesen und in Base64-Kodierung umwandeln
with open(image_path, "rb") as f:
return base64.b64encode(f.read()).decode("utf-8")
# Ein multimodales Modell erstellen (muss Bildeingabe unterstützen)
model = init_chat_model("deepseek:deepseek-v4-flash")
# Eine Nachricht erstellen, die ein Bild enthält
# Hinweis: content verwendet Listenformat und enthält Textblöcke und Bildblöcke
image_data = encode_image("screenshot.png")
messages = [
HumanMessage(content=[
{"type": "text", "text": Bitte beschreiben Sie den Inhalt dieses Screenshots der offiziellen Python-Website.},
{
"type": "image_url",
"image_url": {
"url": f"data:image/png;base64,{image_data}",
"detail": "auto" # Optional: low, high, auto
}
}
])
]
response = model.invoke(messages)
print(fErgebnis der Bildanalyse: {response.content})
Wenn Ihre Nachricht nur ein Bild und keinen Text enthält, können Sie direkt Folgendes verwenden:
Beispiel
model = init_chat_model("deepseek:deepseek-v4-flash")
# Verwenden Sie eine URL, um direkt auf ein Online-Bild zu verweisen
messages = [
{
"role": "user",
"content": [
{"type": "text", "text": Was zeigt dieses Bild?},
{
"type": "image_url",
"image_url": {"url": "https://www.example.com/wp-content/uploads/2024/01/logo.png"}
}
]
}
]
response = model.invoke(messages)
print(response.content)
Nicht alle Modelle unterstützen multimodale Eingaben. Die GPT-4o-Serie von OpenAI, Claude 3+ von Anthropic und die Gemini-Serie von Google unterstützen sie. Wenn Sie ein Bild mit einem nicht unterstützten Modell senden, erhalten Sie einen Fehler.
ToolCall — Tool-Aufruf-Nachricht
Das Feld tool_calls in AIMessage ist eine Liste von ToolCall-Objekten, wobei jedes ToolCall eine Anfrage des Modells zum Aufrufen eines Tools darstellt:
Beispiel
from langchain.messages.tool import ToolCall
# ToolCall manuell erstellen
tool_call = ToolCall(
name="get_weather", # Tool-Name
args={"city": Hangzhou}, # Aufrufargumente
id="call_abc123", # Eindeutige Kennung
type="tool_call", # Fester Wert
)
# AIMessage mit tool_calls erstellen
ai_message = AIMessage(
content="", # Wenn tool_calls vorhanden ist, ist content normalerweise leer
tool_calls=[tool_call],
)
print(fWerkzeugname: {ai_message.tool_calls)
print(fAufrufparameter: {ai_message.tool_calls)
print(fAufruf-ID: {ai_message.tool_calls)
Prüfen, ob AIMessage Tool-Aufrufe enthält
Beispiel
model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)
# Nach dem Binden von Tools kann das Modell tool_calls zurückgeben
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": Wetter abfragen,
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": Stadtname}
},
"required": ["city"]
}
}
}]
model_with_tools = model.bind_tools(tools)
# Frage, die einen Tool-Aufruf auslöst
response = model_with_tools.invoke(Wie ist das Wetter in Hangzhou?)
# Zwei Möglichkeiten, festzustellen, ob ein Tool-Aufruf vorliegt
# Methode 1: Prüfen, ob die tool_calls-Liste nicht leer ist
if response.tool_calls:
print(Modell fordert einen Tool-Aufruf an)
# Methode 2: Prüfen, ob content leer ist
# (Bei den meisten Modellen ist content leer, wenn tool_calls vorhanden ist)
if not response.content:
print(Der Inhalt des Modells ist leer, was bedeutet, dass es ein Tool aufrufen möchte, anstatt direkt zu antworten.)
trim_messages() — Nachrichtenverlauf kürzen
Wenn die Konversation länger wird, kann die Nachrichtenliste das Kontextfenster des Modells überschreiten.trim_messages()Die Funktion hilft Ihnen, den Nachrichtenverlauf intelligent zu kürzen.
Beispiel
HumanMessage, AIMessage, SystemMessage, trim_messages
)
from langchain.chat_models import init_chat_model
# Simuliere einen langen Konversationsverlauf
messages = [
SystemMessage(content=Du bist der KI-Assistent des EXAMPLE-Tutorials.),
HumanMessage(content=Wie fange ich mit Python an?),
AIMessage(content=Der Einstieg in Python kann mit Grundkenntnissen beginnen...),
HumanMessage(content=Gibt es eine empfohlene IDE?),
AIMessage(content=Ich empfehle VS Code oder PyCharm...),
HumanMessage(content=Wie installiere ich Bibliotheken von Drittanbietern?),
AIMessage(content=Verwende den Befehl pip install...),
HumanMessage(content=Was ist NumPy?),
AIMessage(content=NumPy ist eine Bibliothek für wissenschaftliches Rechnen...),
HumanMessage(content=Was ist der Unterschied zwischen pandas und NumPy?),
]
model = init_chat_model("deepseek:deepseek-v4-flash")
# Nachrichten kürzen, damit sie in das Kontextfenster des Modells passen (höchstens 1000 Tokens)
# strategy="last" behält die letzte Systemnachricht und die aktuellste Konversation bei.
trimmed = trim_messages(
messages,
max_tokens=1000, # Höchstens 1000 Token behalten
strategy="last", # Letzte Systemnachricht + neueste Konversation behalten
token_counter=model, # Token-Zählmethode des Modells verwenden
include_system=True, # SystemMessage immer behalten
start_on="human", # Nach dem Kürzen mit einer Human-Nachricht beginnen
)
print(fVor dem Kürzen: {len(messages)} Nachrichten)
print(fNach dem Kürzen: {len(trimmed)} Nachrichten)
for msg in trimmed:
snippet = msg.content[:50] if isinstance(msg.content, str) else str(msg.content)[:50]
print(f" [{msg.type}] {snippet}...")
Ausführungsergebnis:
Before trimming: 10 messages After trimming: 5 messages [system] You are the AI assistant of Example... [human] How do I install third-party libraries?... [ai] Use the pip install command... [human] What is NumPy?... [ai] NumPy is a scientific computing library...
| Strategie | Beschreibung | Anwendbare Szenarien |
|---|---|---|
| strategy="last" | Systemnachricht + aktuellste Konversation beibehalten | In langen Konversationen ist nur der aktuelle Kontext relevant |
| strategy="first" | Systemnachricht + früheste Konversation beibehalten | Sicherstellen, dass wichtiger Kontext nicht gekürzt wird |
start_on="human" stellt sicher, dass die gekürzte Nachrichtenliste mit einer Benutzernachricht beginnt (statt mit einer KI-Nachricht), wodurch verhindert wird, dass das Modell eine Liste erhält, die mit einer isolierten KI-Antwort beginnt.
RemoveMessage — Löschen bestimmter Nachrichten
In einigen fortgeschrittenen Szenarien müssen Sie möglicherweise bestimmte Nachrichten aus dem Nachrichtenverlauf löschen (z. B. zum Bereinigen sensibler Inhalte, zum Neugenerieren von Antworten usw.):
Beispiel
# Angenommen, es gibt eine Konversation
messages = [
HumanMessage(content=Hallo, id="msg_1"),
AIMessage(content=Hallo! Wie kann ich Ihnen helfen?, id="msg_2"),
HumanMessage(content=Prüfe das Wetter für mich, id="msg_3"),
]
# RemoveMessage verwenden, um eine bestimmte Nachricht (anhand der ID) zu löschen
# RemoveMessage wird zusammen mit dem add_messages-Reducer verwendet
# Beim Aktualisieren des Agent-Status entfernt RemoveMessage die Nachricht mit der entsprechenden ID aus der Liste
removal = RemoveMessage(id="msg_3")
print(fZu löschende Nachrichten-ID: {removal.id})
print(fTyp: {removal.type}) # entfernen
RemoveMessage wird normalerweise zusammen mit dem add_messages-Reducer von AgentState verwendet. Das Zurückgeben von RemoveMessage in Middleware- oder after_model-Hooks kann den Nachrichtenverlauf dynamisch bereinigen.
Gängige Methoden für Nachrichteneigenschaften
Alle Nachrichtentypen erben von BaseMessage und teilen einige gemeinsame Methoden:
Beispiel
msg = HumanMessage(content=Hallo, Beispiel)
# Grundlegende Attribute
print(f"content: {msg.content}") # Nachrichteninhalt
print(f"type: {msg.type}") # Nachrichtentyp (human/ai/system/tool)
print(f"id: {msg.id}") # Automatisch generierte eindeutige ID
# text-Attribut: Wenn es sich um Textinhalt handelt, den Text zurückgeben; andernfalls "" zurückgeben
print(f"text: {msg.text}")
# pretty_repr(): formatierte Ausgabe, geeignet zum Debuggen
print(f"Formatierte Ausgabe:\n{msg.pretty_repr()}")
Ausführungsergebnis:
content: Hello, world type: human id: 00000000-0000-4000-8000-000000000000 text: Hello, world Pretty output: ================================ Human Message ================================= Hello, worldWeitere Erweiterungen