在 Keras 中使用 LIT 分析 Gemma 模型

1. 简介

生成式 AI 产品相对较新,与早期形式的软件相比,应用的行为差异更大。因此,探究正在使用的机器学习模型、检查模型的行为示例以及调查意外情况非常重要。

Learning Interpretability Tool(LIT;网站GitHub)是一个用于调试和分析机器学习模型的平台,用于了解模型的行为原因和行为。

在此 Codelab 中,您将学习如何使用 LIT 更充分地利用 Google 的 Gemma 模型。此 Codelab 演示了如何使用序列显著性(一种可解释性方法)来分析不同的提示工程方法。

学习目标:

  1. 了解序列显著性及其在模型分析中的用途。
  2. 为 Gemma 设置 LIT,以计算提示输出和序列显著性。
  3. 通过 LM Salience 模块使用序列显著性来了解提示设计对模型输出的影响。
  4. 在 LIT 中测试假设的提示改进,并查看其影响。

注意:此 Codelab 使用 Gemma 的 KerasNLP 实现,并将 TensorFlow v2 用于后端。强烈建议您使用 GPU 内核。

LIT 界面演示

2. 序列显著性及其在模型分析中的应用

文本到文本生成模型(例如 Gemma)接受词法单元化文本形式的输入序列,并生成新词元,即该输入的典型后续或补全内容。这一代词每次发生一个词元,将每个新生成的词元(循环)附加到输入和之前的任何世代,直到模型达到停止条件。例如,模型生成序列结束 (EOS) 令牌或达到预定义的最大长度。

显著性方法是一类可解释的 AI (XAI) 技术,可告诉您对于模型输出的不同部分,输入的哪些部分对模型很重要。LIT 支持各种分类任务的显著性方法,这些方法可解释一系列输入词元对预测标签的影响。序列显著性将这些方法泛化为文本到文本生成模型,并解释了前面的词法单元对生成的词元的影响。

在这里,您将使用 Grad L2 Norm 方法了解序列显著性,该方法会分析模型的梯度,并提供前面的每个词元对输出的影响程度。这种方法简单高效,事实证明在分类和其他设置中具有良好效果。显著性分数越高,影响就越大。这种方法在 LIT 中得到广泛理解,在可解释性研究社区中被广泛使用。

更高级的基于梯度的显著性方法包括梯度 ⋅ 输入积分梯度。此外,还有基于消解的方法,例如 LIMESHAP,它们更为稳健,但计算费用要高得多。如需查看不同显著性方法的详细比较,请参阅这篇文章

如需详细了解显著性方法的科学原理,请参阅这个入门级交互式可探索显著性

3. 导入、环境和其他设置代码

最好在新版 Colab 中完成此 Codelab 的学习。我们建议您使用加速器运行时,因为您需要将模型加载到内存中,但请注意,加速器选项会随时间推移而变化,并且受限制。如果您希望使用更强大的加速器,Colab 提供付费订阅。或者,如果您的机器具有合适的 GPU,您也可以使用本地运行时

注意:您可能会看到表单中显示的一些警告

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

对于此 Codelab,您需要最新版本的 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 的许可协议。

4. 设置 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)

5. 设置 LIT 数据集

Gemma 是一种文本到文本生成模型,可接受文本输入并生成文本输出。LIT 的模型假定数据集将提供以下字段来支持生成操作:

  • promptKerasGenerationModel 的输入。
  • target:可选的目标序列,例如“标准答案”(金色)答案或模型预先生成的回答。

LIT 包含一小部分 sample_prompts,其中包含来自几个不同来源的示例,例如:

  • GSM8K:使用少样本示例解决小学数学问题。
  • Gigaword Benchmark:生成一系列短报道的标题。
  • 宪法提示:生成有关如何使用带有准则/边界的对象的新想法。

您还可以使用 LIT 的 Dataset API 轻松加载自己的数据,或者加载包含带有 prompt 字段和 target 字段(可选)的记录的 .jsonl 文件(示例)。

运行以下单元以加载示例提示。

from lit_nlp.examples.datasets import lm as lm_data

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

6. 设置 LIT 界面

LIT 是一种交互式模型理解工具,支持人机协同 (human-in-the-loop) 评估和探测模型行为。LIT 界面通过使您能够:

  • 实时直观呈现数据集和模型输出,
  • 运行显著性方法以了解驱动模型行为的输入令牌,以及
  • 创建反事实来测试各种假设。

LIT 在同一个界面中实现所有这些目的,减少不同工具之间的切换。这对于提示工程等任务特别有用,您将在此 Codelab 的后面部分重点了解这些任务。

此界面布局可用于任何其他生成式语言模型。如果您对此处所列功能之外的功能感兴趣,则可点击此处查看完整列表。

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',
)

现在,您可以显示界面了:

lit_widget.render(height=800)

LIT 界面演示

您也可以在新标签页中以整页模式打开 LIT。运行此代码并点击它显示的链接:

lit_widget.render(open_in_new_tab=True)

注意:如果您在常规 .py 脚本中使用 LIT,请使用 lit_nlp.dev_server.Server() 而非 LitWidget 来启动独立服务器。如需了解详情,请参阅 LIT 文档

7. 在 LIT 中分析 Gemma 的少样本提示

如今,提示既是艺术,又是科学,LIT 可以帮助您根据经验来改进针对 Gemma 等大型语言模型的提示。在前面,你会看到一个示例,说明如何使用 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 模块检查提示。

8. 使用序列显著性进行调试

显著性是在最小的级别上计算(即针对每个输入词元),但 LIT 可以将词元显著性聚合为更易于解释的较大 span,例如行、句子或字词。如需详细了解显著性以及如何利用它来识别意外偏差,请参阅我们的 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 界面,则可以使用 LIT 的 Datapoint Editor 添加此提示:

LIT 数据点编辑器

另一种方法是直接使用兴趣提示重新渲染 widget:

lit_widget.render(data=[fewshot_mistake_example])

请注意模型完成度令人惊讶:

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”(句子)然后选择建议行现在,界面应如下所示:

LIT 显著性

这会突出显示人为错误:意外复制和粘贴建议部分且未能更新!

现在,让我们来更正“建议”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')}])

现在,模型完成变为:

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 指南

虽然更正少数镜头提示较好,但还是不太正确:它正确地告诉了用户避开鸡蛋,但推理是不正确的,它说他们不喜欢鸡蛋,而实际上用户已经说不能吃鸡蛋。在接下来的部分,您将了解如何做得更好。

9. 测试假设以改进模型行为

使用 LIT,您可以在同一界面中测试对提示所做的更改。在此示例中,您将测试添加宪法以改进模型的行为。宪法是指遵循原则的设计提示,有助于指导模型的生成。最近的方法甚至能够交互式派生宪法原则。

让我们利用以下想法来进一步改进提示。在提示顶部添加一个包含生成原则的部分,现在开头如下所示:

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')}])

经过此次更新,示例可以重新运行并观察到一个截然不同的输出:

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

然后,可以重新检查提示显著性,以帮助理解为什么会发生这种变化:

LIT 显著性

请注意,此建议更安全。此外,“不适合你”状态的受饮食禁忌和分析(所谓的思维链)的影响。这有助于进一步确保输出的理由是正确的。

10. 让非技术团队参与模型探测和探索

可解释性需要团队共同努力,囊括 XAI、政策、法律等方面的专业知识。

在早期开发阶段与模型交互历来需要大量的技术专业知识,这使得一些协作者更难访问和探究模型。历来还没有工具使这些团队能够参与早期原型设计阶段。

通过 LIT,我们希望这种范式可以改变。正如您在此 Codelab 中所了解到的,LIT 通过可视化媒介和互动功能来检查显著性并探索示例,这有助于不同的利益相关方分享和传达发现结果。这样,你就可以引入更多元化的团队成员,让他们参与模型探索、探测和调试。让他们接触这些技术方法可以加强他们对模型工作原理的理解。此外,早期模型测试方面的专业知识更加多样化,也有助于发现可以改进的不良结果。

11. 要点回顾

总结如下:

  • LIT 界面提供了一个交互式模型执行界面,让用户能够直接生成输出并测试“假设”场景。这对于测试不同的提示变体特别有用。
  • LM Salience 模块以可视化方式呈现显著性,并提供可控制的数据粒度,以便您围绕以人为中心的结构(例如句子和字词)进行沟通,而不是围绕以模型为中心的结构(例如词元)进行沟通。

在模型评估中发现有问题的示例时,将其引入 LIT 进行调试。首先,分析您能认为与建模任务在逻辑上相关的最大合理内容单元,使用可视化结果了解模型在哪些地方正确或错误地处理提示内容,然后深入到较小的内容单元,进一步描述您看到的错误行为,以确定可能的修复方案。

最后:Lit 一直在不断改进!如需详细了解我们的功能并分享您的建议,请点击此处