前端开发AI新尝试,使用Embeddings模拟实现浏览器搜索推荐,简直不要太高级!!!Embeddings是机器学习和
当你在浏览器中输入内容时,会出现以下这种的推荐:
大家肯定会很好奇,这种炫酷的功能是怎么实现的?
下面我将为大家介绍一种全新的AI开发方式--Embedding数据向量化,来实现这一推荐搜索功能。
什么是Embeddings
Embeddings是机器学习和深度学习中一个重要的概念,主要用于将高维的、通常是稀疏的、非数值型的数据转换为低维的、密集的、数值型的向量表示。这些向量通常位于一个连续的向量空间中,能够有效地捕捉原始数据中的模式和结构。
在计算机的内部世界,任何事物的表现形式都是一串串简单的数字,在传统的表结构表示数据时,传入计算机内部的数据也只能是二维的,这种简单结构的数据在表现复杂的事物时难免会出现模糊。
为了解决这个问题,出现一种全新的数据表现形式--向量数据。向量数据可以将一个事物的特征具体细分为多个点,然后每个点都是全新的一个维度,连接这些点组成的一个多维向量数据。
比如一个苹果,计算机是怎么认识的他的呢?
在我们人的大脑中,认识一个苹果可以分为以下几个过程:
- 苹果是浅红色的
- 苹果是椭球状的
- 苹果带有它特定的香味 4.....
在计算内部,一个苹果的表示也是将这一个个的特点转化为一个个的多维坐标点,然后将这些点连接起来组成一个向量数据,最后通过大模型的训练,来判断所识别的物品是否为苹果。浏览器推荐功能的实现原理,也和上述过程类似,下面我将通过一个demo来为大家展示。
创建向量数据
本demo展示所用的语言为Node.js。
一.创建自然语言数据
创建文件:posts.json
里面存放的数据为自然语言数据,形如:
二.将自然语言数据转为向量数据
要实现该功能我们需要在项目中引入opeanai的emdedding库,借助ai帮我们将数据向量化。
新建文件夹:
在app.service.mjs
文件夹中,我们导入openai的接口服务:
import OpenAI from "openai";
import dotenv from "dotenv";
dotenv.config({ path: '.env' });
export const client = new OpenAI({
apiKey: process.env.OpenAI_KEY,
baseURL: 'https://api.302.ai/v1'
})
注意:这段代码中的apiKey为自己特有的,本项目中将该key封装在了.env文件当中
在create-embedding.mjs
文件夹中,使用openai中的embedding模块创建向量数据:
import fs from 'fs/promises'
import { client } from './app.service.mjs'
const inputFilePath = './data/posts.json'
const outputFilePath = './data/posts_with_embeddings.json'
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))
这段代码的主要目的是从一个JSON文件中读取一系列自然语言数据(posts),然后使用OpenAI的API为每个帖子的标题和分类计算嵌入向量,并将原始数据与计算得到的嵌入向量一起保存到一个新的JSON文件中。下面是代码的详细梳理:
-
导入必要的模块:
import fs from 'fs/promises';
: 导入Node.js的fs
模块的Promises版本,用于异步文件操作。import { client } from './app.service.mjs';
: 导入自定义的client
对象,它封装了与OpenAI API交互的功能。
-
定义输入输出文件路径:
const inputFilePath = './data/posts.json';
: 定义输入文件路径,这是包含原始帖子数据的JSON文件。const outputFilePath = './data/posts_with_embeddings.json';
: 定义输出文件路径,这是将保存带有嵌入向量的帖子数据的JSON文件。
-
读取输入文件:
- 使用
fs.readFile
异步读取输入文件的内容,并以UTF-8编码解析为字符串。
- 使用
-
解析数据:
const posts = JSON.parse(data);
: 将读取到的字符串数据解析为JavaScript对象数组。
-
计算嵌入向量并构建新数组:
- 遍历
posts
数组,对于每一个帖子,使用client.embeddings.create
方法调用OpenAI的嵌入向量计算API。 input:
标题:title分类:{title} 分类:title分类:{category}``: 构造输入字符串,包括帖子的标题和分类。model: 'text-embedding-ada-002'
: 指定使用的嵌入模型。response.data[0].embedding
: 获取API响应中的嵌入向量。- 将原始的帖子数据与计算得到的嵌入向量合并,添加到
postsWithEmbedding
数组中。
- 遍历
-
写入输出文件:
- 使用
fs.writeFile
将postsWithEmbedding
数组转换为JSON字符串,并写入到输出文件中。
- 使用
最终,这段代码会生成一个新的JSON文件,其中每个帖子对象都额外包含了一个1536维的嵌入向量,这个向量是基于帖子的标题和分类计算得到的。这样的处理对于后续的数据分析、搜索和推荐系统等应用非常有用。
执行成功这段代码后,我们可以在create-embedding.mjs
文件中看到所有给出的数据全部都向量化:
实现搜索推荐功能
在多维空间中,判断两个数据的相似程度可以通过判断两个向量之间的夹角大小,如果两个数据之间的夹角越大那么它们之间的相似程度就越低,反之越大。那么在数学中就可以通过判断两个向量数据之间的cos大小来判断它们之间的夹角大小,也正是它们之间的相关程度的大小。下面我将通过代码来为大家展示这一过程。
// nlp 相似性搜索
import fs from 'fs/promises'
import { client } from './app.service.mjs'
const inputFilePath = './data/posts_with_embeddings.json'
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;
};
const searchText = '什么时候去旅游'
// 先向量化一下
const response = await client.embeddings.create({
model: 'text-embedding-ada-002',
input: searchText
})
const { embedding } = response.data[0];
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);
这段代码的思路可以总结为如下过程:
-
加载数据:
- 从
./data/posts_with_embeddings.json
文件中读取已经包含了嵌入向量的帖子数据。
- 从
-
定义相似度计算逻辑:
- 实现
cosineSimilarity
函数,用于计算两个向量之间的余弦相似度,这是衡量两个向量方向相似性的标准方法。
- 实现
-
向量化查询文本:
- 使用OpenAI的
text-embedding-ada-002
模型将用户的查询文本转化为嵌入向量。
- 使用OpenAI的
-
计算相似度并排序:
- 遍历所有帖子,对每个帖子的嵌入向量与查询文本的嵌入向量进行余弦相似度计算。
- 将计算结果与帖子信息一起存储,形成一个新的数组,其中包含每个帖子的标题、分类以及与查询文本的相似度。
-
筛选最相似的结果:
- 根据相似度对所有帖子进行排序,选取相似度最高的几条帖子(本例中是前三条)。
-
输出结果:
- 将筛选出的最相似帖子的信息格式化为易读的字符串,并打印到控制台上。
这一过程的核心在于利用嵌入向量来捕捉文本的语义信息,从而实现基于语义的搜索而非简单的关键词匹配,提高了搜索的准确性和相关性。
实现效果:
当输入:什么时候去旅行
当输入: 如何制作美食
以上便是本篇文章的主要内容,希望对大家有所帮助,谢谢大家,如果有用的话,还请大家多多点赞。
转载自:https://juejin.cn/post/7390319492142071847