在OpenAI API中引入文本和代码嵌入技术

1,949 阅读8分钟

Introducing Text and Code Embeddings in the OpenAI API

我们正在介绍嵌入,这是OpenAI API中的一个新的端点,可以轻松地执行自然语言和代码任务,如语义搜索、聚类、主题建模和分类。嵌入是转换为数字序列的概念的数字表示,这使得计算机很容易理解这些概念之间的关系。我们的嵌入在3个标准基准中的表现优于顶级模型,包括在代码搜索方面有20%的相对改进。

阅读文档阅读论文


嵌入对于处理自然语言和代码非常有用,因为它们可以被其他机器学习模型和算法(如聚类或搜索)轻易地消费和比较。

Introducing Text and Code Embeddings in the OpenAI API Introducing Text and Code Embeddings in the OpenAI API Introducing Text and Code Embeddings in the OpenAI API

Introducing Text and Code Embeddings in the OpenAI API Introducing Text and Code Embeddings in the OpenAI API Introducing Text and Code Embeddings in the OpenAI API

数字上相似的嵌入也是语义上相似的。例如,"犬类同伴说 "的嵌入向量将比 "喵 "的嵌入向量更类似于 "汪 "的嵌入向量。

Introducing Text and Code Embeddings in the OpenAI API Introducing Text and Code Embeddings in the OpenAI API

新的终端使用神经网络模型,这是GPT-3的后代,将文本和代码映射到一个矢量表示--将它们 "嵌入 "到一个高维空间。每个维度都捕获了输入的某些方面。

OpenAI API中新的/embeddings端点只需几行代码就能提供文本和代码的嵌入。

import openai
response = openai.Embedding.create(
    input="canine companions say",
    engine="text-similarity-davinci-001")

打印响应


print(response)
{
  "data": [
    {
      "embedding": [
        0.000108064,
        0.005860855,
        -0.012656143,
        ...
        -0.006642727,
        0.002583989,
        -0.012567150
      ],
      "index": 0,
      "object": "embedding"
    }
  ],
  "model": "text-similarity-babbage:001",
  "object": "list"
}

我们发布了三个系列的嵌入模型,每个都被调整为在不同的功能上表现良好:文本相似性、文本搜索和代码搜索。这些模型将文本或代码作为输入,并返回一个嵌入向量。

模型使用案例
文本相似性。捕捉文本片段之间的语义相似性。文本相似性-{Adam, babbage, Curie, Davinci}-001聚类、回归、异常检测、可视化
文本搜索。对文件进行语义信息检索。文本搜索-{马达,巴贝奇,居里,达文西}-{查询,文档}-001搜索,上下文相关性,信息检索
代码搜索。用自然语言的查询来寻找相关的代码。代码搜索-{ada, babbage}-{代码, 文本}-001代码搜索和关联性

文本相似性模型

文本相似性模型提供了捕捉文本片段的语义相似性的嵌入。这些模型对许多任务都很有用,包括聚类数据可视化分类

下面的交互式可视化显示了来自DBpedia数据集的文本样本的嵌入。

拖动来平移、滚动或捏住来缩放

来自text-similarity-babbage-001 模型的嵌入,应用于DBpedia数据集。我们从数据集中随机选择了100个样本,涵盖了5个类别,并通过/embeddings终端计算了嵌入。不同的类别在嵌入空间中显示为5个清晰的聚类。为了使嵌入空间可视化,我们使用PCA将嵌入维度从2048降低到3。关于如何将嵌入空间在三维维度上可视化的代码可在此获得。

为了比较两段文本的相似性,你只需在文本嵌入上使用点积。结果是一个 "相似度分数",有时也称为 "余弦相似度",介于-1和1之间,数字越大意味着相似度越高。在大多数应用中,嵌入可以预先计算,然后进行点积比较是非常快的。

import openai, numpy as np

resp = openai.Embedding.create(
    input=["feline friends go", "meow"],
    engine="text-similarity-davinci-001")

embedding_a = resp['data'][0]['embedding']
embedding_b = resp['data'][1]['embedding']

similarity_score = np.dot(embedding_a, embedding_b)

嵌入的一个流行用途是在机器学习任务中使用它们作为特征,如分类。在机器学习文献中,当使用线性分类器时,这种分类任务被称为 "线性探针"。 我们的文本相似性模型在SentEval(Conneau等人,2018)的线性探针分类上取得了新的最先进的结果,这是一个常用于评估嵌入质量的基准。

7个数据集的线性探针分类

以前的SOTA(Gao等人,2021年)

90.2%

文本相似性-Davinci-001

92.2%

显示更多

文本相似性-Curie-001

91.5%

文本-相似性-巴贝格-001

91.1%

文本-相似性-ADA-001

89.3%

文本搜索模型

文本搜索模型提供了能够实现大规模搜索任务的嵌入,如在给定的文本查询中找到相关的文档。文档和查询的嵌入是分别产生的,然后用余弦相似度来比较查询和每个文档之间的相似度。

基于嵌入的搜索可以比经典关键词搜索中使用的单词重叠技术有更好的概括性,因为它捕捉到了文本的语义,对准确的短语或单词不太敏感。我们在BEIR(Thakur, et al. 2021)搜索评估套件上评估了文本搜索模型的性能,并获得了比以往方法更好的搜索性能。我们的文本搜索指南提供了关于使用嵌入搜索任务的更多细节。

BEIR中11个搜索任务的平均精度

以前的SOTA(Izacard, et al. 2021)

50.2%

文本搜索-davinci-{doc, query}-001

52.8%

显示更多

text-search-curie-{doc, query}-001

50.9%

文本搜索-babbag-{doc, query}-001

50.4%

text-search-ada-{doc, query}-001

49.0%

代码搜索模型

代码搜索模型为代码搜索任务提供代码和文本嵌入。给定一个代码块的集合,任务是为一个自然语言查询找到相关的代码块。我们在CodeSearchNet(Husian等人,2019)评估套件上评估了代码搜索模型,我们的嵌入取得了明显优于先前方法的结果。查看代码搜索指南,使用嵌入进行代码搜索。

6种编程语言的平均精度

以前的SOTA(Guo,等人,2021年)

77.4%

代码搜索-babbag-{doc, query}-001

93.5%

显示更多

code-search-ada-{doc, query}-001

93.4%


Embeddings API实际应用的例子

捷特布雷恩研究公司

JetBrains Research的天体粒子物理实验室分析了《天文学家电报》和NASA的GCN通告等数据,这些报告包含了传统算法无法解析的天文事件。

在OpenAI对这些天文报告的嵌入的支持下,研究人员现在能够在多个数据库和出版物中搜索像 "螃蟹脉冲星爆发 "这样的事件。Embeddings还通过k-means聚类在数据源分类上达到了99.85%的准确性。

FineTune Learning

FineTune Learning是一家建立人类与人工智能混合学习解决方案的公司,比如帮助学生达到学术标准的自适应学习循环

OpenAI的嵌入技术大大改善了根据学习目标寻找教科书内容的任务。OpenAI的文本搜索-urie嵌入模型实现了89.1%的前5名准确率,超过了以前的方法,如Sentence-BERT(64.5%)。虽然人类专家仍然更胜一筹,但FineTune团队现在能够在几秒钟内为整本教科书贴上标签,而专家则需要几个小时。

我们的嵌入与Sentence-BERT、GPT-3搜索和人类主题专家进行了比较,以便将教科书内容与学习目标相匹配。我们报告了准确率@k,即正确答案在前k个预测中的次数。

法比尤斯

Fabius帮助公司将客户对话转化为结构化的洞察力,为计划和优先级提供信息。OpenAI的嵌入允许公司更容易地找到和标记有功能要求的客户通话记录。

例如,客户可能会使用 "自动化 "或 "易于使用 "这样的词来要求一个更好的自助服务平台。以前,Fabius使用模糊的关键词搜索,试图用自助服务平台的标签来标记这些成绩单。有了OpenAI的嵌入,他们现在能够在一般情况下找到2倍以上的例子,对于具有抽象用例的功能,没有明确的客户可能使用的关键词的例子则是6-10倍。

所有API客户都可以从嵌入文件开始,在他们的应用程序中使用嵌入。

阅读文档


鸣谢

感谢以下人员对该版本的贡献。

Tao Xu, Chris Hallacy, Raul Puri, Alec Radford, Jesse Michael Han, Jerry Tworek, Qiming Yuan, Nikolas Tezak, Jong Wook Kim, Johannes Heidecke, Pranav Shyam, Tyna Eloundou Nekoul, Girish Sastry, Gretchen Krueger, David Schnurr, Felipe Petroski Such, Kenny Hsu, Madeleine Thompson, Tabarak Khan, and Toki Sherbakov。

感谢以下人士对本帖的反馈。Tom Kleinpeter, Morgan Gallant, Sam Altman, Ilya Sutskever, Steve Dowling, Rachel Lim, Arun Vijayvergiya, Rajeev Nayak, Peter Welinder, Justin Jay Wang.

.vector-diagram img { display: none; } .vector-diagram img: first-child { display: block; } var printResponse = function (btn) { // append response var responseEl = document .querySelector('.endpoint-code-response') .querySelector('code') var callParentEl = document .querySelector('.endpoint-code-call') .querySelector('pre') if (! responseEl || !callParentEl) return; callParentEl.appendChild(responseEl); // 隐藏按钮 btn.style.display= 'none'; }; var initRotate = function () { var rotates = document.querySelectorAll('.js-rotate'); if (!rotates.length) return; // for each set of rotates rotates.forEach(function (r) { // move first child to end every n seconds window.setting(function() { moveToEnd(r, r.firstElementChild)firstElementChild); }, 1500); }); }; var moveToEnd = function (parent, child) { parent.removeChild(child); parent.appendChild(child); // append to parent }; var initShowMore = function () { var showmores = document.querySelectorAll(' .js-showmore'); showmores.forEach(function (e) { e.addEventListener('click', function () { var showmoreparent = this.parentElement; if (!showmoreparent) return; var more = showmoreparent.querySelector('.js-more'); if (!more) return; more.style.display = 'block'; this.style.display = 'none'; }); }; // init document.addEventListener('DOMContentLoaded', function () { initRotate(); initShowMore(); }) 。 import {Runtime, Inspector, Library} from "unpkg.com/@observable…"; import notebook_topk from "api.observablehq.com/d/20c1e51d6…"; import notebook_embed3d from "api.observablehq.com/d/fef0801cb…" const customWidth = function (selector) { return (new Library).Generators.observe(function(change) { var width = change(document.querySelector(selector).clientWidth); function resized() { var w = document.querySelector(selector) .clientWidth; if (w !== width) change(width = w); } window.addEventListener("resize", resized); return function() { window.removeEventListener("resize", resized); }; }; const topk_renders = { "chart":"#topk-chart", }; new Runtime(Object.assign(new Library, {width: customWidth("#topk-chart")}).module(notebook_topk, name => { const selector = topk_renders[name]; if (selector) { // key exists return new Inspector(document.querySelector(selector)); } else { return true; }); const embed3d_renders = { "chart":"#embed3d-chart", "legend":"#embed3d-legend", }; new Runtime(Object.assign(new Library, {width: customWidth("#embed3d-chart")}).module(notebook_embed3d, name => { const selector = embed3d_renders[name]; if (selector) { // key exists return new Inspector(document.querySelector(selector)); } else { return true; })。