使用 mlflow.evaluate()
评估 Hugging Face LLM
本指南将展示如何加载预训练的 Hugging Face 流水线,将其记录到 MLflow,并使用 mlflow.evaluate()
来评估内置指标以及针对模型的自定义 LLM 判定的指标。
如需详细信息,请阅读关于 使用 MLflow evaluate 的文档。
启动 MLflow 服务器
您可以:
- 通过在笔记本所在目录中运行
mlflow ui
来启动本地跟踪服务器。 - 使用跟踪服务器,如 本概述 中所述。
安装必要的依赖项
%pip install -q mlflow transformers torch torchvision evaluate datasets openai tiktoken fastapi rouge_score textstat
# Necessary imports
import warnings
import pandas as pd
from datasets import load_dataset
from transformers import pipeline
import mlflow
from mlflow.metrics.genai import EvaluationExample, answer_correctness, make_genai_metric
# Disable FutureWarnings
warnings.filterwarnings("ignore", category=FutureWarning)
加载预训练的 Hugging Face 流水线
这里我们正在加载一个文本生成流水线,但您也可以使用文本摘要或问答流水线。
mpt_pipeline = pipeline("text-generation", model="mosaicml/mpt-7b-chat")
Loading checkpoint shards: 0%| | 0/2 [00:00<?, ?it/s]
使用 MLflow 记录模型
我们将流水线记录为 MLflow 模型,它遵循标准格式,允许您以不同的“风格”(flavor)保存模型,这些“风格”可被不同的下游工具理解。在这种情况下,模型属于 transformers “风格”。
mlflow.set_experiment("Evaluate Hugging Face Text Pipeline")
# Define the signature
signature = mlflow.models.infer_signature(
model_input="What are the three primary colors?",
model_output="The three primary colors are red, yellow, and blue.",
)
# Log the model using mlflow
with mlflow.start_run():
model_info = mlflow.transformers.log_model(
transformers_model=mpt_pipeline,
name="mpt-7b",
signature=signature,
registered_model_name="mpt-7b-chat",
)
Successfully registered model 'mpt-7b-chat'. Created version '1' of model 'mpt-7b-chat'.
加载评估数据
从 Hugging Face Hub 加载数据集以用于评估。
下面数据集中的数据字段代表:
- instruction: 描述模型应执行的任务。数据集中的每一行都是要执行的唯一指令(任务)。
- input: 与
instruction
字段中定义的任务相关的可选上下文信息。例如,对于指令“Identify the odd one out”(找出异类),input
上下文指导会给出要从中选择异类的项目列表:“Twitter, Instagram, Telegram”。 - output: 指令(提供可选的
input
上下文)的答案,由原始评估模型(来自 OpenAI 的text-davinci-003
)生成。 - text: 将
instruction
、input
和output
应用到所使用的提示模板后生成的最终完整文本,该文本用于模型的微调。
dataset = load_dataset("tatsu-lab/alpaca")
eval_df = pd.DataFrame(dataset["train"])
eval_df.head(10)
指令 | 输入 | 输出 | 文本 | |
---|---|---|---|---|
0 | 给出保持健康的三条建议。 | 1. 均衡饮食,并确保包含... | 下面是一个描述任务的指令... | |
1 | 三原色是什么? | 三原色是红色、蓝色和黄色... | 下面是一个描述任务的指令... | |
2 | 描述原子的结构。 | 原子由原子核组成,原子核包含... | 下面是一个描述任务的指令... | |
3 | 我们如何减少空气污染? | 有多种方法可以减少空气污染... | 下面是一个描述任务的指令... | |
4 | 描述一个你必须做出艰难决定的时候... | 我在我...的时候必须做出一个艰难的决定... | 下面是一个描述任务的指令... | |
5 | 找出异类。 | Twitter, Instagram, Telegram | Telegram | 下面是一个描述任务的指令,... |
6 | 解释为什么以下分数是等价的... | 4/16 | 分数 4/16 等于 1/4,因为... | 下面是一个描述任务的指令,... |
7 | 用第三人称叙述写一个短篇故事... | 约翰的人生正处于十字路口。他刚刚... | 下面是一个描述任务的指令... | |
8 | 渲染一个房子的 3D 模型 | <无输出> 这种类型的指令无法... | 下面是一个描述任务的指令... | |
9 | 评估这句话的拼写和语法... | He finnished his meal and left the resturant | He finished his meal and left the restaurant. | 下面是一个描述任务的指令,... |
定义指标
鉴于我们正在评估模型对给定指令提供答案的能力,我们可能希望在 mlflow.evaluate()
提供的任何内置指标之上,选择一些额外的指标来帮助衡量这一点。
让我们衡量模型在以下两个指标上的表现:
- 答案是否正确? 这里我们使用预定义指标
answer_correctness
。 - 答案是否流畅、清晰、简洁? 我们将定义一个自定义指标
answer_quality
来衡量这一点。
我们需要将这两个指标作为 mlflow.evaluate()
的 extra_metrics
参数传入,以评估我们模型的质量。
什么是评估指标?
评估指标封装了您想要为模型计算的任何定量或定性衡量标准。对于每种模型类型,mlflow.evaluate()
会自动计算一组内置指标。请参阅 此处,了解每种模型类型将计算哪些内置指标。您还可以传入任何其他要计算的指标作为额外指标。MLflow 提供了一组预定义指标,您可以在 此处 找到,或者您可以定义自己的自定义指标。在本示例中,我们将结合使用预定义指标 mlflow.metrics.genai.answer_correctness
和一个用于质量评估的自定义指标。
让我们加载预定义指标——在本例中,我们使用 GPT-4 的 answer_correctness
。
answer_correctness_metric = answer_correctness(model="openai:/gpt-4")
现在我们想使用 make_genai_metric()
创建一个名为 answer_quality
的自定义 LLM 判定指标。我们需要定义指标定义和评分标准,以及一些供 LLM 判定器使用的示例。
# The definition explains what "answer quality" entails
answer_quality_definition = """Please evaluate answer quality for the provided output on the following criteria:
fluency, clarity, and conciseness. Each of the criteria is defined as follows:
- Fluency measures how naturally and smooth the output reads.
- Clarity measures how understandable the output is.
- Conciseness measures the brevity and efficiency of the output without compromising meaning.
The more fluent, clear, and concise a text, the higher the score it deserves.
"""
# The grading prompt explains what each possible score means
answer_quality_grading_prompt = """Answer quality: Below are the details for different scores:
- Score 1: The output is entirely incomprehensible and cannot be read.
- Score 2: The output conveys some meaning, but needs lots of improvement in to improve fluency, clarity, and conciseness.
- Score 3: The output is understandable but still needs improvement.
- Score 4: The output performs well on two of fluency, clarity, and conciseness, but could be improved on one of these criteria.
- Score 5: The output reads smoothly, is easy to understand, and clear. There is no clear way to improve the output on these criteria.
"""
# We provide an example of a "bad" output
example1 = EvaluationExample(
input="What is MLflow?",
output="MLflow is an open-source platform. For managing machine learning workflows, it "
"including experiment tracking model packaging versioning and deployment as well as a platform "
"simplifying for on the ML lifecycle.",
score=2,
justification="The output is difficult to understand and demonstrates extremely low clarity. "
"However, it still conveys some meaning so this output deserves a score of 2.",
)
# We also provide an example of a "good" output
example2 = EvaluationExample(
input="What is MLflow?",
output="MLflow is an open-source platform for managing machine learning workflows, including "
"experiment tracking, model packaging, versioning, and deployment.",
score=5,
justification="The output is easily understandable, clear, and concise. It deserves a score of 5.",
)
answer_quality_metric = make_genai_metric(
name="answer_quality",
definition=answer_quality_definition,
grading_prompt=answer_quality_grading_prompt,
version="v1",
examples=[example1, example2],
model="openai:/gpt-4",
greater_is_better=True,
)
评估
我们需要设置 OpenAI API 密钥,因为我们使用 GPT-4 来进行 LLM 判定的指标评估。
为了安全地设置您的私钥,请务必通过命令行终端为当前实例导出您的密钥,或者为了永久添加到所有基于用户的会话中,请配置您偏好的环境管理配置文件(即 .bashrc, .zshrc)以包含以下条目:
OPENAI_API_KEY=<your openai API key>
现在,我们可以调用 mlflow.evaluate()
。为了测试,我们使用数据的前 10 行。使用 "text"
模型类型时,毒性和可读性指标将作为内置指标计算。我们还将上面定义的两个指标传入 extra_metrics
参数进行评估。
with mlflow.start_run():
results = mlflow.evaluate(
model_info.model_uri,
eval_df.head(10),
evaluators="default",
model_type="text",
targets="output",
extra_metrics=[answer_correctness_metric, answer_quality_metric],
evaluator_config={"col_mapping": {"inputs": "instruction"}},
)
Downloading artifacts: 0%| | 0/79 [00:00<?, ?it/s]
2023/12/28 11:57:30 INFO mlflow.store.artifact.artifact_repo: The progress bar can be disabled by setting the environment variable MLFLOW_ENABLE_ARTIFACTS_PROGRESS_BAR to false
Loading checkpoint shards: 0%| | 0/66 [00:00<?, ?it/s]
2023/12/28 12:00:25 INFO mlflow.models.evaluation.base: Evaluating the model with the default evaluator. 2023/12/28 12:00:25 INFO mlflow.models.evaluation.default_evaluator: Computing model predictions. 2023/12/28 12:02:23 INFO mlflow.models.evaluation.default_evaluator: Testing metrics on first row... Using default facebook/roberta-hate-speech-dynabench-r4-target checkpoint
0%| | 0/1 [00:00<?, ?it/s]
0%| | 0/1 [00:00<?, ?it/s]
2023/12/28 12:02:43 INFO mlflow.models.evaluation.default_evaluator: Evaluating builtin metrics: token_count 2023/12/28 12:02:43 INFO mlflow.models.evaluation.default_evaluator: Evaluating builtin metrics: toxicity 2023/12/28 12:02:44 INFO mlflow.models.evaluation.default_evaluator: Evaluating builtin metrics: flesch_kincaid_grade_level 2023/12/28 12:02:44 INFO mlflow.models.evaluation.default_evaluator: Evaluating builtin metrics: ari_grade_level 2023/12/28 12:02:44 INFO mlflow.models.evaluation.default_evaluator: Evaluating metrics: answer_correctness
0%| | 0/10 [00:00<?, ?it/s]
2023/12/28 12:02:53 INFO mlflow.models.evaluation.default_evaluator: Evaluating metrics: answer_quality
0%| | 0/10 [00:00<?, ?it/s]
查看结果
results.metrics
是一个字典,包含所有计算指标的聚合值。请参阅 此处,了解每种模型类型的内置指标详情。
results.metrics
{'toxicity/v1/mean': 0.00809656630299287, 'toxicity/v1/variance': 0.0004603014839856817, 'toxicity/v1/p90': 0.010559113975614286, 'toxicity/v1/ratio': 0.0, 'flesch_kincaid_grade_level/v1/mean': 4.9, 'flesch_kincaid_grade_level/v1/variance': 6.3500000000000005, 'flesch_kincaid_grade_level/v1/p90': 6.829999999999998, 'ari_grade_level/v1/mean': 4.1899999999999995, 'ari_grade_level/v1/variance': 16.6329, 'ari_grade_level/v1/p90': 7.949999999999998, 'answer_correctness/v1/mean': 1.5, 'answer_correctness/v1/variance': 1.45, 'answer_correctness/v1/p90': 2.299999999999999, 'answer_quality/v1/mean': 2.4, 'answer_quality/v1/variance': 1.44, 'answer_quality/v1/p90': 4.1}
我们还可以查看 eval_results_table
,它显示了每行数据的指标。
results.tables["eval_results_table"]
Downloading artifacts: 0%| | 0/1 [00:00<?, ?it/s]
指令 | 输入 | 文本 | 输出 | 输出 | token_count | toxicity/v1/score | flesch_kincaid_grade_level/v1/score | ari_grade_level/v1/score | answer_correctness/v1/score | answer_correctness/v1/justification | answer_quality/v1/score | answer_quality/v1/justification | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 给出保持健康的三条建议。 | 下面是一个描述任务的指令... | 1. 均衡饮食,并确保包含... | 给出保持健康的三条建议。1. 均衡饮食... | 19 | 0.000446 | 4.1 | 4.0 | 2 | 模型提供的输出仅包含... | 3 | 输出可理解且流畅,但它... | |
1 | 三原色是什么? | 下面是一个描述任务的指令... | 三原色是红色、蓝色和黄色... | 三原色是什么?三原色是... | 19 | 0.000217 | 5.0 | 4.9 | 5 | 模型提供的输出完全... | 5 | 模型的输出流畅、清晰、简洁... | |
2 | 描述原子的结构。 | 下面是一个描述任务的指令... | 原子由原子核组成,原子核包含... | 描述原子的结构。原子是... | 18 | 0.000139 | 3.1 | 2.2 | 1 | 模型提供的输出不完整... | 2 | 输出不完整且缺乏清晰度,导致... | |
3 | 我们如何减少空气污染? | 下面是一个描述任务的指令... | 有多种方法可以减少空气污染... | 我们如何减少空气污染?有多种方法可以... | 18 | 0.000140 | 5.0 | 5.5 | 1 | 模型提供的输出完全... | 1 | 输出完全无法理解且无法... | |
4 | 描述一个你必须做出艰难决定的时候... | 下面是一个描述任务的指令... | 我在我...的时候必须做出一个艰难的决定... | 描述一个你必须做出艰难决定的时候... | 18 | 0.000159 | 5.2 | 2.9 | 1 | 模型提供的输出完全... | 2 | 输出不完整且缺乏清晰度,导致... | |
5 | 找出异类。 | Twitter, Instagram, Telegram | 下面是一个描述任务的指令,... | Telegram | 找出异类。1. 一辆汽车 2. 一辆卡车... | 18 | 0.072345 | 0.1 | -5.4 | 1 | 模型提供的输出完全... | 2 | 输出不清晰且缺乏流畅性。它... |
6 | 解释为什么以下分数是等价的... | 4/16 | 下面是一个描述任务的指令,... | 分数 4/16 等于 1/4,因为... | 解释为什么以下分数是等价的... | 23 | 0.000320 | 6.4 | 7.6 | 1 | 模型提供的输出完全... | 2 | 输出不清晰且没有回答... |
7 | 用第三人称叙述写一个短篇故事... | 下面是一个描述任务的指令... | 约翰的人生正处于十字路口。他刚刚... | 用第三人称叙述写一个短篇故事... | 20 | 0.000247 | 10.7 | 11.1 | 1 | 模型提供的输出完全... | 1 | 输出与输入完全相同,这... | |
8 | 渲染一个房子的 3D 模型 | 下面是一个描述任务的指令... | <无输出> 这种类型的指令无法... | 在 Blender 中渲染一个房子的 3D 模型 - Blen... | 19 | 0.003694 | 5.2 | 2.7 | 1 | 模型提供的输出完全... | 2 | 输出部分可理解但缺乏... | |
9 | 评估这句话的拼写和语法... | He finnished his meal and left the resturant | 下面是一个描述任务的指令,... | He finished his meal and left the restaurant. | 评估这句话的拼写和语法... | 18 | 0.003260 | 4.2 | 6.4 | 1 | 模型提供的输出完全... | 4 | 输出流畅且清晰,但它不是... |
在 UI 中查看结果
最后,我们可以在 MLflow UI 中查看评估结果。我们可以在左侧边栏选择我们的实验,这将把我们带到以下页面。我们可以看到一个运行记录了我们的模型“mpt-7b-chat”,另一个运行包含了我们评估的数据集。
我们点击“评估”选项卡并隐藏任何不相关的运行。
现在我们可以选择要按哪些列进行分组,以及要比较哪些列。在以下示例中,我们正在查看每个输入-输出对的答案正确性得分,但我们可以选择任何其他指标进行比较。
最后,我们得到以下视图,其中我们可以看到每行的答案正确性的理由和得分。