Erkundung von DSPy und seiner Integration mit Milvus zur Erstellung hocheffizienter RAG-Pipelines
Einführung
Large Language Models (LLMs) verfügen über transformative generative Fähigkeiten und werden durch Tools wie Wissensdatenbanken und Retriever erweitert, was fortschrittliche GenAI-Anwendungen wie Chatbots und Agents antreibt. Im Zentrum der Interaktion mit LLMs stehen Prompts, also Anweisungen, die diese Modelle dabei leiten, bestimmte Aufgaben auszuführen. Das Erstellen effektiver Prompts ist jedoch ein nuancierter und komplexer Prozess, der häufig anspruchsvolle Techniken wie Chain-of-Thought und ReAct erfordert. Dadurch werden Prompts immer komplexer. Darüber hinaus können selbst identische Prompts bei verschiedenen LLMs wie GPT-4 und Gemini aufgrund von Unterschieden in ihren Pre-Training-Methoden und Datensätzen zu abweichenden Ergebnissen führen. Diese Herausforderung hat ein starkes Interesse an Prompt Engineering ausgelöst – einer arbeitsintensiven Aufgabe, die sich darauf konzentriert, Prompts zu verfeinern und zu optimieren, um bessere und maßgeschneiderte Ergebnisse zu erzielen.
Während das manuelle Erstellen von Prompts für einfache LLM-Anwendungen gut funktioniert, wird es bei komplexen LLM-basierten Pipelines mit mehreren Komponenten frustrierend und zeitaufwendig. DSPy stellt einen Paradigmenwechsel in der Art und Weise dar, wie Entwickler mit Sprachmodellen interagieren, indem es eine programmierbare Schnittstelle einführt, die eine algorithmische Optimierung von Modell-Prompts und -Gewichten ermöglicht und so zu einer effizienteren Entwicklung von Sprachmodellen führt. DSPy hat die Milvus-Vektordatenbank nahtlos integriert und automatisiert die Optimierung von Retrieval Augmented Generation(RAG)-Anwendungen mithilfe eines programmatischen Ansatzes.
In den folgenden Abschnitten werden wir das Wesen von DSPy und seine Funktionsweise untersuchen und ein praktisches Beispiel bereitstellen, das zeigt, wie man eine RAG-Anwendung mit DSPy und der Milvus-Vektordatenbank erstellt und optimiert.
Was ist DSPy?
DSPy, eingeführt von der Stanford NLP Group, ist ein programmatisches Framework zur Optimierung von Prompts und Gewichten in Sprachmodellen, das besonders nützlich ist, wenn LLMs über mehrere Pipeline-Stufen hinweg integriert werden. Es stellt verschiedene zusammensetzbare und deklarative Module bereit, um LLMs in Pythonic-Syntax anzuleiten.
Im Gegensatz zu traditionellen Prompt-Engineering-Techniken, die darauf beruhen, Prompts manuell zu erstellen und zu verfeinern, lernt DSPy aus Frage-Antwort-Beispielen und imitiert dieses Lernen, um optimierte Prompts für maßgeschneidertere Ergebnisse zu erzeugen. Dieser Ansatz ermöglicht die dynamische Neuassemblierung der gesamten Pipeline, die explizit auf die Nuancen Ihrer Aufgabe zugeschnitten ist, und beseitigt somit die Notwendigkeit fortlaufender manueller Prompt-Anpassungen.
Schlüsselkonzepte und grundlegende Komponenten
In DSPy bilden drei grundlegende Elemente – Signatures, Modules und Optimizers (früher als Teleprompters bezeichnet) – die zentralen Bausteine für die automatisierte Prompt-Optimierung und das Fine-Tuning von Modellen.
Signatures
Signatures sind deklarative Spezifikationen, die das Eingabe-/Ausgabeverhalten eines DSPy-Moduls definieren. Sie teilen dem Sprachmodell mit, welche Aufgaben es ausführen soll, statt wie wir das Sprachmodell prompten sollten.
- Eine Signatur umfasst drei wesentliche Elemente:
- Eine knappe Beschreibung der Teilaufgabe, die das Sprachmodell lösen soll.
- Eine Beschreibung eines oder mehrerer Eingabefelder (z. B. Eingabefragen), die wir dem Sprachmodell geben.
- Eine Beschreibung eines oder mehrerer Ausgabefelder (z. B. Antworten auf Fragen), die wir vom Sprachmodell erwarten.
Hier sind Beispiele für Signaturen für beliebte LLM-Aufgaben:
- Question Answering:
"question -> answer" - Sentiment Classification:
"sentence -> sentiment" - Retrieval Augmented Question Answering:
"context, question -> answer" - Multiple-Choice Question Answering with Reasoning:
"question, choices -> reasoning, selection"
Diese Signaturen leiten DSPy dabei, LLM-Operationen innerhalb verschiedener Module effizient zu orchestrieren, und fördern eine optimierte und präzise Aufgabenausführung.
Module
DSPy-Module abstrahieren konventionelle Prompting-Techniken innerhalb einer LLM-Pipeline. Sie haben drei Hauptmerkmale:
- Jedes integrierte Modul abstrahiert eine spezifische Prompting-Technik (wie Chain of Thoughts oder ReAct) und verarbeitet DSPy-Signaturen.
- DSPy-Module verfügen über lernbare Parameter, einschließlich Prompt-Komponenten und LLM-Gewichte, wodurch sie Eingaben verarbeiten und Ausgaben generieren können.
- DSPy-Module können kombiniert werden, um größere, komplexere Module zu erstellen.
- DSPy stellt sieben integrierte Module für verschiedene Zwecke bereit, darunter
dspy.ReAct,dspy.ChainofThought,dspy.Predict,dspy.ProgramOfThought,dspy.ReAct,dspy.MultiChainComparisonunddspy.Retrieve.
Optimierer
DSPy-Optimierer, früher Teleprompter, sind Algorithmen, die darauf ausgelegt sind, die Parameter eines DSPy-Programms — wie Prompts und LLM-Gewichte — feinzujustieren, um bestimmte Metriken wie Genauigkeit zu maximieren. Ein typischer DSPy-Optimierer benötigt drei Eingaben:
Ihr DSPy-Programm: kann ein einzelnes Modul (z. B.
dspy.Predict) oder ein komplexes Programm mit mehreren Modulen sein.Ihre gewählte Metrik: eine Funktion, die die Ausgabe des Programms bewertet und ihr eine Punktzahl zuweist (höhere Punktzahlen bedeuten bessere Ergebnisse).
Eine kleine Menge an Trainingseingaben: oft nur 5 bis 10 Beispiele.
Sobald Sie Ihre Trainingsdaten, Module und Metriken definiert haben, optimiert der Optimierer die LLM-Gewichte, Prompt-Anweisungen und Few-Shot-Demonstrationen, um die Programmeffizienz zu steigern. Beispielsweise generiert der BootstrapFewShot-Optimierer Antworten, die mit der angegebenen Metrik übereinstimmen, während Module wie COT (Chain of Thought) strukturiertes Reasoning erzeugen, um zu genauen Antworten zu gelangen. DSPy zeichnet diese erfolgreichen Instanzen und Begründungen als Few-Shot-Demonstrationen auf, um zukünftige Testanfragen zu bearbeiten.
Zusätzlich zu den oben genannten zentralen Bausteinen integriert DSPy Daten, Metriken und Assertions als ergänzende Komponenten, wodurch seine Funktionalität und Anpassungsfähigkeit erweitert werden. Weitere Details finden Sie in der DSPy-Dokumentation.
DSPy-Workflows: Aufbau effizienter LLM-Pipelines
Wie genau funktioniert DSPy beim Aufbau von LLM-Pipelines? Zur Verdeutlichung können wir den Prozess in mehrere wichtige Schritte unterteilen.
- Zuerst müssen Sie Ihre Aufgabe definieren und einige Beispieleingaben vorbereiten – oft ohne Labels (oder ausschließlich mit Labels für die finalen Ausgaben, falls Ihre Metrik diese erfordert).
- Zweitens erstellen Sie Ihre Pipeline, indem Sie aus den integrierten Modulen auswählen, jedem Modul eine Signatur (Input-/Output-Spezifikation) zuweisen und diese Module nahtlos in Ihren Python-Code integrieren.
- Drittens definieren Sie die Validierungslogik für Ihre Pipeline, einschließlich der Metriken und Beispieleingaben, die zur Bewertung der Qualität von Prompts und der finalen Ergebnisse verwendet werden sollen.
- Viertens kompilieren Sie Ihren Code mit einem DSPy-Optimierer, der hochwertige Anweisungen, automatische Few-Shot-Beispiele oder aktualisierte LLM-Gewichte generiert.
- Schließlich treten Sie in einen iterativen Prozess ein, in dem Sie Ihren Datensatz, Ihr Programm oder Ihre Validierungslogik verfeinern, um das gewünschte Leistungsniveau für Ihre Pipeline zu erreichen. Bewerten und verbessern Sie kontinuierlich, um sich wandelnden Anforderungen gerecht zu werden und die Ergebnisse zu optimieren.
DSPy vs. LlamaIndex/LangChain/AutoGPT
DSPy hebt sich durch seinen Ansatz im Vergleich zu vielen anderen beliebten KI-Frameworks wie LangChain, LlamaIndex und AutoGPT ab. Hier ist ein genauerer Blick darauf, wie sie sich unterscheiden und übereinstimmen:
LangChain ist ein Toolkit zur Erstellung maßgeschneiderter Anwendungen. Es nutzt verschiedene Sprachmodelle und Utility-Pakete, sodass Entwickler Anwendungen an spezifische Anforderungen anpassen können.
LlamaIndex ist ein Orchestrierungsframework, das darauf ausgelegt ist, die Integration verschiedener privater Datenquellen mit Sprachmodellen zu optimieren. Es vereinfacht Aufgaben der Datenhandhabung und -verarbeitung.
AutoGPT ist ein fortschrittlicher KI-Agent, der von GPT-4 und GPT3.5 betrieben wird. Er ist so programmiert, dass er auf Grundlage vordefinierter Regeln und Ziele Entscheidungen trifft und Aktionen ausführt. Er betont Autonomie und Entscheidungsfähigkeiten.
Die besonderen Merkmale von DSPy:
- DSPy optimiert und automatisiert die Prompt-Erstellung für eine verbesserte Interaktion mit Sprachmodellen.
- Im Gegensatz zu LangChain und LlamaIndex, die mit vorgefertigten Modulen auf die Entwicklung von High-Level-Anwendungen ausgerichtet sind, bietet DSPy leistungsstarke und universell einsetzbare Module, die lernen können, Prompts zu erstellen oder LLMs innerhalb benutzerdefinierter Pipelines feinzujustieren. Die Stärke von DSPy liegt in seiner Fähigkeit, Prompts dynamisch anzupassen und LLMs auf Grundlage sich ändernder Daten, Anpassungen im Programm-Kontrollfluss oder Variationen der Zielsprache feinzujustieren. Dieser automatisierte Optimierungsprozess kann mit minimalem Aufwand zu qualitativ überlegenen Ausgaben führen, insbesondere wenn Entwickler bereit sind, ihre einfachen oder prototypischen Programme zu anspruchsvolleren Programmen für Produktionszwecke zu skalieren.
- DSPy ist ideal für Anwendungsfälle, die ein leichtgewichtiges, aber automatisch optimierendes Programmiermodell erfordern, anstatt sich auf vordefinierte Prompts und Integrationen zu verlassen, wie sie von Bibliotheken wie LangChain und LlamaIndex angeboten werden.
DSPy-Integration mit Milvus Vector Database
Milvus ist eine hochflexible, zuverlässige und blitzschnelle Cloud-native Open-Source-Vektordatenbank. Sie ermöglicht Vektor-Ähnlichkeitssuche und ist besonders nützlich beim Aufbau verschiedener GenAI- und Retrieval Augmented Generation (RAG)-Anwendungen.
Milvus wurde als Retrieval-Modul in Form des MilvusRM-Clients in den DSPy-Workflow integriert, wodurch die Implementierung einer schnellen und effizienten RAG-Pipeline erleichtert wird.
Aufbau einer RAG-Anwendung mit DSPy und Milvus
Retrieval Augmented Generation (RAG) ist eine Methode, die LLMs befähigt, auf externe Wissensspeicher zuzugreifen, diese Speicher nach kontextbezogenen Informationen zu durchsuchen, die für Benutzeranfragen relevant sind, und verfeinerte Antworten zu generieren.
In dieser Demonstration erstellen wir eine einfache RAG-Anwendung mit GPT-3.5 (gpt-3.5-turbo) zur Antwortgenerierung. Wir verwenden Milvus als Vektorspeicher über MilvusRM und DSPy, um die RAG-Pipeline zu konfigurieren und zu optimieren.
Voraussetzungen
Bevor Sie die RAG-App erstellen, installieren Sie den MilvusRM Client und Milvus.
- Um MilvusRM zu installieren, führen Sie den folgenden Code aus.
pip install dspy-ai[milvus]
- Installieren Sie Milvus. Ausführliche Anweisungen finden Sie in der Milvus-Dokumentation.
Laden des Datensatzes
In diesem Beispiel verwenden wir HotPotQA, eine Sammlung komplexer Frage-Antwort-Paare, als unseren Trainingsdatensatz. Wir können sie über die HotPotQA-Klasse laden.
from dspy.datasets import HotPotQA
# Load the dataset.
dataset = HotPotQA(train_seed=1, train_size=20, eval_seed=2023, dev_size=50, test_size=0)
# Tell DSPy that the 'question' field is the input. Any other fields are labels and/or metadata.
trainset = [x.with_inputs('question') for x in dataset.train]
devset = [x.with_inputs('question') for x in dataset.dev]
Daten in die Milvus-Vektordatenbank importieren
Nehmen Sie die Kontextinformationen zur Vektorabfrage in die Milvus-Collection auf. Diese Collection sollte ein embedding-Feld und ein text-Feld haben. In diesem Fall verwenden wir OpenAIs Modell text-embedding-3-small als standardmäßige Abfrage-Embedding-Funktion.
import requests
MILVUS_URI = "http://localhost:19530"
MILVUS_TOKEN = ""
from pymilvus import MilvusClient, DataType, Collection
from dspy.retrieve.milvus_rm import openai_embedding_function
client = MilvusClient(
uri=MILVUS_URI,
token=MILVUS_TOKEN
)
if 'dspy_example' not in client.list_collections():
client.create_collection(
collection_name="dspy_example",
overwrite= True,
dimension=1536,
primary_field_name="id",
vector_field_name="embedding",
id_type="int",
metric_type="IP",
max_length=65535,
enable_dynamic=True
)
text = requests.get('https://raw.githubusercontent.com/wxywb/dspy_dataset_sample/master/sample_data.txt').text
for idx, passage in enumerate(text.split('\n')):
if len(passage) == 0:
continue
client.insert(collection_name="dspy_example", data = [{"id": idx , "embedding": openai_embedding_function(passage)[0], "text": passage}])
MilvusRM definieren.
Nun müssen Sie MilvusRM definieren.
from dspy.retrieve.milvus_rm import MilvusRM
import os
import dspy
os.environ["OPENAI_API_KEY"] = "<YOUR_OPENAI_API_KEY>"
retriever_model = MilvusRM(
collection_name="dspy_example",
uri=MILVUS_URI,
token=MILVUS_TOKEN, # ignore this if no token is required for Milvus connection
embedding_function = openai_embedding_function
)
turbo = dspy.OpenAI(model='gpt-3.5-turbo')
dspy.settings.configure(lm=turbo)
Signaturen erstellen
Nachdem wir die Daten geladen haben, beginnen wir mit der Definition der Signaturen für die Teilaufgaben unserer Pipeline. Wir können unsere einfache Eingabe question und Ausgabe answer identifizieren, aber da wir eine RAG-Pipeline erstellen, werden wir Kontextinformationen aus Milvus abrufen. Definieren wir unsere Signatur also als context, question --> answer.
class GenerateAnswer(dspy.Signature):
"""Answer questions with short factoid answers."""
context = dspy.InputField(desc="may contain relevant facts")
question = dspy.InputField()
answer = dspy.OutputField(desc="often between 1 and 5 words")
Wir fügen kurze Beschreibungen für die Felder context und answer hinzu, um klarere Richtlinien dafür zu definieren, was das Modell erhält und generieren soll.
Pipeline erstellen
Definieren wir nun die RAG-Pipeline.
class RAG(dspy.Module):
def __init__(self, rm):
super().__init__()
self.retrieve = rm
# This signature indicates the task imposed on the COT module.
self.generate_answer = dspy.ChainOfThought(GenerateAnswer)
def forward(self, question):
# Use milvus_rm to retrieve context for the question.
context = self.retrieve(question).passages
# COT module takes "context, query" and output "answer".
prediction = self.generate_answer(context=context, question=question)
return dspy.Prediction(context=[item.long_text for item in context], answer=prediction.answer)
Ausführen der Pipeline und Abrufen der Ergebnisse
Jetzt haben wir diese RAG-Pipeline erstellt. Probieren wir sie aus und erhalten wir Ergebnisse.
rag = RAG(retriever_model)
print(rag("who write At My Window").answer)
# The result:
# 'Townes Van Zandt'
Wir können die quantitativen Ergebnisse auf dem Datensatz auswerten.
from dspy.evaluate.evaluate import Evaluate
from dspy.datasets import HotPotQA
evaluate_on_hotpotqa = Evaluate(devset=devset, num_threads=1, display_progress=False, display_table=5)
metric = dspy.evaluate.answer_exact_match
score = evaluate_on_hotpotqa(rag, metric=metric)
print('rag:', score)
# The result:
# rag: 50.0
Optimieren der Pipeline
Nach der Definition dieses Programms ist der nächste Schritt die Kompilierung. Dieser Prozess aktualisiert die Parameter innerhalb jedes Moduls, um die Leistung zu verbessern. Der Kompilierungsprozess hängt von drei entscheidenden Faktoren ab:
- Trainingssatz: Für diese Demonstration verwenden wir die 20 Frage-Antwort-Beispiele aus unserem Trainingsdatensatz.
- Validierungsmetrik: Wir werden eine einfache
validate_context_and_answer-Metrik einrichten. Diese Metrik überprüft die Genauigkeit der vorhergesagten Antwort und stellt sicher, dass der abgerufene Kontext die Antwort enthält. - Spezifischer Optimizer (Teleprompter): Der Compiler von DSPy integriert mehrere Teleprompter, die darauf ausgelegt sind, Ihre Programme effektiv zu optimieren.
from dspy.teleprompt import BootstrapFewShot
# Validation logic: check that the predicted answer is correct.
# Also check that the retrieved context does contain that answer.
def validate_context_and_answer(example, pred, trace=None):
answer_EM = dspy.evaluate.answer_exact_match(example, pred)
answer_PM = dspy.evaluate.answer_passage_match(example, pred)
return answer_EM and answer_PM
# Set up a basic teleprompter, which will compile our RAG program.
teleprompter = BootstrapFewShot(metric=validate_context_and_answer)
# Compile!
compiled_rag = teleprompter.compile(rag, trainset=trainset)
# Now compiled_rag is optimized and ready to answer your new question!
Bewerten wir nun das kompilierte RAG-Programm.
score = evaluate_on_hotpotqa(compiled_rag, metric=metric)
print(score)
print('compile_rag:', score)
# The result:
# compile_rag: 52.0
Der Bewertungswert ist von seinem vorherigen Wert von 50.0 auf 52.0 gestiegen, was auf eine Verbesserung der Antwortqualität hinweist.
Zusammenfassung
DSPy markiert einen Sprung nach vorn bei Interaktionen mit Sprachmodellen durch seine programmierbare Schnittstelle, die eine algorithmische und automatisierte Optimierung von Modell-Prompts und Gewichten ermöglicht. Durch den Einsatz von DSPy für die RAG-Implementierung wird die Anpassungsfähigkeit an unterschiedliche Sprachmodelle oder Datensätze zum Kinderspiel, wodurch der Bedarf an mühsamen manuellen Eingriffen drastisch reduziert wird.
Darüber hinaus führt DSPy ein MilvusRM-Retriever-Modul in seinen Workflow ein, indem es die Milvus-Vektordatenbank integriert. Mit dieser neuen Integration können Entwickler die Prompt-Optimierung und Anpassungen von Modellparametern innerhalb von RAG-Anwendungen automatisieren, um die Antwortqualität zu verbessern. Wenn Sie mehr erfahren möchten, lesen Sie den ausführlichen Leitfaden zu MilvusRM in der DSPy-Dokumentation!
Referenzen
DSPy GitHub-Seite: https://github.com/stanfordnlp/dspy
DSPy Paper: https://arxiv.org/pdf/2310.03714
DSPy-Dokumentation: https://dspy-docs.vercel.app/quick-start/installation/
MilvusRM-Leitfaden: https://dspy-docs.vercel.app/docs/deep-dive/retrieval_models_clients/MilvusRM
Milvus-Dokumentation: https://milvus.io/docs
Weiterlesen

Introducing Zilliz CLI and Agent Skills for Zilliz Cloud
Manage your vector database from your terminal or AI coding agent. Zilliz CLI and Agent Skills work with Claude Code, Cursor, Codex, and Copilot.

Democratizing AI: Making Vector Search Powerful and Affordable
Zilliz democratizes AI vector search with Milvus 2.6 and Zilliz Cloud for powerful, affordable scalability, cutting costs in infrastructure, operations, and development.

AI Integration in Video Surveillance Tools: Transforming the Industry with Vector Databases
Discover how AI and vector databases are revolutionizing video surveillance with real-time analysis, faster threat detection, and intelligent search capabilities for enhanced security.



