Der Tag heute dient der Konsolidierung des Wissens aus der ersten Woche. Der Fokus liegt auf der Wiederholung der zentralen Konzepte von DSPy – Signaturen, Module und ChainOfThought – und deren praktischer Anwendung in einem erweiterten Projekt.
Kernkonzepte im Überblick
Die drei wichtigsten Bausteine, die in der ersten Woche eingeführt wurden, sind Signaturen, Module und die ChainOfThought-Logik.
- Signaturen (
dspy.Signature): Eine Signatur ist die formale Deklaration einer Aufgabe für ein Sprachmodell (LLM). Sie definiert die Struktur der Eingabe- und Ausgabefelder. Mittelsdspy.InputFieldunddspy.OutputFieldwird festgelegt, welche Informationen das Modell erhält und welche es generieren soll. Die Beschreibungen innerhalb dieser Felder sowie der Docstring der Signatur-Klasse selbst dienen dem LLM als detaillierte Anweisung und sind entscheidend für die Qualität der Ausgabe. - Module (
dspy.Module): Module sind die Bausteine eines DSPy-Programms. Sie kapseln die Logik und das Verhalten. Das grundlegendste Modul,dspy.Predict, nimmt eine Signatur entgegen und führt einen einfachen LLM-Aufruf aus. Komplexere Programme entstehen durch die Kombination mehrerer Module zu einer Pipeline. - Chain of Thought (
dspy.ChainOfThought): Dies ist ein spezielles Modul, das eine Signatur erweitert, um das LLM zu einer schrittweisen Denkweise anzuregen, bevor es eine endgültige Antwort gibt. Es fügt intern ein Feld für die Argumentation (reasoning) hinzu. Dieser Prozess verbessert die Performanz bei Aufgaben, die logisches Schließen oder mehrstufige Analysen erfordern.
Erweiterung des Zitat-Generators
Das bestehende Programm zur Generierung von Zitaten wird nun um eine zusätzliche Funktionalität erweitert. Ich ergänze es um die Bewertung des generierten Zitats.
Initialisierung des Sprachmodells
Zunächst wird die Verbindung zu einem lokalen Sprachmodell hergestellt. Diese Konfiguration bleibt im Vergleich zum ursprünglichen Skript unverändert.
import dspy
# Konfiguration des lokalen Sprachmodells
local_llm = dspy.LM(
"openai/Qwen3-VL-8B-Instruct-Q4_K_M.gguf",
api_base="http://localhost:8080/v1",
api_key="no_key_needed",
temperature=2,
cache=False
)
dspy.configure(lm=local_llm)
Definition der Signaturen
Die bestehende Signatur GenerateQuote bleibt bestehen und es wird eine neue Signatur, ClassifyQuote hinzugefügt. Diese neue Signatur definiert die Aufgabe der Klassifizierung.
class GenerateQuote(dspy.Signature):
"""Generiere ein Zitat zu einem bestimmten Thema im Stil einer berühmten Persönlichkeit."""
topic = dspy.InputField(desc="Das Thema, über das das Zitat handeln soll.")
persona = dspy.InputField(desc="Die berühmte Persönlichkeit, deren Schreibstil nachgeahmt werden soll.")
quote = dspy.OutputField(desc="Ein prägnantes und inspirierendes Zitat (ca. 1-2 Sätze).")
class VoteQuote(dspy.Signature):
"""Bewerte das folgende Zitat. Wie sehr klingt es nach der Person, von der das Zitat kommt mit den Punten von 1 bis 10.
1 beduetet, es klingt überhaupt nicht nach der berühmte Persönlichkeit
10 bedeutet, es klingt vollkommen nach der berühmte Persönlichkeit"""
quote = dspy.InputField(desc="Das zu bewertende Zitat.")
vote = dspy.OutputField(desc="Eine der Zahlen von 1 bis 10.")
Erstellung eines kombinierten Moduls
Um die beiden Aufgaben (Generierung und Klassifizierung) miteinander zu verketten, wird ein neues, übergeordnetes Modul QuoteAndClassify erstellt. Dieses Modul definiert den Ablauf der Datenverarbeitung.
- Das Modul initialisiert zwei Untermodule:
dspy.Predictfür die Zitat-Generierung unddspy.ChainOfThoughtfür die Klassifizierung, um eine fundiertere Entscheidung zu fördern. - Die
forward-Methode definiert die Ausführungslogik: Zuerst wird das Zitat generiert. Anschließend wird die Ausgabe (prediction.quote) als Eingabe für das Klassifizierungsmodul verwendet.
class QuoteAndVote(dspy.Module):
def __init__(self):
super().__init__()
# Initialisierung der beiden Untermodule
self.quote_generator = dspy.Predict(GenerateQuote)
self.quote_classifier = dspy.ChainOfThought(VoteQuote)
def forward(self, topic, persona):
# Schritt 1: Zitat generieren
prediction_quote = self.quote_generator(topic=topic, persona=persona)
# Schritt 2: Generiertes Zitat klassifizieren
prediction_vote = self.quote_classifier(quote=prediction_quote.quote)
# Rückgabe beider Ergebnisse
return dspy.Prediction(
quote=prediction_quote.quote,
vote=prediction_vote.vote
)
Ausführung und Ergebnis
Das neu erstellte Modul wird instanziiert und mit den Eingabeparametern ausgeführt.
# Instanziieren und Ausführen des kombinierten Moduls
quote_vote_app = QuoteAndVote()
topic_input = "die Bedeutung von künstlicher Intelligenz für die Zukunft der Menschheit"
persona_input = "Albert Einstein"
# Ausführen der gesamten Pipeline
final_prediction = quote_vote_app(topic=topic_input, persona=persona_input)
# Ausgabe der Ergebnisse
print(f"Thema: {topic_input}")
print(f"Persona: {persona_input}")
print("-" * 30)
print(f"Generiertes Zitat: {final_prediction.quote}")
print(f"Bewertung: {final_prediction.vote}")
Interpretation und Vertiefung
Das Ergebnis zeigt eine erfolgreiche Verkettung von zwei voneinander abhängigen LLM-Aufrufen. Das Programm führt nicht nur eine Generierung aus, sondern auch eine Klassifizierung. Beide LLM Aufrufe werden mit dem Modul als Kombi ausgeführt.
Thema: die Bedeutung von künstlicher Intelligenz für die Zukunft der Menschheit
Persona: Albert Einstein
------------------------------
Generiertes Zitat: Künstliche Intelligenz ist kein Werkzeug der Zerstörung, sondern der Verwirklichung unserer tiefsten menschlichen Visionen — doch ihre Macht wird erst dann vollendet, wenn wir sie mit dem gleichen Respekt und Verantwortung behandeln, den wir dem Geist und dem Herz verleihen.
Bewertung: 8
Ein entscheidender Aspekt zur Steuerung des LLM-Verhaltens liegt in der Formulierung der Signaturen. Wenn das Ergebnis nicht gleich ganz passt, kann mit verschiedenen Beschreibungen (desc) und Docstrings zu experimentieren, um deren Auswirkungen zu beobachten – damit ist man dann aber wieder beim Prompt Engineering angelangt.
Experimente
Da das Modell für andere berühmte Persönlichkeiten wie Louis Armstrong oder Otto Walkes keine passenden Zitate erzeugen konnte habe ich GenerateQuote zum Testen auch mal in einem ChainOfThought Untermodul verpackt und den Docstring von GenerateQuote wie folgt geändert.
„““Generiere ein Zitat zu einem bestimmten Thema im Stil einer berühmten Persönlichkeit. Denke zuerst über die Person nach, um ihren Stil zu erfassen.“““
Leider hat das nicht viel geholfen. Vermutlich liegt es einfach daran, dass Qwen keine Informationen über diese Personen hat. Da hilft dann auch das beste DSPy Programm nicht. Wenn das Modell keine Daten hat, kommt auch nix sinnvolles raus. Da hilft dann wohl nur noch RAG. Das kommt aber erst ab Tag 15.
Zusammenfassung
Durch die Kombination von Modulen lassen sich mehrstufige Logik-Pipelines erstellen. Die Signatur dient dabei als präzises Werkzeug zur Steuerung der LLM-Aufgaben. Dieses Wissen bildet die Basis für die kommende Woche, in der die systematische Optimierung (compilation) solcher Programme im Mittelpunkt stehen wird.
