Connect with us

Prompt engineering

Optimerar LLM med DSPy : En steg-för-steg-guide för att bygga, optimera och utvärdera AI-system

mm
DSPy is a framework for algorithmically optimizing LM prompts and weights

Allteftersom förmågan hos stora språkmodeller (LLM) fortsätter att expandera, har utvecklingen av robusta AI-system som utnyttjar deras potential blivit alltmer komplex. Traditionella tillvägagångssätt innebär ofta invecklade prompttekniker, datagenerering för finjustering och manuell vägledning för att säkerställa efterlevnad av domänspecifika begränsningar. Detta process kan dock vara tidskrävande, felbenägen och starkt beroende av mänskligt ingripande.

Här kommer DSPy, ett revolutionerande ramverk som är utformat för att strömlinjeforma utvecklingen av AI-system som drivs av LLM. DSPy introducerar en systematisk metod för att optimera LM-prompt och vikter, vilket möjliggör för utvecklare att bygga avancerade applikationer med minimal manuell ansträngning.

I den här omfattande guiden kommer vi att utforska DSPys kärnprinciper, dess modulära arkitektur och den uppsättning kraftfulla funktioner som det erbjuder. Vi kommer också att dyka in i praktiska exempel och demonstrera hur DSPy kan förvandla sättet du utvecklar AI-system med LLM.

Vad är DSPy, och varför behöver du det?

DSPy är ett ramverk som separerar programmets flöde (moduler) från parametrarna (LM-prompt och vikter) för varje steg. Denna separation möjliggör en systematisk optimering av LM-prompt och vikter, vilket möjliggör för dig att bygga komplexa AI-system med större tillförlitlighet, förutsägbarhet och efterlevnad av domänspecifika begränsningar.

Traditionellt har utvecklingen av AI-system med LLM inneburit en mödosam process som består i att bryta ned problemet i steg, skapa invecklade prompt för varje steg, generera syntetiska exempel för finjustering och manuellt vägleda LLM till att följa specifika begränsningar. Detta tillvägagångssätt var inte bara tidskrävande utan också benäget för fel, eftersom även små förändringar i pipelinen, LM eller data kunde kräva omfattande omarbete av prompt och finjusteringssteg.

DSPy möter dessa utmaningar genom att introducera en ny paradigm: optimerare. Dessa LM-drivna algoritmer kan justera prompt och vikter för dina LM-anrop, givet en mått som du vill maximera. Genom att automatisera optimeringsprocessen ger DSPy utvecklare möjlighet att bygga robusta AI-system med minimal manuell inblandning, vilket förbättrar tillförlitligheten och förutsägbarheten hos LM-utdata.

DSPys modulära arkitektur

I hjärtat av DSPy ligger en modulär arkitektur som underlättar kompositionen av komplexa AI-system. Ramverket tillhandahåller en uppsättning inbyggda moduler som abstraherar olika prompttekniker, såsom dspy.ChainOfThought och dspy.ReAct. Dessa moduler kan kombineras och sammansättas till större program, vilket möjliggör för utvecklare att bygga invecklade pipeliner anpassade till deras specifika krav.

Varje modul inkapslar lärande parametrar, inklusive instruktioner, få-skottsexempel och LM-vikter. När en modul anropas kan DSPys optimerare finjustera dessa parametrar för att maximera den önskade mått, vilket säkerställer att LM-utdata följer de angivna begränsningarna och kraven.

Optimering med DSPy

DSPy introducerar en rad kraftfulla optimerare som är utformade för att förbättra prestandan och tillförlitligheten hos dina AI-system. Dessa optimerare utnyttjar LM-drivna algoritmer för att justera prompt och vikter för dina LM-anrop, vilket maximalt den angivna mått medan de följer domänspecifika begränsningar.

Några av de viktigaste optimerarna som finns tillgängliga i DSPy inkluderar:

  1. BootstrapFewShot: Denna optimerare utökar signaturerna genom att automatiskt generera och inkludera optimerade exempel inom prompten som skickas till modellen, vilket implementerar få-skottslärande.
  2. BootstrapFewShotWithRandomSearch: Tillämpar BootstrapFewShot flera gånger med slumpmässig sökning över genererade demonstrationer, och väljer det bästa programmet under optimeringen.
  3. MIPRO: Genererar instruktioner och få-skottsexempel i varje steg, där instruktionsgenereringen är data-medveten och demonstrations-medveten. Det använder Bayesian Optimization för att effektivt söka över utrymmet för generations-instruktioner och demonstrationer över dina moduler.
  4. BootstrapFinetune: Destillerar ett prompt-baserat DSPy-program till viktuppdateringar för mindre LLM, vilket möjliggör för dig att finjustera den underliggande LLM för förbättrad effektivitet.

Genom att utnyttja dessa optimerare kan utvecklare systematiskt optimera sina AI-system, vilket säkerställer högkvalitativa utdata medan de följer domänspecifika begränsningar och krav.

Komma igång med DSPy

För att illustrera kraften i DSPy, låt oss gå igenom ett praktiskt exempel på att bygga ett system för förstärkt generation (RAG) för frågesvar.

Steg 1: Konfigurera språkmodellen och återställningsmodellen

Det första steget innebär att konfigurera språkmodellen (LM) och återställningsmodellen (RM) inom DSPy.

För att installera DSPy, kör:


pip install dspy-ai

DSPy stöder flera LM- och RM-API:er, samt lokalt modellvärd, vilket gör det enkelt att integrera dina föredragna modeller.


import dspy

# Konfigurera LM och RM
turbo = dspy.OpenAI(model='gpt-3.5-turbo')
colbertv2_wiki17_abstracts = dspy.ColBERTv2(url='http://20.102.90.50:2017/wiki17_abstracts')

dspy.settings.configure(lm=turbo, rm=colbertv2_wiki17_abstracts)

Steg 2: Ladda datasetet

Nästa steg är att ladda HotPotQA-datasetet, som innehåller en samling komplexa fråga-svar-par som vanligtvis besvaras på ett multi-hopp-sätt.


from dspy.datasets import HotPotQA

# Ladda datasetet
dataset = HotPotQA(train_seed=1, train_size=20, eval_seed=2023, dev_size=50, test_size=0)

# Ange 'fråga'-fältet som indata
trainset = [x.with_inputs('fråga') for x in dataset.train]
devset = [x.with_inputs('fråga') for x in dataset.dev]

Steg 3: Bygga signaturer

DSPy använder signaturer för att definiera beteendet hos moduler. I det här exemplet kommer vi att definiera en signatur för uppgiften att generera svar, som specificerar indatafälten (kontext och fråga) och utdatafältet (svar).


class GenerateAnswer(dspy.Signature):
"""Svara på frågor med korta faktoid-svar."""

kontext = dspy.InputField(desc="kan innehålla relevanta fakta")
fråga = dspy.InputField()
svar = dspy.OutputField(desc="ofta mellan 1 och 5 ord")

Steg 4: Bygga pipelinen

Vi kommer att bygga vår RAG-pipeline som en DSPy-modul, som består av en initieringsmetod (__init__) för att deklarera undermoduler (dspy.Retrieve och dspy.ChainOfThought) och en framåtriktad metod (forward) för att beskriva kontrollflödet för att svara på frågan med hjälp av dessa moduler.


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, fråga):
kontext = self.retrieve(fråga).passages
prediktion = self.generate_answer(kontext=kontext, fråga=fråga)
return dspy.Prediction(kontext=kontext, svar=prediktion.svar)

Steg 5: Optimera pipelinen

Med pipelinen definierad kan vi nu optimera den med hjälp av DSPys optimerare. I det här exemplet kommer vi att använda BootstrapFewShot-optimera, som genererar och väljer effektiva prompt för våra moduler baserat på en träningsuppsättning och en mått för validering.


from dspy.teleprompt import BootstrapFewShot

# Valideringsmått
def validera_kontext_och_svar(exempel, pred, spår=None):
svar_EM = dspy.evaluate.svar_exakt_match(exempel, pred)
svar_PM = dspy.evaluate.svar_passage_match(exempel, pred)
return svar_EM and svar_PM

# Ställ in optimeraren
teleprompter = BootstrapFewShot(metric=validera_kontext_och_svar)

# Kompilera programmet
kompilerat_rag = teleprompter.compile(RAG(), trainset=trainset)

Steg 6: Utvärdera pipelinen

Efter att ha kompilerat programmet är det viktigt att utvärdera dess prestanda på en utvecklingsuppsättning för att säkerställa att det uppfyller önskad noggrannhet och tillförlitlighet.


from dspy.evaluate import Evaluate

# Ställ in utvärderaren
utvärdera = Evaluate(devset=devset, metric=validera_kontext_och_svar, num_threads=4, display_progress=True, display_table=0)

# Utvärdera det kompilerade RAG-programmet
utvärderingsresultat = utvärdera(kompilerat_rag)

print(f"Utvärderingsresultat: {utvärderingsresultat}")

Steg 7: Inspektera modellens historia

För en djupare förståelse av modellens interaktioner kan du granska de senaste generationerna genom att inspektera modellens historia.


# Inspektera modellens historia
turbo.inspektera_historia(n=1)

Steg 8: Gör förutsägelser

Med pipelinen optimerad och utvärderad kan du nu använda den för att göra förutsägelser på nya frågor.


# Exempelfråga
fråga = "Vilket pris fick Gary Zukavs första bok?"

# Gör en förutsägelse med det kompilerade RAG-programmet
förutsägelse = kompilerat_rag(fråga)

print(f"Fråga: {fråga}")
print(f"Svar: {förutsägelse.svar}")
print(f"Återställda kontexter: {förutsägelse.kontext}")

Minimalt fungerande exempel med DSPy

Nu, låt oss gå igenom ett annat minimalt fungerande exempel med hjälp av GSM8K-datasetet och OpenAI GPT-3.5-turbo-modellen för att simulera prompt-uppgifter inom DSPy.

Setup

Först, se till att din miljö är korrekt konfigurerad:


import dspy
from dspy.datasets.gsm8k import GSM8K, gsm8k_metric

# Ställ in LM
turbo = dspy.OpenAI(model='gpt-3.5-turbo-instruct', max_tokens=250)
dspy.settings.configure(lm=turbo)

# Ladda matematikfrågor från GSM8K-datasetet
gsm8k = GSM8K()
gsm8k_trainset, gsm8k_devset = gsm8k.train[:10], gsm8k.dev[:10]

print(gsm8k_trainset)

Jag har under de senaste fem åren dykt ner i den fascinerande världen av Machine Learning och Deep Learning. Min passion och expertis har lett mig till att bidra till över 50 olika mjukvaruutvecklingsprojekt, med särskild fokus på AI/ML. Min pågående nyfikenhet har också dragit mig mot Natural Language Processing, ett område som jag är angelägen om att utforska vidare.