使用基于Embedding的搜索来实现问答

注:本文来自OpenAI的Cookbook,原文是英文,以下译文完全是由AI翻译的:

GPT擅长回答问题,但仅限于它从训练数据中记住的内容。

如果你希望GPT回答有关不熟悉的内容,该怎么办?例如:

  • 2021年9月之后,最近发生的事件;
  • 你的非公开文档;
  • 来自过去对话的信息等。

本文演示了一种基于搜索-提问的两步法,使GPT能够使用参考文本库回答问题。

  1. 搜索:在文本库中搜索相关文本片段;
  2. 提问:将检索到的文本片段连同消息一并发送至GPT并提问问题。

为什么搜索比微调更好

GPT可以通过两种方式学习知识:

  • 通过模型权重(即在训练集上微调模型)
  • 通过模型输入(即将知识插入在输入消息中)

尽管微调感觉像是更自然的选择(毕竟,数据训练是GPT学习所有其他知识的方式),但我们通常不推荐将其作为教授模型知识的方式。微调更适合教授专门的任务或风格,但对于事实来说不太可靠。

打个比方,模型权重就像长期记忆。当你对模型进行微调时,就像为一周后的考试做准备一样。当考试到来时,模型可能会忘记细节,或者记错它从未读过的事实。

相比之下,消息输入就像短期记忆。当你在消息中插入知识时,就像用现成的笔记参加考试一样。有了笔记,模型更有可能得出正确答案。

文本搜索相对于微调的一个缺点是每个模型都受到一次可以读取的最大文本量的限制:

模型最大文本长度
gpt-3.5-turbo4,096个Token(约5页)
gpt-48,192个Token(约10页)
gpt-4-32k32,768个Token(约40页)

继续这个类比,你可以把这个模型想象成一个学生,尽管书架上可能有很多课本可供参考,但一次只能看几页笔记。

因此,为了构建一个能够利用大量文本来回答问题的系统,我们建议使用“搜索-提问”的方法。

搜索

可以通过多种方式搜索文本。例如:

  • 基于词汇的搜索
  • 基于图的搜索
  • 基于Embedding的搜索

此示例文档使用基于Embedding(嵌入)的搜索。Embedding很容易实现,并且特别适用于回答问题,因为问题在词汇上通常不会与其答案重叠。

可以将使用Embedding搜索视为你自己的系统的起点。更好的搜索系统可能会结合多种搜索方法,以及诸如流行度、新鲜度、用户历史记录、先前搜索结果的冗余度、点击率数据等特征。问答检索性能也可以通过HyDE等技术来提高,在Embedding之前,问题首先被转换为假设的答案。同样,GPT还可以通过自动将问题转换为关键字或搜索词组来改善搜索结果。

完整程序

具体来说,本文演示了以下过程:

  1. 准备搜索数据(每个文档仅需准备一次)

    1. 收集:我们将下载数百篇有关2022年奥运会的维基百科文章;
    2. 分块:文档被分成简短的、独立的片段用于Embedding;
    3. Embedding:每个部分都使用OpenAI API来实现Embedding;
    4. 保存:Embedding被存储起来(对于大型数据集,使用矢量数据库)。
  2. 搜索(针对每次查询)

    1. 给定用户问题,使用OpenAI API将查询转换成Embedding;
    2. 使用Embedding,根据查询的相关性对文本部分进行排名。
  3. 提问(针对每次查询)

    1. 将问题和最相关的部分插入至发送到GPT的消息中;
    2. 返回GPT给出的答案。

成本

由于GPT比Embedding搜索更昂贵,因此具有大量查询的系统成本将主要由步骤3决定。

  • 对于每个查询使用约1,000个Token的gpt-3.5-turbo,每个查询的成本约为0.002美元,或1美元约500个查询(截至2023年4月);
  • 对于gpt-4,再次假设每个查询约1,000个Token,每个查询的成本约为0.03美元,或1美元约30个查询(截至2023年4月)。

当然,确切的成本将取决于系统的具体实现和使用模式。

前言

我们将从以下开始:

  • 导入必要的库;
  • 选择Embedding搜索和问答的模型。
    在这里插入图片描述
疑难解答:安装库

如果你需要安装上述任何库,请在终端中运行pip install {library_name}

例如,要安装openai库,请运行:

pip install openai

(你也可以在notebook中使用!pip install openai%pip install openai来执行此操作。)

安装后,重新启动notebook,以便可以加载库。

疑难解答:设置API密钥

OpenAI库将尝试从OPENAI_API_KEY环境变量中读取你的API密钥。如果你还没有设置此环境变量,则可以按照此说明进行设置。

一个示例:GPT无法回答有关时事的问题

由于gpt-3.5-turbogpt-4的训练数据大多于2021年9月结束,因此模型无法回答有关近期事件的问题,例如2022年冬季奥运会。

例如,让我们尝试提问“哪些运动员赢得了2022年冰壶金牌?”:

在这里插入图片描述
在这里插入图片描述

在这种情况下,模型不知道2022年发生的事情,无法回答该问题。

你可以通过将某个主题的内容插入到输入消息中来提供有关该主题的GPT知识

为了帮助模型了解2022年冬季奥运会的冰壶知识,我们可以将相关维基百科文章的上半部分复制并粘贴到我们的消息中:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

由于输入消息中包含维基百科文章,因此GPT能够正确回答。

在这个特殊案例中,GPT足够聪明,意识到最初的问题未明确说明,因为冰壶金牌项目有三项,而不仅仅是一项。

当然,这个例子部分依赖于人类智慧。我们知道问题是关于冰壶的,所以我们插入了一篇关于冰壶的维基百科文章。

本文的其余部分展示了如何通过基于嵌入的搜索来自动实现知识的插入。

1. 准备搜索数据

为了节省您的时间和费用,我们准备了一个预嵌入数据集,其中包含数百篇有关2022年冬季奥运会的维基百科文章。

要了解我们如何构建此数据集或自行修改它,请参阅嵌入维基百科文章以进行搜索。

在这里插入图片描述

2. 搜索

现在我们将定义一个搜索函数:

  • 接受用户查询和带有文本和Embedding列的数据框;

  • 使用OpenAI API嵌入用户查询;

  • 根据查询和文本的Embedding距离对文本进行排序;

  • 返回两个列表:

    • 前N个文本,按相关性排名;
    • 它们对应的相关性分数。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 提问

通过上面的搜索功能,我们现在可以自动检索相关知识并将其插入到GPT的消息中。

下面,我们定义一个函数ask

  • 接受用户查询;
  • 搜索与查询相关的文本;
  • 将该文本填充到GPT消息中;
  • 将消息发送到GPT;
  • 返回GPT的答案。
    在这里插入图片描述在这里插入图片描述

示例问题

最后,让我们向系统提问有关金牌冰壶的原始问题:

在这里插入图片描述

尽管gpt-3.5-turbo对2022年冬季奥运会一无所知,但我们的搜索系统能够检索参考文本供模型阅读,从而使其能够正确列出男子和女子锦标赛的金牌获得者。

然而,它仍然不太完美——该模型未能列出混双项目的金牌获得者。

解决错误答案问题

要查看错误是否是由于缺乏相关源文本(即搜索步骤失败)或缺乏推理可靠性(即提问步骤失败)造成的,你可以通过设置print_message=True

在这个特定情况下,查看下面的文本,看起来为模型提供的第1篇文章确实包含所有三个项目的奖牌获得者,但后来的结果强调了男子和女子比赛,这可能分散了模型给出的注意力更完整的答案。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

知道这个错误是由于提问步骤中的推理不完善,而不是搜索步骤中的检索不完善造成的,所以让我们重点改进提问步骤。

改善结果的最简单方法是使用功能更强大的模型,例如GPT-4。我们来试试吧。
在这里插入图片描述

GPT-4的回答十分完美,正确识别了所有12名冰壶金牌得主。

更多示例

以下是该系统实际运行的几个示例。请随意尝试自己的问题,看看效果如何。一般来说,基于搜索的系统在具有简单查找的问题上表现最好,在需要组合和推理多个部分源的问题上表现最差。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费
  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用numpy实现embedding使用余弦相似度的NTxent的示例代码: ``` python import numpy as np # 定义一些超参数 k = 10 # top-k正样本 T = 0.5 # 温度参数 # 假设我们有n个样本,每个样本有m维特征 n, m = 1000, 128 # 随机初始化嵌入向量 embeddings = np.random.randn(n, m) # 计算余弦相似度矩阵 norms = np.linalg.norm(embeddings, axis=1, keepdims=True) similarities = np.dot(embeddings, embeddings.T) / np.dot(norms, norms.T) # 对于每个样本i,选择top-k个正样本和一组负样本 pos_samples = np.zeros((n, k)) neg_samples = np.zeros((n, k)) for i in range(n): pos_samples[i] = np.argsort(similarities[i])[::-1][1:k+1] neg_samples[i] = np.random.choice(np.delete(np.arange(n), pos_samples[i]), k, replace=False) # 计算交叉熵损失 loss = 0 for i in range(n): pos_scores = np.sum(embeddings[i] * embeddings[pos_samples[i]], axis=1) / T neg_scores = np.sum(embeddings[i] * embeddings[neg_samples[i]], axis=1) / T scores = np.concatenate((pos_scores, neg_scores)) labels = np.zeros(k*2) labels[:k] = 1 loss += -np.mean(labels * np.log(np.exp(scores) / np.sum(np.exp(scores)))) print('NTxent loss:', loss) ``` 在这个示例中,我们首先随机初始化n个样本的m维嵌入向量,然后计算余弦相似度矩阵。接着,对于每个样本i,我们选择top-k个余弦相似度最大的样本作为正样本,随机选择一组与i余弦相似度较小的样本作为负样本。最后,我们计算每个样本i的交叉熵损失,并输出总的NTxent损失。 需要注意的是,这只是一个简单的示例,实际使用时需要根据具体情况进行调整和优化。此外,还需要对嵌入向量进行归一化处理,以保证余弦相似度的取值范围在[-1, 1]之间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值