使用 LIT 在 Keras 中分析 Gemma 模型

查看生成式 AI 在 Google Colab 中執行 在 GitHub 上查看原始碼 前往程式碼研究室學習

簡介

生成式 AI 產品相對較新,應用程式行為可能與舊版軟體不同。因此,請務必探測正在使用的機器學習模型、檢查模型的行為範例,並調查意外結果。

學習可解釋性工具 (LIT;網站GitHub) 是用於偵錯及分析機器學習模型的平台,可協助您瞭解模型的原因和行為方式。

在本程式碼研究室中,您將瞭解如何使用 LIT,充分運用 Google 的 Gemma 模型。本程式碼研究室會示範如何使用序列一致性這項可解釋性技術,分析不同的提示工程方法。

學習目標:

  1. 瞭解序列顯著性及其在模型分析中的用途。
  2. 設定 Gemma 的 LIT 以計算提示輸出內容和序列顯著性。
  3. 透過 LM Salience 模組使用序列顯著性,瞭解提示設計對模型輸出的影響。
  4. 測試註解中的假設資料改善項目,看看成效如何。

注意:本程式碼研究室使用的是 Gemma 的 KerasNLP 實作,以及後端的 TensorFlow v2。因此強烈建議您使用 GPU 核心來跟進。

序列顯著性及其在模型分析中的用途

文字轉文字生成式模型 (例如 Gemma) 會擷取「代碼化」文字形式的輸入序列,並產生該輸入一般後續或完成形式的新符記。這項作業一次只會產生一個權杖,每個新產生的權杖都會加上 (循環) 至輸入中,再加上任何先前產生的符記,直到模型達到停止條件為止。例如模型產生序列後 (EOS) 符記,或達到預先定義的長度上限。

顯著性方法是可解釋的 AI (XAI) 技術類別,可指出輸入的哪些部分對於模型的不同部分具有重要意義。LIT 支援各種分類工作的統計方法,說明一系列輸入符記對預測標籤的影響。序列識別功能會將這些方法一般化為文字轉文字生成式模型,並解釋上述符記對產生的符記的影響。

您將使用這裡的 Grad L2 Norm 方法進行序列精確度,這會分析模型的梯度,並提供每個前面符記對輸出內容的影響程度。此方法簡單且有效率,已展示在分類和其他設定中成效良好。顯著性分數越高,影響力越大。此方法在 LIT 中使用,因為在可解釋性研究社群中十分瞭解且廣泛運用。

更進階的梯度式顯著性方法包括「Grad ⋅ Input」和「積分梯度」。此外,還有一些以阿拉法為基礎的方法,例如 LIMESHAP,這類方法更為強大,運算成本也較高。請參閱這篇文章,進一步瞭解不同顯著性方法的詳細比較。

如要進一步瞭解證據方法的科學,請參閱這份互動式探索的入門介紹

匯入、環境和其他設定程式碼

ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
bigframes 0.21.0 requires scikit-learn>=1.2.2, but you have scikit-learn 1.0.2 which is incompatible.
google-colab 1.0.0 requires ipython==7.34.0, but you have ipython 8.14.0 which is incompatible.

您可以放心忽略這些內容。

安裝 LIT 和 Keras NLP

在本程式碼研究室中,您需要最新版的 keras (3) keras-nlp (0.8.0) 和 lit-nlp (1.1) 和 Kaggle 帳戶,才能下載基礎模型。

pip install -q -U lit-nlp
pip uninstall -y umap-learn
pip install -q -U keras-nlp
pip install -q -U keras

Kaggle 存取權

如要登入 Kaggle,您可以將 kaggle.json 憑證檔案儲存在 ~/.kaggle/kaggle.json 中,或是在 Colab 環境中執行下列指令。詳情請參閱 kagglehub 套件說明文件

import kagglehub

kagglehub.login()

您也必須接受 Gemma 的授權協議。

設定 Gemma 的 LIT

設定 LIT 模型

import os

os.environ["KERAS_BACKEND"] = "tensorflow"
import keras
import keras_nlp

# Run at half precision.
keras.config.set_floatx("bfloat16")
model_name = 'gemma_instruct_2b_en'
gemma_model = keras_nlp.models.GemmaCausalLM.from_preset(model_name)

下列程式碼會初始化 LIT 包裝函式,以便支援 Gemma 模型。LIT 架構將兩者稱為模型,但在本例中,這些端點就是您在上方載入的相同基礎 gemma_model 的不同端點。如此一來,LIT 即可視需求計算生成、權杖化和對資料的可用性。

from lit_nlp.examples.models import instrumented_keras_lms

batch_size = 1
max_sequence_length = 512
init_models = instrumented_keras_lms.initialize_model_group_for_salience
models = init_models(model_name, gemma_model,
                     batch_size=batch_size,
                     max_length=max_sequence_length)

設定 LIT 資料集

Gemma 是文字轉文字生成式模型,可輸入文字並產生文字輸出。LIT 的模型假設資料集會提供下列欄位來支援產生作業:

  • promptKerasGenerationModel 的輸入內容。
  • target:選用的目標序列,例如「真值」(黃金) 答案,或模型預先產生的回應。

LIT 包含少量 sample_prompts,其中包含幾個不同來源的範例,例如:

  • [GSM8K][GSM8K]:提供少數樣本,藉此解決年級學校的數學問題。
  • [Gigaword Benchmark][gigaword]:產生短篇報導的標題。
  • [憲法提示][憲法]:如何根據具有指引/界線的物件產生新想法

您也可以用 LIT 的 Dataset API 輕鬆載入自己的資料,方法是使用含有 prompt 和選用 target 欄位記錄的 .jsonl 檔案 ([example][jsonl-example]),或是從任何格式載入資料。

執行下方的儲存格以載入範例提示。

from lit_nlp.examples.datasets import lm as lm_data

datasets = {
  'sample_prompts': lm_data.PromptExamples(
      lm_data.PromptExamples.SAMPLE_DATA_PATH
  ),
}

設定 LIT UI

LIT 是互動式模型理解工具,支援人機迴圈評估和模型行為。LIT UI 可讓您:

  • 即時以視覺化方式呈現資料集和模型輸出結果
  • 執行顯著性方法以瞭解推動模型行為的輸入符記
  • 建立反事實事實來測試假設。

LIT 可在相同介面上進行上述操作,減少切換不同工具的麻煩。這對於提示工程等工作特別實用,因為您之後會在本程式碼研究室中著重這些工作。

這個 UI 版面配置可用於任何其他生成式語言模型。如果您對此處所列的功能感興趣,請參閱這裡的完整清單。

from lit_nlp.api import layout
modules = layout.LitModuleName

LM_SALIENCE_LAYOUT = layout.LitCanonicalLayout(
    left={
        'Data Table': [modules.DataTableModule],
        'Datapoint Editor': [modules.DatapointEditorModule],
    },
    upper={  # if 'lower' not specified, this fills the right side
        'Salience': [modules.LMSalienceModule],
    },
    layoutSettings=layout.LayoutSettings(leftWidth=40),
    description='Custom layout for language model salience.',
)

這個儲存格會初始化 LIT 伺服器。這項作業可能需要幾秒鐘的時間,因為這項作業也會在範例提示上執行模型並快取結果。

from lit_nlp import notebook as lit_notebook

lit_widget = lit_notebook.LitWidget(
    models=models,
    datasets=datasets,
    layouts={'default': LM_SALIENCE_LAYOUT},
    default_layout='default',
)

您現在可以顯示 UI:

lit_widget.render(height=800)
<IPython.core.display.Javascript object>

你也可以在新分頁中開啟品牌提升評估,以完整頁面的形式開啟。執行這個儲存格,然後按一下隨即顯示的連結:

lit_widget.render(open_in_new_tab=True)
<IPython.core.display.Javascript object>

分析 LIT 中的少量相片提示

時至今日,提示與科學一樣是科學,而 LIT 可協助您改善 Gemma 等大型語言模型的提示。首先,您會看到 LIT 的範例,說明如何使用 LIT 探索 Gemma 的行為、預測潛在問題,並改善安全性。

找出複雜提示中的錯誤

如要製作高品質 LLM 原型設計與應用方式,就有兩個最重要的提示技術,分別是少量樣本提示 (包括提示中要求的行為範例) 和思考過程 (包括 LLM 最終輸出內容前的解說或推理)。但想提供有效的提示通常仍是一大挑戰。

不妨舉例說明,能幫助他人根據自己的喜好評估自己是否喜歡食物。思想起的初始原型設計鏈結可能如下所示:

def analyze_menu_item_template(food_likes, food_dislikes, menu_item):
  return f"""Analyze a menu item in a restaurant.

## For example:

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Onion soup
Analysis: it has cooked onions in it, which you don't like.
Recommendation: You have to try it.

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Baguette maison au levain
Analysis: Home-made leaven bread in france is usually great
Recommendation: Likely good.

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Macaron in france
Analysis: Sweet with many kinds of flavours
Recommendation: You have to try it.

## Now analyze one more example:

Taste-likes: {food_likes}
Taste-dislikes: {food_dislikes}
Suggestion: {menu_item}
Analysis:"""

你是否發現這則提示有問題?LIT 將協助你使用 LM Salience 模組檢查提示。

使用序列顯著性進行偵錯

這個模組會醒目顯示模型產生答案時提示的部分,系統會用最小的層級 (即每個輸入符記) 計算顯著性,但 LIT 可以將符記語態匯總至較能夠解釋的大型時距,例如行、句子或字詞。如要進一步瞭解難度,以及如何使用它找出非預期偏誤,請參閱Saliency Explorable

首先,為提示範本變數提供新的範例輸入內容:

food_likes = """Cheese"""
food_dislikes = """Can't eat eggs"""
menu_item = """Quiche Lorraine"""

prompt = analyze_menu_item_template(food_likes, food_dislikes, menu_item)
print(prompt)

fewshot_mistake_example = {'prompt': prompt}  # you'll use this below
Analyze a menu item in a restaurant.

## For example:

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Onion soup
Analysis: it has cooked onions in it, which you don't like.
Recommendation: You have to try it.

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Baguette maison au levain
Analysis: Home-made leaven bread in france is usually great
Recommendation: Likely good.

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Macaron in france
Analysis: Sweet with many kinds of flavours
Recommendation: You have to try it.

## Now analyze one more example:

Taste-likes: Cheese
Taste-dislikes: Can't eat eggs
Suggestion: Quiche Lorraine
Analysis:

如果您已在上方儲存格或另一個分頁中開啟 LIT UI,可以使用 LIT 的「Datapoint Editor」新增以下提示:

1_Datapoint_editor.png

另一個方法是在輸入提示時直接重新轉譯小工具:

lit_widget.render(data=[fewshot_mistake_example])
<IPython.core.display.Javascript object>

請注意令人驚訝的模型完成模型:

Taste-likes: Cheese
Taste-dislikes: Can't eat eggs
Suggestion: Quiche Lorraine
Analysis: A savoury tart with cheese and eggs
Recommendation: You might not like it, but it's worth trying.

為什麼模型建議您留意您明確表示不能吃的東西?

序列顯著性有助於強調根本問題 (我們僅列舉幾個例子)。在第一個範例中,分析區段 it has cooked onions in it, which you don't like 中思維鏈原因與最終建議 You have to try it 不符。

在 LM Salience 模組中,依序選取「Sentences」和建議行。UI 現在應如下所示:

3_few_shots_mistake..png

現在,請將第一個範例中的「Recommendation」更正為 Avoid,然後再試一次。LIT 已在範例提示中預先載入此範例,因此您可以使用這個小型公用程式函式擷取此範例:

def get_fewshot_example(source: str) -> str:
  for example in datasets['sample_prompts'].examples:
    if example['source'] == source:
      return example['prompt']
  raise ValueError(f'Source "{source}" not found in the dataset.')
lit_widget.render(data=[{'prompt': get_fewshot_example('fewshot-fixed')}])
<IPython.core.display.Javascript object>

現在模型完成狀態變成:

Taste-likes: Cheese
Taste-dislikes: Can't eat eggs
Suggestion: Quiche Lorraine
Analysis: This dish contains eggs and cheese, which you don't like.
Recommendation: Avoid.

想要避免這種情況,一個重要的課題是:早期原型設計有助於發現您可能未曾想到的風險,而語言模型本質上容易出錯,就意味著必須主動設計出可出錯的問題。如要進一步瞭解有關這項功能的討論,請參閱使用者 + AI 指南,瞭解如何使用 AI 進行設計。

雖然經過修正的少量樣本提示更為理想,但仍不盡理想:正確通知使用者避免開蛋,但原因並不正確,但事實上使用者表示他們不喜歡卵子,但事實並非如此。下一節將告訴您如何提高成效。

測試假設以改善模型行為

LIT 可讓您在相同介面中測試對提示所做的變更。在本範例中,您會測試新增 constitution 以改善模型的行為。憲法是指設計提示和原則,協助引導模型產生。最近的方法甚至能啟用憲法原則的互動式衍生作品

讓我們據此進一步改善提示。請在提示頂端新增一個說明產生原則的區段,首先如下:

Analyze a menu item in a restaurant.

* The analysis should be brief and to the point.
* The analysis and recommendation should both be clear about the suitability for someone with a specified dietary restriction.

## For example:

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Onion soup
Analysis: it has cooked onions in it, which you don't like.
Recommendation: Avoid.

...

lit_widget.render(data=[{'prompt': get_fewshot_example('fewshot-constitution')}])
<IPython.core.display.Javascript object>

透過這項更新,您可以重新執行範例,觀察到截然不同的輸出內容:

Taste-likes: Cheese
Taste-dislikes: Can't eat eggs
Suggestion: Quiche Lorraine
Analysis: This dish containts eggs, which you can't eat.
Recommendation: Not suitable for you.

接著,您可以再次提示意識,瞭解這項變更發生的原因:

3_few_shot_constitution.png

請注意,這項建議較為安全。此外,根據飲食限制以及分析 (所謂的「思考鏈」),這項原則會清楚指出合適度,並影響「不適合您」的描述。這樣一來,您就能更放心地認為輸出內容正好有正確原因。

將非技術團隊納入模型探測和探索階段

可解釋性的用途是讓團隊合作,範圍涵蓋 XAI、政策、法律等領域的專業知識。

在早期開發階段與模型互動時,往往需要具備大量的技術專業知識,這導致部分協作者較難存取及探測模型。工具向來不存在工具,讓這些團隊能參與早期原型設計階段。

我們希望透過 LIT,這個模式可以改變。正如本程式碼研究室所述,LIT 的視覺媒介和互動能力可檢驗顯著性和探索範例,有助於不同的相關人員共用及溝通發現項目。如此一來,您的團隊成員就能加入更多元的團隊成員,一起進行模型探索、探測及偵錯。向這些技術方法公開他們,有助於他們進一步瞭解模型的運作方式。此外,初期模型測試的專業知識組合更加多元,也有助於找出有待改進的不當結果。

重點回顧

一起來複習:

  • LIT UI 提供互動式模型執行介面,可讓使用者直接產生輸出內容,並測試「假設」情境。測試不同的提示變化時,這個做法特別實用。
  • LM Salience 模組以視覺化方式呈現顯著性,並提供可控管的資料精細程度,以便您說明以人為本的建構項目 (例如句子和字詞),而非以模型為中心的結構 (例如符記)。

如果在模型評估中發現有問題的範例,請將這些範例帶入 LIT 中進行偵錯。首先,您可以分析與建模工作相關的最大合理內容單元,接著透過視覺化內容瞭解模型在哪些位置正確或錯誤地播放提示內容,接著深入分析畫面上出現的錯誤行為,以找出可能的修正行為。

最後:李子一直在進步!如要進一步瞭解我們的功能並分享建議,請按這裡

附錄:LIT 如何計算序列一致性

LIT 會在多步驟程序中計算序列顯著性。

  1. 根據輸入字串 (提示以及模型的生成或「黃金」目標序列),為模型輸入符記化。
  2. 「滾動」輸入符記左側一個位置,計算「目標」序列。
  3. 擷取嵌入,並計算產生程序與「目標」序列之間的個別符記損失
  4. 將損失遮蓋來隔離您想解釋的符記。
  5. 使用 tf.GradientTape.gradient() 函式計算與遮蓋損失相關的輸入嵌入的梯度。
  6. 處理梯度,為每個輸入符記提供單一分數。例如,取每個位置的漸層 L2 常態。

附錄:透過程式輔助方式計算顯著性

您可以直接從 Python 計算顯著性分數,採用與 LIT 工具內部執行的相同步驟相同。設定方式分成三個步驟:

  1. 準備範例並執行模型權杖化工具,
  2. 準備遮罩,選取要說明哪些 (預測) 符記:
  3. 呼叫 salience 包裝函式。

製作 LIT 的輸入範例

{'prompt': 'Keras is a',
 'target': ' deep learning library for Python that provides a wide range of tools and functionalities for building, training, and evaluating deep learning models.\n\n**'}

呼叫慣例:權杖化工具和顯著性包裝函式都會使用 LIT 的 Model API,其中 .predict() 函式會使用範例 (索引) 清單,並傳回回應 (索引) 的產生器。處理大型資料集或模型速度較慢時,彈性會比較多,但這表示如果您現在只想根據其中一個範例進行預測,就需要使用類似下列內容包裝:list(model.predict([example])[0]

取得權杖以便選取說明目標

array(['<bos>', 'K', 'eras', '▁is', '▁a', '▁deep', '▁learning',
       '▁library', '▁for', '▁Python', '▁that', '▁provides', '▁a', '▁wide',
       '▁range', '▁of', '▁tools', '▁and', '▁functionalities', '▁for',
       '▁building', ',', '▁training', ',', '▁and', '▁evaluating', '▁deep',
       '▁learning', '▁models', '.', '\n\n', '**'], dtype='<U16')

如要計算顯著性,您需要建立目標遮罩來指定要解釋的 (預測) 符記。目標遮罩是與符記長度相同的陣列,而您要說明的符記位置會是 1。讓我們使用 ▁training▁evaluating 做為目標:

準備目標遮罩

{'prompt': 'Keras is a',
 'target': ' deep learning library for Python that provides a wide range of tools and functionalities for building, training, and evaluating deep learning models.\n\n**',
 'target_mask': array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0.],
       dtype=float32)}

呼叫顯著性模型

{'grad_l2': array([45.75, 36.75, 61, 5.40625, 4.09375, 5.625, 6.46875, 7.3125, 3.375,
        5.03125, 3.23438, 4.5625, 2.375, 3.40625, 2.75, 1.97656, 3.95312,
        3.42188, 14.125, 4.53125, 11.375, 12.625, 18.5, 4.5625, 6.5, 0, 0,
        0, 0, 0, 0, 0], dtype=bfloat16),
 'grad_dot_input': array([-4.03125, 3.04688, -7.03125, -0.800781, 0.769531, -0.679688,
        -0.304688, 2.04688, 0.275391, -1.25781, -0.376953, -0.0664062,
        -0.0405273, -0.357422, 0.355469, -0.145508, -0.333984, 0.0181885,
        -5.0625, 0.235352, -0.470703, 2.25, 3.90625, -0.199219, 0.929688,
        0, 0, 0, 0, 0, 0, 0], dtype=bfloat16),
 'tokens': array(['<bos>', 'K', 'eras', '▁is', '▁a', '▁deep', '▁learning',
        '▁library', '▁for', '▁Python', '▁that', '▁provides', '▁a', '▁wide',
        '▁range', '▁of', '▁tools', '▁and', '▁functionalities', '▁for',
        '▁building', ',', '▁training', ',', '▁and', '▁evaluating', '▁deep',
        '▁learning', '▁models', '.', '\n\n', '**'], dtype='<U16')}

就是這樣!grad_l2grad_dot_input 欄位中的分數與 tokens 對齊,與 LIT UI 中顯示的分數相同。

請注意,最後幾個分數為 0:由於我們的模型是由左至右的語言模型,因此目標範圍右側的符記不會影響預測結果。