使用 OpenAI 的 Embedding模型 构建知识向量库并进行相似搜索

OpenAI的embedding模型的使用

       首先第一篇文章中探讨和使用了ChatGPT4的API-Key实现基础的多轮对话和流式输出,完成了对GPT-API的一个初探索,那第二步打算使用OpenAI的embedding模型来构建一个知识向量库,其实知识向量库本质上就是一个包含着一组向量的数组,然后通过查询输入文本生成的向量和数据库文本中的向量的余弦相似度来进行相似度判断,在使用的过程中还是非常舒服的。

前置文章:ChatGPT4 API-Key初探-本地调用API进行多轮对话方和流式输出

文章目录

  • OpenAI的embedding模型的使用
    • 1.什么是Embedding
    • 2.使用OpenAI的embedding模型生成一个词向量
    • 3.使用OpenAI的embedding模型获得一个知识向量库
    • 3.从知识向量库中进行相似文本的查询
  • 结束

1.什么是Embedding


       Embedding在AI领域被翻译成词嵌入,但是光看这三个字其实不好理解,如果用一句话解释的话:embedding就是将文字转换成一个向量


在这里插入图片描述

图: Embedding的工作过程


  • 那为什么要转换成向量?
    因为要获得两段文字在空间中的关系进行运算,例如后续需要做的计算两个词的相似度,就需要首先经过embedding模型将两端文字转换成向量,然后算两个向量的余弦相似度。

       如果你不是研究自然语言处理的研究生或者算法工程师,那你只需要了解这一点就可以了,至于怎么转换的这一点可以不用深究,就像你可能不了解计算机组成原理但是你依然可以熟练的使用计算机。

2.使用OpenAI的embedding模型生成一个词向量


       OpenAI为我们提供了了一个方便的API接口来将输入文本直接转换为词向量,在官方文档的代码中其实并没有新手向的代码的表达都会集成一些功能一起发布,但是为了学习和理解要把其中最简单和核心的部分抽出来。

       下面的代码使用的是OpenAI的text-embedding-3-small模型将文本"父亲"转换为词向量。经过API之后得到了一个长度为1536的向量。

from openai import OpenAI
import numpy as np

# client = OpenAI(api_key="your-api-key-here") # 如果想在代码中设置Api-key而不是全局变量就用这个代码
client = OpenAI()

model = "text-embedding-3-small"


def get_embedding(text, model=model):
    return client.embeddings.create(input=text, model=model).data[0].embedding


text = '父亲'
vector = np.array(get_embedding(text))
print(vector.shape)
# (1536,)

3.使用OpenAI的embedding模型获得一个知识向量库


       OK那既然一条文本能转换成向量,那多条文本那就必然能转换成多个词向量,且词向量的长度是一致的,然后将这些词向量转换成数组然后保存这样就得到了一个知识向量库,本质上就是保存一个数组,返璞归真。

       首先我们得有一段文本,我让ChatGPT给我生成了50个医疗词汇,每个词汇一行,文本内容我放在文章最后。接下来给出代码。

       下列代码将本文中的医疗词汇逐行读取然后转换成词向量,保存到一个numpy数组当中,然后再将Numpy数组保存到本地,这样就得到了一个知识向量库。

from openai import OpenAI
import pandas as pd
import numpy as np
import time

# client = OpenAI(api_key="your-api-key-here") # 如果想在代码中设置Api-key而不是全局变量就用这个代码
client = OpenAI()

model = "text-embedding-3-small"

with open('test.txt', 'r', encoding='utf-8') as file:
    lines = file.readlines()

embedding = [client.embeddings.create(input=i.strip(), model=model).data[0].embedding for i in lines]

t = time.time()
np.save('embedding.npy', np.array(embedding))
print(time.time() - t)
# 0.002991914749145508 (运行时间/s)

测试用的文本内容

糖尿病
高血压
抑郁症
阿尔茨海默症
慢性阻塞性肺疾病(COPD)
骨折
哮喘
乳腺癌
心肌梗塞
脑卒中
化疗
放射疗法
心脏搭桥手术
经皮冠状动脉介入治疗(PCI)
腹腔镜手术
物理疗法
认知行为疗法
血液透析
绝育手术
骨髓移植
MRI扫描仪
CT扫描仪
心电图机
超声波设备
血糖仪
血压计
吸氧机
呼吸机
脉搏血氧仪
自动体外除颤器(AED)
青霉素
阿司匹林
他汀类药物
阿片类镇痛药
抗生素
抗抑郁药
胰岛素
利尿剂
抗凝血药
抗病毒药
免疫疗法
基因编辑
微创手术
患者健康记录(PHR)
电子医疗记录(EMR)
临床试验
医疗保健大数据
精准医疗
遥感监测
医疗伦理

3.从知识向量库中进行相似文本的查询


       首先在介绍查询方法之需要说一下计算相似度的余弦相似度,当两个向量夹角越小的时候两个向量的相似度越高,其计算公式如下:


cosine similarity ( A , B ) = A ⋅ B ∥ A ∥ ∥ B ∥ = ∑ i = 1 n A i B i ∑ i = 1 n A i 2 ∑ i = 1 n B i 2 \text{cosine similarity}(\mathbf{A}, \mathbf{B}) = \frac{\mathbf{A} \cdot \mathbf{B}}{\|\mathbf{A}\| \|\mathbf{B}\|} = \frac{\sum_{i=1}^{n}A_iB_i}{\sqrt{\sum_{i=1}^{n}A_i^2} \sqrt{\sum_{i=1}^{n}B_i^2}} cosine similarity(A,B)=A∥∥BAB=i=1nAi2 i=1nBi2 i=1nAiBi


       在查询任务中我们需要计算输入文本的向量和知识向量库中所有文本向量的余弦相似度,然后进行排序,当然作为一个算法工程师我们当然不能直接用for循环进行计算,本文基于numpy的广播机制,自己实现了一个高效的计算一个向量和一群向量的余弦相似度的代码。同时由于算法本身使用的是numpy,基于numpy底层为C语言实现,因此本程序的效率较高,作为新手的话只需要知道输入输出是什么就行了。代码如下。

import numpy as np

def cos_similarity(target, embedding):
    numerator = np.sum(target * embedding, axis=1)
    denominator = np.sqrt(np.sum(np.square(target)) * np.sum(np.square(embedding),axis=1))
    return numerator / denominator


if __name__ == '__main__':

    x = np.array([1, 2])
    y = np.array([[1, 2], [1, 1]])

    print(cos_similarity(x, y))
	# [1.        0.9486833]

将知识向量库中的文本按照相似度从大到小输出,代码如下:

  • 生成知识向量库和查询使用的模型得是一个模型别忘了,不然会报维度错误。
import numpy as np
from openai import OpenAI

model="text-embedding-3-small"
# client = OpenAI(api_key="your-api-key-here") # 如果想在代码中设置Api-key而不是全局变量就用这个代码
client = OpenAI()

def get_embedding(text, model=model):
   return client.embeddings.create(input=text, model=model).data[0].embedding

def cos_similarity(target, embedding):
    numerator = np.sum(target * embedding, axis=1)
    denominator = np.sqrt(np.sum(np.square(target)) * np.sum(np.square(embedding),axis=1))
    return numerator / denominator

with open('test.txt', 'r', encoding='utf-8') as file:
    lines = file.readlines()

# 获得文本数据
name = np.array([i.strip() for i in lines])
# 获得向量库
embedding = np.load("embedding.npy",allow_pickle=True)


# 获取用户的输入文本
search_text = input("User:")
# 获取用户输入文本使用embedding模型转换得到的词向量
search_embedding = get_embedding(search_text)
# 计算用户输入文本
embedding_similarity = cos_similarity(search_embedding,embedding)


# 由上到下输入相似度
for i in np.argsort(embedding_similarity)[::-1]:
    print(name[i],embedding_similarity[i])

接下来让GPT解释一下这段代码助于理解,我看了一下基本没有问题。

  1. 导入所需的库:使用了numpy库来处理数学运算和数组操作,以及OpenAI的API客户端来获取文本的嵌入向量。

  2. 设置模型和客户端:选择了一个特定的模型text-embedding-3-small来从OpenAI获取文本嵌入。这里有一段被注释掉的代码,用于手动设置API密钥,但在这个例子中,默认使用了全局变量设置的API密钥。

  3. 定义函数获取嵌入向量get_embedding函数通过OpenAI的API将文本转换成嵌入向量。这个向量是文本的数学表示,用于计算相似度。

  4. 定义余弦相似度函数cos_similarity函数计算两组向量之间的余弦相似度,这是衡量向量相似度的一种方法。余弦相似度越接近1,表示两个向量越相似。

  5. 读取文本数据:从test.txt文件中读取每行文本,每行代表一个可查询的项,并将其存储在名为name的数组中。

  6. 加载嵌入向量库:从embedding.npy文件加载预先计算好的嵌入向量,这些向量对应于test.txt文件中的文本项。

  7. 获取用户输入:通过input函数获取用户的查询文本。

  8. 获取查询文本的嵌入向量:使用get_embedding函数将用户的查询文本转换为嵌入向量。

  9. 计算相似度:使用cos_similarity函数计算用户查询的嵌入向量与嵌入向量库中所有向量之间的余弦相似度。

输出结果如下,这里就不全部粘贴了,把前面的几个粘贴上。

User:糖尿病
糖尿病 1.0
血糖仪 0.6027716430115105
高血压 0.4807989892102901
乳腺癌 0.46976679922966263
利尿剂 0.44671493260605705
抑郁症 0.3989793244972647
胰岛素 0.3678633339750386
心肌梗塞 0.3630205294730911
阿尔茨海默症 0.3554829250733137
血压计 0.3527248065537073
抗病毒药 0.3223748925983246

在这里插入图片描述

结束


官方文档:https://platform.openai.com/docs/guides/embeddings/embedding-models
目前支持的Embedding模型如下。
在这里插入图片描述
       在官方文档中还详细讲了很多的使用方式,例如如何进行可视化,如何进行机器学习技术等,但是文章中的内容是我抽出主要内容然后加上自己的理解实现的。如果有什么不对或者更好的方式非常欢迎交流。

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

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

相关文章

电脑自带dll修复在哪里打开呢?马上教会你

由于各种原因,电脑可能会出现一些问题,其中之一就是dll文件丢失。Dll文件是动态链接库文件,它们包含了许多程序运行所需的函数和资源。当这些文件丢失或损坏时,可能会导致程序无法正常运行或出现错误提示。本文将介绍电脑dll文件丢…

springboot蛋糕订购小程序的设计与实现

摘 要 相比于以前的传统手工管理方式,智能化的管理方式可以大幅降低商家的运营人员成本,实现了蛋糕订购的标准化、制度化、程序化的管理,有效地防止了蛋糕订购的随意管理,提高了信息的处理速度和精确度,能够及时、准确…

工作总结!日志打印的11条建议

前言 大家好,我是 JavaPub。日志是我们定位问题的得力助手,也是我们团队间协作沟通(甩锅)、明确责任归属(撕B)的利器。没有日志的程序运行起来就如同脱缰的野🐎。打印日志非常重要。今天我们来…

Linux内存管理--系列文章貮

接上文,用户态写完,本章写内核态内存空间。 3.2内核态内存 大家会发现用户态空间不管32还是64位,这种内存分布是相差不大的。是因为使用虚拟内存的系统,会让应用程序感到和别的程序是相互独立的,互不干扰&#xff0c…

mysql索引 (索引的忧缺点 ,联合索引)

索引的忧缺点 优点 (增加读操作效率,排序成本) 1 查询效率高 2 降低排序成本,索引对应的字段 就已经 自动排序,因为索引本身就是一种排好序的数据结构 缺点(降低写操作效率,占用空间&#xf…

【Unity】读取Json的三种方法(JsonUtility,LitJson,Newtonsoft)

介绍 在Unity开发过程中,Json是比较常用的一种数据存储文本,尤其是在和第三方交互中,基本都是json格式。 先给出一个Json示例,我们来看看是如何解析的。 {"Player": [{"id": 1001,"name": "…

UCORE 清华大学os实验 lab0 环境配置

打卡 lab 0 : 环境配置 : 首先在ubt 上的环境,可以用虚拟机或者直接在windows 上面配置 然后需要很多工具 如 qemu gdb cmake git 就是中间犯了错误,误以为下载的安装包,一直解压不掉,结果用gpt 检查 结…

Js输入输出语句

输入语法 prompt("您想输入的是&#xff1f;")输出语法: 语法1: document.write(‘要出的内容’&#xff09; <body><script>document.write("你好")document.write("<h1>我是<h1>")</script> </body>作…

【开发】Spring整合MyBatis、MyBatisPlus

目录 前言 Spring整合MyBatis 1. 在项目中的pom.xml中导入MyBatis和Spring相关的依赖&#xff1a; 2. 配置数据源 3. 编写实体类 4. 编写API接口 5. 编写单元测试方法&#xff08;业务&#xff09; Spring整合MyBatis-Plus 1. 在项目中导入依赖&#xff1a; 2. 配置数…

电大搜题:开启学习新时代

身处信息化时代&#xff0c;学习的方式已经发生了巨大的变革。在这个多元化的学习环境中&#xff0c;传统的学习模式已经无法满足现代学习者的需求。然而&#xff0c;电大搜题应运而生&#xff0c;为学习者提供了一个高效、便捷的学习途径。 电大搜题&#xff0c;作为黑龙江开…

“智慧农业新篇章:AI大模型引领生态与气象科研的未来“

AI大模型引领未来智慧科研暨ChatGPT在地学、GIS、气象、农业、生态、环境等领域中的应用 以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮&#xff0c;可以面向科研选题、思维导图、数…

鸿蒙开发实现弹幕功能

鸿蒙开发实现弹幕功能如下&#xff1a; 弹幕轮播组件&#xff1a;BannerScroll import type { IDanMuInfoList, IDanMuInfoItem } from ../model/DanMuData //定义组件 Component export default struct BannerScroll {//Watch 用来监视状态数据的变化&#xff0c;包括&#…

【Git版本控制系统】:起步

目录 前言 版本控制 集中式与分布式的区别 Windows安装Git 核心 文件状态 工作区域 基本工作流程 配置用户信息 获取帮助 在线资源 前言 本篇文件的环境是Windows环境下实现。 在日常工作中git少不了&#xff0c;所以编写本篇文章介绍Git基础&#xff0c;专栏会不…

【DAY3 3.16】

1.【刷题】 【知识点与思路】 用乘法求余公式&#xff0c;暴力计算最大的m。 ans1,2,6,24,120...。计算这些阶乘的和是否是能被ans其整除&#xff0c;也就是判断&#xff1a; A[1]!%ansA[2]!%ans....A[n]!%ans0 要是不行的话&#xff0c;就输出当前ans对应的阶乘数。 【代码】 …

为什么国外客户在你跟进的过程中“消失”了?

看着别人跟的客户终于下单了&#xff0c;再看看自己的&#xff0c;怎么跟着跟着就没了。很多时候我们的客户就是不知不觉就被我们给跟丢了&#xff0c;因为我们的跟进方法是有问题的&#xff0c;下面给大家一些比较好的跟进方式和思路。 首先要跟进哪些客户&#xff1f; 不是所…

解压即用,2024最简单好用AI开源换脸应用,整合包已备好

软件整合包&#xff1a;点击下载 关键词&#xff1a;#AI换脸 #开源应用 #可视化界面 #实时换脸 #高清修复 #多个模型 #人脸遮挡处理 #模糊修复 #性能优化 #操作简单 总结&#xff1a;本软件是一款2024年最强大、最易用的AI换脸开源应用。该应用界面经过汉化&#xff0c;操作简…

数字万用表 (Digital Multimeter)

数字万用表 [Digital Multimeter] 1. Product parameters2. 交流频率测量3. 面板介绍4. 背光屏References 1. Product parameters 2. 交流频率测量 在交流 750V 档处按 HOLD 键切换到市电频率 3. 面板介绍 4. 背光屏 ​ References [1] Yongqiang Cheng, https://yongqiang…

Internet协议的安全性

Internet协议的安全性 文章目录 Internet协议的安全性1. 网络层1. IP*62. ARP*33. ICMP * 3 2. 传输层协议1. TCP1. * SYN-Flood攻击攻击检测* 防御 2. TCP序号攻击攻击 3. 拥塞机制攻击 2. UDP 3. 应用层协议1. DNS攻击*3防范*3: 2. FTP3. TELNET: 改用ssh4. 电子邮件1. 攻击2…

【leetcode-53最大子数组和】

题目&#xff1a; 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。子数组是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5,4] …

Java关于物联网消息引擎:EMQ X

1.背景 1、5G 时代&#xff0c;万物互联 随着5G的到来&#xff0c;万物互联已经成为现实&#xff0c;物联网行业得以蓬勃发展&#xff0c;催生了很多的应用&#xff0c;比如&#xff1a;物联网pass平台&#xff0c;车联网&#xff0c;面向云平台的IOT-Hub&#xff0c;NB-IoT蜂…