Toolformer是meta ai在23年2月发表的论文,主要提出了一种新方法,可以教导大语言模型通过调用api来使用扩展工具。
这个方法首先通过自监督的方法构建了一个包含扩展工具调用的语料库,再结合扩展预料库和原始语料库没通过fine-tune的方式训练语言模型。
数据集构建
在论文中每个api调用由一个数组表示,
c
=
(
a
c
,
i
c
)
c=(a_c,i_c)
c=(ac,ic),
a
c
a_c
ac表示调用的api名称,
i
c
i_c
ic表示调用api所对应的输入。r表示api调用c的返回结果。
e
(
c
)
=
<
A
P
I
>
a
c
(
i
c
)
<
/
A
P
I
>
e
(
c
,
r
)
=
<
A
P
I
>
a
c
(
i
c
)
→
r
i
<
/
A
P
I
>
e(c) = <API>a_c(i_c)</API> \\ e(c, r) = <API>a_c(i_c) \rightarrow r_i</API>
e(c)=<API>ac(ic)</API>e(c,r)=<API>ac(ic)→ri</API>
其中<API>
、</API>
、→
都是特殊的token,在实际使用中使用[
代替<API>
,]
代替</API>
,->
代替→
。文章中为了便于阅读,不进行这种替换。
接下来将未经调整的文本数据集 C = { x 1 , . . . , x ∣ C ∣ } C=\{x^1,...,x^{|C|}\} C={x1,...,x∣C∣}转换为带有api调用注释的数据集 C C C,转换流程如下图所示。接下来会详细介绍下每个步骤。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hd3GY2o3-1681652827475)(D:\study\notes\Toolformer学习.assets\屏幕截图 2023-04-02 202657.png)]
API采样
对于每个api,都会写下提示词和示例
P
(
x
)
P(x)
P(x),将这部分内容结合原始文本作为上下文输入语言模型,让模型基于此预测每个字符后面生成[
的概率。
下面是调用QA系统api的示例,最后一个Input后面的 x = x 1 , x 2 , . . . , x n x=x_1,x_2,...,x_n x=x1,x2,...,xn表示原始文本输入。
Your task is to add calls to a Question Answering API to a piece of text. The questions should help you get
information required to complete the text. You can call the API by writing "[QA(question)]" where "question" is the question you want to ask. Here are some examples of API
calls:
Input: Joe Biden was born in Scranton, Pennsylvania.
Output: Joe Biden was born in [QA("Where was Joe
Biden born?")] Scranton, [QA("In which state is
Scranton?")] Pennsylvania.
Input: Coca-Cola, or Coke, is a carbonated soft drink manufactured by the Coca-Cola Company.
Output: Coca-Cola, or [QA("What other name is Coca-Cola known by?")] Coke, is a carbonated soft drink
manufactured by [QA("Who manufactures Coca-Cola?")]the Coca-Cola Company.
Input: x
Output:
生成时从Output后面开始生成,每次添加x中的一个字符,获取语言模型预测下一个字符为[
的概率,将x中每一个字符后面接[
的概率记录下来,保留其中大于阈值
τ
s
\tau_s
τs的位置,如果大于k个,则只保留k个候选位置。
p
i
=
p
M
(
<
A
P
I
>
∣
P
(
x
)
,
x
1
:
i
−
1
)
p_i = p_M(<API> | P(x), x_{1:i−1})
pi=pM(<API>∣P(x),x1:i−1)
得到所有候选位置后,从每一个候选位置开始调用语言模型,即将序列P(x), x1, . . . , xi−1,[
作为模型输入前缀,直到模型生成]
作为终止。
**注意:**移除所有不生成]
的示例。
API执行
将上面所有生成的形如[QA("Where was Joe Biden born?")]
这类api调用进行执行,得到相应的调用返回结果
r
i
r_i
ri。
API过滤
将执行过api调用的例子生成如下三种形式的序列:
- 包含返回结果。注意因为语言模型还未经过微调,此时将 c i , r i c_i,r_i ci,ri插入原文中会因为没有和模型训练预料对齐导致文本连续性中断,所以选择直接使用 e ( c , r ) e(c,r) e(c,r)序列。
- 不包含返回结果。注意因为语言模型还未经过微调,此时将 c i , ϵ c_i,\epsilon ci,ϵ插入原文中会因为没有和模型训练预料对齐导致文本连续性中断,所以选择直接使用 e ( c , ϵ ) e(c,\epsilon) e(c,ϵ)序列。 ϵ \epsilon ϵ表示空序列
- 不包含接口调用。即原始序列 [ x 1 : x i ] [x_1:x_i] [x1:xi]。
在过滤时首先使用下列公式计算上述序列的加权交叉熵损失:
L
i
(
z
)
=
−
∑
j
=
i
n
w
j
−
i
⋅
log
p
M
(
x
j
∣
z
,
x
1
:
j
−
1
)
L_i(\textbf{z}) = −\sum_{j=i}^nw_{j-i}\cdot \log p_M(x_j|\textbf{z},x_{1:j-1})
Li(z)=−j=i∑nwj−i⋅logpM(xj∣z,x1:j−1)
其中
w
i
,
i
∈
R
w_i,i\in \mathbb{R}
wi,i∈R是给定的损失权重。
在原文没有提及权重给定方式,推测是根据文本重要性生成权重
在分别得到上述三个序列的权重L1,L2,L3后,保留 L 1 ≥ m a x ( L 2 , L 3 ) + τ L1\geq max(L2,L3)+\tau L1≥max(L2,L3)+τ的生成示例。
模型微调
将通过上述操作构建的包含api调用注释的数据集替换到原始数据集中,对于多个api调用的文本,重复api调用数据集生成和替换数据集步骤。使用新的数据集微调语言模型,微调时使用标准语言模型目标,即自回归任务。
模型推理
在模型推理时整体和普通语言模型推理一致,只是在遇到字符 − > -> −>时会调用相应的接口,并将接口返回的内容拼接到原有的文本上,之后继续进行语言模型的推理。