Prompt engineering
Optimer LLM med DSPy: En trinnvis guide til å bygge, optimere og evaluere AI-systemer
Ettersom evnene til store språkmodeller (LLM) fortsetter å utvides, har utvikling av robuste AI-systemer som utnytter deres potensiale blitt stadig mer kompleks. Konvensjonelle metoder innebærer ofte intrikate prompt-teknikker, datagenerering for finjustering og manuell veiledning for å sikre overholdelse av domenespesifikke begrensninger. Dette prosessen kan være tidskrevende, feilfølsom og sterkt avhengig av menneskelig inngripen.
DSPy er et revolusjonerende rammeverk designet for å forenkle utviklingen av AI-systemer drevet av LLM. DSPy innfører en systematisk tilnærming til å optimere LM-prompter og vekter, som muliggjør utviklere å bygge sofistikerte applikasjoner med minimal manuell innsats.
I denne omfattende guiden vil vi utforske de grunnleggende prinsippene i DSPy, dens modulære arkitektur og de kraftfulle funksjonene det tilbyr. Vi vil også dykke ned i praktiske eksempler som demonstrerer hvordan DSPy kan transformere måten du utvikler AI-systemer med LLM.
Hva er DSPy, og hvorfor trenger du det?
DSPy er et rammeverk som skiller programstrømmen fra parameterne (LM-prompter og vekter) for hver enkelt trinn. Denne skille muliggjør en systematisk optimalisering av LM-prompter og vekter, som gjør det mulig å bygge komplekse AI-systemer med større pålitelighet, forutsigbarhet og overholdelse av domenespesifikke begrensninger.
Tradisjonelt har utvikling av AI-systemer med LLM innebærer en tidskrevende prosess med å bryte ned problemet i trinn, lage intrikate prompter for hvert trinn, generere syntetiske eksempler for finjustering og manuell veiledning for å sikre overholdelse av bestemte begrensninger. Denne tilnærmingen var ikke bare tidskrevende, men også feilfølsom, da selv små endringer i røret, LM eller data kunne nødvendiggjøre omfattende omarbeidelse av prompter og finjusteringstrinn.
DSPy møter disse utfordringene ved å innføre en ny paradigme: optimalisatorer. Disse LM-drevne algoritmene kan finjustere promptene og vektene for LM-kall, gitt en metode du ønsker å maksimere. Ved å automatisere optimaliseringsprosessen, gir DSPy utviklere mulighet til å bygge robuste AI-systemer med minimal manuell inngripen, og forbedrer påliteligheten og forutsigbarheten av LM-utdata.
DSPy’s modulære arkitektur
I hjertet av DSPy ligger en modulær arkitektur som muliggjør komposisjon av komplekse AI-systemer. Rammeverket tilbyr en rekke innebygde moduler som abstraherer ulike prompt-teknikker, som dspy.ChainOfThought og dspy.ReAct. Disse modulene kan kombineres og komponeres til større programmer, som muliggjør utviklere å bygge intrikate rør tilpasset deres spesifikke krav.
Hver modul inkapslerer lærbare parametre, inkludert instruksjoner, få-shot-eksempler og LM-vektorer. Når en modul aktiveres, kan DSPy’s optimalisatorer finjustere disse parameterne for å maksimere den ønskede metoden, og sikre at LM-utdataene overholder de spesifiserte begrensningene og kravene.
Optimere med DSPy
DSPy innfører en rekke kraftfulle optimalisatorer designet for å forbedre ytelsen og påliteligheten av dine AI-systemer. Disse optimalisatorene utnytter LM-drevne algoritmer for å finjustere promptene og vektene for LM-kall, og maksimere den spesifiserte metoden mens de overholder domenespesifikke begrensninger.
Noen av de viktigste optimalisatorene som er tilgjengelige i DSPy inkluderer:
- BootstrapFewShot: Denne optimalisatoren utvider signaturer ved å automatisk generere og inkludere optimerte eksempler i prompten som sendes til modellen, og implementerer få-shot-læring.
- BootstrapFewShotWithRandomSearch: Denne optimalisatoren anvender
BootstrapFewShotflere ganger med tilfeldig søk over genererte demonstrasjoner, og velger det beste programmet over optimaliseringen. - MIPRO: Denne optimalisatoren genererer instruksjoner og få-shot-eksempler i hvert trinn, med instruksjonsgenerering som er data- og demonstrasjonsbevisst. Den bruker Bayesian-Optimizing for å effektivt søke over rommet av genereringsinstruksjoner og demonstrasjoner over modulene.
- BootstrapFinetune: Denne optimalisatoren destillerer en prompt-basert DSPy-program til vektoppdateringer for mindre LM, og muliggjør finjustering av underliggende LLM for bedre effisiens.
Ved å utnytte disse optimalisatorene, kan utviklere systematisk optimere sine AI-systemer, og sikre høykvalitetsutdata mens de overholder domenespesifikke begrensninger og krav.
Komme i gang med DSPy
For å illustrere kraften til DSPy, la oss gå gjennom et praktisk eksempel på å bygge et retrieval-augmentert genereringsystem (RAG) for spørsmål-svar.
Trinn 1: Konfigurere språkmodellen og hentingmodellen
Det første trinnet innebærer å konfigurere språkmodellen (LM) og hentingmodellen (RM) i DSPy.
For å installere DSPy, kjør:
pip install dspy-ai
DSPy støtter flere LM- og RM-API-er, samt lokale modellhåndtering, og gjør det enkelt å integrere dine foretrukne modeller.
import dspy <p># Konfigurer LM og 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>
Trinn 2: Last inn datasettet
Neste trinn er å laste inn HotPotQA-datasettet, som inneholder en samling komplekse spørsmål-svar-par som vanligvis besvares på en multi-hop-måte.
from dspy.datasets import HotPotQA
<p># Last inn datasettet
dataset = HotPotQA(train_seed=1, train_size=20, eval_seed=2023, dev_size=50, test_size=0)</p>
<p># Spesifiser 'spørsmål'-feltet som inndata
trainset = [x.with_inputs('spørsmål') for x in dataset.train]
devset = [x.with_inputs('spørsmål') for x in dataset.dev]</p>
Trinn 3: Bygge signaturer
DSPy bruker signaturer for å definere oppførselen til moduler. I dette eksemplet vil vi definere en signatur for oppgaven å generere svar, og spesifisere inndatafeltene (kontekst og spørsmål) og utdatafeltet (svar).
<p>class GenerateAnswer(dspy.Signature): """Besvar spørsmål med korte faktoid-svar.""" kontekst = dspy.InputField(desc="kan inneholde relevante fakta") spørsmål = dspy.InputField() svar = dspy.OutputField(desc="ofte mellom 1 og 5 ord")
Trinn 4: Bygge røret
Vi vil bygge vårt RAG-rør som en DSPy-modul, som består av en init-metode for å erklære undermoduler (dspy.Retrieve og dspy.ChainOfThought) og en forward-metode for å beskrive kontrollflyten for å besvare spørsmålet ved hjelp av disse modulene.
<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, spørsmål): kontekst = self.retrieve(spørsmål).passages prediksjon = self.generate_answer(kontekst=kontekst, spørsmål=spørsmål) return dspy.Prediction(kontekst=kontekst, svar=prediksjon.svar)
Trinn 5: Optimere røret
Med røret definert, kan vi nå optimere det ved hjelp av DSPy’s optimalisatorer. I dette eksemplet vil vi bruke BootstrapFewShot-optimatisatoren, som genererer og velger effektive prompter for våre moduler basert på et treningssett og en metode for validering.
<p>from dspy.teleprompt import BootstrapFewShot</p> <p># Valideringsmetode def valider_kontekst_og_svar(eksempel, pred, spor=None): svar_EM = dspy.evaluate.svar_nøyaktig_treffe(eksempel, pred) svar_PM = dspy.evaluate.svar_passasje_treffe(eksempel, pred) return svar_EM and svar_PM</p> <p># Sett opp optimalisatoren teleprompter = BootstrapFewShot(metric=valider_kontekst_og_svar)</p> <p># Kompilér programmet kompilert_rag = teleprompter.compile(RAG(), trainset=trainset)</p>
Trinn 6: Evaluere røret
Etter å ha kompilert programmet, er det viktig å evaluere dets ytelse på et utviklingssett for å sikre at det møter de ønskede kravene til nøyaktighet og pålitelighet.
from dspy.evaluate import Evaluate
<p># Sett opp evaluator
evaluate = Evaluate(devset=devset, metric=valider_kontekst_og_svar, num_threads=4, display_progress=True, display_table=0)</p>
<p># Evaluér det kompilerte RAG-programmet
evalueringsresultat = evaluate(kompilert_rag)</p>
<p>print(f"Evaluering Resultat: {evalueringsresultat}")</p>
Trinn 7: Inspectere modellhistorikk
For en dypere forståelse av modellens interaksjoner, kan du se på de siste genereringene ved å inspisere modellens historikk.
<p># Inspecter modellens historikk turbo.inspect_history(n=1)</p>
Trinn 8: Gjøre prediksjoner
Med røret optimert og evaluert, kan du nå bruke det til å gjøre prediksjoner på nye spørsmål.
<p># Eksempel-spørsmål
spørsmål = "Hva er tittelen på Gary Zukavs første bok?"</p>
<p># Gjør en prediksjon ved hjelp av det kompilerte RAG-programmet
prediksjon = kompilertrag(spørsmål)</p>
<p>print(f"Spørsmål: {spørsmål}")
print(f"Svar: {prediksjon.svar}")
print(f"Hentede kontekster: {prediksjon.kontekst}")</p>
Minimalt arbeids eksempel med DSPy
La oss nå gå gjennom et annet minimalt arbeids eksempel som bruker GSM8K-datasettet og OpenAI GPT-3.5-turbo-modellen for å simulere prompt-oppdrag i DSPy.
Oppsett
Først må du sikre at din miljø er korrekt konfigurert:
<p>import dspy from dspy.datasets.gsm8k import GSM8K, gsm8k_metric</p> <p># Sett opp LM turbo = dspy.OpenAI(model='gpt-3.5-turbo-instruct', max_tokens=250) dspy.settings.configure(lm=turbo)</p> <p># Last inn matematikk-spørsmål fra GSM8K-datasettet gsm8k = GSM8K() gsm8k_trainset, gsm8k_devset = gsm8k.train[:10], gsm8k.dev[:10]</p> print(gsm8k_trainset)
Definere modulen
Neste trinn er å definere en egen program som bruker ChainOfThought-modulen for stegvis resonnering:
<p>class CoT(dspy.Module):
def __init__(self):
super().__init__()
self.prog = dspy.ChainOfThought("spørsmål -> svar")
def forward(self, spørsmål):
return self.prog(spørsmål=spørsmål)</p>
Kompilér og evaluér modellen
Nå kan du kompilere det med BootstrapFewShot-teleprompteren:
<p>from dspy.teleprompt import BootstrapFewShot</p> <p># Sett opp optimalisatoren config = dict(max_bootstrapped_demos=4, max_labeled_demos=4)</p> <p># Optimér med gsm8k-metrikken teleprompter = BootstrapFewShot(metric=gsm8k_metric, **config) optimalt_cot = teleprompter.compile(CoT(), trainset=gsm8k_trainset)</p> <p># Sett opp evaluator from dspy.evaluate import Evaluate</p> <p>evaluate = Evaluate(devset=gsm8k_devset, metric=gsm8k_metric, num_threads=4, display_progress=True, display_table=0) evaluate(optimalt_cot)</p> <p># Inspecter modellens historikk turbo.inspect_history(n=1)</p>
Dette eksemplet demonstrerer hvordan du kan sette opp din miljø, definere en egen modul, kompilere en modell og grundig evaluere dens ytelse ved hjelp av det tilgjengelige datasettet og teleprompt-konfigurasjonene.
Datahåndtering i DSPy
DSPy opererer med trenings-, utviklings- og testsett. For hvert eksempel i dine data, har du vanligvis tre typer verdier: inndata, mellomliggende etiketter og endelige etiketter. Mens mellomliggende eller endelige etiketter er valgfrie, er det viktig å ha noen få eksempel-inndata.
Opprette eksempel-objekter
Eksempel-objekter i DSPy er lignende Python-ordbøker, men kommer med nyttige verktøy:
<p>qa_par = dspy.Example(spørsmål="Dette er et spørsmål?", svar="Dette er et svar.")</p> <p>print(qa_par) print(qa_par.spørsmål) print(qa_par.svar)</p>
Utdata:
<p>Eksempel({'spørsmål': 'Dette er et spørsmål?', 'svar': 'Dette er et svar.'}) (inndata_nøkler=None)
Dette er et spørsmål?
Dette er et svar.</p>
Spesifisere inndata-nøkler
I DSPy har eksempel-objekter en metode for å markere bestemte felt som inndata:
<p>print(qa_par.with_inputs("spørsmål"))
print(qa_par.with_inputs("spørsmål", "svar"))</p>
Verdier kan aksesseres ved hjelp av punkt-operatoren, og metoder som inputs() og labels() returnerer nye eksempel-objekter som inneholder bare inndata eller ikke-inndata-nøkler.
Optimalisatorer i DSPy
En DSPy-optimalisator finjusterer parameterne til et DSPy-program (dvs. prompter og/eller LM-vektorer) for å maksimere spesifiserte metrikker. DSPy tilbyr flere innebygde optimalisatorer, hver med ulike strategier.
Tilgjengelige optimalisatorer
- BootstrapFewShot: Genererer få-shot-eksempler ved hjelp av labeled inndata og utdata-punkter.
- BootstrapFewShotWithRandomSearch: Anvender BootstrapFewShot flere ganger med tilfeldig søk over genererte demonstrasjoner.
- COPRO: Genererer og finjusterer nye instruksjoner for hvert trinn, og optimaliserer dem med koordinat-stigning.
- MIPRO: Optimerer instruksjoner og få-shot-eksempler ved hjelp av Bayesian-Optimizing.
Velge en optimalisator
Hvis du er usikker på hvor du skal starte, bruk BootstrapFewShotWithRandomSearch:
For svært lite data (10 eksempler), bruk BootstrapFewShot.
For litt mer data (50 eksempler), bruk BootstrapFewShotWithRandomSearch.
For større datasett (300+ eksempler), bruk MIPRO.
Her er hvordan du kan bruke BootstrapFewShotWithRandomSearch:
<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=DIN_METRIKK_HER, **config) optimalt_program = teleprompter.compile(DITT_PROGRAM_HER, trainset=DITT_TRENINGSSETT_HER)</p>
Lagre og last inn optimaliserte programmer
Etter å ha kjørt et program gjennom en optimalisator, kan du lagre det for fremtidig bruk:
optimalt_program.save(DITT_LAGRINGSSTI)
Last inn et lagret program:
<p>lastet_inn_program = DITT_PROGRAMKLASS() lastet_inn_program.load(path=DITT_LAGRINGSSTI)</p>
Avanserte funksjoner: DSPy-påstander
DSPy-påstander automatiserer håndhevingen av beregningsbegrensninger på LM, og forbedrer påliteligheten, forutsigbarheten og riktigheten av LM-utdata.
Bruke påstander
Definér valideringsfunksjoner og erklær påstander etter modellgenereringen. For eksempel:
<p>dspy.Suggest(
len(spørsmål) <= 100,
"Spørsmål skal være kort og mindre enn 100 tegn",
)</p>
<p>dspy.Suggest(
valider_spørsmål_distinksjon_local(forrige_spørsmål, spørsmål),
"Spørsmål skal være distinkt fra: " + "; ".join(f"{i+1}) {q}" for i, q in enumerate(forrige_spørsmål)),
)</p>
Transformere programmer med påstander
<p>from dspy.primitives.assertions import assert_transform_module, backtrack_handler</p> <p>baleen_med_påstander = assert_transform_module(SimplifiedBaleenAssertions(), backtrack_handler)</p>
Alternativt kan du aktivere påstander direkte på programmet:
<p>baleen_med_påstander = SimplifiedBaleenAssertions().activate_assertions()</p>
Påstand-drevne optimaliseringer
DSPy-påstander fungerer med DSPy-optimaliseringer, spesielt med BootstrapFewShotWithRandomSearch, inkludert innstillinger som:
- Kompilering med påstander
- Kompilering + inferens med påstander
Konklusjon
DSPy tilbyr en kraftfull og systematisk tilnærming til å optimere språkmodeller og deres prompter. Ved å følge trinnene i disse eksemplene, kan du bygge, optimere og evaluere komplekse AI-systemer med lettighet. DSPy’s modulære design og avanserte optimalisatorer muliggjør effektiv og effektiv integrering av ulike språkmodeller, og gjør det til et verdifullt verktøy for alle som arbeider i feltet NLP og AI.
Uansett om du bygger et enkelt spørsmål-svar-system eller et mer komplekst rør, tilbyr DSPy fleksibilitet og robusthet for å oppnå høy ytelse og pålitelighet.












