Überspringen und zum Inhalt gehen →

30-Tage-DSPy-Challenge: Tag 3 – Signaturen, das Herzstück des Programms

Eine Signatur definiert auf deklarative Weise die Ein- und Ausgabestruktur für einen Aufruf an ein Sprachmodell (LLM). Sie ist das Kernstück, um die Interaktion mit dem Modell programmatisch und strukturiert zu gestalten, anstatt manuelle Prompts zu formulieren.

Theorie: Die Funktion von DSPy-Signaturen

Eine DSPy-Signatur ist eine Spezifikation, die dem LLM mitteilt, welche Aufgabe es ausführen soll. Sie besteht im Wesentlichen aus zwei Komponenten:

  • Eingabefelder (Input Fields)
    Diese definieren, welche Informationen dem Modell zur Verfügung gestellt werden.
  • Ausgabefelder (Output Fields)
    Diese legen fest, welche Informationen das Modell generieren soll.

Anstatt einen langen, detaillierten Prompt zu konstruieren, deklariert eine Signatur die semantischen Rollen der Ein- und Ausgaben. Zum Beispiel unterscheidet eine Signatur klar zwischen einer frage und einer antwort.

Es gibt zwei primäre Methoden, Signaturen zu definieren: Inline oder als Klasse. Die klassenbasierte Methode bietet mehr Kontrolle und ermöglicht es, die Aufgabe durch einen Docstring genauer zu beschreiben. Dieser Docstring dient dem LLM als übergeordnete Anweisung und präzisiert den Kontext der Aufgabe.

Die entscheidende Rolle des Docstrings
Der Docstring innerhalb einer Signatur-Klasse ist nicht nur eine Dokumentation für den Entwickler. Er wird von DSPy aktiv genutzt, um dem LLM Anweisungen auf hoher Ebene zu geben. Damit lässt sich das Verhalten des Modells steuern, ohne die Details des eigentlichen Prompts manuell festlegen zu müssen.

Praxis: Definition einer Übersetzungs-Signatur

Die praktische Umsetzung demonstriert, wie eine klassenbasierte Signatur für eine Übersetzungsaufgabe vom Deutschen ins Englische erstellt wird.

Umgebung einrichten
Zuerst müssen die notwendigen DSPy-Komponenten importiert und ein Sprachmodell konfiguriert werden.

import dspy

local_llm = dspy.LM(
    "openai/Qwen3-VL-8B-Instruct-Q4_K_M.gguf", 
    api_base="http://localhost:8080/v1", 
    api_key="no_key_needed"
)

dspy.configure(lm=local_llm)

Signatur-Klasse definieren
Im nächsten Schritt wird eine Klasse DeutschNachEnglisch erstellt, die von dspy.Signature erbt. Der Docstring beschreibt die Aufgabe klar. Die Klasse definiert ein Eingabefeld (german_text) und ein Ausgabefeld (english_translation).

class DeutschNachEnglisch(dspy.Signature):
    """Translate a given German text into English."""

    # Definition des Eingabefeldes
    german_text = dspy.InputField()

    # Definition des Ausgabefeldes
    english_translation = dspy.OutputField()

Signatur in einem Modul verwenden
Signaturen werden typischerweise innerhalb von DSPy-Modulen wie dspy.Predict verwendet. Dieses Modul nimmt die Signatur entgegen und kümmert sich um die Ausführung des LLM-Aufrufs.

# Erstellen einer Vorhersage-Instanz mit der definierten Signatur
translate = dspy.Predict(DeutschNachEnglisch)

Ausführung und Ergebnis
Anschließend kann das translate-Objekt aufgerufen werden, um eine Übersetzung durchzuführen.

# Ein deutscher Satz als Eingabe
deutscher_satz = "DSPy abstrahiert die Komplexität des Prompt-Engineerings."

# Aufruf des Modells
response = translate(german_text=deutscher_satz)

# Ausgabe der Übersetzung
print(response.english_translation)

Ergebnis und Interpretation

Die erwartete Ausgabe des obigen Code-Blocks ist die englische Übersetzung des eingegebenen deutschen Satzes, zum Beispiel:

"DSPy abstracts away the complexity of prompt engineering."

Durch die DeutschNachEnglisch-Signatur hat DSPy im Hintergrund einen effektiven Prompt für das Sprachmodell generiert. Der Docstring "Translate a given German text into English." diente als allgemeine Anweisung. Die Feldnamen german_text und english_translation informierten das Modell über die spezifische Rolle der Eingabe- und Ausgabedaten. Das Ergebnis ist eine korrekte Übersetzung, ohne dass ein einziger Prompt manuell formuliert werden musste.

Den resultierenden Prompt kann man wieder mit dem Befehl local_llm.inspect_history(n=1) ausgeben.

System message:

Your input fields are:
1. `german_text` (str):
Your output fields are:
1. `english_translation` (str):
All interactions will be structured in the following way, with the appropriate values filled in.

[[ ## german_text ## ]]
{german_text}

[[ ## english_translation ## ]]
{english_translation}

[[ ## completed ## ]]
In adhering to this structure, your objective is:
Translate a given German text into English.


User message:

[[ ## german_text ## ]]
DSPy abstrahiert die Komplexität des Prompt-Engineerings.

Respond with the corresponding output fields, starting with the field `[[ ## english_translation ## ]]`, and then ending with the marker for `[[ ## completed ## ]]`.


Response:

[[ ## english_translation ## ]]
DSPy abstracts away the complexity of prompt engineering.

[[ ## completed ## ]]

Analyse des generierten Prompts

Eine Inspektion des von DSPy generierten Prompts zeigt die interne Funktionsweise. Der Prompt ist hochgradig strukturiert und besteht aus einer Systemnachricht und einer Benutzernachricht.

Systemnachricht (System message):
Die Systemnachricht fungiert als Template und allgemeine Anweisung. Sie definiert explizit die erwarteten Ein- und Ausgabefelder (german_textenglish_translation) und deren Datentyp. Anschließend wird ein striktes Format für alle Interaktionen vorgegeben, bei dem jedes Feld von spezifischen Markern wie [[ ## field_name ## ]] umschlossen wird. Entscheidend ist, dass die Anweisung aus dem Docstring der Signatur – „Translate a given German text into English.“ – hier als Kernziel (objective) für das Modell eingebettet wird.

Benutzernachricht (User message):
Die Benutzernachricht füllt dieses Template mit den konkreten Daten. Der german_text wird in die vordefinierte Struktur eingesetzt. Das Modell wird abschließend instruiert, die Antwort zu generieren, indem es mit dem Marker für das Ausgabefeld [[ ## english_translation ## ]] beginnt und mit [[ ## completed ## ]] endet.

Diese methodische Vorgehensweise stellt sicher, dass die Ausgabe des LLMs nicht nur inhaltlich korrekt ist, sondern auch eine präzise, maschinenlesbare Struktur aufweist. Die strikte Formatierung macht das Parsing der Modellausgabe zuverlässig und robust. DSPy wandelt die abstrakte, semantische Definition der Signatur in eine konkrete, effektive Anweisung um, die das LLM zu einer vorhersehbaren Ausgabe anleitet.

Zusammenfassung

Signaturen sind ein zentrales Konzept in DSPy, das den traditionellen Ansatz des Prompt-Engineerings durch eine strukturierte, programmatische Methode ersetzt. Sie definieren klar die Schnittstelle zum Sprachmodell, indem sie Ein- und Ausgabefelder mit semantisch aussagekräftigen Namen versehen. Durch die Verwendung von Docstrings in klassenbasierten Signaturen lässt sich das Verhalten des Modells präzise steuern. Dieser Ansatz erhöht nicht nur die Lesbarkeit und Wartbarkeit von LLM-basierten Anwendungen, sondern ist auch die Voraussetzung für die automatische Optimierung durch DSPy-Compiler.

Veröffentlicht in Allgemein