iT邦幫忙

2024 iThome 鐵人賽

DAY 28
1
生成式 AI

2024 年用 LangGraph 從零開始實現 Agentic AI System系列 第 28

【Day 28】- 從零開始的 DSPy:打造高效翻譯錯誤檢測系統

  • 分享至 

  • xImage
  •  

摘要
這篇文章介紹了一個名為 DSPy 的 AI 開發框架,它能夠幫助開發者更有效地構建和優化語言模型。文章從一個翻譯錯誤檢測任務為例,一步一步地示範了如何使用 DSPy 來設計、訓練和評估模型。過程中,文章詳細介紹了 DSPy 的各個功能模塊,包括環境配置、模型準備、數據集準備、基礎問答模組、評估方法、優化器、思維鏈 (Chain of Thought) 技術,以及最終模型的保存和性能比較。作者以圖表和程式碼示例的方式,清晰地展示了 DSPy 如何通過自動優化來提升模型性能,特別是對於基礎問答模型,DSPy 甚至能帶來超過 50% 的性能提升。最後,文章總結了 DSPy 的優勢,以及使用 DSPy 開發 AI 模型的整體流程,並強調了自動優化技術在提升模型性能和簡化開發流程方面的重要性。

引言:AI 開發的新紀元

各位開發者朋友們,你是否曾經為了調教一個語言模型而夜不能寐?是不是常常覺得,明明只是想讓 AI 回答幾個問題,卻要花上好幾天來調整 prompt?如果你有這些困擾,那麼今天介紹的 DSPy 框架絕對會讓你眼前一亮!

DSPy 是一個革命性的 AI 開發工具,它讓我們能夠以更高效、更直觀的方式來構建和優化語言模型管道。想像一下,如果有一個工具能夠自動幫你優化 prompt,自動找出最佳的參數組合,那會是多麼美妙的事情?沒錯,DSPy 就是這樣一個神奇的工具!

首圖

無論您是 AI 開發新手還是經驗豐富的專家,這篇教程都將帶您:

  1. 瞭解 DSPy 的基本原理和優勢
  2. 學習如何使用 DSPy 配置環境和準備數據
  3. 掌握從基礎問答到思維鏈的模型構建技巧
  4. 體驗 DSPy 自動優化的強大威力

今天的實作之旅:DSPy 的魔力初體驗

接下來的教程中,我們將一步步帶你體驗 DSPy 的強大功能。我們的實作之旅包括以下幾個階段:

  1. 環境配置:我們會先設置好所有必要的工具,包括安裝 DSPy 和 vLLM。
  2. 模型準備:使用 vLLM 來加載和運行一個強大的語言模型。
  3. 資料集介紹:我們會使用一個真實世界的資料集來測試我們的 AI。
  4. 基礎模組開發:從最簡單的問答系統開始,逐步構建我們的 AI。
  5. 評估方法設計:學習如何評估 AI 的表現,這是優化的關鍵。
  6. DSPy 優化魔法:這是重頭戲!我們將見證 DSPy 如何自動優化我們的 AI。
  7. 進階技巧:思維鏈:我們會引入更複雜的 AI 推理方法,讓 AI 的回答更加智能。
  8. 成果對比與保存:最後,我們會對比優化前後的效果,並保存我們的成果。

無論你是 AI 開發新手,還是經驗豐富的老手,這個教程都會讓你對 AI 開發有全新的認識。準備好開始這段精彩的 DSPy 之旅了嗎?讓我們一起深入探索 AI 開發的新境界吧!

DSPy 實作指南:語言模型優化實踐

1. 環境配置

首先,我們需要安裝必要的套件。DSPy 是我們的主要工具,而 vLLM 則用於高效運行語言模型。

!pip install --quiet dspy-ai vllm

這行指令會幫我們安裝 DSPy 和 vLLM。vLLM 是什麼?它是一個高效能的大型語言模型服務框架,能讓我們的模型運行得飛快!

2. 模型準備

接下來,我們使用 vLLM 來啟動一個語言模型服務器。這裡選用的是 Mistral 7B 模型的一個變體,經過了 AWQ 量化處理。

!nohup python -m vllm.entrypoints.openai.api_server --model TheBloke/dolphin-2.6-mistral-7B-dpo-laser-AWQ --quantization awq > server.log 2>&1 &

為確保服務器正常運行,我們可以檢查日誌和可用模型:

!tail server.log
!curl http://localhost:8000/v1/models

vllm&DSPy 執行截圖img

最佳實踐:我們選擇使用 Mistral 7B 模型的 AWQ 量化版本,是因為它在性能和效率之間取得了良好的平衡。AWQ(Activation-aware Weight Quantization)技術可以大幅減少模型大小,同時保持較高的性能。而 vLLM 的使用則可以顯著提高推理速度,這對於我們後續的優化過程至關重要。

3. DSPy 配置

現在我們將 DSPy 與我們的語言模型連接起來:

import dspy

# 初始化 vLLM 客戶端
vLLM = dspy.HFClientVLLM(
    model="TheBloke/dolphin-2.6-mistral-7B-dpo-laser-AWQ", 
    port=8000, 
    url="http://localhost"
)

# 配置 DSPy 使用此語言模型
dspy.settings.configure(lm=vLLM)

提醒:將 DSPy 與我們的語言模型連接是至關重要的一步。這使得 DSPy 可以直接與模型交互,進行預測和優化。通過這種配置,我們為後續的模塊開發和自動化優化鋪平了道路,確保了整個流程的順暢性和效率。

4. 資料集準備

我們使用 BIG-Bench Hard 資料集中的「顯著翻譯錯誤檢測」任務作為示例:

from datasets import load_dataset

# 加載數據集
ds = load_dataset("maveriq/bigbenchhard", "salient_translation_error_detection")["train"]

# 將數據轉換為 DSPy 可用的格式
examples = [dspy.Example({"question": r["input"], "answer": r["target"]}).with_inputs("question") for r in ds]

print(f"總樣本數:{len(examples)}")

# 分割訓練集和驗證集
trainset = examples[:20]
valset = examples[20:]

資料範例內容
img

可以直接到 HuggingFace 上查看

解說:我們選擇 BIG-Bench Hard 數據集中的'顯著翻譯錯誤檢測'任務,是因為它代表了一個具有挑戰性的實際應用場景。這個任務要求模型不僅要理解原文和譯文,還要識別出可能的翻譯錯誤。這種複雜性使得它成為展示 DSPy 優化能力的理想選擇,特別是在提高模型推理能力方面。

5. 基礎問答模組

首先,我們定義一個簡單的問答模組:

class BasicQA(dspy.Module):
    def __init__(self):
        super().__init__()
        # 定義一個從問題到答案的預測模組
        self.prog = dspy.Predict("question -> answer")

    def forward(self, question):
        # 給定問題,返回預測的答案
        return self.prog(question=question)

# 初始化基礎問答模組
basic_qa = BasicQA()

問答範例截圖 img

在開發任何 AI 系統時,評估其性能都是至關重要的一步。通過設計合適的評估指標,我們不僅可以量化模型的表現,還能夠識別出需要改進的地方。在 DSPy 框架中,評估過程更是優化的關鍵驅動力。接下來,我們將設計一個評估方法,它將指導我們後續的優化過程,幫助我們逐步提升模型的性能。

6. 評估方法

我們的評估指標將檢查 llm 輸出是否包含正確的多項選擇答案。為了在 DSPy 中定義評估指標,我們建立一個如下例所示的函數。前兩個輸入應該是 dspy.Example 的實例。度量函數可以包含評估任務所需的任何邏輯。您可以在文件中閱讀有關 trace 參數的更多資訊。它需要存在,即使沒有明確使用它。

import re

def eval_metric(true, prediction, trace=None):
    """
    評估預測結果是否正確
    
    參數:
    true: Example 對象,包含真實答案
    prediction: 包含預測答案的對象
    trace: 追蹤信息,此處未使用
    
    返回:
    布爾值,表示預測是否正確
    """
    pred = prediction.answer
    # 使用正則表達式提取答案中的選項
    matches = re.findall(r"\([A-Z]\)", pred)
    parsed_answer = matches[-1] if matches else ""
    return parsed_answer == true.answer

# 初始化評估器
from dspy.evaluate import Evaluate

evaluate = Evaluate(
    devset=valset,
    metric=eval_metric,
    num_threads=6,
    display_progress=True,
    display_table=10
)

第一次評估截圖 img

7. DSPy 優化

我們使用 DSPy 的 BootstrapFewShotWithRandomSearch 優化器來完善我們的 CoT 模組。此優化器會自動產生範例並迭代地提高模型在資料集上的效能。

BootstrapFewShotWithRandomSearch 優化器是 DSPy 中一個強大的工具。它的工作原理是通過隨機搜索不同的提示和參數組合,並使用少量樣本(few-shot)學習的方式來自動生成高質量的訓練示例。這種方法特別適合我們的任務,因為它能夠在有限的標註數據基礎上,自動發現最有效的問答策略。通過迭代優化,它可以顯著提高模型在目標任務上的表現,而無需大量的人工干預。

from dspy.teleprompt import BootstrapFewShotWithRandomSearch

# 配置優化參數
config = dict(
    max_bootstrapped_demos=2,
    max_labeled_demos=4,
    num_candidate_programs=2,
    num_threads=6
)

# 初始化優化器
teleprompter = BootstrapFewShotWithRandomSearch(metric=eval_metric, **config)

# 編譯並優化模組
optimized_qa = teleprompter.compile(basic_qa, trainset=trainset, valset=valset)

第一次優化後截圖 img

選擇哪一種 Optimizer,官方指南說啥都不知道就選 BootstrapFewShotWithRandomSearch

8. 性能比較

讓我們比較優化前後的性能:

# 評估優化後的模組
compiled_qa_score = evaluate(optimized_qa)

# 評估原始模組
uncompiled_qa_score = evaluate(basic_qa)

print(f"未優化模組評分:{uncompiled_qa_score}")
print(f"優化後模組評分:{compiled_qa_score}")
print(f"優化提升:{compiled_qa_score - uncompiled_qa_score}%")

img

9. 進階技巧:思維鏈

接下來,我們引入思維鏈(Chain of Thought)技術。思維鏈 (CoT) 方法涉及模型生成通往最終答案的中間步驟,模仿人類如何解決推理問題。

class CoT(dspy.Module):
    def __init__(self):
        super().__init__()
        # 使用思維鏈方法進行預測
        self.prog = dspy.ChainOfThought("question -> answer")

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

# 初始化思維鏈模組
cot_qa = CoT()

思維鏈(Chain of Thought,CoT)是一種高級的推理技術,與基礎問答方法有著本質的區別。這種方法模仿了人類解決複雜問題的過程,通過生成一系列邏輯步驟來得出最終答案。對於我們的翻譯錯誤檢測任務,CoT 可能特別有效,因為它允許模型逐步分析原文和譯文,識別潛在的不一致之處,從而做出更準確的判斷。

10. 優化思維鏈模組

我們再次使用 DSPy 優化器來改進思維鏈模組:

# 配置優化參數
config = dict(
    max_bootstrapped_demos=1,
    max_labeled_demos=4,
    num_candidate_programs=4,
    num_threads=6
)

# 初始化優化器
teleprompter = BootstrapFewShotWithRandomSearch(metric=eval_metric, **config)

# 編譯並優化思維鏈模組
optimized_cot_qa = teleprompter.compile(cot_qa, trainset=trainset, valset=valset)

11. 最終性能評估

最後,我們比較思維鏈模組優化前後的性能:

# 評估優化後的思維鏈模組
compiled_cot_qa_score = evaluate(optimized_cot_qa)

# 評估原始思維鏈模組
uncompiled_cot_qa_score = evaluate(cot_qa)

print(f"未優化思維鏈模組評分:{uncompiled_cot_qa_score}")
print(f"優化後思維鏈模組評分:{compiled_cot_qa_score}")
print(f"優化提升:{compiled_cot_qa_score - uncompiled_cot_qa_score}%")

img

12. 保存模型

為了日後使用,我們將優化後的模型保存下來:

# 保存優化後的基礎問答模組
optimized_qa.save(path="optimized_qa_module.json")

# 保存優化後的思維鏈模組
optimized_cot_qa.save(path="optimized_cot_qa_module.json")

DSPy 優化效果分析:基礎問答 vs. 思維鏈方法

讓我們仔細分析這張 "DSPy 示範" 圖表,它展示了在 BIG-Bench Hard 數據集的顯著翻譯錯誤檢測任務中,基礎問答和思維鏈(Chain of Thought,簡稱 COT)兩種方法在 DSPy 優化前後的表現。

結果分析img

1. 基礎問答方法的顯著提升

  • 優化前評分:31.3
  • 優化後評分:47.83
  • 提升幅度:16.53 個百分點(52.8% 的相對提升)
    基礎問答方法在 DSPy 優化後獲得了巨大的性能提升。這表明 DSPy 的優化技術對於相對簡單的模型特別有效,能夠顯著提高其性能。

2. 思維鏈方法的穩定提升

  • 優化前評分:51.3
  • 優化後評分:56.52
  • 提升幅度:5.22 個百分點(10.2% 的相對提升)
    思維鏈方法在優化前就已經表現優秀,優化後仍有小幅提升。這反映出 COT 方法本身的強大性,同時也說明 DSPy 能夠進一步優化已經表現良好的模型。

3. 方法間的比較

  • 未優化時,COT 比基礎問答高出 20 個百分點。
  • 優化後,COT 仍領先,但差距縮小到 8.69 個百分點。

這個對比凸顯了思維鏈方法的優勢,特別是在處理複雜任務時。同時,它也展示了 DSPy 優化能夠顯著縮小不同方法之間的性能差距。

4. 小結

  1. DSPy 展現了在不同複雜度任務上的優化能力,特別是對基礎方法的大幅提升。
  2. 對於已經表現優秀的方法(如 COT),DSPy 仍能帶來進一步的改進。
  3. 在選擇方法時,除了考慮原始性能,還應考慮優化後的潛力。某些看似表現欠佳的方法可能在優化後獲得巨大提升。
  4. DSPy 的應用可能有助於縮小不同方法間的性能差距,為模型選擇和系統設計提供了新的思路。

這些結果清楚地展示了 DSPy 優化的威力。我們可以看到,無論是基礎問答模型還是更複雜的思維鏈模型,在經過 DSPy 優化後都取得了顯著的性能提升。特別值得注意的是,基礎模型的大幅進步說明了 DSPy 能夠大大提高簡單模型的上限。而思維鏈模型雖然提升幅度較小,但其最終性能仍然優於優化後的基礎模型,這凸顯了結合高級推理技術和自動化優化的潛力。這些結果不僅證明了 DSPy 的有效性,也為我們在不同場景下選擇和優化 AI 模型提供了寶貴的指導。

總結

在這個實作中,我們探索了如何使用 DSPy 框架來構建、優化和評估語言模型的問答系統。我們從基礎的問答模組開始,逐步引入了更複雜的思維鏈技術,並使用 DSPy 的優化器來自動改進模型性能。這種方法不僅簡化了開發過程,還顯著提高了模型的效能。

通過這個過程,我們展示了 DSPy 如何能夠自動化許多傳統上需要手動調整的步驟,為開發者提供了一個強大而靈活的工具來構建和優化複雜的語言模型應用。

即刻前往教學程式碼 Repo,親自動手熟悉 DSPy 帶給你的力量!別忘了給專案按個星星並持續關注更新,讓我們一起探索AI代理的新境界。

X. 參考資料

  1. Databricks
  2. Fearnworks 撰寫文章,有系統性整理 DSPy
  3. Chris Levy 使用 Custom Dataset 來進行評估

上一篇
【Day 27】- 告別提示工程:DSPy如何革新大型語言模型的應用開發
下一篇
【Day 29】- 網站開發遇上 AI:FastAPI、Streamlit 與 LangServe 的實戰指南
系列文
2024 年用 LangGraph 從零開始實現 Agentic AI System29
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言