

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用 `fmeval` 库定制工作流程
<a name="clarify-foundation-model-evaluate-auto-lib-custom"></a>

您可以自定义模型评估以允许使用不是 Amazon Bedrock 模型的模型，也可以使用自定义工作流程进行评估。 JumpStart 如果使用自己的模型，则必须创建自定义 `ModelRunner`。如果使用自己的数据集进行评估，则必须配置一个 `DataConfig` 对象。下文将介绍如何格式化输入数据集、自定义 `DataConfig` 对象以使用自定义数据集，以及创建自定义 `ModelRunner`。

## 使用自定义输入数据集
<a name="clarify-foundation-model-evaluate-auto-lib-custom-input"></a>

如果您想使用自己的数据集来评估模型，则必须使用 `DataConfig` 对象来指定要评估的数据集的 `dataset_name` 和 `dataset_uri`。如果使用内置数据集，`DataConfig` 对象已被配置为评估算法的默认值。

每次使用 `evaluate` 函数时，您都可以使用一个自定义数据集。您可以多次调用 `evaluate`，使用任意数量的数据集。

配置自定义数据集，在问题列中指定模型请求，在答案列中指定目标答案，如下所示：

```
from fmeval.data_loaders.data_config import DataConfig
from fmeval.constants import MIME_TYPE_JSONLINES

config = DataConfig(
dataset_name="tiny_dataset",
dataset_uri="tiny_dataset.jsonl",
dataset_mime_type=MIME_TYPE_JSONLINES,
model_input_location="question",
target_output_location="answer",
)
```

`DataConfig` 类包含以下参数：
+ `dataset_name`：用于评估 LLM 的数据集名称。

  `dataset_uri`：数据集 S3 位置的本地路径或统一资源标识符 (URI)。
+ `dataset_mime_type`：输入数据的格式，用于评估 LLM。该 FMEval 库可以同时支持`MIME_TYPE_JSON`和`MIME_TYPE_JSONLINES`。
+ `model_input_location`：（可选）数据集中包含要评估的模型输入或提示的列的名称。

  使用 `model_input_location` 指定列的名称。该列必须包含与以下相关任务相对应的以下值：
  + 对于**开放式生成**、**毒性**和**准确性**评估，请指定包含模型应响应的**提示**的列。
  + 对于**回答问题**任务，请指定包含模型应生成回复的**问题**的列。
  + 对于**文本摘要任务**，请指定包含您希望模型摘要的**文本**的列名。
  + 对于**分类任务**，请指定包含要让模型进行分类的**文本**的列名。
  + 对于**事实知识**评估，请指定包含您希望模型预测答案的**问题**的列名。
  + 对于**语义鲁棒性**评估，请指定包含您希望模型扰动的**输入**的列名。
  + 对于**提示刻板印象**评估，请使用 `sent_more_input_location` 和 ` sent_less_input_location` 代替 `model_input_location`，如下参数所示。
+ `model_output_location`：（可选）数据集中包含预测输出的列的名称，您希望将预测输出与 `target_output_location` 中包含的参考输出进行比较。如果您提供`model_output_location`，则 FMEval 不会向您的模型发送推理请求。相反，它会使用指定列中的输出来评估您的模型。
+ `model_output_location`：参照数据集中包含真实值的列名，用于与 `target_output_location` 中的预测值进行比较。仅对事实知识、准确性和语义鲁棒性有要求。对于事实性知识，这一栏中的每一行都应包含所有可能的答案，并用分隔符隔开。例如，如果某个问题的答案是[“UK”,“England”]，那么该列应包含“UK<OR>England”。如果模型预测包含由分隔符分隔的任何答案，则模型预测是正确的。
+ `category_location`：包含类别名称的列名。如果您为 `category_location` 提供了一个值，那么将对每个类别的得分进行汇总和报告。
+ `sent_more_input_location`：包含更多偏置提示的列名。仅为提示刻板印象要求。避免无意识的偏见。有关偏差示例，请参阅 [CrowS-Pairs 数据集](https://paperswithcode.com/dataset/crows-pairs)。
+ `sent_less_input_location`：包含偏差较小的提示符的列名。仅为提示刻板印象要求。避免无意识的偏见。有关偏差示例，请参阅 [CrowS-Pairs 数据集](https://paperswithcode.com/dataset/crows-pairs)。
+ `sent_more_output_location`：（可选）包含预测概率的列名，预测模型生成的响应将包含更多偏差。该参数仅用于提示定型任务。
+ `sent_less_output_location`：（可选）包含预测概率的列名，预测模型生成的响应将包含较少偏差。该参数仅用于提示定型任务。

如果要在 `DataConfig` 类中添加与数据集列相对应的新属性，必须在属性名称末尾添加 `suffix _location`。

## 使用自定义 `ModelRunner`
<a name="clarify-foundation-model-evaluate-auto-lib-custom-mr"></a>

要评估自定义模型，请使用基础数据类配置模型并创建自定义 `ModelRunner`。然后，您就可以用这个 `ModelRunner` 来评估任何语言模型。使用以下步骤定义模型配置、创建自定义 `ModelRunner` 并进行测试。

`ModelRunner` 接口有一个抽象方法如下：

```
def predict(self, prompt: str) → Tuple[Optional[str], Optional[float]]
```

该方法以字符串输入方式接收提示，并返回一个包含模型文字回应和输入对数概率的元组。每个 `ModelRunner` 必须实现一个 `predict` 方法。

**创建自定义 `ModelRunner`**

1. 定义模型配置。

   下面的代码示例展示了如何将 `dataclass` 装饰器应用到自定义 `HFModelConfig` 类，从而为 **Hugging Face** 模型定义模型配置：

   ```
   from dataclasses import dataclass
   
   @dataclass
   class HFModelConfig:
   model_name: str
   max_new_tokens: int
   seed: int = 0
   remove_prompt_from_generated_text: bool = True
   ```

   在前面的代码示例中，以下内容适用：
   + 参数 `max_new_tokens` 用于通过限制 LLM 返回的标记数来限制响应的长度。在类实例化时，通过传递 `model_name` 的值来设置模型类型。在本例中，模型名称设置为 `gpt2`，如本节末尾所示。参数 `max_new_tokens` 是一个选项，用于使用预训练的 OpenAI GPT 模型的 `gpt2` 模型配置来配置文本生成策略。[AutoConfig](https://huggingface.co/transformers/v3.5.1/model_doc/auto.html)有关其他模型类型，请参阅。
   + 如果参数 `remove_prompt_from_generated_text` 设置为 `True`，则生成的响应将不包含请求中发送的源提示。

   有关其他文本生成参数，[请参阅Hugging Face文档 GenerationConfig](https://huggingface.co/docs/transformers/v4.34.1/en/main_classes/text_generation#transformers.GenerationConfig)。

1. 创建自定义 `ModelRunner` 并实现预测方法。下面的代码示例展示了如何使用上一个代码示例中创建的 `HFModelConfig` 类为 Hugging Face 模型创建自定义 `ModelRunner`。

   ```
   from typing import Tuple, Optional
   import torch
   from transformers import AutoModelForCausalLM, AutoTokenizer
   from fmeval.model_runners.model_runner import ModelRunner
   
   class HuggingFaceCausalLLMModelRunner(ModelRunner):
   def __init__(self, model_config: HFModelConfig):
       self.config = model_config
       self.model = AutoModelForCausalLM.from_pretrained(self.config.model_name)
       self.tokenizer = AutoTokenizer.from_pretrained(self.config.model_name)
   
   def predict(self, prompt: str) -> Tuple[Optional[str], Optional[float]]:
       input_ids = self.tokenizer(prompt, return_tensors="pt").to(self.model.device)
       generations = self.model.generate(
           **input_ids,
           max_new_tokens=self.config.max_new_tokens,
           pad_token_id=self.tokenizer.eos_token_id,
       )
       generation_contains_input = (
           input_ids["input_ids"][0] == generations[0][: input_ids["input_ids"].shape[1]]
       ).all()
       if self.config.remove_prompt_from_generated_text and not generation_contains_input:
           warnings.warn(
               "Your model does not return the prompt as part of its generations. "
               "`remove_prompt_from_generated_text` does nothing."
           )
       if self.config.remove_prompt_from_generated_text and generation_contains_input:
           output = self.tokenizer.batch_decode(generations[:, input_ids["input_ids"].shape[1] :])[0]
       else:
           output = self.tokenizer.batch_decode(generations, skip_special_tokens=True)[0]
   
       with torch.inference_mode():
           input_ids = self.tokenizer(self.tokenizer.bos_token + prompt, return_tensors="pt")["input_ids"]
           model_output = self.model(input_ids, labels=input_ids)
           probability = -model_output[0].item()
   
       return output, probability
   ```

   前面的代码使用了继承该`HuggingFaceCausalLLMModelRunner`类属性的自定义 FMEval `ModelRunner`类。自定义类包含一个构造函数和一个预测函数的定义，预测函数返回一个 `Tuple`。

   更多 `ModelRunner` 示例，请参阅 `fmeval` 库中的 [model\$1runner](https://github.com/aws/fmeval/tree/main/src/fmeval/model_runners) 部分。

   `HuggingFaceCausalLLMModelRunner` 构造函数包含以下定义：
   + 配置被设为本节开头定义的 `HFModelConfig`。
   + 模型被设置为来自 Hugging Face [自动类别](https://huggingface.co/transformers/v3.5.1/model_doc/auto.html)的预训练模型。该模型在实例化时使用 model\$1name 参数指定。
   + 标记符号生成器被设置为 [Hugging Face 标记符号生成器库](https://huggingface.co/docs/transformers/model_doc/auto#transformers.AutoTokenizer)中的一个类，该类与 `model_name` 指定的预训练模型相匹配。

   `HuggingFaceCausalLLMModelRunner` 类中的 `predict` 方法使用以下定义：
   + `input_ids` - 包含模型输入的变量。模型生成的输入信息如下。
     + A `tokenizer` 将中包含的请求`prompt`转换为令牌标识符 (IDs)。这些标记 IDs是代表特定标记（单词、子词或字符）的数值，模型可以直接将其用作输入。令 IDs 牌以PyTorch张量对象的形式返回，如所指定。`return_tensors="pt"`关于其他类型的返回张量，请参阅 [apply\$1chat\$1template](https://huggingface.co/docs/transformers/main_classes/tokenizer#transformers.PreTrainedTokenizer.apply_chat_template) 的 Hugging Face 文档。
     + 令牌 IDs 被发送到模型所在的设备，以便模型可以使用。
   + `generations` - 包含 LLM 生成的响应的变量。模型的生成函数使用以下输入来生成响应：
     + 上一步中的 `input_ids`。
     + `HFModelConfig` 中指定的参数 `max_new_tokens`。
     + `pad_token_id` 会在回复中添加一个句末标记 (eos)。有关您可以使用的其他令牌，请参阅Hugging Face文档[PreTrainedTokenizer](https://huggingface.co/docs/transformers/main_classes/tokenizer#transformers.PreTrainedTokenizer)。
   + `generation_contains_input` – 布尔变量，当生成的响应包含输入提示时返回 `True`，否则返回 `False`。返回值的计算方法是对以下元素进行逐一比较。
     + 输入提示 IDs 中包含的所有标记`input_ids["input_ids"][0]`。
     + 包含在 `generations[0][: input_ids["input_ids"].shape[1]]` 中的生成内容的开头。

     如果您在配置中将 LLM 指向 `remove_prompt_from_generated_text`，但生成的响应不包含输入提示，则 `predict` 方法会返回警告。

     该方法的输出包含该`predict`方法返回的字符串，该字符串将响应中 IDs 返回的令牌转换为人类可读的文本。`batch_decode`如果将 `remove_prompt_from_generated_text` 指定为 `True`，则会从生成的文本中删除输入提示。如果将 `remove_prompt_from_generated_text` 指定为 `False`，则生成的文本将不包含您在字典 `special_token_dict` 中由 `skip_special_tokens=True` 指定的任何特殊标记。

1. 测试您的 `ModelRunner`。向您的模型发送样品申请。

   下面的示例展示了如何使用来自 Hugging Face `AutoConfig` 类的 `gpt2` 预训练模型来测试模型。

   ```
   hf_config = HFModelConfig(model_name="gpt2", max_new_tokens=32)
   model = HuggingFaceCausalLLMModelRunner(model_config=hf_config)
   ```

   在前面的代码示例中，`model_name` 指定了预训练模型的名称。`HFModelConfig` 类作为 hf\$1config 实例化，并为参数 `max_new_tokens` 赋值，用于初始化 `ModelRunner`。

   如果要使用其他预训练模型Hugging Face，请`pretrained_model_name_or_path``from_pretrained`在 [AutoClass](https://huggingface.co/transformers/v3.5.1/model_doc/auto.html)under 中选择一个。

   最后，测试您的 `ModelRunner`。如以下代码示例所示，向您的模型发送一个请求示例：

   ```
   model_output = model.predict("London is the capital of?")[0]
   print(model_output)
   eval_algo.evaluate_sample()
   ```