当前位置:   article > 正文

AI大模型的使用-语义检索,利用Embedding优化你的搜索功能_让大模型对某个数据源进行搜索

让大模型对某个数据源进行搜索

Embedding 向量适合作为一个中间结果,用于传统的机器学习场景,比如分类、聚类。

Completion 接口,一方面可以直接拿来作为一个聊天机器人,另一方面,你只要善用提示词,就能完成合理的文案撰写、文本摘要、机器翻译等一系列的工作。

我们之前都是网上查找数据集或者openAI提供的数据集进行处理,这里我们可以利用AI给我们生成数据,我们根据它生成的数据进行搜索,推荐等处理。

接下来让AI帮我们搜索给我们今天要测试的数据集

1 让 AI 生成实验数据

让它给我们淘宝网里商品的标题,要求每条名称30字左右,数码类产品,每行一条

  1. ! pip install openai
  2. ! pip install os
  3. import openai,os
  4. openai.api_key=''
  5. COMPLETION_MODEL = "text-davinci-003"
  6. # 调用openAI
  7. def generate_data_by_prompt(prompt):
  8. response=openai.Completion.create(
  9. engine=COMPLETION_MODEL,
  10. prompt=prompt,
  11. temperature=0.5,
  12. max_tokens=2048,
  13. top_p=1,
  14. )
  15. return response.choices[0].text
  16. prompt="""
  17. 请你生成50条淘宝网里的商品的标题,每条在30个字左右,品类是3C数码产品,标题里往往也会有一些促销类的信息,每行一条。
  18. """
  19. data=generate_data_by_prompt(prompt)
  20. print(data)

反馈的结果:

  1. 1.【新品上市】Apple/苹果 iPhone 11 Pro Max 手机
  2. 2.【现货特价】华为Mate 30 Pro 5G手机
  3. 3.【抢购优惠】小米MIX Alpha智能折叠手机
  4. 4.【热卖爆款】三星Galaxy Note 10 Plus 旗舰手机
  5. 5.【限时促销】荣耀V30 Pro 5G超薄手机
  6. 6.【时尚潮流】OPPO Reno 10X Zoom双摄手机
  7. 7.【新品特惠】vivo NEX 3 5G超级旗舰手机
  8. 8.【超值优惠】联想Z6 Pro 5G游戏手机
  9. 9.【热销精品】金立S10 Pro 5G 全面屏手机
  10. 10.【抢购热卖】魅族16s Pro 全面屏手机
  11. 11.【热卖抢购】荣耀20 Pro 5G超薄手机
  12. 12.【爆款热销】Apple/苹果 iPhone 11 手机
  13. 13.【特价热卖】华为P30 Pro 全面屏手机
  14. 14.【新品优惠】三星Galaxy S10 Plus 旗舰手机
  15. 15.【限时特惠】OPPO Reno 10X 折叠手机
  16. 16.【时尚潮流】vivo iQOO Pro 5G超级旗舰手机
  17. 17.【新品特价】联想Z5 Pro 5G全面屏手机
  18. 18.【超值促销】金立S10 5G 全面屏手机
  19. 19.【抢购热卖】魅族16s 全面屏手机
  20. 20.【热销特惠】荣耀20 5G超薄手机
  21. 21.【爆款特价】Apple/苹果 iPhone XS Max 手机
  22. 22.【特价热卖】华为Mate 20 Pro 5G手机
  23. 23.【新品优惠】小米MIX 3 智能折叠手机
  24. 24.【热卖爆款】三星Galaxy Note 9 Plus 旗舰手机
  25. 25.【限时促销】荣耀V20 Pro 5G超薄手机
  26. 26.【时尚潮流】OPPO Reno 8X Zoom双摄手机
  27. 27.【新品特惠】vivo NEX 3S 5G超级旗舰手机
  28. 28.【超值优惠】联想Z6 5G游戏手机
  29. 29.【热销精品】金立S10 5G 全面屏手机
  30. 30.【抢购热卖】魅族16s Plus 全面屏手机
  31. 31.【热卖抢购】荣耀20 5G超薄手机
  32. 32.【爆款热销】Apple/苹果 iPhone XR 手机
  33. 33.【特价热卖】华为P20 Pro 全面屏手机
  34. 34.【新品优惠】三星Galaxy S9 Plus 旗舰手机
  35. 35.【限时特惠】OPPO Reno 8 折叠手机
  36. 36.【时尚潮流】vivo iQOO 5G超级旗舰手机
  37. 37.【新品特价】联想Z5 5G全面屏手机
  38. 38.【超值促销】金立S10 Pro 5G 全面屏手机
  39. 39.【抢购热卖】魅族16 Plus 全面屏手机
  40. 40.【热销特惠】荣耀20 Pro 5G超薄手机
  41. 41.【爆款特价】Apple/苹果 iPhone X 手机
  42. 42.【特价热卖】华为Mate 10 Pro 5G手机
  43. 43.【新品优惠】小米MIX 2S智能折叠手机
  44. 44.【热卖爆款】三星Galaxy Note 8 Plus 旗舰手机
  45. 45.【限时促销】荣耀V10 Pro 5G超薄手机
  46. 46.【时尚潮流】OPPO Reno 7X Zoom双摄手机
  47. 47.【新品特惠】vivo NEX 2 5G超级旗舰手机
  48. 48.【超值优惠】联想Z4 Pro 5G游戏手机
  49. 49.【热销精品】金立S10 Plus 5G 全面屏手机
  50. 50.【抢购热卖】魅族16 全面屏手机

我们将给的数据处理下,改成我们能处理的数据,将数据转换为DataFrame,并起一个key名为product_name。

  1. !pip install pandas
  2. import pandas as pd
  3. # 按行分割,strip()函数去掉两边的空白
  4. product_names=data.strip().split("\n")
  5. # 将数据存储成行列,列名为product_name
  6. df=pd.DataFrame({'product_name':product_names})
  7. # 显示前几行数据
  8. df.head()

结果如下:

 我们看到它返回的数据都自带了编号,我们把编号去掉,不要它标题的编号:

  1. # 去掉列里自带的编号,apply()函数用于对DataFrame的一列(Series)中的每个元素应用一个函数。然后匿名函数处理列里数据
  2. # 列里根.字符进行分割,取索引1的数据就可。最后赋值给远列product_name
  3. df.product_name=df.product_name.apply(lambda x: x.split('.')[1].strip())
  4. df.head()

结果:

 我们再获取一些女装,也是用上边的方式,方便后面实验测试数据

  1. clothes_prompt = """请你生成50条淘宝网里的商品的标题,每条在30个字左右,品类是女性的服饰箱包等等,标题里往往也会有一些促销类的信息,每行一条。"""
  2. clothes_data = generate_data_by_prompt(clothes_prompt)
  3. clothes_product_names=clothes_data.strip().split('\n')
  4. clothes_df=pd.DataFrame({'product_name':clothes_product_names})
  5. clothes_df.product_name= clothes_df.product_name.apply(lambda x: x.split('.')[1].strip())
  6. clothes_df.head()

查看结果:用head取出前5条数据

 将上面得到的数码产品和女士服饰箱包这两种数据合并一起,方便后续搜索数据处理:

  1. #把这两个 DataFrame 拼接在一起,就是我们接下来用于做搜索实验的数据。
  2. # concat()此函数用来合并,方式为axis=0按行合并
  3. df = pd.concat([df, clothes_df], axis=0)
  4. # 重制索引。drop=True对原来的索引采取丢弃操作,保留重制后的索引
  5. df=df.reset_index(drop=True)
  6. display(df)

得到结果:你会发现 AI 有时候返回的条数没有 50 条,不过没有关系,这个基本不影响我们使用这个数据源。你完全可以多运行几次,获得足够你需要的数据。

然后我们把这些数据通过Embedding转成向量,用于计算相似度搜索~ 

我们还是利用 backoff 和 batch 处理,让代码能够容错,并且快速处理完这些商品标题。

  1. !pip install openai
  2. !pip install os
  3. !pip install backoff
  4. import openai
  5. import os
  6. import backoff
  7. import pandas as pd
  8. from openai.embeddings_utils import get_embeddings
  9. openai.api_key = ''
  10. embedding_model = "text-embedding-ada-002"
  11. batch_size = 100
  12. # 在线colab加上此注解报错,所以在去掉了,你可以测试下你的环境可不可以
  13. @backoff.on_exception(backoff.expo, openai.error.RateLimitError)
  14. def get_embeddings_with_backoff(prompts, engine):
  15. print("len(prompts):",len(prompts))
  16. embeddings = []
  17. for i in range(0, len(prompts), batch_size):
  18. batch = prompts[i:i+batch_size]
  19. print("第二个batch数据:",batch)
  20. embeddings += get_embeddings(list_of_text=batch, engine=engine)
  21. return embeddings
  22. prompts = df.product_name.tolist()
  23. prompt_batches = [prompts[i:i+batch_size] for i in range(0, len(prompts), batch_size)]
  24. print("prompt_batches:",prompt_batches)
  25. embeddings = []
  26. for batch in prompt_batches:
  27. print("第一个batch数据:",batch)
  28. batch_embeddings = get_embeddings_with_backoff(prompts=batch, engine=embedding_model)
  29. embeddings += batch_embeddings
  30. df["embedding"] = embeddings
  31. df.to_parquet("taobao_product_title.parquet", index=False)

将数据转换成向量数据完毕!

2 通过 Embedding 进行语义搜索

然后我们就可以写搜索产品的代码啦,主要通过关键字进行搜索,将关键搜索词转换成向量,因为我们的数据源已经转换成向量了,所以计算两个向量的相似度以后得到数据,并将数据返回即可。

  1. # 搜索商品逻辑-----------------------------------------------------------------
  2. from openai.embeddings_utils import get_embedding, cosine_similarity
  3. # 第一个参数df代表要搜索的数据源,在colab有上下文的
  4. # 第二个参数query代表是搜索关键词
  5. # 第三个参数n代表返回多少条记录
  6. # pprint 是一个布尔值,控制是否打印结果,默认为 True。
  7. def search_product(df,query,n=3,pprint=True):
  8. # 获取给定文本的嵌入向量,采用此模型计算查询
  9. produce_embedding=get_embedding(
  10. query,
  11. engine=embedding_model,
  12. )
  13. # 计算embedding与produce_embedding相似度,采用余弦相似度来衡量查询与个产品之间的相似度,并把结果存储到df["similarity"]列中
  14. df["similarity"]=df.embedding.apply(lambda x: cosine_similarity(x,produce_embedding))
  15. # 按照相似度降序排列,然后选取前n个产品,并提他们的产品名称
  16. # ascending是用于排序的,True为正序,False为倒序
  17. # 它会根据"similarity"列的值找到相似度最高的n个产品,并返回它们的产品名称。
  18. results=(
  19. df.sort_values("similarity",ascending=False)
  20. .head(n)
  21. .product_name
  22. )
  23. # pprint为True,则会打印每个匹配结果的产品
  24. if pprint:
  25. for r in results:
  26. print(r)
  27. return results
  28. results=search_product(df,"自然淡雅书包",n=3)

结果内容:

  1. 【新款】时尚简约女士手提包,柔软质感更耐用!
  2. 【新款】简约时尚女士手提包,柔软质感更耐用!
  3. 【特惠】精致简约女士手提包,潮流时尚更显靓丽!

我们可以试下搜索手机

results=search_product(df,"华为手机",n=3)

结果:

  1. 【新品上市】华为Mate 30 5G 智能手机
  2. 【新品上市】华为P40 Pro 5G 智能手机
  3. 【热销爆款】华为Mate 30 Pro 5G 智能手机

简简单单就以向量的方式做了一个搜索检查。

3 利用 Embedding 信息进行商品推荐的冷启动

什么是冷启动,在新的用户或新的商品的情况下,因为没有历史数据作为佐证,无法准确的评估推荐到每一个人,所以就需要,通过合理的策略和算法,推荐系统可以在没有量历史数据的情况下,为新用户和新商品提供有针对性的推荐,从而提高推荐的准确性和个性化程度。

咱们这里只要是搜索过这个商品的话就给推荐相似商品

这个和上面的搜索代码类似,唯一不同的是,上面的代码给出搜索关键字以后又去找openai调用获取向量,咱们这个直接对比标题内容以后从列中取出向量,没必要浪费去查一次,然后再对比相似度,代码如下:

也就是说我们给的关键字是存在于数据源中的(此处需要与原数据中的产品名称一模一样否则取不出向量会报错)那么可以直接在原数据中产品名称对比,如果一样取出当前产品名称的向量即可。

  1. def recommend_product(df,product_name,n=3,pprint=True):
  2. product_embedding = df[df['product_name'] == product_name].iloc[0].embedding
  3. df['similarity']=df.embedding.apply(lambda x: cosine_similarity(x,product_embedding))
  4. results = (
  5. df.sort_values("similarity", ascending=False)
  6. .head(n)
  7. .product_name
  8. )
  9. if pprint:
  10. for r in results:
  11. print(r)
  12. return results
  13. results=recommend_product(df,"【新品上市】苹果iPhone 11 Pro Max全网通手机",n=3)

结果内容:这样一个新的商品根据语义相似度,就能推荐对应商品。

  1. 【新品上市】苹果iPhone 11 Pro Max全网通手机
  2. 【新品上市】苹果iPhone 11 Pro 512GB全网通手机
  3. 【新品上市】苹果iPhone 11 256GB全网通手机

4 通过 FAISS 加速搜索过程

先把向量数据加载到faiss里,为什么呢,因为面对大数据量我们每次都要计算距离,那速度肯定是慢的不行,所以可以利用一些向量数据库,或者能够快速搜索相似性的软件包就可以了,比如,我比较推荐你使用 Facebook 开源的 Faiss 这个 Python 包,它的全称就是 Facebook AI Similarity Search,也就是快速进行高维向量的相似性搜索。

把索引加载到 Faiss 里面非常容易,我们直接把整个的 Embedding 变成一个二维矩阵,整个加载到 Faiss 里面就好了。

  1. !pip install faiss-gpu
  2. !pip install numpy
  3. import faiss
  4. import numpy as np
  5. def load_embeddings_to_faiss(df):
  6. # (DataFrame)中的嵌入(embedding)列转换为一个浮点型的 NumPy 数组(numpy array)
  7. # df['embedding'].tolist():将数据框中名为 "embedding" 的列转换为 Python 列表。
  8. # np.array(...):将 Python 列表转换为 NumPy 数组。
  9. # astype('float32'):将数组中的元素类型转换为浮型(32 位浮点数)。
  10. embeddings = np.array(df['embedding'].tolist()).astype('float32')
  11. # 创建了一个 Faiss 的索引对象,用于存储商品embeddings,embeddings.shape[1]=embeddings数组的第二个维度的大小
  12. index = faiss.IndexFlatL2(embeddings.shape[1])
  13. # embeddings加入到索引中,以便可以使用 Faiss 进行快速的相似度搜索
  14. index.add(embeddings)
  15. return index
  16. index = load_embeddings_to_faiss(df)
  17. print("index:",index)

然后用这种方式搜索下,围绕着index搜索,需要把我们的关键搜索词转换为向量,再转换为numpy数组,通过reshape转换为二维数组,其实和上边没什么区别,目的还是为了数据都是在一个维度上进行对比。然后经过处理的数据传入index的search函数里进行搜索,搜索出k个相同的数据,并返回

通过faiss搜索,代码如下:

  1. def search_index(index, df, query, k=5):
  2. # reshape转换为二维数组,
  3. query_vector = np.array(get_embedding(query, engine=embedding_model)).reshape(1, -1).astype('float32')
  4. # 搜索与query_vector 最相似的 k 个向量返回的结果一个包含两个数组的元组
  5. # 第一个是最相似的向量与 query_vector 之间的距离
  6. # 第二个数组是最相似的向量在索引中的索引位置
  7. distances, indexes = index.search(query_vector, k)
  8. print("distances:",distances)
  9. print("indexes",indexes)
  10. # 封装返回结果
  11. results = []
  12. for i in range(len(indexes)):
  13. product_names = df.iloc[indexes[i]]['product_name'].values.tolist()
  14. print('for product_names :',product_names)
  15. results.append((distances[i], product_names))
  16. return results
  17. products = search_index(index, df, "自然淡雅背包", k=3)
  18. print("products:",products)
  19. # 将得到的结果解析打印
  20. for distances, product_names in products:
  21. print("distances:",distances)
  22. for i in range(len(distances)):
  23. print(product_names[i], distances[i])

结果如下:Faiss 的原理,是通过 ANN 这样的近似最近邻的算法,快速实现相似性的搜索。

  1. distances: [[0.21429113 0.21453398 0.22011249]]
  2. indexes [[ 90 140 112]]
  3. for product_names : ['【新款】优雅百搭女士单肩包', '【新款】优雅百搭女士单肩包', '【新款】优雅百搭女士手拿包']
  4. products: [(array([0.21429113, 0.21453398, 0.22011249], dtype=float32), ['【新款】优雅百搭女士单肩包', '【新款】优雅百搭女士单肩包', '【新款】优雅百搭女士手拿包'])]
  5. distances: [0.21429113 0.21453398 0.22011249]
  6. 【新款】优雅百搭女士单肩包 0.21429113
  7. 【新款】优雅百搭女士单肩包 0.21453398
  8. 【新款】优雅百搭女士手拿包 0.22011249

本章视频说明:AI大模型-巧用Embedding实现搜索和推荐功能_哔哩哔哩_bilibili

本文根据徐文浩老师的《AI大模型之美》 整理记录

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/411269
推荐阅读
相关标签
  

闽ICP备14008679号