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

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

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

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

相关推荐

JPA实体类注解,看这篇就全会了

基本注解@Entity标注于实体类声明语句之前,指出该Java类为实体类,将映射到指定的数据库表。name(可选):实体名称。缺省为实体类的非限定名称。该名称用于引用查询中的实体。不与@Tab...

Dify教程02 - Dify+Deepseek零代码赋能,普通人也能开发AI应用

开始今天的教程之前,先解决昨天遇到的一个问题,docker安装Dify的时候有个报错,进入Dify面板的时候会出现“InternalServerError”的提示,log日志报错:S3_USE_A...

用离散标记重塑人体姿态:VQ-VAE实现关键点组合关系编码

在人体姿态估计领域,传统方法通常将关键点作为基本处理单元,这些关键点在人体骨架结构上代表关节位置(如肘部、膝盖和头部)的空间坐标。现有模型对这些关键点的预测主要采用两种范式:直接通过坐标回归或间接通过...

B 客户端流RPC (clientstream Client Stream)

客户端编写一系列消息并将其发送到服务器,同样使用提供的流。一旦客户端写完消息,它就等待服务器读取消息并返回响应gRPC再次保证了单个RPC调用中的消息排序在客户端流RPC模式中,客户端会发送多个请...

我的模型我做主02——训练自己的大模型:简易入门指南

模型训练往往需要较高的配置,为了满足友友们的好奇心,这里我们不要内存,不要gpu,用最简单的方式,让大家感受一下什么是模型训练。基于你的硬件配置,我们可以设计一个完全在CPU上运行的简易模型训练方案。...

开源项目MessageNest打造个性化消息推送平台多种通知方式

今天介绍一个开源项目,MessageNest-可以打造个性化消息推送平台,整合邮件、钉钉、企业微信等多种通知方式。定制你的消息,让通知方式更灵活多样。开源地址:https://github.c...

使用投机规则API加快页面加载速度

当今的网络用户要求快速导航,从一个页面移动到另一个页面时应尽量减少延迟。投机规则应用程序接口(SpeculationRulesAPI)的出现改变了网络应用程序接口(WebAPI)领域的游戏规则。...

JSONP安全攻防技术

关于JSONPJSONP全称是JSONwithPadding,是基于JSON格式的为解决跨域请求资源而产生的解决方案。它的基本原理是利用HTML的元素标签,远程调用JSON文件来实现数据传递。如果...

大数据Doris(六):编译 Doris遇到的问题

编译Doris遇到的问题一、js_generator.cc:(.text+0xfc3c):undefinedreferenceto`well_known_types_js’查找Doris...

网页内嵌PDF获取的办法

最近女王大人为了通过某认证考试,交了2000RMB,官方居然没有给线下教材资料,直接给的是在线教材,教材是PDF的但是是内嵌在网页内,可惜却没有给具体的PDF地址,无法下载,看到女王大人一点点的截图保...

印度女孩被邻居家客人性骚扰,父亲上门警告,反被围殴致死

微信的规则进行了调整希望大家看完故事多点“在看”,喜欢的话也点个分享和赞这样事儿君的推送才能继续出现在你的订阅列表里才能继续跟大家分享每个开怀大笑或拍案惊奇的好故事啦~话说只要稍微关注新闻的人,应该...

下周重要财经数据日程一览 (1229-0103)

下周焦点全球制造业PMI美国消费者信心指数美国首申失业救济人数值得注意的是,下周一希腊还将举行第三轮总统选举需要谷歌日历同步及部分智能手机(安卓,iPhone)同步日历功能的朋友请点击此链接,数据公布...

PyTorch 深度学习实战(38):注意力机制全面解析

在上一篇文章中,我们探讨了分布式训练实战。本文将深入解析注意力机制的完整发展历程,从最初的Seq2Seq模型到革命性的Transformer架构。我们将使用PyTorch实现2个关键阶段的注意力机制变...

聊聊Spring AI的EmbeddingModel

序本文主要研究一下SpringAI的EmbeddingModelEmbeddingModelspring-ai-core/src/main/java/org/springframework/ai/e...

前端分享-少年了解过iframe么

iframe就像是HTML的「内嵌画布」,允许在页面中加载独立网页,如同在画布上叠加另一幅动态画卷。核心特性包括:独立上下文:每个iframe都拥有独立的DOM/CSS/JS环境(类似浏...