Prompt engineering

Optimaliseer LLM met DSPy: een stap-voor-stap gids voor het bouwen, optimaliseren en evalueren van AI-systemen

mm
Voeg Unite.AI toe aan je voorkeursbronnen op Google
DSPy is a framework for algorithmically optimizing LM prompts and weights

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:

  1. 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.
  2. BootstrapFewShotWithRandomSearch: Past BootstrapFewShot meerdere keren toe met een willekeurige zoekopdracht over gegenereerde demonstraties, waarbij het beste programma over de optimalisatie wordt geselecteerd.
  3. 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.
  4. 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):
&quot;&quot;&quot;Beantwoord vragen met korte feitenvragen.&quot;&quot;&quot;</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 -&gt; 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) &lt; 100,
&#039;Vraag moet kort en minder dan 100 tekens zijn&#039;,
)</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.

Ik heb de afgelopen vijf jaar doorgebracht met het onderdompelen van mezelf in de fascinerende wereld van Machine Learning en Deep Learning. Mijn passie en expertise hebben me geleid om bij te dragen aan meer dan 50 diverse software-engineeringprojecten, met een bijzondere focus op AI/ML. Mijn voortdurende nieuwsgierigheid heeft me ook aangetrokken tot Natural Language Processing, een vakgebied dat ik graag verder wil verkennen.