签名
在 DSPy 中,当我们将任务分配给 LM 时,我们将我们需要的行为规定为一个 Signature。
Signature 是对 DSPy 模块的输入/输出行为的声明性规范。 Signature 允许您告诉 LM 需要做什么,而不是指定我们应该如何要求 LM 去做。
您可能熟悉函数签名,它们指定输入和输出参数及其类型。DSPy 签名类似,但不同之处在于:
-
传统的函数签名只是描述事物,而 DSPy 签名则定义和控制模块的行为。
-
在 DSPy 签名中,字段名称很重要。您用简单的英语表达语义角色:
question
与answer
不同,sql_query
与python_code
也不同。
我为什么要使用 DSPy 签名?
简短回答: 为了模块化和清晰的代码,其中 LM 调用可以优化为高质量提示(或自动微调)。
详细回答: 大多数人通过修改冗长且脆弱的提示来强迫 LM 完成任务。或者通过收集/生成数据进 行微调。
编写签名比在提示或微调上进行修改更模块化、适应性更强、可重复性更好。DSPy 编译器将找出如何为您的 LM 构建高度优化的提示(或微调您的小型 LM)以适应您的签名、您的数据和您的流程。在许多情况下,我们发现编译出的提示比人类编写的更好。并不是因为 DSPy 优化器比人类更有创造力,而仅仅是因为它们可以尝试更多的方法并直接调整指标。
内联 DSPy 签名
签名可以定义为一个简短的字符串,其中参数名称定义了输入/输出的语义角色。
-
问答:
"question -> answer"
-
情感分类:
"sentence -> sentiment"
-
摘要:
"document -> summary"
您的签名也可以具有多个输入/输出字段。
-
基于检索的问答:
"context, question -> answer"
-
具有推理的多项选择问答:
"question, choices -> reasoning, selection
提示: 对于字段,任何有效的变量名称都可以使用!字段名称应具有语义意义,但要简单起见,不要过早优化关键字!将这种修改留给 DSPy 编译器。例如,对于摘要,可能可以说 "document -> summary"
、"text -> gist"
或 "long_context -> tldr"
。
示例 A:情感分类
sentence = "it's a charming and often affecting journey." # 来自 SST-2 数据集的示例。
classify = dspy.Predict('sentence -> sentiment')
classify(sentence=sentence).sentiment
输出:
'Positive'
示例 B:摘要
# XSum 数据集中的示例。
document = """这位 21 岁的球员在上赛季为锤子队出场七次,在一场欧洲联赛预选赛中攻入了他们的唯一进球,对阵安道尔球队 FC Lustrains。上赛季,李在英甲联赛有两次租借经历,先是去了布莱克浦,然后是科尔切斯特联队。他为科尔切斯特联队打入两球,但未能帮助球队免于降级。李与晋级的泰克斯队签订的合同长度尚未透露。在我们专门的页面上查看所有最新的足球转会消息。"""
summarize = dspy.ChainOfThought('document -> summary')
response = summarize(document=document)
print(response.summary)
输出:
21岁的李在上个赛季为西汉姆联队出场7次,打入1球。他曾在英甲联赛租借效力于布莱克浦和科尔切斯特联队,后者他打入了两球。他现在已经与巴恩斯利签约,但合同的期限尚未透露。
许多 DSPy 模块(除了 dspy.Predict
)会在幕后扩展您的签名以返回辅助信息。
例如,dspy.ChainOfThought
还会添加一个 rationale
字段,其中包含 LM 在生成输出 summary
之前的推理过程。
print("推理:", response.rationale)