使用向量数据库pinecone构建应用03:推荐系统 Recommender Systems

news2024/9/22 13:23:01

Building Applications with Vector Databases

下面是这门课的学习笔记:https://www.deeplearning.ai/short-courses/building-applications-vector-databases/

Learn to create six exciting applications of vector databases and implement them using Pinecone.

Build a hybrid search app that combines both text and images for improved multimodal search results.

Learn how to build an app that measures and ranks facial similarity.

Lesson 3 - Recommender Systems

在这里插入图片描述

Import the Needed Packages

import warnings
warnings.filterwarnings('ignore')
from langchain.text_splitter import RecursiveCharacterTextSplitter
from openai import OpenAI
from pinecone import Pinecone, ServerlessSpec
from tqdm.auto import tqdm, trange
from DLAIUtils import Utils

import pandas as pd
import time
import os

获取api key

utils = Utils()
PINECONE_API_KEY = utils.get_pinecone_api_key()
OPENAI_API_KEY = utils.get_openai_api_key()

Load the Dataset

with open('./data/all-the-news-3.csv', 'r') as f:
    header = f.readline()
    print(header)

Output

date,year,month,day,author,title,article,url,section,publication
df = pd.read_csv('./data/all-the-news-3.csv', nrows=99)
df.head()

Output

在这里插入图片描述

Setup Pinecone

openai_client = OpenAI(api_key=OPENAI_API_KEY)
util = Utils()
INDEX_NAME = utils.create_dlai_index_name('dl-ai')
pinecone = Pinecone(api_key=PINECpONE_API_KEY)

if INDEX_NAME in [index.name for index in pinecone.list_indexes()]:
  pinecone.delete_index(INDEX_NAME)

pinecone.create_index(name=INDEX_NAME, dimension=1536, metric='cosine',
  spec=ServerlessSpec(cloud='aws', region='us-west-2'))

index = pinecone.Index(INDEX_NAME)

1. Create Embeddings of the News Titles

通过文章标题来创建embedding

将输入的文章列表转换为嵌入向量(embeddings)

def get_embeddings(articles, model="text-embedding-ada-002"):
   return openai_client.embeddings.create(input = articles, model=model)

为标题生成embeddings,然后形成字典插入到pinecone索引中

CHUNK_SIZE=400
TOTAL_ROWS=10000
progress_bar = tqdm(total=TOTAL_ROWS)
chunks = pd.read_csv('./data/all-the-news-3.csv', chunksize=CHUNK_SIZE, 
                     nrows=TOTAL_ROWS)
chunk_num = 0
for chunk in chunks:
    titles = chunk['title'].tolist()
    embeddings = get_embeddings(titles)
    prepped = [{'id':str(chunk_num*CHUNK_SIZE+i), 
                'values':embeddings.data[i].embedding,
                'metadata':{'title':titles[i]},} for i in range(0,len(titles))]
    chunk_num = chunk_num + 1
    if len(prepped) >= 200:
      index.upsert(prepped)
      prepped = []
    progress_bar.update(len(chunk))

上述代码会产生总共 TOTAL_ROWS / CHUNK_SIZE 个 chunks,即数据集中总行数除以每个 chunk 的大小。在这个例子中,总行数为 10000,每个 chunk 的大小为 400,因此会产生 25 个 chunks。

这段代码的功能是:

  1. 从名为 './data/all-the-news-3.csv' 的 CSV 文件中逐个读取数据块(chunks),每个数据块包含 400 行数据,总共读取 10000 行数据。

  2. 对于每个数据块,提取其中的标题列,并将这些标题传递给一个名为 get_embeddings 的函数,以获取标题的嵌入向量。

  3. 将每个标题的嵌入向量与相应的标题一起打包成记录,并为每个记录分配一个唯一的 ID。

  4. 如果准备好的记录数量达到 200 条,则将这些记录批量插入到一个名为 index 的索引中。

  5. 在处理每个数据块时,更新进度条,以显示处理的进度。

综合起来,这段代码的主要功能是从 CSV 文件中读取数据块,并将其中的标题列转换为嵌入向量,然后将这些向量插入到一个名为 index 的索引中。

index.describe_index_stats()

Output

index.describe_index_stats()
{'dimension': 1536,
 'index_fullness': 0.0,
 'namespaces': {'': {'vector_count': 10000}},
 'total_vector_count': 10000}

Build the Recommender System

def get_recommendations(pinecone_index, search_term, top_k=10):
  embed = get_embeddings([search_term]).data[0].embedding # openai的接口
  res = pinecone_index.query(vector=embed, top_k=top_k, include_metadata=True) 
  return res

下面是对embed = get_embeddings([search_term]).data[0].embedding的解释:

它等价于openai_client.embeddings.create(input = articles, model=model).data[0].embedding

一个可能的openai请求embedding的例子:

可以看到embedding是在data这个key下面的。对于上述的很多embedding,自然有很多的data,上面选择的是data[0],也可以选择data[1]等等

{
  "object": "list",
  "data": [
    {
      "object": "embedding",
      "embedding": [
        0.0011064255,
        -0.0093271292,
        .... (1536 floats total for ada-002)
        -0.0033842222,
      ],
      "index": 0
    }
  ],
  "model": "text-embedding-ada-002",
  "usage": {
    "prompt_tokens": 8,
    "total_tokens": 8
  }
}

获取推荐文章的标题:含有obama的文章推荐

reco = get_recommendations(index, 'obama')
for r in reco.matches:
    print(f'{r.score} : {r.metadata["title"]}')

Output:前面是pinecone检索的分数,后面是文章的标题

这是通过对新闻标题进行embedding,然后检索得到的新闻标题:

0.84992218 : Barack Obama just stepped off the sidelines to defend Obamacare
0.848674893 : President Obama has a new plan to fight the opioid epidemic
0.848271608 : “Our democracy is at stake”: Obama delivers his first post-presidency campaign speech
0.848052 : Obama: if you were fine with big government until it served black people, rethink your biases
0.845821619 : President Obama: Michelle & I Are Gonna Be Renters
0.844207942 : Obama meets with national security team on Syria, Islamic State
0.843172133 : Vox Sentences: Obama got a warmer welcome in Hiroshima than the Japanese prime minister
0.84271574 : Watch President Obama dance the tango in Argentina
0.840892255 : Obama and Supreme Court Tag Team on Juvenile Justice Reform
0.839049876 : Clinton, Obama pledge unity behind Trump presidency

2. Create Embeddings of All News Content

通过文章内容来创建embedding

一些pinecone的配置,创建名为articles_index的pinecone索引

if INDEX_NAME in [index.name for index in pinecone.list_indexes()]:
  pinecone.delete_index(name=INDEX_NAME)

pinecone.create_index(name=INDEX_NAME, dimension=1536, metric='cosine',
  spec=ServerlessSpec(cloud='aws', region='us-west-2'))
# 创建了一个名为 INDEX_NAME 的索引对象,该对象可以用于存储和检索向量数据。
articles_index = pinecone.Index(INDEX_NAME) 

embed的函数如下:

def embed(embeddings, title, prepped, embed_num):
  for embedding in embeddings.data:
    prepped.append({'id':str(embed_num), 
                    'values':embedding.embedding, 
                    'metadata':{'title':title}})
    embed_num += 1
    if len(prepped) >= 100:
        articles_index.upsert(prepped)
        prepped.clear()
  return embed_num

(Note: news_data_rows_num = 100): In this lab, we've initially set news_data_rows_num to 100 for speedier results, allowing you to observe the outcomes faster. Once you've done an initial run, consider increasing this value to 200, 400, 700, and 1000. You'll likely notice better and more relevant results.

news_data_rows_num = 100

embed_num = 0 #keep track of embedding number for 'id'
text_splitter = RecursiveCharacterTextSplitter(chunk_size=400, 
    chunk_overlap=20) # how to chunk each article
prepped = []
df = pd.read_csv('./data/all-the-news-3.csv', nrows=news_data_rows_num)
articles_list = df['article'].tolist()
titles_list = df['title'].tolist()

# 处理每一篇文章,
for i in range(0, len(articles_list)):
    print(".",end="")
    art = articles_list[i]
    title = titles_list[i]
    if art is not None and isinstance(art, str):
      texts = text_splitter.split_text(art) # 将文章内容进行切分成小段
      embeddings = get_embeddings(texts) # 获取文章内容的embedding
      embed_num = embed(embeddings, title, prepped, embed_num) # 存入pinecone索引中

text_splitter = RecursiveCharacterTextSplitter(chunk_size=400, chunk_overlap=20)的解释:

  • chunk_size=400:这是一个参数,指定了每个文本块的大小。在这里,每个文本块的大小被设置为 400 个字符。

  • chunk_overlap=20:这是另一个参数,指定了文本块之间的重叠量。在这里,文本块之间的重叠量被设置为 20 个字符。这意味着,相邻的文本块会有部分内容重叠,以确保文本的连续性和完整性。

所以,这行代码创建了一个文本拆分器对象,该对象使用指定的参数将文章文本拆分成较小的文本块,以便进行后续处理,例如将其转换为嵌入向量。

查看向量数据库中的结果

articles_index.describe_index_stats()

Output

{'dimension': 1536,
 'index_fullness': 0.0,
 'namespaces': {'': {'vector_count': 1000}},
 'total_vector_count': 1000}

Build the Recommender System

reco = get_recommendations(articles_index, 'obama', top_k=100)
seen = {}
for r in reco.matches:
    title = r.metadata['title']
    if title not in seen:
        print(f'{r.score} : {title}')
        seen[title] = '.'

Output:通过文章内容进行embedding,然后检索得到的相关文章的标题

0.821158946 : Why Obama is vetting Nevada's Republican governor for the Supreme Court
0.818882763 : U.S. lawmakers ask for disclosure of number of Americans under surveillance
0.812377512 : NYPD Honcho Insulted by 'Hamilton' Star Lin-Manuel Miranda Celebrating Obama's Controversial Prisoner Release
0.806862772 : Why Jews Are Getting Themselves Arrested at ICE Centers Around the Country
0.806241512 : Trump keeping options open as Republican feud rages
of number of Americans under surveillance
0.812377512 : NYPD Honcho Insulted by 'Hamilton' Star Lin-Manuel Miranda Celebrating Obama's Controversial Prisoner Release
0.806862772 : Why Jews Are Getting Themselves Arrested at ICE Centers Around the Country
0.806241512 : Trump keeping options open as Republican feud rages

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

07 STL 简介

目录 什么是STLSTL的版本STL的六大组件STL的重要性如何学习STLSTL的缺陷 1. 什么是STL c标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构和算法的软件框架 2. STL的版本 原始版本 Alexander Stepanov、Meng Lee在惠普实验室的…

postman测试上传文件、导出excel的方法

按照如下操作步骤执行就可以了: 1、PostMan测试接口实现上传文件 第一步: 打开postman,将上传方式改为POST,再点击下【Body】 第二步: 然后,我们点击里面的【form-data】选项(如图所示)。 第三步&#xff…

微服务Day6

文章目录 DSL查询文档RestClient查询文档快速入门 旅游案例 DSL查询文档 RestClient查询文档 快速入门 Testvoid testMatchAll() throws IOException {//1.准备RequestSearchRequest request new SearchRequest("hotel");//2.准备DSLrequest.source().query(QueryB…

医院信息系统(HIS):一文扫盲,算是所有信息系统里面复杂的

大家好,我是贝格前端工场,本期继续分享常见的B端管理系统,欢迎大家关注,如有B端写系统界面的设计和前端需求,可以联络我们。 一、什么是HIS系统 HIS系统(Hospital Information System)是医院信…

【探索Linux】—— 强大的命令行工具 P.23(线程池 —— 简单模拟)

阅读导航 引言一、线程池简单介绍二、Linux下线程池代码⭕Makefile文件⭕ . h 头文件✅Task.hpp✅thread.hpp✅threadPool.hpp ⭕ . cpp 文件✅testMain.cpp 三、线程池的优点温馨提示 引言 在Linux下,线程池是一种常见的并发编程模型,它能够有效地管理…

C++ Primer Plus 笔记(持续更新)

编译器的正解 数据+算法程序 赋值从右向左进行 cin,cout的本质也是对象 类和对象的解释

扫盲贴:Svg动画和Canvas动画有什么区别

hello,我是贝格前端工场,网页中动画的实现有N种方式,比如css动画,js动画,svg动画,canvas动画等等,每一种动画都有对应的场景,本问重点介绍一下svg和canvas动画的异同点,欢…

基于SpringBoot的家教管理系统

基于SpringBootVue的家教管理系统的设计与实现~ 开发语言:Java数据库:MySQL技术:SpringBootMyBatis工具:IDEA/Ecilpse、Navicat、Maven 系统展示 前台主页 家教 个人中心 管理员界面 摘要 本文介绍了基于SpringBoot框架开发的家…

我花了5天时间,开发了一个在线学习的小网站

大三寒假赋闲在家,闲来无事,用了5天时间做了一个在线学习的小网站,一鼓作气部署上线,制作的过程比较坎坷。内心经历过奔溃,也经历过狂喜。 按照惯例先放出网址,欢迎大家来访问学习:www.pbjlove…

KNN算法使用模拟PLINKO规则,计算出概率最接近的投掷位子

模拟器 以PLINKO为例,利用程序,模拟出来,如: 投放位置与落入点关系 思考: 在300处丢下圆盘, 预计会落入哪个篮筐? 流程梳理 1. 收集数据集记录多次的实现数

Minimize Inversions

先来看看官方题解的做法,他一反常态的没有在逆序对题目里面考虑每个位置的贡献,而是直接回到定义考虑每对数是否是逆序对 我们考虑原数列中任意的一组数\((a_i,a_j)\)和\((b_i,b_j)\)。如果最开始两个都不是逆序对,那么交换之后两个都是逆序对…

Uniapp小程序开发-底部tabbar的开发思路

文章目录 前言一、uniapp 实现 tabbar二、图标使用网络图片后端返回tabbar信息uniapp方式中的setTabBarItem 总结 前言 记录uniapp 开发小程序的底部tabbar ,这里讨论的不是自定义tabbar的情况。而是使用wx.setTabBarItem(Object object) 这个api的情况。关于custo…

【数据结构与算法初学者指南】【冲击蓝桥篇】String与StringBuilder的区别和用法

🎉🎉欢迎光临🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟特别推荐给大家我的最新专栏《数据结构与算法:初学者入门指南》📘&am…

【安装】CentOS 7 使用 OUI 图形界面安装 Oracle Database 19.3

需安装使用 X Server 协议的软件(如 Xorg)和如桌面图形软件(Gnome 或 KDE)。 使用 root 用户执行: # curl -o oracle-database-preinstall-19c-1.0-1.el7.x86_64.rpm https://yum.oracle.com/repo/OracleLinux/OL7/l…

代码随想录|day 23

Day 23 一、回溯 二、代码 216. 组合总和 III - 力扣&#xff08;LeetCode&#xff09; class Solution { private:vector<int>path;vector<vector<int>>result;void backtracing(int sum,int k,int n,int startindex){//中止条件if(path.size()k){if(sum…

【FreeRTOS】任务创建

参考博客&#xff1a; ESP-IDF FreeRTOS 任务创建分析 - [Genius] - 博客园 (cnblogs.com) 1.什么是任务 1&#xff09;独立的无法返回的函数称为任务 2&#xff09;任务是无线循环 3&#xff09;无返回数据 2.任务的实现过程 1.定义任务栈 裸机程序&#xff1a;统一分配到一…

性能测试的几个指标范围(CPU,内存,IO,网络)

性能测试中&#xff0c;对服务端的指标监控也是很重要的一个环节。通过对各项服务器性能指标的监控分析&#xff0c;可以定位到性能瓶颈。 后端性能指标有 CPU&#xff0c;内存&#xff0c;网络&#xff0c;jvm&#xff0c;I/O 等等 分析思路 整体系统 CPU 利用率 内存利用…

C# If与Switch的区别

在 switch 语句中使用表达式比较时&#xff0c;编译器会生成一个查找表&#xff0c;其中包含所有表达式的值和对应的 case 标签。因此&#xff0c;与使用常量或字面量比较相比&#xff0c;使用表达式比较可能会略微降低性能。 只有当 switch 语句中的所有 case 标签都使用常量或…

AI:136-基于深度学习的图像生成与风格迁移

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带关键代码,详细讲解供大家学习,希望…

提升装备制造企业竞争力:2023年CRM选型与应用完全解读

在加快产业转型升级的大背景下&#xff0c;高端装备制造业既面临机遇也面临挑战。随着公司规模的不断壮大&#xff0c;再加上装备制造业营销体系及服务体系管理体系的复杂性&#xff0c;一些问题逐渐暴露出来&#xff0c;装备制造业企业需要根据自身业务需求和管理流程选择合适…