Rekayasa prompt

Optimalkan LLM dengan DSPy: Panduan Langkah-demi-Langkah untuk Membangun, Mengoptimalkan, dan Mengevaluasi Sistem AI

mm
Tambahkan Unite.AI ke sumber pilihan Anda di Google
DSPy is a framework for algorithmically optimizing LM prompts and weights

Karena kemampuan model bahasa besar (LLM) terus berkembang, mengembangkan sistem AI yang kuat yang memanfaatkan potensi mereka telah menjadi semakin kompleks. Pendekatan konvensional sering melibatkan teknik prompting yang rumit, generasi data untuk fine-tuning, dan bimbingan manual untuk memastikan kepatuhan terhadap konstrain spesifik domain. Namun, proses ini dapat memakan waktu, rentan terhadap kesalahan, dan sangat bergantung pada intervensi manusia.

Masuklah DSPy, sebuah kerangka kerja revolusioner yang dirancang untuk mempermudah pengembangan sistem AI yang ditenagai oleh LLM. DSPy memperkenalkan pendekatan sistematis untuk mengoptimalkan prompt LM dan bobot, memungkinkan pengembang untuk membangun aplikasi canggih dengan upaya manual minimal.

Dalam panduan komprehensif ini, kita akan menjelajahi prinsip-prinsip inti DSPy, arsitektur modularnya, dan berbagai fitur kuat yang ditawarkannya. Kita juga akan mempelajari contoh praktis, menunjukkan bagaimana DSPy dapat mengubah cara Anda mengembangkan sistem AI dengan LLM.

Apa itu DSPy, dan Mengapa Anda Membutuhkannya?

DSPy adalah kerangka kerja yang memisahkan aliran program Anda (modul) dari parameter (prompt LM dan bobot) dari setiap langkah. Pemisahan ini memungkinkan optimasi sistematis prompt LM dan bobot, memungkinkan Anda untuk membangun sistem AI kompleks dengan keandalan, prediktabilitas, dan kepatuhan terhadap konstrain spesifik domain yang lebih baik.

Secara tradisional, mengembangkan sistem AI dengan LLM melibatkan proses yang melelahkan untuk memecah masalah menjadi langkah-langkah, membuat prompt yang rumit untuk setiap langkah, menghasilkan contoh sintetis untuk fine-tuning, dan membimbing LM secara manual untuk mematuhi konstrain tertentu. Pendekatan ini tidak hanya memakan waktu tetapi juga rentan terhadap kesalahan, karena bahkan perubahan kecil pada pipeline, LM, atau data dapat memerlukan perubahan ekstensif pada prompt dan langkah fine-tuning.

DSPy mengatasi tantangan ini dengan memperkenalkan paradigma baru: optimizer. Algoritma LM yang didorong ini dapat menyetel prompt dan bobot panggilan LM, diberikan metrik yang ingin dimaksimalkan. Dengan mengotomatisasi proses optimasi, DSPy memberdayakan pengembang untuk membangun sistem AI yang kuat dengan intervensi manual minimal, meningkatkan keandalan dan prediktabilitas output LM.

Arsitektur Modular DSPy

Di jantung DSPy terdapat arsitektur modular yang memfasilitasi komposisi sistem AI kompleks. Kerangka kerja ini menyediakan serangkaian modul bawaan yang mengabstraksi berbagai teknik prompting, seperti dspy.ChainOfThought dan dspy.ReAct. Modul-modul ini dapat digabungkan dan disusun menjadi program yang lebih besar, memungkinkan pengembang untuk membangun pipeline yang rumit yang disesuaikan dengan kebutuhan spesifik mereka.

Setiap modul mengandung parameter yang dapat dipelajari, termasuk instruksi, contoh few-shot, dan bobot LM. Ketika modul diaktifkan, optimizer DSPy dapat menyetel parameter ini untuk memaksimalkan metrik yang diinginkan, memastikan bahwa output LM mematuhi konstrain dan kebutuhan yang ditentukan.

Mengoptimalkan dengan DSPy

DSPy memperkenalkan berbagai optimizer kuat yang dirancang untuk meningkatkan kinerja dan keandalan sistem AI Anda. Optimizer-optimizer ini menggunakan algoritma LM yang didorong untuk menyetel prompt dan bobot panggilan LM, memaksimalkan metrik yang ditentukan sambil mematuhi konstrain spesifik domain.

Beberapa optimizer kunci yang tersedia di DSPy termasuk:

  1. BootstrapFewShot: Optimizer ini memperluas tanda tangan dengan secara otomatis menghasilkan dan memasukkan contoh yang dioptimalkan dalam prompt yang dikirim ke model, mengimplementasikan few-shot learning.
  2. BootstrapFewShotWithRandomSearch: Menggunakan BootstrapFewShot beberapa kali dengan pencarian acak atas demonstrasi yang dihasilkan, memilih program terbaik selama optimasi.
  3. MIPRO: Menghasilkan instruksi dan contoh few-shot di setiap langkah, dengan instruksi yang dihasilkan menjadi data-aware dan demonstrasi-aware. Ini menggunakan Optimasi Bayesian untuk mencari ruang generasi instruksi dan demonstrasi di seluruh modul Anda.
  4. BootstrapFinetune: Mengdistilasi program DSPy berbasis prompt menjadi pembaruan bobot untuk LM yang lebih kecil, memungkinkan Anda untuk fine-tuning LM dasar untuk efisiensi yang ditingkatkan.

Dengan menggunakan optimizer-optimizer ini, pengembang dapat secara sistematis mengoptimalkan sistem AI mereka, memastikan output berkualitas tinggi sambil mematuhi konstrain dan kebutuhan spesifik domain.

Menggunakan DSPy

Untuk mengilustrasikan kekuatan DSPy, mari kita jalankan contoh praktis membangun sistem generasi yang ditingkatkan dengan retrieval (RAG) untuk pertanyaan-jawaban.

Langkah 1: Mengatur Model Bahasa dan Model Pencarian

Langkah pertama melibatkan konfigurasi model bahasa (LM) dan model pencarian (RM) dalam DSPy.

Untuk menginstal DSPy, jalankan:


pip install dspy-ai

DSPy mendukung beberapa LM dan RM API, serta hosting model lokal, membuatnya mudah untuk mengintegrasikan model yang Anda sukai.


import dspy

<p># Konfigurasi LM dan 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>

Langkah 2: Memuat Dataset

Selanjutnya, kita akan memuat dataset HotPotQA, yang berisi koleksi pasangan pertanyaan-jawaban yang kompleks yang biasanya dijawab dalam cara multi-hop.


from dspy.datasets import HotPotQA

<p># Muat dataset
dataset = HotPotQA(train_seed=1, train_size=20, eval_seed=2023, dev_size=50, test_size=0)</p>

<p># Tentukan 'pertanyaan' sebagai input
trainset = [x.with_inputs('pertanyaan') for x in dataset.train]
devset = [x.with_inputs('pertanyaan') for x in dataset.dev]</p>

Langkah 3: Membangun Tanda Tangan

DSPy menggunakan tanda tangan untuk mendefinisikan perilaku modul. Dalam contoh ini, kita akan mendefinisikan tanda tangan untuk tugas generasi jawaban, menentukan bidang input (konteks dan pertanyaan) dan bidang output (jawaban).


<p>class GenerateJawaban(dspy.Signature):
"""Jawab pertanyaan dengan jawaban faktoid pendek."""

konteks = dspy.InputField(desc="mungkin berisi fakta relevan")
pertanyaan = dspy.InputField()
jawaban = dspy.OutputField(desc="seringkali antara 1 dan 5 kata")

Langkah 4: Membangun Pipeline

Kita akan membangun pipeline RAG kita sebagai modul DSPy, yang terdiri dari metode inisialisasi (__init__) untuk mendeklarasikan sub-modul (dspy.Retrieve dan dspy.ChainOfThought) dan metode forward (forward) untuk mendeskripsikan aliran kontrol menjawab pertanyaan menggunakan modul-modul ini.


<p>class RAG(dspy.Module):
def __init__(self, num_passages=3):
super().__init__()

self.retrieve = dspy.Retrieve(k=num_passages)
self.generate_jawaban = dspy.ChainOfThought(GenerateJawaban)

def forward(self, pertanyaan):
konteks = self.retrieve(pertanyaan).passages
prediksi = self.generate_jawaban(konteks=konteks, pertanyaan=pertanyaan)
return dspy.Prediction(konteks=konteks, jawaban=prediksi.jawaban)

Langkah 5: Mengoptimalkan Pipeline

Dengan pipeline yang didefinisikan, kita sekarang dapat mengoptimalkannya menggunakan optimizer DSPy. Dalam contoh ini, kita akan menggunakan optimizer BootstrapFewShot, yang menghasilkan dan memilih prompt yang efektif untuk modul kita berdasarkan set pelatihan dan metrik validasi.


<p>from dspy.teleprompt import BootstrapFewShot</p>

<p># Metrik validasi
def validate_konteks_dan_jawaban(contoh, pred, jejak=None):
jawaban_EM = dspy.evaluate.jawaban_eksak_match(contoh, pred)
jawaban_PM = dspy.evaluate.jawaban_passage_match(contoh, pred)
return jawaban_EM and jawaban_PM

<p># Atur optimizer
teleprompter = BootstrapFewShot(metric=validate_konteks_dan_jawaban)

<p># Kompilasi program
compiled_rag = teleprompter.compile(RAG(), trainset=trainset)

Langkah 6: Mengevaluasi Pipeline

Setelah mengompilasi program, penting untuk mengevaluasi kinerjanya pada set pengembangan untuk memastikan bahwa itu memenuhi akurasi dan keandalan yang diinginkan.


from dspy.evaluate import Evaluate

<p># Atur evaluator
evaluate = Evaluate(devset=devset, metric=validate_konteks_dan_jawaban, num_threads=4, display_progress=True, display_table=0)

<p># Evaluasi program RAG yang dikompilasi
evaluation_result = evaluate(compiled_rag)

<p>print(f"Evaluasi Hasil: {evaluation_result}")

Langkah 7: Mengeksplorasi Riwayat Model

Untuk memahami lebih dalam interaksi model, Anda dapat meninjau generasi terbaru dengan mengeksplorasi riwayat model.


<p># Eksplorasi riwayat model
turbo.inspect_history(n=1)

Langkah 8: Membuat Prediksi

Dengan pipeline yang dioptimalkan dan dievaluasi, Anda sekarang dapat menggunakannya untuk membuat prediksi pada pertanyaan baru.


<p># Contoh pertanyaan
pertanyaan = "Apa penghargaan yang diterima buku pertama Gary Zukav?"

<p># Buat prediksi menggunakan program RAG yang dikompilasi
prediksi = compiled_rag(pertanyaan)

<p>print(f"Pertanyaan: {pertanyaan}")
print(f"Jawaban: {prediksi.jawaban}")
print(f"Konteks yang Diperoleh: {prediksi.konteks}")

Contoh Kerja Minimal dengan DSPy

Sekarang, mari kita jalankan contoh kerja minimal lainnya menggunakan dataset GSM8K dan model OpenAI GPT-3.5-turbo untuk mensimulasikan tugas prompting dalam DSPy.

Pengaturan

Pertama, pastikan lingkungan Anda dikonfigurasi dengan benar:


<p>import dspy
from dspy.datasets.gsm8k import GSM8K, gsm8k_metric</p>

<p># Atur LM
turbo = dspy.OpenAI(model='gpt-3.5-turbo-instruct', max_tokens=250)
dspy.settings.configure(lm=turbo)

<p># Muat pertanyaan matematika dari dataset GSM8K
gsm8k = GSM8K()
gsm8k_trainset, gsm8k_devset = gsm8k.train[:10], gsm8k.dev[:10]

print(gsm8k_trainset)

Dataset gsm8k_trainset dan gsm8k_devset berisi daftar contoh dengan setiap contoh memiliki bidang pertanyaan dan jawaban.

Definisikan Modul

Selanjutnya, definisikan program kustom menggunakan modul ChainOfThought untuk penalaran langkah demi langkah:


<p>class CoT(dspy.Module):
def __init__(self):
super().__init__()
self.prog = dspy.ChainOfThought("pertanyaan -&gt; jawaban")

def forward(self, pertanyaan):
return self.prog(pertanyaan=pertanyaan)

Kompilasi dan Evaluasi Model

Sekarang, kompilasi dengan teleprompter BootstrapFewShot:


<p>from dspy.teleprompt import BootstrapFewShot</p>

<p># Atur optimizer
config = dict(max_bootstrapped_demos=4, max_labeled_demos=4)

<p># Optimalkan menggunakan gsm8k_metric
teleprompter = BootstrapFewShot(metric=gsm8k_metric, **config)
optimized_cot = teleprompter.compile(CoT(), trainset=gsm8k_trainset)

<p># Atur evaluator
from dspy.evaluate import Evaluate

<p>evaluate = Evaluate(devset=gsm8k_devset, metric=gsm8k_metric, num_threads=4, display_progress=True, display_table=0)
evaluate(optimized_cot)

<p># Eksplorasi riwayat model
turbo.inspect_history(n=1)

Contoh ini menunjukkan bagaimana mengatur lingkungan, mendefinisikan modul kustom, mengompilasi model, dan mengevaluasi kinerjanya dengan menggunakan dataset dan konfigurasi teleprompter yang disediakan.

Pengelolaan Data di DSPy

DSPy beroperasi dengan set pelatihan, pengembangan, dan pengujian. Untuk setiap contoh dalam data Anda, Anda biasanya memiliki tiga jenis nilai: input, label antara, dan label akhir. Sementara label antara atau akhir bersifat opsional, memiliki beberapa contoh input sangat penting.

Membuat Objek Contoh

Objek contoh di DSPy mirip dengan kamus Python tetapi dilengkapi dengan utilitas yang berguna:


<p>qa_pair = dspy.Example(pertanyaan="Ini adalah pertanyaan?", jawaban="Ini adalah jawaban.")

<p>print(qa_pair)
print(qa_pair.pertanyaan)
print(qa_pair.jawaban)

Output:


<p>Example({'pertanyaan': 'Ini adalah pertanyaan?', 'jawaban': 'Ini adalah jawaban.'}) (input_keys=None)
Ini adalah pertanyaan?
Ini adalah jawaban.

Menentukan Kunci Input

Di DSPy, objek contoh memiliki metode with_inputs() untuk menandai bidang tertentu sebagai input:


<p>print(qa_pair.with_inputs("pertanyaan"))
print(qa_pair.with_inputs("pertanyaan", "jawaban"))

Nilai dapat diakses menggunakan operator titik, dan metode seperti inputs() dan labels() mengembalikan objek contoh baru yang berisi hanya kunci input atau non-input.

Optimizer di DSPy

Optimizer DSPy menyetel parameter program DSPy (yaitu, prompt dan/atau bobot LM) untuk memaksimalkan metrik yang ditentukan. DSPy menawarkan berbagai optimizer bawaan, masing-masing menggunakan strategi yang berbeda.

Optimizer yang Tersedia

  • BootstrapFewShot: Menghasilkan contoh few-shot menggunakan data input dan output yang dilabeli.
  • BootstrapFewShotWithRandomSearch: Menggunakan BootstrapFewShot beberapa kali dengan pencarian acak atas demonstrasi yang dihasilkan.
  • COPRO: Menghasilkan dan memperbarui instruksi baru untuk setiap langkah, mengoptimalkannya dengan kenaikan koordinat.
  • MIPRO: Mengoptimalkan instruksi dan contoh few-shot menggunakan Optimasi Bayesian.

Memilih Optimizer

Jika Anda tidak yakin dari mana harus memulai, gunakan BootstrapFewShotWithRandomSearch:

Untuk sedikit data (10 contoh), gunakan BootstrapFewShot.
Untuk sedikit lebih banyak data (50 contoh), gunakan BootstrapFewShotWithRandomSearch.
Untuk dataset yang lebih besar (300+ contoh), gunakan MIPRO.

Begini cara menggunakan 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=METRIK_ANDA_DISINI, **config)
optimized_program = teleprompter.compile(PROGRAM_ANDA_DISINI, trainset=SET_PELATIHAN_ANDA_DISINI)

Menyimpan dan Memuat Program yang Dioptimalkan

Setelah menjalankan program melalui optimizer, simpan untuk digunakan di masa depan:

optimized_program.save(JALUR_SIMPAN_ANDA)

Muat program yang disimpan:


<p>loaded_program = KELAS_PROGRAM_ANDA()
loaded_program.load(path=JALUR_SIMPAN_ANDA)

Fitur Lanjutan: Asertasi DSPy

Asertasi DSPy mengotomatisasi penerapan konstrain komputasi pada LM, meningkatkan keandalan, prediktabilitas, dan kebenaran output LM.

Menggunakan Asertasi

Definisikan fungsi validasi dan deklarasikan asertasi setelah generasi model yang sesuai. Misalnya:


<p>dspy.Suggest(
len(query) &lt;= 100,
&quot;Pertanyaan harus singkat dan kurang dari 100 karakter&quot;,
)

<p>dspy.Suggest(
validate_query_distinction_local(prev_queries, query),
"Pertanyaan harus berbeda dari: " + "; ".join(f"{i+1}) {q}" for i, q in enumerate(prev_queries)),
)

Mengubah Program dengan Asertasi


<p>from dspy.primitives.assertions import assert_transform_module, backtrack_handler</p>

<p>baleen_with_assertions = assert_transform_module(SimplifiedBaleenAssertions(), backtrack_handler)

<p>Alternatif, aktifkan asertasi langsung pada program:</p>

[code language="Python"]

<p>baleen_with_assertions = SimplifiedBaleenAssertions().activate_assertions()

Optimasi yang Didorong Asertasi

Asertasi DSPy bekerja dengan optimasi DSPy, terutama dengan BootstrapFewShotWithRandomSearch, termasuk pengaturan seperti:

  • Kompilasi dengan Asertasi
  • Kompilasi + Inferensi dengan Asertasi

Kesimpulan

DSPy menawarkan pendekatan yang kuat dan sistematis untuk mengoptimalkan model bahasa dan prompt. Dengan mengikuti langkah-langkah yang diuraikan dalam contoh ini, Anda dapat membangun, mengoptimalkan, dan mengevaluasi sistem AI kompleks dengan mudah. Desain modular DSPy dan optimizer canggih memungkinkan integrasi efisien dan efektif berbagai model bahasa, membuatnya menjadi alat yang berharga bagi siapa saja yang bekerja di bidang NLP dan AI.

Apakah Anda membangun sistem pertanyaan-jawaban sederhana atau pipeline yang lebih kompleks, DSPy menyediakan fleksibilitas dan keandalan yang diperlukan untuk mencapai kinerja tinggi dan keandalan.

Saya telah menghabiskan lima tahun terakhir dengan membenamkan diri dalam dunia Machine Learning dan Deep Learning yang menarik. Minat dan keahlian saya telah memimpin saya untuk berkontribusi pada lebih dari 50 proyek rekayasa perangkat lunak yang beragam, dengan fokus khusus pada AI/ML. Rasa ingin tahu saya yang terus-menerus juga telah menarik saya ke arah Natural Language Processing, sebuah bidang yang saya ingin jelajahi lebih lanjut.