六、OpenAI之嵌入式(Embedding)


嵌入模式

学习怎么将文本转换成数字,解锁搜索等案例。

新的嵌入模型
text-embedding-3-small 和 text-embedding-3-large,是目前最新的并且性能最好的嵌入模型,成本低,支持多语言,拥有控制所有大小的新参数

1. 什么是嵌入?

OpenAI的文本嵌入衡量文本字符串的相关性。嵌入通常用于:

  • 搜索(通过一个查询字符串的相关性将结果排序)
  • 聚类(通过相似性将文本字符串进行分组)
  • 推荐(推荐与文本字符串相关的条目)
  • 异常检测(相关性不大的异常值被识别出来)
  • 多样性衡量(分析相似度分布)
  • 分类(通过最相似的标签分类文本字符串)

嵌入是一个浮点型的向量。用距离衡量两个向量的相关性。小的距离暗示高相关性,大的距离暗示低相关性。

2. 怎样获得嵌入?

要获得嵌入模式,将文本字符串与嵌入模型ID一起发送到嵌入API端点(例如:text-embedding-3-small)。响应会包含一个嵌入模式(浮点型列表),能被提取保存到一个向量数据库,能被许多的应用案例所使用。

curl https://api.openai.com/v1/embeddings \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "input": "Your text string goes here",
    "model": "text-embedding-3-small"
  }'

响应将包含嵌入向量以及一些额外的元数据

{
  "object": "list",
  "data": [
    {
      "object": "embedding",
      "index": 0,
      "embedding": [
        -0.006929283495992422,
        -0.005336422007530928,
        ... (omitted for spacing)
        -4.547132266452536e-05,
        -0.024047505110502243
      ],
    }
  ],
  "model": "text-embedding-3-small",
  "usage": {
    "prompt_tokens": 5,
    "total_tokens": 5
  }
}

默认,text-embedding-3-small嵌入向量的长度是1536,text-embedding-3-large嵌入向量的长度是3072。您可以通过传入dimensions参数来降低嵌入的维度,而不会使嵌入模式失去其表示概念的属性。

3. 嵌入模型

OpenAI提供两个功能强大第三代嵌入模型(使用模型ID -3表示)。

模型版本分词器最大输入tokens
V3cl100k_base8191
V2cl100k_base8191

4. 使用案例

亚马逊美食评论数据集 提取码: a5uh 案例开发如下:

4.1 获得嵌入

数据集总计包含568,454条食品评论。只使用1000条数据子集。评论内容使用英文,其中有正面和负面的。评论字段:ProductId,UserId,Score,Summary,Text,例如:

ProductIdUserIdScoreSummaryText
B001E4KFG0A3SGXH7AUHU8GW5Good Quality Dog FoodI have bought several of the Vitality canned…
B001E4KFG0A1D87F6ZCVE5NK1Not as AdvertisedProduct arrived labeled as Jumbo Salted Peanut…

我们将把评论摘要和评论文本合并为一个综合文本。该模型将对该组合文本进行编码,并输出单个向量嵌入

from openai import OpenAI
client = OpenAI()

def get_embedding(text, model="text-embedding-3-small"):
   text = text.replace("\n", " ")
   return client.embeddings.create(input = [text], model=model).data[0].embedding

df['ada_embedding'] = df.combined.apply(lambda x: get_embedding(x, model='text-embedding-3-small'))
df.to_csv('output/embedded_1k_reviews.csv', index=False)

从保存的文件加载数据:

import pandas as pd

df = pd.read_csv('output/embedded_1k_reviews.csv')
df['ada_embedding'] = df.ada_embedding.apply(eval).apply(np.array)

4.2 减少嵌入维度

使用特大的嵌入,例如为检索存储它们到向量中,会产生更高的成本和消耗更多的CPU、内存和存储,相比而言比较小的嵌入消耗的资源更少。
这两个新的模型都是用同一种技术所训练,允许开发者平衡他们的表现和成本。具体来说,开发人员可以通过传递维度API参数来缩短嵌入(即从序列的末尾删除一些数字),而不会使嵌入失去其表示概念的属性。例如,在MTEB基准测试中,text-embedding-3-large的嵌入可以缩短到256的大小,同时仍然优于未缩短的text-embedding-ada-002的大小为1536的嵌入。
通常,当创建嵌入时建议采用dimensions参数,在某些情况下,您可能需要在生成嵌入维度之后更改它。当你手动改变维度时,你需要确认嵌入维度标准化,就像下边这样:

from openai import OpenAI
import numpy as np

client = OpenAI()

def normalize_l2(x):
    x = np.array(x)
    if x.ndim == 1:
        norm = np.linalg.norm(x)
        if norm == 0:
            return x
        return x / norm
    else:
        norm = np.linalg.norm(x, 2, axis=1, keepdims=True)
        return np.where(norm == 0, x, x / norm)


response = client.embeddings.create(
    model="text-embedding-3-small", input="Testing 123", encoding_format="float"
)

cut_dim = response.data[0].embedding[:256]
norm_dim = normalize_l2(cut_dim)

print(norm_dim)

动态改变维度让使用更加灵活。例如:当使用一个向量数据库存储时,仅支持到1024维的长度嵌入,但开发者现在仍然可以使用最好的嵌入模型text-embedding-3-large,并指定API 参数 dimensions为1024,而不是3072维,但需要衡量使用小的向量对精度的影响。

4.3 基于嵌入搜索回答问题

在许多常见的情况下,模型没有根据包含关键事实和信息的数据进行训练,而希望在生成对用户查询的响应时可以访问这些数据。有一种方法可以解决这个问题,就像下面展示的,加上额外的信息至模型输入窗口。在许多的用例中是有效果的,但会导致消耗更多的token。 在这个笔记中,我们将探索此方法与基于搜索的嵌入的平衡点。

query = f"""Use the below article on the 2022 Winter Olympics to answer the subsequent question. If the answer cannot be found, write "I don't know."

Article:
\"\"\"
{wikipedia_article_on_curling}
\"\"\"

Question: Which athletes won the gold medal in curling at the 2022 Winter Olympics?"""

response = client.chat.completions.create(
    messages=[
        {'role': 'system', 'content': 'You answer questions about the 2022 Winter Olympics.'},
        {'role': 'user', 'content': query},
    ],
    model=GPT_MODEL,
    temperature=0,
)

print(response.choices[0].message.content)

4.4 基于嵌入的文本搜索

为了检索最相关的文档,我们使用查询的嵌入向量和每个文档之间的余弦相似度,并返回得分最高的文档。

from openai.embeddings_utils import get_embedding, cosine_similarity

def search_reviews(df, product_description, n=3, pprint=True):
   embedding = get_embedding(product_description, model='text-embedding-3-small')
   df['similarities'] = df.ada_embedding.apply(lambda x: cosine_similarity(x, embedding))
   res = df.sort_values('similarities', ascending=False).head(n)
   return res

res = search_reviews(df, 'delicious beans', n=3)

4.5 基于嵌入的代码搜索

代码搜索的工作原理类似于基于嵌入的文本搜索。我们提供了一个从给定存储库中的所有Python文件中提取Python函数的方法。然后通过文本嵌入-3-small模型对每个函数进行索引。
为了执行代码搜索,我们使用相同的模型在自然语言中嵌入查询。然后我们计算结果查询嵌入和每个函数嵌入之间的余弦相似度。余弦相似性最高的结果是最相关的。

from openai.embeddings_utils import get_embedding, cosine_similarity

df['code_embedding'] = df['code'].apply(lambda x: get_embedding(x, model='text-embedding-3-small'))

def search_functions(df, code_query, n=3, pprint=True, n_lines=7):
   embedding = get_embedding(code_query, model='text-embedding-3-small')
   df['similarities'] = df.code_embedding.apply(lambda x: cosine_similarity(x, embedding))

   res = df.sort_values('similarities', ascending=False).head(n)
   return res
res = search_functions(df, 'Completions API tests', n=3)

4.6 基于嵌入的推荐

因为嵌入向量之间的距离越短表示相似性越大,所以嵌入对推荐很有用。
下面,我们将演示一个基本的推荐器。它接受一个字符串列表和一个“源”字符串,计算它们的嵌入,然后返回字符串的排名,从最相似到最不相似。作为一个具体的例子,下面链接的笔记将此函数的一个版本应用于AG新闻数据集(采样到2,000篇新闻文章描述),以返回与任何给定源文章最相似的前5篇文章。

def recommendations_from_strings(
   strings: List[str],
   index_of_source_string: int,
   model="text-embedding-3-small",
) -> List[int]:
   """返回给定字符串最相近的."""

   # 返回所有字符串的嵌入
   embeddings = [embedding_from_string(string, model=model) for string in strings]

   # 返回源字符串的嵌入
   query_embedding = embeddings[index_of_source_string]

   # 返回源嵌入和给定嵌入之前的距离(函数来自embeddings_utils.py)
   distances = distances_from_embeddings(query_embedding, embeddings, distance_metric="cosine")

   # 返回最近邻的索引
   indices_of_nearest_neighbors = indices_of_nearest_neighbors_from_distances(distances)
   return indices_of_nearest_neighbors

4.7 2D可视化数据

嵌入的大小随底层模型的复杂度而变化。为了可视化这些高维数据,我们使用t-SNE算法将数据转换为二维。
我们根据评论者给出的星级评分给个人评论上色:
1星:红色
2星:深橙色
三星级:黄金
四星级:绿松石
五星:深绿色
在这里插入图片描述
可视化似乎产生了大约3个集群,其中一个的评价大多是负面的。

import pandas as pd
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
import matplotlib

df = pd.read_csv('output/embedded_1k_reviews.csv')
matrix = df.ada_embedding.apply(eval).to_list()

# Create a t-SNE model and transform the data
tsne = TSNE(n_components=2, perplexity=15, random_state=42, init='random', learning_rate=200)
vis_dims = tsne.fit_transform(matrix)

colors = ["red", "darkorange", "gold", "turquiose", "darkgreen"]
x = [x for x,y in vis_dims]
y = [y for x,y in vis_dims]
color_indices = df.Score.values - 1

colormap = matplotlib.colors.ListedColormap(colors)
plt.scatter(x, y, c=color_indices, cmap=colormap, alpha=0.3)
plt.title("Amazon ratings visualized in language using t-SNE")

4.8 嵌入作为机器学习算法的文本特征编码器

嵌入可以用作机器学习模型中的一般自由文本特征编码器。结合嵌入将提高任何机器学习模型的性能.如果一些相关输入是自由文本,整合嵌入将提高任何机器学习模型的性能。嵌入也可以用作ML模型中的分类特征编码器。如果分类变量的名称有意义且数量众多,例如职位名称,那么这将增加最大的价值。对于这个任务,相似嵌入通常比搜索嵌入表现得更好。
我们观察到,通常嵌入表示是非常丰富和信息密集的。例如,使用SVD或PCA降低输入的维数,即使降低10%,通常也会导致特定任务的下游性能变差。
这段代码将数据分成训练集和测试集,它们将被以下两个用例使用,即回归和分类。

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    list(df.ada_embedding.values),
    df.Score,
    test_size = 0.2,
    random_state=42
)

使用嵌入特征进行回归

嵌入提供了一种预测数值的优雅方式。在这个例子中,我们根据评论者的评论文本来预测他们的星级。因为嵌入中包含的语义信息很高,所以即使评论很少,预测也很不错。
我们假设分数是1到5之间的连续变量,并允许算法预测任何浮点值。ML算法将预测值与真实分数的距离最小化,并实现了0.39的平均绝对误差,这意味着平均预测误差不到半颗星。

from sklearn.ensemble import RandomForestRegressor

rfr = RandomForestRegressor(n_estimators=100)
rfr.fit(X_train, y_train)
preds = rfr.predict(X_test)

4.9 使用嵌入特征进行分类

这一次,不是让算法预测1到5之间的值,我们将尝试将评论的确切星星数量分为5个区,范围从1到5颗星。经过训练,该模型学会预测1星和5星评论,比预测更细微的评论(2-4星)要好得多,这可能是由于更极端的情绪表达。

from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, accuracy_score

clf = RandomForestClassifier(n_estimators=100)
clf.fit(X_train, y_train)
preds = clf.predict(X_test)

4.10 零样本学习分类

我们可以在没有任何标记训练数据的情况下使用嵌入进行零射击分类。对于每个类,我们嵌入类名或类的简短描述。为了以零概率的方式对一些新文本进行分类,我们将其嵌入与所有类嵌入进行比较,并预测相似性最高的类。

from openai.embeddings_utils import cosine_similarity, get_embedding

df= df[df.Score!=3]
df['sentiment'] = df.Score.replace({1:'negative', 2:'negative', 4:'positive', 5:'positive'})

labels = ['negative', 'positive']
label_embeddings = [get_embedding(label, model=model) for label in labels]

def label_score(review_embedding, label_embeddings):
   return cosine_similarity(review_embedding, label_embeddings[1]) - cosine_similarity(review_embedding, label_embeddings[0])

prediction = 'positive' if label_score('Sample Review', label_embeddings) > 0 else 'negative'

4.11 获取冷启动推荐的用户和产品嵌入

我们可以通过平均所有评论来获得用户嵌入。类似地,我们可以通过平均所有关于该产品的评论来获得产品嵌入。为了展示这种方法的有效性,我们使用5万评论的子集来覆盖每个用户和每个产品的更多评论。
我们在一个单独的测试集上评估这些嵌入的有用性,其中我们将用户和产品嵌入的相似性绘制为评级的函数。有趣的是,基于这种方法,即使在用户收到产品之前,我们也可以比随机更好地预测他们是否喜欢
在这里插入图片描述

user_embeddings = df.groupby('UserId').ada_embedding.apply(np.mean)
prod_embeddings = df.groupby('ProductId').ada_embedding.apply(np.mean)

4.12 聚类

聚类是理解大量文本数据的一种方法。嵌入对于这项任务很有用,因为它们为每个文本提供了语义上有意义的向量表示。因此,以一种无监督的方式,聚类将揭示数据集中隐藏的分组。
在这个例子中,我们发现了四个不同的集群:一个关注狗粮,一个关注负面评论,两个关注正面评论。
在这里插入图片描述

import numpy as np
from sklearn.cluster import KMeans

matrix = np.vstack(df.ada_embedding.values)
n_clusters = 4

kmeans = KMeans(n_clusters = n_clusters, init='k-means++', random_state=42)
kmeans.fit(matrix)
df['Cluster'] = kmeans.labels_

5. 常见问题

5.1 在嵌入字符串之前,我如何知道字符串有多少个tokens

在Python中,您可以使用OpenAI的标记器tiktoken将字符串拆分为标记

import tiktoken

def num_tokens_from_string(string: str, encoding_name: str) -> int:
    """Returns the number of tokens in a text string."""
    encoding = tiktoken.get_encoding(encoding_name)
    num_tokens = len(encoding.encode(string))
    return num_tokens

num_tokens_from_string("tiktoken is great!", "cl100k_base")

对于第三代嵌入模型,如text- embeddings -3-small,使用cl100k_base编码。

5.2 如何快速检索K个最近的嵌入向量

为了快速搜索多个矢量,我们建议使用向量数据库。

5.3 我应该使用哪个距离函数?

我们推荐余弦相似度。距离函数的选择通常不太重要。
OpenAI嵌入归一化为长度1,这意味着:

  • 余弦相似度可以用点积稍微快一点
  • 余弦相似度和欧几里得距离将导致相同的排名

5.4 我能在线共享嵌入的内容吗?

是的,客户拥有我们模型的输入和输出,包括嵌入的情况。您有责任确保您输入到我们的API的内容不违反任何适用法律或我们的使用条款。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/417529.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

周鸿祎免费课演示AI新品,瞬时流量暴增现场增加服务器

2月29日,360创始人周鸿祎首堂AI免费课开讲,吸引千万网友围观。演讲现场周鸿祎演示了两款AI驱动的新产品。在演示测试版360AI搜索时,由于用户体验火爆,瞬时流量暴增44倍,为满足用户和全网用户需求临时增加了服务器。产品…

solidity编程

一.Solidity 简介 Solidity 是⼀种⽤于编写以太坊虚拟机( EVM )智能合约的 编程语⾔。我认为掌握 Solidity 是参与链上项⽬的必备技 能:区块链项⽬⼤部分是开源的,如果你能读懂代码,就可以 规避很多亏钱项⽬。…

LeetCode 2265.统计值等于子树平均值的节点数

给你一棵二叉树的根节点 root ,找出并返回满足要求的节点数,要求节点的值等于其 子树 中值的 平均值 。 注意: n 个元素的平均值可以由 n 个元素 求和 然后再除以 n ,并 向下舍入 到最近的整数。 root 的 子树 由 root 和它的所…

大模型量化技术原理-ZeroQuant系列

近年来,随着Transformer、MOE架构的提出,使得深度学习模型轻松突破上万亿规模参数,从而导致模型变得越来越大,因此,我们需要一些大模型压缩技术来降低模型部署的成本,并提升模型的推理性能。 模型压缩主要分…

什么是VR紧急情况模拟|消防应急虚拟展馆|VR游戏体验馆加盟

VR紧急情况模拟是利用虚拟现实(Virtual Reality,简称VR)技术来模拟各种紧急情况和应急场景的训练和演练。通过VR技术,用户可以身临其境地体验各种紧急情况,如火灾、地震、交通事故等,以及应对这些紧急情况的…

IM(即时通讯-聊天工具):一文读懂,技术栈和界面设计。

大家好,我是贝格前端工场,本期继续分享IM(即时通讯)的设计,欢迎大家关注,如有B端写系统界面的设计和前端需求,可以联络我们。 一、什么是IM(聊天工具) IM即时通讯工具是指一类用于…

C++——类和对象(2):构造函数、析构函数、拷贝构造函数

2. 类的6个默认成员函数 我们将什么成员都没有的类称为空类,但是空类中并不是什么都没有。任何类中都会存在6个默认成员函数,这6个默认成员函数如果用户没有实现,则会由编译器默认生成。 6个默认成员函数包括:负责初始化工作的构造…

怎么调用文心一言的api接口生成一个简单的聊天机器人(python代码)

寒假在学习大模型,但也没弄出多少眉目,电脑性能还有点小问题,大模型总跑不起来,只会简单调用一下现有的大模型的接口,例如:文心一言,下面展示一下代码: import tkinter as tk impor…

Linux中如何在创建子线程的时候设置为分离属性

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<unistd.h> #include <pthread.h> void *mythread(void *arg) {printf("id[%ld]\n",pthread_self()); } int main() { //定义pthread_…

力扣550 游戏玩法分析 IV

目录 题目描述 思路整理 1. 首次登录日期 2. 第二天登录 3. 计算比率 实现思路 完整代码及解释 题目描述 Table: Activity ----------------------- | Column Name | Type | ----------------------- | player_id | int | | device_id | int | | ev…

华为自动驾驶技术详解报告分享

ADS2.0首发搭载问界M5智驾版&#xff0c;城市NCA计划年底全国开通。2023年4月16日华为在智能汽车解决方案发布会上发布了最新的ADS2.0产品&#xff0c;硬件数量减少至27个(11个摄像头12个超声波雷达3个毫米波雷达1个激光雷达,ADS1.0有34个)&#xff0c;车载计算平台改为MDC610&…

苹果ios群控软件开发常用源代码分享!

在移动软件开发领域&#xff0c;苹果设备由于其封闭性和安全性受到了广大开发者的青睐&#xff0c;然而&#xff0c;这也为开发者带来了一些挑战&#xff0c;特别是在进行群控软件开发时。 群控软件是指可以同时控制多台设备的软件&#xff0c;这在自动化测试、批量操作等场景…

网络编程难点之select、poll与epoll详解

前言 为什么需要I/O多路复用技术&#xff1f; 首先&#xff0c;I/O多路复用技术主要被应用在需要高性能的网络服务器程序中。 高性能网络服务器程序需要做的事情就是供多个客户端同时进行连接并处理客户端传送过来的数据请求&#xff1a; 对于这种情况&#xff0c;很多人自然…

二叉树——二叉树所有路径

二叉树所有路径 给你一个二叉树的根节点 root &#xff0c;按 任意顺序 &#xff0c;返回所有从根节点到叶子节点的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,null,5] 输出&#xff1a;["1->2->5","1-…

leetcode刷题日记-合并N个升序链表

题目描述 解题思路 相信大家都做过两个有序链表合并的习题吧。该题的解决思路是建立在两个有序链表合并的基础上。使用的方法是递归。 两个有序链表合并思路 1.如果其中一个链表为空&#xff0c;直接返回另一个链表&#xff0c;因为一个空链表和非空链表的合并结果就是非空链…

在微服务整合dubbo,以为微服务版的若依为例

在微服务整合dubbo&#xff0c;以为微服务版的若依为例 一、环境二、整合过程1、父模块依赖2、生产者3、消费者 三、修改若依的服务调用方式为dubbo1、改造系统模块2、改造认证授权中心 四、整合过程遇到的问题1、出现循环引用2、出现依赖冲突3、启动出现端口号被占用4、出现某…

windows U盘不能识别

windows U盘不能识别 1、问题描述2、问题分析解决3、把U盘插到windows电脑上试试能不能识别 1、问题描述 windwos u盘不能识别 u盘被拿到mac电脑上做了启动盘之后&#xff0c;就不能被windows识别了。题主很奇怪里面被mac电脑的同学放了什么&#xff0c;因此想到把优盘挂载到L…

【LeetCode周赛】第 386 场周赛

目录 3046. 分割数组 简单3047. 求交集区域内的最大正方形面积 中等3048. 标记所有下标的最早秒数 I 中等 3046. 分割数组 简单 3046. 分割数组 分析&#xff1a; 查看数组内有没有重复超过2次的数即可。 代码&#xff1a; class Solution { public:bool isPossibleToSplit…

类和对象(2)——距离C++又近了一步

目录 一、构造函数 1.1声明和定义构造函数 1.2成员名和参数名 1.3构造函数的使用 1.4初始化列表 二、析构函数 2.1析构函数的概念 2.2析构函数的性质 三、拷贝构造函数 四、赋值运算符重载 4.1运算符重载 4.2赋值运算符重载 一、构造函数 我们知道&#xff0c;C中…

Python:练习:输出int值a占b的百分之几。例如:输入1和4,输出:25%。

案例&#xff1a; 输出int值a占b的百分之几。例如&#xff1a;输入1和4&#xff0c;输出&#xff1a;25%。 思考&#xff1a; 所有的一步步思考&#xff0c;最后综合起来。 首先&#xff0c;确定 输出&#xff0c;那么就用input&#xff0c;而且是int值&#xff0c;所以肯定…
最新文章