百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

DSPy教程-第3章:DSPy的评估(Evaluation)

zhezhongyun 2025-03-19 18:34 49 浏览

3 DSPy 中的评估(Evaluation)

3.1 概述

有了初步的系统,下一步就是收集开发数据集,以便能更系统地对系统进行优化。建议数据集不低于20个(200个效果会好些)。根据开发的系统的评估指标不同,数据集可能只需要输入数据,不需要标签。也可能输入数据和最终输出都需要。

提示:可以在HuggingFace数据集或像StackExchange这样的找到与你任务相似的数据集。条件允许,建议使用这些数据。当然,你可以手动标注一些示例。

接下来,定义DSPy指标。什么样的输出是好的还是坏的。这需要投入精力来定义这些指标,并逐步优化;不然就很难持续进行改进。指标也是一个函数,它获取从数据输入,并根据输出的结果,返回一个评分。对于简单的任务,这评分可能是“准确率”,例如简单的分类或短问答任务等。对于大多数应用,系统会生成很长的输出,因此你的指标将是一个较小的DSPy程序,用于检查输出的多种属性。

有开发数据和DSPy指标函数,就可以运行评估来权衡你设计的流程控制。反复的查看输出和指标评分,来设定一个基线。

3.2 DSPy的数据对象

DSPy 是一个机器学习框架,其在工作通常用到训练集、开发集和测试集,每个示例(Example)是数据集最小组成单位。示例内部通常可以分为三类:输入、中间标签或者最终标签。示例可以没有中间标签或最终标签,但至少需要输入。接下来是我们要介绍的DSPy数据集示例:Example。

3.2.1 DSPy的 Example 对象

DSPy中的核心数据类型是Example。DSPy使用Example 来表示训练集和测试集中的项目。

Example类似于Python dict类型 ,但它可以包含一些工具。DSPy 模块返回 类型的值Prediction,是 Example 的一个特殊子类。

qa_pair = dspy.Example(question="This is a question?", answer="This is an answer.")

print(qa_pair)
print(qa_pair.question)
print(qa_pair.answer)

日志打印

Example({'question': 'This is a question?', 'answer': 'This is an answer.'}) (input_keys=None)
This is a question?
This is an answer.

Example的参数可以是任何字段键(Keys )和值类型(value),默认是字符串,单个Example如下:

object = Example(field1=value1, field2=value2, field3=value3, ...)

训练集是多个Example列表(list),如下:

trainset = [dspy.Example(report="LONG REPORT 1", summary="short summary 1"), ...]

3.2.2 Example 键的指定及访问

在传统的机器学习(Machine Learning, ML)中,数据通常被分为两部分:

  • 输入(Input):也称为特征(Features),是模型用来学习和预测的数据。例如,在图像分类任务中,输入可能是图像的像素值;在房价预测任务中,输入可能是房屋的面积、位置等信息。
  • 标签(Label):也称为目标(Target)或输出(Output),是模型需要预测的值。例如,在图像分类任务中,标签可能是图像的类别(如“猫”或“狗”);在房价预测任务中,标签可能是房屋的价格。

在 DSPy 中, Example 对象可以使用with_inputs()方法某个字段作为收入键input。(不标记则默认为元数据或标签键label)

# 单个输入,标记question为输入标签
print(qa_pair.with_inputs("question"))

# 多个输入;注意这里的answer也是输入
print(qa_pair.with_inputs("question", "answer"))

Example 对象可以通过. (点) 运算符来访问键的值。如:Example(name="John Doe", job="sleep"),可以通过object.name来访问name键的值。

也可以使用 inputs() 和 labels()方法,访问所有输入和标签的值如下:

# article已标记为inputs,summary未标记则默认为labels
article_summary = dspy.Example(article= "This is an article.", summary= "This is a summary.").with_inputs("article")

input_key_only = article_summary.inputs()
non_input_key_only = article_summary.labels()

print("Example object with Input fields only:", input_key_only)
print("Example object with Non-Input fields only:", non_input_key_only)

日志打印

Example object with Input fields only: Example({'article': 'This is an article.'}) (input_keys=None)
Example object with Non-Input fields only: Example({'summary': 'This is a summary.'}) (input_keys=None)

3.3 Metrics 指标

DSPy 是一个机器学习框架,因此需要考虑用于评估的自动指标(以跟踪进展)和用于优化的自动指标(以便 DSPy 可以使程序更有效)

3.3.1 指标概述

指标只是一个函数,它通过数据集的输入、获取系统输出,及返回评分。来衡量系统的输出效果是好是坏。

于简单的任务,如简单的分类或简短形式的问答任等,可以使用“准确率”或“精确匹配”或“F1 分数”来作为指标。

然而,对于大多数应用来说,需要输出很长的内容。那么,指标应该是一个较小的DSPy程序,用于检查输出的多个属性(很可能使用来自LM的AI反馈)。一次做到完美不太可能,应该从简单的东西开始,然后逐步改进。

3.3.2 简单的指标

DSPy 指标是一个 Python 函数, 它传入的参数主要是数据集example(训练集或开发) 和DSPy 程序的输出pred,返回评估的结果 float分数(int 或 bool )。

指标还可以传入第三个参数 trace[可选],可以暂时忽略这个参数,在以后得高阶技能,这个参数非常重要。

下面是一个简单的示例,指标是比较 example.answer 和 pred.answer 是否相对,返回一个 bool 值。

def validate_answer(example, pred, trace=None):
    return example.answer.lower() == pred.answer.lower()

上面的例子也可以改用DSPy内置的工具进行比较:

  • dspy.evaluate.metrics.answer_exact_match

上例的指标可以改成的复杂点,例如检查多个属性。如下:

  • 当用于评估或优化时,返回一个浮点数;
  • 当用于启动示范时,返回一个布尔值。
def validate_context_and_answer(example, pred, trace=None):
    # check the gold label and the predicted answer are the same
    answer_match = example.answer.lower() == pred.answer.lower()

    # check the predicted answer comes from one of the retrieved contexts
    context_match = any((pred.answer.lower() in c) for c in pred.context)

    if trace is None: # if we're doing evaluation or optimization
        return (answer_match + context_match) / 2.0
    else: # if we're doing bootstrapping, i.e. self-generating good demonstrations of each step
        return answer_match and context_match

提示:定义一个好的指标函数是一个迭代过程,进行初步评估并查看数据和输出是关键。

3.3.3 Evaluation 评估指标

有了指标函数,现在可以进行循环评估了。

scores = []
for x in devset:
    pred = program(**x.inputs())
    score = metric(x, pred)
    scores.append(score)

Evaluate 内置了一些工具,可以帮助进行并行评估(多线程)或显示输入/输出样本以及指标评分。

from dspy.evaluate import Evaluate

# Set up the evaluator, which can be re-used in your code.
evaluator = Evaluate(devset=YOUR_DEVSET, num_threads=1, display_progress=True, display_table=5)

# Launch evaluation.
evaluator(YOUR_PROGRAM, metric=YOUR_METRIC)

3.3.4 中级:使用AI反馈优化指标

对于大多数应用,系统会输出长格式的内容,因此指标应该使用来自语言模型(LM)的AI反馈来检查输出的多个维度。下面是一个Signature的简单例子:

# Define the signature for automatic assessments.
class Assess(dspy.Signature):
    """Assess the quality of a tweet along the specified dimension."""

    assessed_text = dspy.InputField()
    assessment_question = dspy.InputField()
    assessment_answer: bool = dspy.OutputField()

例如,下面是一个简单的指标,用于检查生成的推文.评估维度为:

  1. 是否正确回答了给定的问题;
  2. 是否具有吸引力;
  3. len(tweet) <= 280 个字符。
def metric(gold, pred, trace=None):
    question, answer, tweet = gold.question, gold.answer, pred.output

    engaging = "Does the assessed text make for a self-contained, engaging tweet?"
    correct = f"The text should answer `{question}` with `{answer}`. Does the assessed text contain this answer?"

    correct =  dspy.Predict(Assess)(assessed_text=tweet, assessment_question=correct)
    engaging = dspy.Predict(Assess)(assessed_text=tweet, assessment_question=engaging)

    correct, engaging = [m.assessment_answer for m in [correct, engaging]]
    score = (correct + engaging) if correct and (len(tweet) <= 280 else 0 if trace is not none: return score>= 2
    return score / 2.0

当 trace is not None 为 True 时,返回 score >= 2 。否则,将返回一个介于 0 到 1 之间的分数(即, score / 2.0 )。

3.3.5 高级:使用 DSPy 程序作为指标

如果你的评估指标本身是一个 DSPy 程序(优化器optimize),它的迭代方法是编译这个评估指标本身,只需要通过收集几个例子即可。

高级:访问 trace

当你的指标在评估运行中被使用时,DSPy 不会尝试跟踪你程序的步骤。

但在编译(优化器optimize)过程中,DSPy 会跟踪你的 LM 调用。跟踪信息将包含每个 DSPy 预测器的输入/输出,你可以利用这些信息验证优化过程中的中间步骤。

def validate_hops(example, pred, trace=None):
    hops = [example.question] + [outputs.query for *_, outputs in trace if 'query' in outputs]

    if max([len(h) for h in hops]) > 100: return False
    if any(dspy.evaluate.answer_exact_match_str(hops[idx], hops[:idx], frac=0.8) for idx in range(2, len(hops))): return False

    return True

相关推荐

JavaScript做个贪吃蛇小游戏(过关-加速),无需网络直接玩。

JavaScript做个贪吃蛇小游戏(过关-则加速)在浏览器打开文件,无需网络直接玩。<!DOCTYPEhtml><htmllang="en"><...

大模型部署加速方法简单总结(大模型 ai)

以下对大模型部署、压缩、加速的方法做一个简单总结,为后续需要备查。llama.cppGithub:https://github.com/ggerganov/llama.cppLLaMA.cpp项...

安徽医大第一医院应用VitaFlow Liberty(R)Flex为患者焕然一“心”

近日,在安徽医科大学第一附属医院心血管内科负责人暨北京安贞医院安徽医院业务副院长喻荣辉教授的鼎力支持和卓越带领下,凭借着先进的VitaFlowLiberty(R)Flex经导管主动脉瓣可回收可...

300 多行代码搞定微信 8.0 的「炸」「裂」特效!

微信8.0更新的一大特色就是支持动画表情,如果发送的消息只有一个内置的表情图标,这个表情会有一段简单的动画,一些特殊的表情还有全屏特效,例如烟花表情有全屏放烟花的特效,炸弹表情有爆炸动画并且消息和...

让div填充屏幕剩余高度的方法(div填充20px)

技术背景在前端开发中,经常会遇到需要让某个div元素填充屏幕剩余高度的需求,比如创建具有固定头部和底部,中间内容区域自适应填充剩余空间的布局。随着CSS技术的发展,有多种方法可以实现这一需求。实现步骤...

css之div内容居中(css中div怎么居中)

div中的内容居中显示,包括水平和垂直2个方向。<html><head><styletype="text/css">...

使用uniapp开发小程序遇到的一些问题及解决方法

1、swiper组件自定义知识点swiper组件的指示点默认是圆圈,想要自己设置指示点,需要获得当前索引,然后赋给当前索引不同的样式,然后在做个动画就可以了。*关键点用change方法,然后通过e.d...

微信小程序主页面排版(怎样设置小程序的排版)

开发小程序的话首先要了解里面的每个文件的作用小程序没有DOM对象,一切基于组件化小程序的四个重要的文件*.js*.wxml--->view结构---->html*.wxss--...

Vue动态组件的实践与原理探究(vue动态组件component原理)

我司有一个工作台搭建产品,允许通过拖拽小部件的方式来搭建一个工作台页面,平台内置了一些常用小部件,另外也允许自行开发小部件上传使用,本文会从实践的角度来介绍其实现原理。ps.本文项目使用VueCLI...

【HarmonyOS Next之旅】兼容JS的类Web开发(四) -> tabs

目录1->创建Tabs2->设置Tabs方向3->设置样式4->显示页签索引5->场景示例编辑1->创建Tabs在pages/index目录...

CSS:前端必会的flex布局,我把布局代码全部展示出来了

进入我的主页,查看更多CSS的分享!首先呢,先去看文档,了解flex是什么,这里不做赘述。当然,可以看下面的代码示例,辅助你理解。一、row将子元素在水平方向进行布局:1.垂直方向靠顶部,水平方向靠...

【HarmonyOS Next之旅】兼容JS的类Web开发(四) -> swiper

目录1->创建Swiper组件2->添加属性3->设置样式4->绑定事件5->场景示例编辑1->创建Swiper组件在pages/index...

CSS:Flex布局,网页排版神器!(css3 flex布局)

还在为网页排版抓狂?别担心,CSS的flex布局来了,让你轻松玩转各种页面布局,实现网页设计自由!什么是Flex布局?Flex布局,也称为弹性布局,是CSS中的一种强大布局方式,它能够让你...

移动WEB开发之flex布局,附携程网首页案例制作

一、flex布局体验传统布局兼容性好布局繁琐局限性,不能再移动端很好的布局1.1flex弹性布局:操作方便,布局极为简单,移动端应用很广泛PC端浏览器支持情况较差IE11或更低版本,不支持或仅部...

2024最新升级–前端内功修炼 5大主流布局系统进阶(mk分享)

2024最新升级–前端内功修炼5大主流布局系统进阶(mk分享)获课》789it.top/14658/前端布局是网页设计中至关重要的一环,它决定了网页的结构和元素的排列方式。随着前端技术的不断发展,现...