前言
随着互联网的发展,用户对产品及服务的需求日益增加,为了满足用户对商品和服务的需求,我们需要提供更好的服务体验,在很多领域,基于用户搜索、浏览记录等行为数据的推荐系统已经成为行业的热门话题,举个例子,当我们在浏览掘金这种网站并搜索相关内容时,他的旁边是不是会自动推荐出和你搜索的内容相关的一些文章和内容,你有没有想过这是如何实现的呢?
其实这里就是利用了用户的历史行为数据和搜索记录以及推荐算法自动
生成更加符合用户需求的内容推送给用户,今天,小编就带大家来利用OpenAI提供的embeddings服务接口来实现一个这样的搜索推荐功能。
正文
整体思路
这里的大概思路就是通过将咱们用户的搜索记录搜索框中输入的内容数据和浏览器里或者数据库里的数据通过推荐算法向量化,然后计算向量的余弦相似度,向量的余弦值越大,这两个向量就越接近,也就是说,这两个向量所表示的文本内容或数据就越相关,因此就能够输出相似度越高的内容。
embeddings
首先什么是embeddings呢?embeddings是OpenAI提供的一项服务接口。OpenAI的embeddings API允许你将文本转换为多维空间中的向量表示,这些向量能够捕捉文本的语义含义。也就是说任何一个词或物体都可以在空间中找到。相同的东西就分布在相近的空间之中。这个接口可以用于多种自然语言处理任务,如文本分类、语义搜索、问答系统等,其中向量之间的距离反映了文本片段之间的语义相似度。这也就是为何能推荐出相似内容的原因。
这个接口如何调用呢?
首先咱们需要在咱们的项目中通过npm i openai安装openai官方的库。
npm i openai
接着添加一个入口文件index.mjs启动咱们的es6模块化,
接着就需要引入咱们的接口服务了
import OpenAI from "openai";
import dotenv from "dotenv";
dotenv.config({path:'.env'});
将key存放在.env文件中
这里先创建一个openai的实例对象便于调用openai的接口
数据向量化
同样是上面的代码,咱们先输入一句简单的话来测试一下看看openai的embeddings接口能否将咱们的数据向量化。打印看看
通过输出结果我们可以看到成功的将我们输入的数据向量化了。
接着咱们就需要准备一份文本文件来模拟咱们的数据库,这里咱们就准备了一份json文件
就着咱们就可以调用openAI的embeddings接口将里面的json数据进行向量化然后输出到另一个posts_with_embeddings.json文件中,在里面的每一个对象中添加了一个key为embedding,值为它的空间向量。同样以json文件的格式输出
// 先把所有的内容计算向量
import fs from 'fs/promises'
//openai 实例封装
import {client} from './app.service.mjs'
//文件输入的路径
const inputFilePath = './data/posts.json'
//输出包含向量的文件路径
const outputFilePath = './data/posts_with_embeddings.json'
//promisify
const data=await fs.readFile(inputFilePath,'utf-8')
//console.log(data)
const posts=JSON.parse(data)
//新数组
const postsWithEmbedding=[]
for(const {title,category} of posts){
const response=await client.embeddings.create({
model:'text-embedding-ada-002',
// vue vue-router react
input:`标题:${title} 分类:${category}`
})
postsWithEmbedding.push({
title,
category,
embedding:response.data[0].embedding
})
}
await fs.writeFile(outputFilePath,JSON.stringify(postsWithEmbedding))
咱们来看结果
可以看到data文件夹中多了一份json文件,和咱们之前的文件相比多每个数据都多了它自己的空间向量,
计算余弦相似度
接下来咱们就只需要获取到用户输入在输入框中的值然后向量化后的数据,需要通过一些推荐算法计算余弦相似度,将这个文件向量化后的数据和已有数据库中向量化后好的数据进行相似度比较,将相似度较高的数据返回返回给前端即可。至于计算向量的余弦相似度函数咱们直接在网上找一个就好啦。
// nlp 相似性搜索
import fs from 'fs/promises'
import { client } from './app.service.mjs'
const inputFilePath = './data/posts_with_embeddings.json'
// select * 内存中
const posts = JSON.parse(await fs.readFile(inputFilePath));
// 计算向量的余弦相似度 cosine
const cosineSimilarity = (v1, v2) => {
// 计算向量的点积
const dotProduct = v1.reduce((acc, curr, i) => acc + curr * v2[i], 0);
// 计算向量的长度
const lengthV1 = Math.sqrt(v1.reduce((acc, curr) => acc + curr * curr, 0));
const lengthV2 = Math.sqrt(v2.reduce((acc, curr) => acc + curr * curr, 0));
// 计算余弦相似度
const similarity = dotProduct / (lengthV1 * lengthV2);
return similarity;
};
// vue| 组件 | 开发? LLM 语义搜索, 而不是简单的文字匹配
const searchText = 'vue'
// 先向量化一下
const response = await client.embeddings.create({
model: 'text-embedding-ada-002',
input:searchText
})
// 要推荐的原文embedding
const { embedding } = response.data[0];
// posts每一项embedding 进行cosin 计算
const results = posts.map(item => ({
...item,
similarity:cosineSimilarity(embedding, item.embedding)
}))
.sort((a, b) => a.similarity - b.similarity)
.reverse()
.slice(0, 3)
.map((item, index) => `${index + 1}, ${item.title}, ${item.category}`)
.join('\n')
console.log(results);
效果实现
最后咱们来看效果
当我们输入vue前端开发时
来看后端返回的数据
当我们输入 react前端开发时
来看后端返回的数据
可以看到,效果基本不错,基本都能匹配成功,相似的内容。
总结
今天咱们主要学习通过调用openai中的embeddings接口来将数据向量化,并通过一些推荐算法来计算余弦相似度,最终返回相似度高的文件,依次来实现相似的内容推荐。项目的所有源码大家可以到我的gitee仓库上查看 gitee.com/Luo-zhao-fa… 如果觉得本文对你有所帮助的话,可以点个免费的赞赞嘛,感谢感谢!