Stop-Sequenzen
Auf dieser Seite
Generierung zum richtigen Zeitpunkt beenden
Standardmäßig stoppt das Modell aus nur zwei Gründen: Es hat entschieden, dass seine Antwort abgeschlossen ist und emittiert sein End-Token, oder es erreicht die Obergrenze max_tokens. Diese beiden Kriterien decken nicht jeden Anwendungsfall ab. Manchmal möchten Sie, dass die Generierung an einem Punkt endet, den nur Sie kennen – kurz vor dem nächsten Abschnitt eines Dokuments, direkt nachdem ein JSON-Block geschlossen wurde, oder sobald das Modell Kommentare hinzufügt, die Sie nicht benötigen.
Stop-Sequenzen fügen dieses dritte Kriterium hinzu: Sobald das Modell eine Textsequenz erzeugt, die Sie festgelegt haben, wird die Generierung sofort gestoppt. Denken Sie daran als präzises Schneidewerkzeug, das natürliche Gegenstück zu den Formatierungsanweisungen in Ihrem System-Prompt, die das Modell zwar gut, aber nicht immer perfekt befolgt.
Funktionsweise des stop-Parameters
Der Parameter akzeptiert eine Liste von Zeichenfolgen. Die erste, die im Ausgabe-Text erscheint, beendet die Generierung:
from mistralai.client import Mistral
import os
client = Mistral(api_key=os.getenv("MISTRAL_API_KEY"))
response = client.chat.complete(
model="mistral-large-latest",
messages=[
{"role": "user", "content": "Listen Sie die 10 größten Städte in Frankreich auf."}
],
stop=["6."] # Stoppt nach den ersten 5
)
print(response.choices[0].message.content)
# 1. Paris
# 2. Marseille
# 3. Lyon
# 4. Toulouse
# 5. Nice
In diesem Beispiel fallen zwei Verhaltensweisen auf. Die Stop-Sequenz wird nicht im Antworttext enthalten: Sie erhalten den Text, der ihr vorausgeht, ohne dass Sie eine Bereinigung vornehmen müssen. Und das finish_reason ist "stop", genau wie bei einem natürlichen Stopp – die API unterscheidet nicht zwischen beiden, sodass es Ihre Aufgabe ist, sich daran zu erinnern, was Sie angefordert haben.
Drei typische Anwendungsfälle
Der erste Fall behandelt das chatty Modell. Sie fragen nach einer Hauptstadt, und das Modell liefert die Hauptstadt plus drei Sätze Erklärung, die Ihr Interface nicht erwartet hat. Der System-Prompt setzt die Absicht; Stop-Sequenzen erzwingen diese:
response = client.chat.complete(
model="mistral-large-latest",
messages=[
{
"role": "system",
"content": "Antworten Sie nur mit dem Stadtnamen, nichts anderes."
},
{
"role": "user",
"content": "Was ist die Hauptstadt Italiens?"
}
],
stop=["\n", ".", "Explanation"] # Stoppt beim ersten Zeilenumbruch oder Punkt
)
print(response.choices[0].message.content.strip())
# Rom
Der zweite Fall deckt die schrittweise Generierung von Dokumenten ab, wenn Sie die Kontrolle zwischen den Teilen behalten möchten, anstatt das Modell zu lassen, einen gesamten Bericht auf einmal zu produzieren. Sie stoppen an den Delimitern, die signalisieren, was als Nächstes kommt:
response = client.chat.complete(
model="mistral-large-latest",
messages=[
{
"role": "system",
"content": "Schreiben Sie den Abschnitt Einführung eines Berichts."
},
{
"role": "user",
"content": "Thema: Die Auswirkungen der KI auf die Beschäftigung in Europa."
}
],
stop=["## ", "---", "Conclusion"] # Stoppt vor dem nächsten Abschnitt
)
Der dritte Fall ist in der Praxis der kosteneffizienteste: Extrahieren Sie nutzbares JSON ohne Bereinigungsschritt. Modelle neigen dazu, ihre Ausgabe in erklärenden Text zu verpacken, was json.loads() unterbricht; das Schneiden an einem doppelten Zeilenumbruch oder drei Backticks eliminiert das Problem an der Quelle.
response = client.chat.complete(
model="mistral-large-latest",
messages=[
{
"role": "system",
"content": "Reagieren Sie nur mit gültigem JSON."
},
{
"role": "user",
"content": "Geben Sie mir Informationen für Paris: Bevölkerung, Land, Zeitzone."
}
],
stop=["\n\n", "```"] # Stoppt nach dem JSON-Block
)
Kombination von Stop-Sequenzen und Streaming
Es gibt nichts, das Sie daran hindert, beide Mechanismen zu kombinieren: Der Stream stoppt, sobald eine der Stop-Sequenzen im generierten Text erkannt wird, und die Pakete, die Sie bereits erhalten haben, bleiben gültig.
stream = client.chat.stream(
model="mistral-large-latest",
messages=[
{"role": "user", "content": "Erzählen Sie eine kurze Geschichte."}
],
stop=["Fin.", "THE END", "---"]
)
full_text = ""
for chunk in stream:
content = chunk.data.choices[0].delta.content
if content:
full_text += content
print(content, end="", flush=True)
print(f"\n\nText: {len(full_text)} Zeichen")
Einschränkungen des Mechanismus
Vier Beschränkungen regeln die Verwendung des stop-Parameters. Sie können pro Anfrage maximal vier Sequenzen angeben, was Sie zwingt, die aussagekräftigsten auszuwählen, anstatt sie einfach aufzuhäufen. Sie sind fallensensitiv: "end" wird niemals "End" erfassen, sodass Sie die Varianten berücksichtigen müssen, die relevant sind. Die Sequenz wird niemals im Antworttext enthalten, was wichtig ist, wenn Ihr erwartetes Format mit diesem Delimiter endet. Schließlich erfolgt die Erkennung Token für Token: Wenn Ihre Sequenz mitten in einem Token liegt, bleibt sie unbemerkt – ein weiterer Grund, mehrzeilige Delimiter statt eines einzelnen Symbols zu wählen.
Kostspielige Fehler
Der häufigste Fehler ist eine zu kurze Sequenz, die zu vorzeitigen Stoppungen führt. Ein einzelner Punkt stoppt die Generierung beim ersten Satz, den er sieht, selbst mitten in einer Abkürzung; das symmetrische Missverständnis besteht darin, eine Zeichenfolge auszuwählen, die das Modell niemals produzieren wird, in welchem Fall der Parameter nichts bewirkt und Sie fälschlicherweise glauben, eine Schutzmaßnahme eingerichtet zu haben.
# SCHLECHT: Sequenz zu kurz, vorzeitige Stoppungen
stop=["."] # Stoppt bei jedem Satz!
# GUT: kontextspezifische Sequenz
stop=[".\n\n"] # Stoppt nach einem Punkt gefolgt von einem doppelten Zeilenumbruch
# SCHLECHT: Sequenz, die das Modell niemals produzieren wird
stop=["XYZZY"] # Hat keine Wirkung
# GUT: realistische Sequenz basierend auf dem erwarteten Format
stop=["Nächste Frage:", "---"]
Die Regel, die sich aus diesen vier Zeilen ergibt, ist einfach: Eine gute Stop-Sequenz leitet sich aus dem Format ab, das Sie vom Modell verlangt haben, niemals aus Ihrer Phantasie.
Komplettes Beispiel: Kontrollierter Q&A
Lassen Sie uns diese Elemente zu einer kurzen Frage-Antwort-Funktion zusammenfügen, bei der eine niedrige Temperatur die faktische Stabilität sicherstellt, max_tokens eine Sicherheitsgrenze setzt und Stop-Sequenzen die Kommentare abschneiden, die das Modell nach seiner Antwort hinzufügen könnte:
from mistralai.client import Mistral
import os
client = Mistral(api_key=os.getenv("MISTRAL_API_KEY"))
def ask_single_question(frage: str) -> str:
"""Stellen Sie eine Frage und erhalten Sie eine knappe Antwort ohne Geschwafel."""
response = client.chat.complete(
model="mistral-large-latest",
messages=[
{
"role": "system",
"content": "Antworten Sie in einem einzigen Satz, direkt und faktisch."
},
{"role": "user", "content": frage}
],
max_tokens=100,
stop=["\n\n", "Bemerkung:", "Hinweis:"],
temperature=0.1
)
return response.choices[0].message.content.strip()
# Test
fragen = [
"Wie schnell ist das Licht?",
"Wer hat das Telefon erfunden?",
"Wie viele Planeten gibt es im Sonnensystem?"
]
for f in fragen:
print(f"F: {f}")
print(f"A: {ask_single_question(f)}\n")
Führen Sie dieses Skript einmal so aus, dann ein zweites Mal nach dem Entfernen des stop-Parameters: Der Vergleich der beiden Ausgaben zeigt Ihnen genau, was diese drei Sequenzen filtern.
Kernaussagen
- Stop-Sequenzen stoppen die Generierung, wenn das Modell spezifischen Text erzeugt
- Maximum von 4 Sequenzen pro Anfrage; fallensensitiv
- Die Stop-Sequenz wird niemals im Antworttext enthalten
- Verwenden Sie Sequenzen, die spezifisch genug sind, um vorzeitige Stoppungen zu vermeiden
- Kompatibel mit Streaming und allen anderen Parametern