假设你和我一样在预备24年的春招,在前端全栈外,再预备一些AI的内容是非常有必要的。24年是AI盈利年,AIGC+各种岗位大厂机会会多些,同意的请点赞。也欢迎朋友们加我微信shunwuyu, 一同交流。

前言

前端也能够这样零根底入门Pinecone二 – (juejin.cn)文章中,咱们在RAG应用中运用了Pinecone向量数据库。本文,持续给咱们展示Pinecone拿手的应用场景。咱们一同来看下引荐体系是怎么做的。

故事

我有位高中同学,是做引荐体系的大佬,在Facebook做广告体系。优异的大学同学有很多,但这位是隔壁的他。做前端的我, 回家春节,给老妈些钱去买房。老妈约上同学他妈,一同去看楼。我妈看上了一套小三房, 他妈也看中了,不过是这个洋房的整个一单元。

这便是我,一位前端老狗的忧伤。再怎么写vue、react, 也赚不过引荐算法工程师,几十万美金+顶级大厂股票……

好了, 现在有了LLM, 前端老狗也能够搞引荐体系了。闭关一年,成为AI Nativer, 赚到新钱也给老妈买单元….

Demo

前端也能够这样零根底入门Pinecone三

图片是虎嗅(huxiu.com)网一篇文章的相关引荐截图,咱们要做的功能就类似这种。咱们将下载一个新闻类的数据源,embedding向存入Pinecone。某篇文章的标题,让它在Pinecone里做类似度查询,就完成了相关内容引荐。

数据集

# wget 指令下载 -q 安静形式,不输出下载相关信息  --show-progress 只展示进展信息  -O 重命名为all-the-news-3.zip  数据地址在dropbox里的all-the-news
!wget -q --show-progress -O all-the-news-3.zip https://www.dropbox.com/scl/fi/wruzj2bwyg743d0jzd7ku/all-the-news-3.zip?rlkey=rgwtwpeznbdadpv3f01sznwxa&dl=1%22
# 解压数据
!unzip all-the-news-3.zip

前端也能够这样零根底入门Pinecone三

我是在colab环境中调试demo, 从上图能够看出all-the-news-3.zip 166.04M 挺大的。玩NLP, 要有LLM、Dataset的概念,HuggingFace便是方便的帮咱们提供了这两者,所以大受欢迎!如果您是前端刚预备玩AI,主张去看在些HuggingFace相关的内容,能够快速上手。

看下数据

# with 关键字, `with`句子能够保证在履行完相应的代码块后,无论是否产生反常,都会正确、安全地封闭文件
with open('./all-the-news-3.csv', 'r') as f:
    # csv文件的首行是表头
    header = f.readline()
    # 打印表头,咱们就知道了有多少列
    print(header)
# 时刻、作者、标题、文章内容、url, 主题等
date,year,month,day,author,title,article,url,section,publication

pandas 读取数据

# 引进pandas数据剖析结构
import pandas as pd
# 读取99特内容
df = pd.read_csv('./all-the-news-3.csv', nrows=99)
# 默认返回DataFrame的前五行数据
df.head()

前端也能够这样零根底入门Pinecone三

读取文件和读取数据的差异,咱们应该清楚了。pandas 能够直接读取csv格局的文件。下一步开个pandas的系列学习吧!

创立pinecone index表

# Pinecone 用于衔接向量数据库   ServerlessSpec 云服务
from pinecone import Pinecone, ServerlessSpec
# index 名字为dl-ai
INDEX_NAME = 'dl-ai'
# PINECONE_API_KEY能够到pinecone 后台拿
pinecone = Pinecone(api_key='')
# pinecone.list_indexes 方法列出一切的数据表 
if INDEX_NAME in [index.name for index in pinecone.list_indexes()]:
    # 如果有, 先移除
  pinecone.delete_index(INDEX_NAME)
# create_index 创立index,
# 1536 是openai的向量维度
pinecone.create_index(name=INDEX_NAME, 
dimension=1536, metric='cosine',
# 亚马逊  西部2区
  spec=ServerlessSpec(cloud='aws', region='us-west-2'))
# 当前index对象,后边将用它来刺进和查询
index = pinecone.Index(INDEX_NAME)

封装Embedding函数

from openai import OpenAI
#OPENAI_API_KEY 填自己的
openai_client = OpenAI(api_key='')
# 适合做embedding的模型是text-embedding-ada-002
# 这处系列的榜首篇文章运用的是all-MiniLM-L6-v2 免费的,运用HuggingFace的 sentence_transformers
def get_embeddings(articles, model="text-embedding-ada-002"):
   # 调用openai 的embeddings模块的create方法 返回向量
   return openai_client.embeddings.create(input = articles, model=model)

Embedding

#引进pandas 数据剖析库
import pandas as pd
# 指令行东西
from tqdm.auto import tqd
# 一批履行400个
CHUNK_SIZE=400
# 一共履行1万个, 计25次轮回
TOTAL_ROWS=10000
# tqdm 指令行东西, embedding 需求时刻,tqdm 提供相关运转信息
# 等下调用它的update方法更新进展条信息
progress_bar = tqdm(total=TOTAL_ROWS)
# 逐块读取 不会一次性的读到内存, 迭代读取
chunks = pd.read_csv('./all-the-news-3.csv', chunksize=CHUNK_SIZE, 
                     nrows=TOTAL_ROWS)
# 开始为0
chunk_num = 0
# 遍历每一chunk
for chunk in chunks:
    # 取出标题 tolist将这一列的一切元素值转化为一个Python列表
    titles = chunk['title'].tolist()
    # 得到embeddings
    embeddings = get_embeddings(titles)
    # pinecone 一个数据节点的结构
    # 多个标题, 每个都加入metadata
    prepped = [{'id':str(chunk_num*CHUNK_SIZE+i), 
    # 某个标题的embedding
    'values':embeddings.data[i].embedding,
                'metadata':{'title':titles[i]},} for i in range(0,len(titles))]
    chunk_num = chunk_num + 1
    # 200 是比较适宜的
    if len(prepped) >= 200:
      # 刺进
      index.upsert(prepped)
      # 重置prepped 
      prepped = []
    # 更新下载进展
    progress_bar.update(len(chunk))
  • 封装引荐函数
# 参数有index 名字、关键字、 top_k 返回的数量
def get_recommendations(pinecone_index, search_term, top_k=10):
  get_embeddings 需求的是数组
  embed = get_embeddings([search_term]).data[0].embedding
  # 类似度查询
  res = pinecone_index.query(vector=embed, top_k=top_k, include_metadata=True)
  return res
  • 取得引荐成果
# 查询关于obama的引荐
reco = get_recommendations(index, 'obama')
for r in reco.matches:
    print(f'{r.score} : {r.metadata["title"]}')
  • 为一切的新闻内容也做嵌入, 这个开支就大了哈
# 删除了之前的index , 从头创立了index
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'))
articles_index = pinecone.Index(INDEX_NAME)
  • 重写嵌入函数
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
  • 对内容做嵌入
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('./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)
      embed_num = embed(embeddings, title, prepped, embed_num)
  • 针对内容进行embedding
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] = '.'

总结

  • 读取文件和读取数据的差异,csv 是常用的数据文件格局,比方mysql等就能够导出为csv格局。其特点是每行一条数据,代表mysql 的 row。f.readline()读取到的便是标题行,pandas有预设置DataFrame, 能够直接做数据导入和处理。
  • pandas的逐块读取csv’
  • embedding 函数的封装

参阅内容