Оперативна інженерія
Оптимізуйте LLM за допомогою DSPy: покроковий посібник зі створення, оптимізації та оцінки систем ШІ

Оскільки можливості великих мовних моделей (LLM) продовжують розширюватися, розробка надійних систем ШІ, які використовують їхній потенціал, стає дедалі складнішою. Звичайні підходи часто передбачають складні методи підказок, генерацію даних для точного налаштування та ручне керівництво для забезпечення дотримання обмежень, що стосуються домену. Однак цей процес може бути виснажливим, схильним до помилок і сильно залежати від втручання людини.
Enter DSPy, революційний фреймворк, призначений для оптимізації розробки систем штучного інтелекту на базі LLM. DSPy представляє систематичний підхід до оптимізації підказок і вагових коефіцієнтів LM, що дозволяє розробникам створювати складні програми з мінімальними ручними зусиллями.
У цьому вичерпному посібнику ми дослідимо основні принципи DSPy, його модульну архітектуру та набір потужних функцій, які він пропонує. Ми також зануримося в практичні приклади, демонструючи, як DSPy може змінити спосіб розробки систем ШІ за допомогою LLM.
Що таке DSPy і навіщо він потрібен?
DSPy — це структура, яка розділяє потік вашої програми (modules
) від параметрів (підказки LM і ваги) кожного кроку. Такий поділ дозволяє систематично оптимізувати підказки та вагові коефіцієнти LM, дозволяючи створювати складні системи штучного інтелекту з більшою надійністю, передбачуваністю та дотриманням доменних обмежень.
Традиційно розробка систем штучного інтелекту з LLM передбачала трудомісткий процес розбиття проблеми на кроки, створення складних підказок для кожного кроку, генерування синтетичних прикладів для тонкого налаштування та ручне керування LM для дотримання певних обмежень. Цей підхід не лише забирав багато часу, але також був схильний до помилок, оскільки навіть незначні зміни в конвеєрі, LM або даних могли вимагати значної переробки підказок і кроків тонкого налаштування.
DSPy вирішує ці проблеми, запроваджуючи нову парадигму: оптимізатори. Ці керовані LM алгоритми можуть налаштовувати підказки та ваги ваших викликів LM, враховуючи показник, який ви хочете максимізувати. Автоматизуючи процес оптимізації, DSPy дозволяє розробникам створювати надійні системи штучного інтелекту з мінімальним ручним втручанням, підвищуючи надійність і передбачуваність результатів LM.
Модульна архітектура DSPy
В основі DSPy лежить модульна архітектура, яка полегшує створення складних систем ШІ. Фреймворк надає набір вбудованих модулів, які абстрагують різні методи підказок, як-от dspy.ChainOfThought
та dspy.ReAct
. Ці модулі можна комбінувати та складати у більші програми, дозволяючи розробникам створювати складні конвеєри відповідно до їхніх конкретних вимог.
Кожен модуль містить параметри, які можна вивчати, включаючи інструкції, кілька прикладів і ваги LM. Коли модуль викликається, оптимізатори DSPy можуть точно налаштувати ці параметри, щоб максимізувати бажану метрику, гарантуючи, що виходи LM відповідають заданим обмеженням і вимогам.
Оптимізація за допомогою DSPy
DSPy представляє ряд потужних оптимізаторів, призначених для підвищення продуктивності та надійності ваших систем ШІ. Ці оптимізатори використовують керовані LM алгоритми для налаштування підказок і ваги ваших викликів LM, максимізуючи вказану метрику, дотримуючись обмежень, що стосуються домену.
Деякі з ключових оптимізаторів, доступних у DSPy, включають:
- BootstrapFewShot: цей оптимізатор розширює сигнатуру, автоматично генеруючи та включаючи оптимізовані приклади в підказку, надіслану до моделі, запроваджуючи короткочасне навчання.
- BootstrapFewShotWithRandomSearch: Застосовується
BootstrapFewShot
кілька разів із довільним пошуком згенерованих демонстрацій, вибираючи найкращу програму замість оптимізації. - МІПРО: генерує інструкції та невеликі приклади на кожному кроці, при цьому генерація інструкцій здійснюється з урахуванням даних і демонстрації. Він використовує байєсовську оптимізацію для ефективного пошуку в просторі інструкцій генерації та демонстрацій у ваших модулях.
- BootstrapFinetune: дистилює програму DSPy на основі підказок до оновлень ваги для менших LM, дозволяючи вам точно налаштувати базові LLM для підвищення ефективності.
Використовуючи ці оптимізатори, розробники можуть систематично оптимізувати свої системи штучного інтелекту, забезпечуючи високоякісні результати, дотримуючись обмежень і вимог, що стосуються конкретної області.
Початок роботи з DSPy
Щоб проілюструвати потужність DSPy, давайте розглянемо практичний приклад побудови системи пошуково-доповненої генерації (RAG) для відповідей на запитання.
Крок 1: Налаштування мовної моделі та моделі пошуку
Перший крок передбачає налаштування мовної моделі (LM) і моделі пошуку (RM) у DSPy.
Щоб інсталювати DSPy, запустіть:
pip install dspy-ai
DSPy підтримує кілька API LM і RM, а також локальне розміщення моделей, що полегшує інтеграцію бажаних моделей.
import dspy # Configure the LM and 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)
Крок 2: завантаження набору даних
Далі ми завантажимо набір даних HotPotQA, який містить колекцію складних пар запитань-відповідей, на які зазвичай відповідають у режимі кількох стрибків.
from dspy.datasets import HotPotQA # Load the dataset dataset = HotPotQA(train_seed=1, train_size=20, eval_seed=2023, dev_size=50, test_size=0) # Specify the 'question' field as the input trainset = [x.with_inputs('question') for x in dataset.train] devset = [x.with_inputs('question') for x in dataset.dev]
Крок 3: Створення підписів
DSPy використовує сигнатури для визначення поведінки модулів. У цьому прикладі ми визначимо підпис для завдання генерації відповіді, вказавши поля введення (контекст і запитання) і поле виводу (відповідь).
class GenerateAnswer(dspy.Signature): """Answer questions with short factoid answers.""" context = dspy.InputField(desc="may contain relevant facts") question = dspy.InputField() answer = dspy.OutputField(desc="often between 1 and 5 words")
Крок 4: Побудова трубопроводу
Ми створимо наш конвеєр RAG як модуль DSPy, який складається з методу ініціалізації (__init__) для оголошення підмодулів (dspy.Retrieve та dspy.ChainOfThought) і методу forward (forward) для опису потоку керування відповідями питання використання цих модулів.
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, question): context = self.retrieve(question).passages prediction = self.generate_answer(context=context, question=question) return dspy.Prediction(context=context, answer=prediction.answer)
Крок 5: Оптимізація конвеєра
Визначивши конвеєр, тепер ми можемо оптимізувати його за допомогою оптимізаторів DSPy. У цьому прикладі ми використаємо оптимізатор BootstrapFewShot, який генерує та вибирає ефективні підказки для наших модулів на основі навчального набору та метрики для перевірки.
from dspy.teleprompt import BootstrapFewShot # Validation metric 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 # Set up the optimizer teleprompter = BootstrapFewShot(metric=validate_context_and_answer) # Compile the program compiled_rag = teleprompter.compile(RAG(), trainset=trainset)
Крок 6: Оцінка конвеєра
Після компіляції програми важливо оцінити її продуктивність на наборі для розробки, щоб переконатися, що вона відповідає бажаній точності та надійності.
from dspy.evaluate import Evaluate # Set up the evaluator evaluate = Evaluate(devset=devset, metric=validate_context_and_answer, num_threads=4, display_progress=True, display_table=0) # Evaluate the compiled RAG program evaluation_result = evaluate(compiled_rag) print(f"Evaluation Result: {evaluation_result}")
Крок 7: перевірка історії моделі
Щоб глибше зрозуміти взаємодію моделі, ви можете переглянути останні покоління, переглянувши історію моделі.
# Inspect the model's history turbo.inspect_history(n=1)
Крок 8: Створення прогнозів
Завдяки оптимізації та оцінці конвеєра тепер ви можете використовувати його, щоб робити прогнози щодо нових питань.
# Example question question = "Which award did Gary Zukav's first book receive?" # Make a prediction using the compiled RAG program prediction = compiled_rag(question) print(f"Question: {question}") print(f"Answer: {prediction.answer}") print(f"Retrieved Contexts: {prediction.context}")
Мінімальний робочий приклад із DSPy
Тепер давайте розглянемо ще один мінімальний робочий приклад, використовуючи Набір даних GSM8K і модель OpenAI GPT-3.5-turbo для імітації завдань підказок у DSPy.
Setup
Спочатку переконайтеся, що ваше середовище правильно налаштовано:
import dspy from dspy.datasets.gsm8k import GSM8K, gsm8k_metric # Set up the LM turbo = dspy.OpenAI(model='gpt-3.5-turbo-instruct', max_tokens=250) dspy.settings.configure(lm=turbo) # Load math questions from the GSM8K dataset gsm8k = GSM8K() gsm8k_trainset, gsm8k_devset = gsm8k.train[:10], gsm8k.dev[:10] print(gsm8k_trainset)
Команда gsm8k_trainset та gsm8k_devset набори даних містять список прикладів, у кожному з яких є поле запитання та відповіді.
Визначте модуль
Далі визначте спеціальну програму, використовуючи модуль ChainOfThought для покрокових міркувань:
class CoT(dspy.Module): def __init__(self): super().__init__() self.prog = dspy.ChainOfThought("question -> answer") def forward(self, question): return self.prog(question=question)
Скомпілюйте та оцініть модель
Тепер скомпілюйте його за допомогою BootstrapFewShot телесуфлер:
from dspy.teleprompt import BootstrapFewShot # Set up the optimizer config = dict(max_bootstrapped_demos=4, max_labeled_demos=4) # Optimize using the gsm8k_metric teleprompter = BootstrapFewShot(metric=gsm8k_metric, **config) optimized_cot = teleprompter.compile(CoT(), trainset=gsm8k_trainset) # Set up the evaluator 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) # Inspect the model's history turbo.inspect_history(n=1)
Цей приклад демонструє, як налаштувати ваше середовище, визначити спеціальний модуль, скомпілювати модель і ретельно оцінити її продуктивність за допомогою наданого набору даних і конфігурацій телесуфлера.
Управління даними в DSPy
DSPy працює з наборами для навчання, розробки та тестування. Для кожного прикладу даних у вас зазвичай є три типи значень: вхідні дані, проміжні мітки та кінцеві мітки. Хоча проміжні або остаточні мітки є необов’язковими, наявність кількох прикладів вхідних даних є важливою.
Створення прикладів об’єктів
Приклади об’єктів у DSPy подібні до словників Python, але мають корисні утиліти:
qa_pair = dspy.Example(question="This is a question?", answer="This is an answer.") print(qa_pair) print(qa_pair.question) print(qa_pair.answer)
вихід:
Example({'question': 'This is a question?', 'answer': 'This is an answer.'}) (input_keys=None) This is a question? This is an answer.
Визначення клавіш введення
У DSPy об’єкти Example мають метод with_inputs() для позначення певних полів як вхідних даних:
print(qa_pair.with_inputs("question")) print(qa_pair.with_inputs("question", "answer"))
Значення можна отримати за допомогою оператора крапки, а такі методи, як inputs() і labels(), повертають нові об’єкти-приклади, що містять лише вхідні або невведені ключі відповідно.
Оптимізатори в DSPy
Оптимізатор DSPy налаштовує параметри програми DSPy (тобто підказки та/або ваги LM), щоб максимізувати вказані показники. DSPy пропонує різні вбудовані оптимізатори, кожен з яких використовує різні стратегії.
Доступні оптимізатори
- BootstrapFewShot: генерує невеликі приклади, використовуючи надані позначені вхідні та вихідні точки даних.
- BootstrapFewShotWithRandomSearch: Застосовує BootstrapFewShot кілька разів із довільним пошуком згенерованих демонстрацій.
- КОПРО: генерує та вдосконалює нові інструкції для кожного кроку, оптимізуючи їх за допомогою координатного підйому.
- МІПРО: оптимізує інструкції та невеликі приклади за допомогою байєсівської оптимізації.
Вибір оптимізатора
Якщо ви не впевнені, з чого почати, використовуйте BootstrapFewShotWithRandomSearch:
Для дуже малого обсягу даних (10 прикладів) використовуйте BootstrapFewShot.
Щоб отримати трохи більше даних (50 прикладів), використовуйте BootstrapFewShotWithRandomSearch.
Для більших наборів даних (300+ прикладів) використовуйте MIPRO.
Ось як використовувати BootstrapFewShotWithRandomSearch:
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=YOUR_METRIC_HERE, **config) optimized_program = teleprompter.compile(YOUR_PROGRAM_HERE, trainset=YOUR_TRAINSET_HERE)
Збереження та завантаження оптимізованих програм
Після запуску програми через оптимізатор збережіть її для подальшого використання:
optimized_program.save(YOUR_SAVE_PATH)
Завантажте збережену програму:
loaded_program = YOUR_PROGRAM_CLASS() loaded_program.load(path=YOUR_SAVE_PATH)
Розширені функції: твердження DSPy
DSPy Assertions автоматизує застосування обчислювальних обмежень для LM, підвищуючи надійність, передбачуваність і правильність вихідних даних LM.
Використання тверджень
Визначте функції перевірки та оголошуйте твердження після створення відповідної моделі. Наприклад:
dspy.Suggest( len(query) <= 100, "Query should be short and less than 100 characters", ) dspy.Suggest( validate_query_distinction_local(prev_queries, query), "Query should be distinct from: " + "; ".join(f"{i+1}) {q}" for i, q in enumerate(prev_queries)), )
Перетворення програм із твердженнями
from dspy.primitives.assertions import assert_transform_module, backtrack_handler baleen_with_assertions = assert_transform_module(SimplifiedBaleenAssertions(), backtrack_handler)
Як варіант, активуйте твердження безпосередньо в програмі:
baleen_with_assertions = SimplifiedBaleenAssertions().activate_assertions()
Оптимізація, керована твердженнями
Твердження DSPy працюють із оптимізацією DSPy, зокрема з BootstrapFewShotWithRandomSearch, включаючи такі налаштування, як:
- Компіляція з твердженнями
- Компіляція + Висновок із твердженнями
Висновок
DSPy пропонує потужний і системний підхід до оптимізації мовних моделей та їхніх підказок. Дотримуючись кроків, описаних у цих прикладах, ви можете з легкістю створювати, оптимізувати та оцінювати складні системи ШІ. Модульна конструкція DSPy і розширені оптимізатори дозволяють ефективно і ефективно інтегрувати різні мовні моделі, що робить його цінним інструментом для всіх, хто працює в галузі НЛП і ШІ.
Незалежно від того, створюєте ви просту систему відповідей на запитання чи більш складний конвеєр, DSPy забезпечує гнучкість і надійність, необхідні для досягнення високої продуктивності та надійності.