Prompt engineering
Optimaliseer LLM met DSPy: een stap-voor-stap gids voor het bouwen, optimaliseren en evalueren van AI-systemen
Naarmate de mogelijkheden van grote taalmodellen (LLMâs) zich blijven uitbreiden, is het ontwikkelen van robuuste AI-systemen die hun potentieel benutten, steeds complexer geworden. Traditionele benaderingen omvatten vaak ingewikkelde prompttechnieken, gegevensgeneratie voor fine-tuning en handmatige begeleiding om te garanderen dat ze voldoen aan domeinspecifieke beperkingen. Dit proces kan echter tijdrovend, foutgevoelig en sterk afhankelijk van menselijke interventie zijn.
Kom DSPy binnen, een revolutionair kader dat is ontworpen om de ontwikkeling van AI-systemen die op LLMâs zijn gebaseerd, te stroomlijnen. DSPy introduceert een systematische aanpak voor het optimaliseren van LM-prompts en -gewichten, waardoor ontwikkelaars geavanceerde toepassingen kunnen bouwen met minimale handmatige inspanning.
In deze uitgebreide gids zullen we de kernbeginselen van DSPy, de modulaire architectuur en de reeks krachtige functies die het biedt, verkennen. We zullen ook praktische voorbeelden behandelen waarin wordt aangetoond hoe DSPy de manier waarop u AI-systemen met LLMâs ontwikkelt, kan transformeren.
Wat is DSPy en waarom hebt u het nodig?
DSPy is een kader dat de stroom van uw programma (modules) scheidt van de parameters (LM-prompts en -gewichten) van elke stap. Deze scheiding maakt een systematische optimalisatie van LM-prompts en -gewichten mogelijk, waardoor u complexe AI-systemen met grotere betrouwbaarheid, voorspelbaarheid en naleving van domeinspecifieke beperkingen kunt bouwen.
Traditioneel omvatte het ontwikkelen van AI-systemen met LLMâs een tijdrovend proces van het opbreken van het probleem in stappen, het creÃŦren van ingewikkelde prompts voor elke stap, het genereren van synthetische voorbeelden voor fine-tuning en het handmatig begeleiden van de LLMâs om te voldoen aan specifieke beperkingen. Deze benadering was niet alleen tijdrovend, maar ook foutgevoelig, aangezien zelfs kleine wijzigingen in de pipeline, LM of gegevens een uitgebreide herwerking van prompts en fine-tuningstappen konden vereisen.
DSPy lost deze uitdagingen op door een nieuw paradigma te introduceren: optimalisatoren. Deze LM-gestuurde algoritmen kunnen de prompts en gewichten van uw LM-aanroepen afstemmen op een door u gedefinieerde metriek. Door het optimalisatieproces te automatiseren, geeft DSPy ontwikkelaars de mogelijkheid om robuuste AI-systemen te bouwen met minimale handmatige interventie, waardoor de betrouwbaarheid en voorspelbaarheid van LM-uitvoer worden verbeterd.
De modulaire architectuur van DSPy
Het hart van DSPy is een modulaire architectuur die de compositie van complexe AI-systemen faciliteert. Het kader biedt een reeks ingebouwde modules die verschillende prompttechnieken abstractiseren, zoals dspy.ChainOfThought en dspy.ReAct. Deze modules kunnen worden gecombineerd en samengesteld tot grotere programmaâs, waardoor ontwikkelaars ingewikkelde pipelines kunnen bouwen die zijn aangepast aan hun specifieke vereisten.
Elke module bevat leerbare parameters, waaronder instructies, few-shot-voorbeelden en LM-gewichten. Wanneer een module wordt aangeroepen, kunnen de optimalisatoren van DSPy deze parameters fine-tunen om de gewenste metriek te maximaliseren, waardoor wordt gegarandeerd dat de LM-uitvoer voldoet aan de gespecificeerde beperkingen en vereisten.
Optimaliseren met DSPy
DSPy introduceert een reeks krachtige optimalisatoren die zijn ontworpen om de prestaties en betrouwbaarheid van uw AI-systemen te verbeteren. Deze optimalisatoren gebruiken LM-gestuurde algoritmen om de prompts en gewichten van uw LM-aanroepen af te stemmen op de gespecificeerde metriek, terwijl ze domeinspecifieke beperkingen naleven.
Enkele van de belangrijkste optimalisatoren die beschikbaar zijn in DSPy, zijn:
- BootstrapFewShot: Deze optimalisator breidt de handtekening uit door automatisch geoptimaliseerde voorbeelden te genereren en op te nemen in de prompt die naar het model wordt verzonden, waardoor few-shot-learning wordt geÃŊmplementeerd.
- BootstrapFewShotWithRandomSearch: Past
BootstrapFewShotmeerdere keren toe met een willekeurige zoekopdracht over gegenereerde demonstraties, waarbij het beste programma over de optimalisatie wordt geselecteerd. - MIPRO: Genereert instructies en few-shot-voorbeelden in elke stap, waarbij de instructiegeneerfunctie gegevensbewust en demonstratiebewust is. Het gebruikt Bayesian-optimalisatie om effectief te zoeken naar de ruimte van generatie-instructies en -demonstraties over uw modules.
- BootstrapFinetune: Distilleert een prompt-gebaseerd DSPy-programma in gewichtsupdates voor kleinere LLMâs, waardoor u de onderliggende LLM(s) kunt fine-tunen voor verbeterde efficiÃŦntie.
Door deze optimalisatoren te gebruiken, kunnen ontwikkelaars hun AI-systemen systematisch optimaliseren, waardoor wordt gegarandeerd dat de uitvoer van hoge kwaliteit is en voldoet aan domeinspecifieke beperkingen en vereisten.
Aan de slag met DSPy
Om de kracht van DSPy te demonstreren, zullen we een praktisch voorbeeld doorlopen van het bouwen van een retrieval-augmenteerd generatiesysteem (RAG) voor vraagbeantwoording.
Stap 1: Configureren van de taalmodel en de retrievalmodel
De eerste stap omvat het configureren van de taalmodel (LM) en de retrievalmodel (RM) binnen DSPy.
Installeer DSPy door het volgende commando uit te voeren:
pip install dspy-ai
DSPy ondersteunt meerdere LM- en RM-APIâs, evenals lokale modelhosting, waardoor het gemakkelijk is om uw voorkeursmodellen te integreren.
import dspy <p># Configureer de LM en RM turbo = dspy.OpenAI(model='gpt-3.5-turbo') colbertv2_wiki17_abstracts = dspy.ColBERTv2(url='http://20.102.90.50:2017/wiki17_abstracts')</p> <p>dspy.settings.configure(lm=turbo, rm=colbertv2_wiki17_abstracts)</p>
Stap 2: Laden van de dataset
Vervolgens zullen we de HotPotQA-dataset laden, die een verzameling complexe vraag-antwoordparen bevat die meestal op een multi-hop-manier worden beantwoord.
from dspy.datasets import HotPotQA
<p># Laad de dataset
dataset = HotPotQA(train_seed=1, train_size=20, eval_seed=2023, dev_size=50, test_size=0)</p>
<p># Specificeer het 'vraag'-veld als invoer
trainset = [x.with_inputs('vraag') for x in dataset.train]
devset = [x.with_inputs('vraag') for x in dataset.dev]</p>
Stap 3: Bouwen van handtekeningen
DSPy gebruikt handtekeningen om het gedrag van modules te definiÃŦren. In dit voorbeeld zullen we een handtekening definiÃŦren voor de antwoordgeneratiettaak, waarbij we het invoerveld (context en vraag) en het uitvoerveld (antwoord) specificeren.
<p>class GenerateAnswer(dspy.Signature): """Beantwoord vragen met korte feitenvragen."""</p> <p>context = dspy.InputField(desc='kan relevante feiten bevatten') vraag = dspy.InputField() antwoord = dspy.OutputField(desc='vaak tussen 1 en 5 woorden')</p>
Stap 4: Bouwen van de pipeline
We zullen onze RAG-pipeline bouwen als een DSPy-module, die bestaat uit een initialisatiemethode (__init__) om de submodules (dspy.Retrieve en dspy.ChainOfThought) te declareren en een forward-methode (forward) om de controlestroom van het beantwoorden van de vraag met behulp van deze modules te beschrijven.
<p>class RAG(dspy.Module): def __init__(self, num_passages=3): super().__init__() self.retrieve = dspy.Retrieve(k=num_passages) self.generate_answer = dspy.ChainOfThought(GenerateAnswer) def forward(self, vraag): context = self.retrieve(vraag).passages prediction = self.generate_answer(context=context, vraag=vraag) return dspy.Prediction(context=context, antwoord=prediction.antwoord)
Stap 5: Optimaliseren van de pipeline
Met de pipeline gedefinieerd, kunnen we deze nu optimaliseren met behulp van de optimalisatoren van DSPy. In dit voorbeeld zullen we de BootstrapFewShot-optimalisator gebruiken, die effectieve prompts voor onze modules genereert en selecteert op basis van een trainingsset en een metriek voor validatie.
<p>from dspy.teleprompt import BootstrapFewShot</p> <p># Validatiemetriek 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 # Stel de optimalisator in teleprompter = BootstrapFewShot(metric=validate_context_and_answer) # Compileer het programma compiled_rag = teleprompter.compile(RAG(), trainset=trainset)
Stap 6: Evalueren van de pipeline
Na het compileren van het programma, is het essentieel om de prestaties te evalueren op een ontwikkelingsset om te garanderen dat deze voldoet aan de gewenste nauwkeurigheid en betrouwbaarheid.
from dspy.evaluate import Evaluate
<p># Stel de evaluator in
evaluate = Evaluate(devset=devset, metric=validate_context_and_answer, num_threads=4, display_progress=True, display_table=0)
# Evalueer het gecompileerde RAG-programma
evaluation_result = evaluate(compiled_rag)
print(f'Evaluatieresultaat: {evaluation_result}')
Stap 7: Inspecteren van modelgeschiedenis
Voor een dieper inzicht in de interacties van het model, kunt u de meest recente generaties bekijken door de geschiedenis van het model te inspecteren.
<p># Inspecteer de geschiedenis van het model turbo.inspect_history(n=1)
Stap 8: Maken van voorspellingen
Met de pipeline geoptimaliseerd en geÃŦvalueerd, kunt u deze nu gebruiken om voorspellingen te doen voor nieuwe vragen.
<p># Voorbeeldvraag
vraag = 'Welke prijs ontving het eerste boek van Gary Zukav?'</p>
<p># Maak een voorspelling met het gecompileerde RAG-programma
prediction = compiled_rag(vraag)
print(f'Vraag: {vraag}')
print(f'Antwoord: {prediction.antwoord}')
print(f'Geretrieerde contexten: {prediction.context}')
Minimale werkende voorbeeld met DSPy
Laten we nu een minimale werkende voorbeeld doorlopen met behulp van de GSM8K-dataset en de OpenAI GPT-3.5-turbo-model om prompttaken binnen DSPy te simuleren.
Setup
Eerst moet u ervoor zorgen dat uw omgeving correct is geconfigureerd:
<p>import dspy from dspy.datasets.gsm8k import GSM8K, gsm8k_metric</p> <p># Stel de LM in turbo = dspy.OpenAI(model='gpt-3.5-turbo-instruct', max_tokens=250) dspy.settings.configure(lm=turbo) # Laad wiskunde-vragen uit de GSM8K-dataset gsm8k = GSM8K() gsm8k_trainset, gsm8k_devset = gsm8k.train[:10], gsm8k.dev[:10] print(gsm8k_trainset)
De gsm8k_trainset en gsm8k_devset datasets bevatten een lijst met voorbeelden waarbij elk voorbeeld een vraag- en antwoordveld heeft.
Definieer de module
Definieer een aangepast programma met behulp van de ChainOfThought-module voor stap-voor-stap-redenering:
<p>class CoT(dspy.Module):
def __init__(self):
super().__init__()
self.prog = dspy.ChainOfThought('vraag -> antwoord')
def forward(self, vraag):
return self.prog(vraag=vraag)
Compileer en evalueer het model
Compileer het nu met de BootstrapFewShot-teleprompter:
<p>from dspy.teleprompt import BootstrapFewShot</p> <p># Stel de optimalisator in config = dict(max_bootstrapped_demos=4, max_labeled_demos=4) # Optimaliseer met de gsm8k_metric teleprompter = BootstrapFewShot(metric=gsm8k_metric, **config) optimized_cot = teleprompter.compile(CoT(), trainset=gsm8k_trainset) # Stel de evaluator in from dspy.evaluate import Evaluate evaluate = Evaluate(devset=gsm8k_devset, metric=gsm8k_metric, num_threads=4, display_progress=True, display_table=0) evaluate(optimized_cot) # Inspecteer de geschiedenis van het model turbo.inspect_history(n=1)
Dit voorbeeld toont hoe u uw omgeving kunt configureren, een aangepaste module kunt definiÃŦren, een model kunt compileren en de prestaties ervan kunt evalueren met behulp van de verstrekte dataset en teleprompter-configuraties.
Gegevensbeheer in DSPy
DSPy werkt met trainings-, ontwikkelings- en testsets. Voor elk voorbeeld in uw gegevens hebt u meestal drie soorten waarden: invoer, tussenliggende labels en finale labels. Hoewel tussenliggende of finale labels optioneel zijn, is het hebben van een paar voorbeeldinvoer essentieel.
CreÃŦren van voorbeeldobjecten
Voorbeeldobjecten in DSPy zijn vergelijkbaar met Python-woordenlijsten, maar ze hebben ook nuttige hulpmiddelen:
<p>qa_pair = dspy.Example(vraag='Dit is een vraag?', antwoord='Dit is een antwoord.')</p> <p>print(qa_pair) print(qa_pair.vraag) print(qa_pair.antwoord)
Uitvoer:
<p>Example({'vraag': 'Dit is een vraag?', 'antwoord': 'Dit is een antwoord.'}) (input_keys=None)
Dit is een vraag?
Dit is een antwoord.
Specificeren van invoersleutels
In DSPy hebben Example-objecten een with_inputs()-methode om specifieke velden te markeren als invoer:
<p>print(qa_pair.with_inputs('vraag'))
print(qa_pair.with_inputs('vraag', 'antwoord'))
Waarden kunnen worden opgehaald met de puntoperator en methoden zoals inputs() en labels() retourneren nieuwe Example-objecten die alleen invoer- of niet-invoersleutels bevatten.
Optimalisatoren in DSPy
Een DSPy-optimalisator stemt de parameters van een DSPy-programma (d.w.z. prompts en/of LM-gewichten) af op een door u gedefinieerde metriek. DSPy biedt verschillende ingebouwde optimalisatoren, waarvan elk een andere strategie gebruikt.
Beschikbare optimalisatoren
- BootstrapFewShot: Genereert few-shot-voorbeelden met behulp van verstrekte gelabelde invoer- en uitvoergegevens.
- BootstrapFewShotWithRandomSearch: Past BootstrapFewShot meerdere keren toe met een willekeurige zoekopdracht over gegenereerde demonstraties.
- COPRO: Genereert en verfijnt nieuwe instructies voor elke stap, waarbij deze worden geoptimaliseerd met behulp van coordinate ascent.
- MIPRO: Optimaliseert instructies en few-shot-voorbeelden met behulp van Bayesian-optimalisatie.
Kiezen van een optimalisator
Als u niet zeker weet waar u moet beginnen, gebruikt u BootstrapFewShotWithRandomSearch:
Gebruik voor zeer weinig gegevens (10 voorbeelden) BootstrapFewShot.
Gebruik voor iets meer gegevens (50 voorbeelden) BootstrapFewShotWithRandomSearch.
Gebruik voor grotere datasets (300+ voorbeelden) MIPRO.
Hieronder ziet u hoe u BootstrapFewShotWithRandomSearch kunt gebruiken:
<p>from dspy.teleprompt import BootstrapFewShotWithRandomSearch</p> <p>config = dict(max_bootstrapped_demos=4, max_labeled_demos=4, num_candidate_programs=10, num_threads=4) teleprompter = BootstrapFewShotWithRandomSearch(metric=YOUR_METRIC_HERE, **config) optimized_program = teleprompter.compile(YOUR_PROGRAM_HERE, trainset=YOUR_TRAINSET_HERE)
Op slaan en laden van geoptimaliseerde programmaâs
Na het uitvoeren van een programma door een optimalisator, slaat u dit op voor toekomstig gebruik:
optimized_program.save(YOUR_SAVE_PATH)
Laad een opgeslagen programma:
<p>loaded_program = YOUR_PROGRAM_CLASS() loaded_program.load(path=YOUR_SAVE_PATH)
Geavanceerde functies: DSPy-asserties
DSPy-asserties automatiseren de handhaving van computationele beperkingen op LLMâs, waardoor de betrouwbaarheid, voorspelbaarheid en correctheid van LM-uitvoer worden verbeterd.
Gebruiken van asserties
Definieer validatiefuncties en declareer asserties na de respectieve modelgeneratie. Bijvoorbeeld:
<p>dspy.Suggest(
len(query) < 100,
'Vraag moet kort en minder dan 100 tekens zijn',
)</p>
<p>dspy.Suggest(
validate_query_distinction_local(prev_queries, query),
'Vraag moet verschillend zijn van: ' + '; '.join(f'{i+1}) {q}' for i, q in enumerate(prev_queries)),
)</p>
Transformeren van programmaâs met asserties
<p>from dspy.primitives.assertions import assert_transform_module, backtrack_handler</p> <p>baleen_with_assertions = assert_transform_module(SimplifiedBaleenAssertions(), backtrack_handler)
Alternatief kunt u asserties rechtstreeks op het programma activeren:
<p>baleen_with_assertions = SimplifiedBaleenAssertions().activate_assertions()
Assertie-gestuurde optimalisaties
DSPy-asserties werken met DSPy-optimalisaties, met name met BootstrapFewShotWithRandomSearch, inclusief instellingen zoals:
- Compileren met asserties
- Compileren + afleiden met asserties
Conclusie
DSPy biedt een krachtige en systematische aanpak voor het optimaliseren van taalmodellen en hun prompts. Door de stappen te volgen die in deze voorbeelden worden beschreven, kunt u complexe AI-systemen bouwen, optimaliseren en evalueren met gemak. De modulaire ontwerp en geavanceerde optimalisatoren van DSPy maken het mogelijk om verschillende taalmodellen efficiÃŦnt en effectief te integreren, waardoor het een waardevol instrument is voor iedereen die werkt in het veld van NLP en AI.
Of u nu een eenvoudig vraagbeantwoordingsysteem of een meer complexe pipeline bouwt, DSPy biedt de flexibiliteit en robuustheid die nodig is om hoge prestaties en betrouwbaarheid te bereiken.












