Prompt engineering

Optimizează LLM cu DSPy: Un ghid pas cu pas pentru a construi, optimiza și evalua sisteme AI

mm
Adaugă Unite.AI la sursele tale preferate pe Google
DSPy is a framework for algorithmically optimizing LM prompts and weights

Pe măsură ce capacitățile modelelor de limbaj mare (LLM) continuă să se extindă, dezvoltarea unor sisteme robuste de inteligență artificială (AI) care să exploateze potențialul lor a devenit din ce în ce mai complexă. Abordările convenționale implică adesea tehnici de promptare intricate, generare de date pentru fine-tuning și îndrumare manuală pentru a asigura respectarea constrângerilor specifice domeniului. Cu toate acestea, acest proces poate fi laborios, predispus la erori și puternic dependent de intervenția umană.

Intră în scenă DSPy, un cadru revoluționar proiectat pentru a simplifica dezvoltarea sistemelor de inteligență artificială alimentate de LLM. DSPy introduce o abordare sistematică pentru optimizarea prompturilor și a greutăților LM, permițând dezvoltatorilor să construiască aplicații sofisticate cu efort minim.

În acest ghid cuprinzător, vom explora principiile de bază ale DSPy, arhitectura sa modulară și varietatea de funcții puternice pe care le oferă. De asemenea, vom prezenta exemple practice, demonstrând cum DSPy poate transforma modul în care dezvoltați sisteme de inteligență artificială cu LLM.

Ce este DSPy și de ce aveți nevoie de el?

DSPy este un cadru care separă fluxul programului dvs. (module) de parametrii (prompturi LM și greutăți) fiecărui pas. Această separare permite optimizarea sistematică a prompturilor și a greutăților LM, permițându-vă să construiți sisteme complexe de inteligență artificială cu o mai mare fiabilitate, previzibilitate și respectare a constrângerilor specifice domeniului.

În mod tradițional, dezvoltarea sistemelor de inteligență artificială cu LLM a implicat un proces laborios de descompunere a problemei în pași, creare de prompturi complexe pentru fiecare pas, generare de exemple sintetice pentru fine-tuning și îndrumare manuală a LLM pentru a respecta anumite constrângeri. Această abordare nu a fost doar timp-consuming, ci și predispusă la erori, deoarece chiar și modificări minore ale pipeline-ului, LM sau datelor ar fi putut necesita o re lucru extinsă a prompturilor și a pașilor de fine-tuning.

DSPy abordează aceste provocări prin introducerea unui nou paradigme: optimizatori. Acești algoritmi condusi de LM pot ajusta prompturile și greutățile apelurilor LM, date fiind o metrică pe care doriți să o maximizați. Prin automatizarea procesului de optimizare, DSPy împuternicește dezvoltatorii să construiască sisteme robuste de inteligență artificială cu intervenție minimă, îmbunătățind fiabilitatea și previzibilitatea ieșirilor LM.

Arhitectura modulară a DSPy

La baza DSPy se află o arhitectură modulară care facilitează compunerea sistemelor complexe de inteligență artificială. Cadru oferă o serie de module încorporate care abstractizează diverse tehnici de promptare, cum ar fi dspy.ChainOfThought și dspy.ReAct. Aceste module pot fi combinate și compuse în programe mai mari, permițând dezvoltatorilor să construiască pipeline-uri complexe personalizate pentru cerințele lor specifice.

Fiecare modul encapsulează parametri învățați, inclusiv instrucțiuni, exemple de few-shot și greutăți LM. Când un modul este invocat, optimizatorii DSPy pot ajusta acești parametri pentru a maximiza metrica dorită, asigurând că ieșirile LM respectă constrângerile și cerințele specificate.

Optimizarea cu DSPy

DSPy introduce o serie de optimizatori puternici proiectați pentru a îmbunătăți performanța și fiabilitatea sistemelor dvs. de inteligență artificială. Acești optimizatori utilizează algoritmi condusi de LM pentru a ajusta prompturile și greutățile apelurilor LM, maximizând metrica specificată și respectând constrângerile specifice domeniului.

Printre optimizatorii disponibili în DSPy se numără:

  1. BootstrapFewShot: Acest optimizator extinde semnătura prin generarea și includerea automată a exemplelor optimizate în promptul trimis modelului, implementând învățarea few-shot.
  2. BootstrapFewShotWithRandomSearch: Apliquează BootstrapFewShot de mai multe ori cu o căutare aleatoare a demonstrațiilor generate, selectând cel mai bun program pe parcursul optimizării.
  3. MIPRO: Generează instrucțiuni și exemple de few-shot la fiecare pas, instrucțiunile de generare fiind conștiente de date și demonstrații. Utilizează optimizarea Bayesiană pentru a căuta eficient spațiul de generare a instrucțiunilor și demonstrațiilor de-a lungul modulelor dvs.
  4. BootstrapFinetune: Distilează un program DSPy bazat pe prompt în actualizări de greutate pentru LLM mai mici, permițându-vă să fine-tuneți LLM subiacent pentru o eficiență îmbunătățită.

Prin utilizarea acestor optimizatori, dezvoltatorii pot optimiza sistematic sistemele lor de inteligență artificială, asigurând ieșiri de înaltă calitate și respectând constrângerile și cerințele specifice domeniului.

Începerea cu DSPy

Pentru a ilustra puterea DSPy, să trecem printr-un exemplu practic de construire a unui sistem de generare augmentat cu recuperare (RAG) pentru întrebări și răspunsuri.

Pașul 1: Configurarea modelului de limbaj și a modelului de recuperare

Primul pas implică configurarea modelului de limbaj (LM) și a modelului de recuperare (RM) în cadrul DSPy.

Pentru a instala DSPy, rulați:

“`python
pip install dspy-ai
“`

DSPy acceptă multiple API-uri LM și RM, precum și găzduire locală de modele, ceea ce face ușor să integrați modelele dvs. preferate.

“`python
import dspy

# Configurați LM și 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)
“`

Pașul 2: Încărcarea setului de date

Următorul pas implică încărcarea setului de date HotPotQA, care conține o colecție de perechi de întrebări și răspunsuri complexe, de obicei răspunsuri într-un mod multi-hop.

“`python
from dspy.datasets import HotPotQA

# Încărcați setul de date
dataset = HotPotQA(train_seed=1, train_size=20, eval_seed=2023, dev_size=50, test_size=0)

# Specificați câmpul ‘întrebare’ ca intrare
trainset = [x.with_inputs(‘întrebare’) for x in dataset.train]
devset = [x.with_inputs(‘întrebare’) for x in dataset.dev]
“`

Pașul 3: Construirea semnăturilor

DSPy utilizează semnături pentru a defini comportamentul modulelor. În acest exemplu, vom defini o semnătură pentru sarcina de generare a răspunsurilor, specificând câmpurile de intrare (context și întrebare) și câmpul de ieșire (răspuns).

“`python
class GenerateAnswer(dspy.Signature):
“””Răspunde la întrebări cu răspunsuri scurte și factuale.”””
context = dspy.InputField(desc=”poate conține fapte relevante”)
întrebare = dspy.InputField()
răspuns = dspy.OutputField(desc=”de obicei între 1 și 5 cuvinte”)
“`

Pașul 4: Construirea pipeline-ului

Vom construi pipeline-ul nostru RAG ca un modul DSPy, care constă într-o metodă de inițializare (__init__) pentru a declara submodulele (dspy.Retrieve și dspy.ChainOfThought) și o metodă forward (forward) pentru a descrie fluxul de control al răspunsului la întrebare utilizând aceste module.

“`python
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, întrebare):
context = self.retrieve(întrebare).passages
predicție = self.generate_answer(context=context, întrebare=întrebare)
return dspy.Prediction(context=context, răspuns=predicție.răspuns)
“`

Pașul 5: Optimizarea pipeline-ului

Cu pipeline-ul definit, putem acum să-l optimizăm utilizând optimizatorii DSPy. În acest exemplu, vom utiliza optimizatorul BootstrapFewShot, care generează și selectează prompturi eficiente pentru modulele noastre pe baza unui set de antrenare și a unei metrice de validare.

“`python
from dspy.teleprompt import BootstrapFewShot

# Metrică de validare
def validate_context_and_answer(exemplu, pred, urmă=None):
answer_EM = dspy.evaluate.answer_exact_match(exemplu, pred)
answer_PM = dspy.evaluate.answer_passage_match(exemplu, pred)
return answer_EM și answer_PM

# Configurați optimizatorul
teleprompter = BootstrapFewShot(metric=validate_context_and_answer)

# Compilați programul
compiled_rag = teleprompter.compile(RAG(), trainset=trainset)
“`

Pașul 6: Evaluarea pipeline-ului

După compilarea programului, este esențial să evaluăm performanța sa pe un set de dezvoltare pentru a ne asigura că îndeplinește acuratețea și fiabilitatea dorită.

“`python
from dspy.evaluate import Evaluate

# Configurați evaluatorul
evaluate = Evaluate(devset=devset, metric=validate_context_and_answer, num_threads=4, display_progress=True, display_table=0)

# Evaluati programul RAG compilat
evaluation_result = evaluate(compiled_rag)

print(f”Evaluare Rezultat: {evaluation_result}”)
“`

Pașul 7: Inspectarea istoricului modelului

Pentru o înțelegere mai profundă a interacțiunilor modelului, puteți revizui generațiile cele mai recente prin inspectarea istoricului modelului.

“`python
# Inspectați istoricul modelului
turbo.inspect_history(n=1)
“`

Pașul 8: Facerea predicțiilor

Cu pipeline-ul optimizat și evaluat, puteți acum să-l utilizați pentru a face predicții pe întrebări noi.

“`python
# Exemplu de întrebare
întrebare = “Care a fost premiul acordat primei cărți a lui Gary Zukav?”

# Faceți o predicție utilizând programul RAG compilat
predicție = compiled_rag(întrebare)

print(f”Întrebare: {întrebare}”)
print(f”Răspuns: {predicție.răspuns}”)
print(f”Contexte recuperate: {predicție.context}”)
“`

Exemplu minim de lucru cu DSPy

Acum, să trecem printr-un alt exemplu minim de lucru utilizând setul de date GSM8K și modelul OpenAI GPT-3.5-turbo pentru a simula sarcini de promptare în cadrul DSPy.

Configurare

Mai întâi, asigurați-vă că mediul dvs. este configurat corespunzător:

“`python
import dspy
from dspy.datasets.gsm8k import GSM8K, gsm8k_metric

# Configurați LM
turbo = dspy.OpenAI(model=’gpt-3.5-turbo-instruct’, max_tokens=250)
dspy.settings.configure(lm=turbo)

# Încărcați întrebări matematice din setul de date GSM8K
gsm8k = GSM8K()
gsm8k_trainset, gsm8k_devset = gsm8k.train[:10], gsm8k.dev[:10]

print(gsm8k_trainset)
“`

Setul de date `gsm8k_trainset` și `gsm8k_devset` conțin o listă de exemple, fiecare exemplu având un câmp de întrebare și un câmp de răspuns.

Definirea modulului

Următorul pas implică definirea unui program personalizat utilizând modulul ChainOfThought pentru raționament pas cu pas:

“`python
class CoT(dspy.Module):
def __init__(self):
super().__init__()
self.prog = dspy.ChainOfThought(“întrebare -> răspuns”)

def forward(self, întrebare):
return self.prog(întrebare=întrebare)
“`

Compilarea și evaluarea modelului

Acum, compilați-l cu teleprompterul BootstrapFewShot:

“`python
from dspy.teleprompt import BootstrapFewShot

# Configurați optimizatorul
config = dict(max_bootstrapped_demos=4, max_labeled_demos=4)

# Optimizați utilizând metrica gsm8k
teleprompter = BootstrapFewShot(metric=gsm8k_metric, **config)
optimized_cot = teleprompter.compile(CoT(), trainset=gsm8k_trainset)

# Configurați evaluatorul
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)

# Inspectați istoricul modelului
turbo.inspect_history(n=1)
“`

Acest exemplu demonstrează cum să configurați mediul, să definiți un modul personalizat, să compilați un model și să evaluați riguros performanța sa utilizând setul de date și configurarea teleprompterului furnizate.

Managementul datelor în DSPy

DSPy funcționează cu seturi de antrenare, dezvoltare și testare. Pentru fiecare exemplu din datele dvs., aveți de obicei trei tipuri de valori: intrări, etichete intermediare și etichete finale. Deși etichetele intermediare sau finale sunt opționale, aveți nevoie de câteva exemple de intrare.

Crearea obiectelor de exemplu

Obiectele de exemplu în DSPy sunt similare cu dicționarele Python, dar vin cu utilități utile:

“`python
qa_pair = dspy.Example(întrebare=”Aceasta este o întrebare?”, răspuns=”Aceasta este un răspuns.”)

print(qa_pair)
print(qa_pair.întrebare)
print(qa_pair.răspuns)
“`

Ieșire:

“`python
Exemplu({‘întrebare’: ‘Aceasta este o întrebare?’, ‘răspuns’: ‘Aceasta este un răspuns.’}) (input_keys=None)
Aceasta este o întrebare?
Aceasta este un răspuns.
“`

Specificarea cheilor de intrare

În DSPy, obiectele de exemplu au o metodă `with_inputs()` pentru a marca anumite câmpuri ca intrări:

“`python
print(qa_pair.with_inputs(“întrebare”))
print(qa_pair.with_inputs(“întrebare”, “răspuns”))
“`

Valorile pot fi accesate utilizând operatorul punct, iar metodele precum `inputs()` și `labels()` returnează obiecte de exemplu noi care conțin doar chei de intrare sau non-intrare, respectiv.

Optimizatori în DSPy

Un optimizator DSPy ajustează parametrii unui program DSPy (adică prompturi și/sau greutăți LM) pentru a maximiza metrici specificate. DSPy oferă diverse optimizatori încorporați, fiecare utilizând strategii diferite.

Optimizatori disponibili

  • BootstrapFewShot: Generează exemple de few-shot utilizând date de intrare și ieșire etichetate.
  • BootstrapFewShotWithRandomSearch: Aplică BootstrapFewShot de mai multe ori cu o căutare aleatoare a demonstrațiilor generate.
  • COPRO: Generează și rafinează noi instrucțiuni pentru fiecare pas, optimizându-le cu ascensiunea coordonată.
  • MIPRO: Optimizați instrucțiuni și exemple de few-shot utilizând optimizarea Bayesiană.

Alegerea unui optimizator

Dacă sunteți nesigur de unde să începeți, utilizați BootstrapFewShotWithRandomSearch:

Pentru foarte puține date (10 exemple), utilizați BootstrapFewShot.
Pentru date puțin mai multe (50 de exemple), utilizați BootstrapFewShotWithRandomSearch.
Pentru seturi de date mai mari (300+ de exemple), utilizați MIPRO.

Iată cum să utilizați BootstrapFewShotWithRandomSearch:

“`python
from dspy.teleprompt import BootstrapFewShotWithRandomSearch

config = dict(max_bootstrapped_demos=4, max_labeled_demos=4, num_candidate_programs=10, num_threads=4)
teleprompter = BootstrapFewShotWithRandomSearch(metric=METRICA_DVS, **config)
optimized_program = teleprompter.compile(PROGRAMUL_DVS, trainset=SETUL_DE_ANTRENARE_DVS)
“`

Salvarea și încărcarea programelor optimizate

După rularea unui program printr-un optimizator, salvați-l pentru utilizare ulterioară:

optimized_program.save(CALEA_DE_SALVARE)

Încărcați un program salvat:

“`python
loaded_program = CLASA_PROGRAMULUI()
loaded_program.load(path=CALEA_DE_SALVARE)
“`

Caracteristici avansate: Asertările DSPy

Asertările DSPy automatează impunerea constrângerilor computaționale asupra LLM, îmbunătățind fiabilitatea, previzibilitatea și corectitudinea ieșirilor LM.

Utilizarea asertărilor

Definiți funcții de validare și declarați asertări după generarea modelului. De exemplu:

“`python
dspy.Suggest(
len(întrebare) <= 100,
"Întrebarea ar trebui să fie scurtă și să aibă mai puțin de 100 de caractere",
)
“`

Transformarea programelor cu asertări

“`python
from dspy.primitives.assertions import assert_transform_module, backtrack_handler

baleen_with_assertions = assert_transform_module(SimplifiedBaleenAssertions(), backtrack_handler)
“`

Alternativ, activați asertările direct pe program:

“`python
baleen_with_assertions = SimplifiedBaleenAssertions().activate_assertions()
“`

Optimizări conduse de asertări

Asertările DSPy funcționează cu optimizările DSPy, în special cu BootstrapFewShotWithRandomSearch, inclusiv setări precum:

  • Compilarea cu asertări
  • Compilarea + inferență cu asertări

Concluzie

DSPy oferă o abordare puternică și sistematică pentru optimizarea modelelor de limbaj și a prompturilor lor. Prin urmarea pașilor prezentați în aceste exemple, puteți construi, optimiza și evalua sisteme complexe de inteligență artificială cu ușurință. Arhitectura modulară a DSPy și optimizatorii avansați permit o integrare eficientă și eficace a diverselor modele de limbaj, făcându-l un instrument valoros pentru oricine lucrează în domeniul NLP și AI.

Indiferent dacă construiți un sistem simplu de întrebări și răspunsuri sau un pipeline mai complex, DSPy oferă flexibilitatea și robustețea necesare pentru a obține performanță și fiabilitate ridicată.

Am petrecut ultimii cinci ani scufundându-mă în lumea fascinantă a Machine Learning și Deep Learning. Pasinea și expertiza mea m-au condus să contribui la peste 50 de proiecte diverse de inginerie software, cu un focus deosebit pe AI/ML. Curiozitatea mea în continuare m-a atras și spre Natural Language Processing, un domeniu pe care sunt dornic să îl explorez mai departe.