【AIGC】AI怎样匹配RAG知识库:关键词搜刮

打印 上一主题 下一主题

主题 2023|帖子 2023|积分 6069

引言

RAG作为镌汰模型幻觉和让模型分析、回答私域干系知识最简朴高效的方式,我们除了使用之外可以实验相识其是怎样实现的。在实现RAG的过程中,有语义搜刮也有关键词搜刮,我们这篇文章来用jieba库以及TF-IDF实现关键词搜刮RAG。
jieba库简介

jieba(结巴)是一个在Python中广泛使用的分词库,特殊适用于中文文本处理。jieba库不仅支持基本的分词功能,还提供了关键词提取、词性标注、命名实体识别等多种功能。在关键词检测范畴,jieba库的TF-IDF和TextRank算法被广泛应用于提取文本中的关键词。
TF-IDF简介

TF-IDF(Term Frequency-Inverse Document Frequency)是一种用于信息检索和文本挖掘的常用加权技术。它通过盘算词汇在文档中的频率(Term Frequency, TF)和在整个语料库中的逆文档频率(Inverse Document Frequency, IDF),来评估词汇的告急性和干系性。
TF-IDF的盘算公式如下:

简朴来说关键词出现的次数越多且存在于其他文档中的频率越低,那么这个关键词就越告急。
实践

我们来模仿用户询问题目,模型根据题目从知识库中检索出干系文档,并根据检索到的文档天生回答。
我们假设用户输出是text1,text2中是多个以";"隔开的文档,我们使用jieba库分割关键词并使用TF-IDF去实现关键词搜刮RAG,搜刮text2中最适配text1的文档。

例子

  1. # Example text
  2. text = "发到顺丰"
  3. # Example text2
  4. text2 = "您好,是您拨打的客服电话吗;你好,我的这个货想要通过顺丰去发;订单号发我一下;xxxxxx;好的我这边给您发顺丰"
复制代码
用jieba库提取关键词

  1. # 切割 text2 并将其作为文档
  2. documents = text2.split(';')
  3. # 提取关键词的函数
  4. def extract_keywords(text):
  5.     return jieba.analyse.extract_tags(text)
  6. # 提取查询关键词
  7. query_keywords = extract_keywords(text)
  8. # 提取文档关键词
  9. documents_keywords = [extract_keywords(doc) for doc in documents]
复制代码
盘算TF-IDF

各自盘算查询关键词和文档关键词的TF-IDF为之后盘算余弦相似度举行准备
  1. # 计算查询关键词的词频 (TF)
  2. query_keyword_counts = Counter(query_keywords)
  3. # 总文档数
  4. total_documents = len(documents)
  5. # 计算所有关键词的逆文档频率 (IDF)
  6. all_keywords = set()
  7. for doc_keywords in documents_keywords:
  8.     all_keywords.update(doc_keywords)
  9. keyword_idf = {}
  10. for keyword in all_keywords:
  11.     doc_count_containing_keyword = sum(1 for doc_keywords in documents_keywords if keyword in doc_keywords)
  12.     keyword_idf[keyword] = math.log((1 + total_documents) / (1 + doc_count_containing_keyword)) + 1
  13. # 计算查询关键词的 TF-IDF
  14. query_tfidf = {}
  15. for keyword, count in query_keyword_counts.items():
  16.     tf = count
  17.     idf = keyword_idf.get(keyword, 0)
  18.     query_tfidf[keyword] = tf * idf
  19. # 计算所有文档的 TF-IDF
  20. documents_tfidf = []
  21. for doc_keywords in documents_keywords:
  22.     doc_keyword_counts = Counter(doc_keywords)
  23.     doc_tfidf = {}
  24.     for keyword, count in doc_keyword_counts.items():
  25.         tf = count
  26.         idf = keyword_idf.get(keyword, 0)
  27.         doc_tfidf[keyword] = tf * idf
  28.     documents_tfidf.append(doc_tfidf)
复制代码
盘算文档和查询相似度

通过盘算余弦相似度来盘算查询词与文档相似度
  1. # 计算余弦相似度
  2. def cosine_similarity(vec1, vec2):
  3.     intersection = set(vec1.keys()) & set(vec2.keys())
  4.     numerator = sum(vec1[x] * vec2[x] for x in intersection)
  5.     sum1 = sum(vec1[x] ** 2 for x in vec1)
  6.     sum2 = sum(vec2[x] ** 2 for x in vec2)
  7.     denominator = math.sqrt(sum1) * math.sqrt(sum2)
  8.     if not denominator:
  9.         return 0.0
  10.     else:
  11.         return float(numerator) / denominator
  12. # 计算文档与查询的相似度
  13. similarities = []
  14. for doc_tfidf in documents_tfidf:
  15.     similarity = cosine_similarity(query_tfidf, doc_tfidf)
  16.     similarities.append(similarity)
  17. # 按相似度排序并返回结果
  18. sorted_documents = sorted(zip(documents, similarities), key=lambda x: x[1], reverse=True)
  19. # 打印结果
  20. for i, (doc, score) in enumerate(zip(documents, similarities)):
  21.     print(f"Document {i+1}: {doc}\nScore: {score}\n")
复制代码
结果

Score得分越高,则文档越匹配查询词,可以看到,我们根据关键词搜刮,找到了最适配text1的文档,Document 2。
  1. Document 1: 您好,是您拨打的客服电话吗
  2. Score: 0.0
  3. Document 2: 你好,我的这个货想要通过顺丰去发
  4. Score: 0.4472135954999579
  5. Document 3: 订单号发我一下
  6. Score: 0.0
  7. Document 4: xxxxxx
  8. Score: 0.0
  9. Document 5: 好的我这边给您发顺丰
  10. Score: 0.0
复制代码
完整代码:

  1. import jiebafrom jieba.analyse import default_tfidffrom collections import Counterimport math# Example text
  2. text = "发到顺丰"
  3. # Example text2
  4. text2 = "您好,是您拨打的客服电话吗;你好,我的这个货想要通过顺丰去发;订单号发我一下;xxxxxx;好的我这边给您发顺丰"
  5. # 切割 text2 并将其作为文档
  6. documents = text2.split(';')
  7. # 提取关键词的函数
  8. def extract_keywords(text):
  9.     return jieba.analyse.extract_tags(text)
  10. # 提取查询关键词
  11. query_keywords = extract_keywords(text)
  12. # 提取文档关键词
  13. documents_keywords = [extract_keywords(doc) for doc in documents]
  14. # 计算查询关键词的词频 (TF)
  15. query_keyword_counts = Counter(query_keywords)
  16. # 总文档数
  17. total_documents = len(documents)
  18. # 计算所有关键词的逆文档频率 (IDF)
  19. all_keywords = set()
  20. for doc_keywords in documents_keywords:
  21.     all_keywords.update(doc_keywords)
  22. keyword_idf = {}
  23. for keyword in all_keywords:
  24.     doc_count_containing_keyword = sum(1 for doc_keywords in documents_keywords if keyword in doc_keywords)
  25.     keyword_idf[keyword] = math.log((1 + total_documents) / (1 + doc_count_containing_keyword)) + 1
  26. # 计算查询关键词的 TF-IDF
  27. query_tfidf = {}
  28. for keyword, count in query_keyword_counts.items():
  29.     tf = count
  30.     idf = keyword_idf.get(keyword, 0)
  31.     query_tfidf[keyword] = tf * idf
  32. # 计算所有文档的 TF-IDF
  33. documents_tfidf = []
  34. for doc_keywords in documents_keywords:
  35.     doc_keyword_counts = Counter(doc_keywords)
  36.     doc_tfidf = {}
  37.     for keyword, count in doc_keyword_counts.items():
  38.         tf = count
  39.         idf = keyword_idf.get(keyword, 0)
  40.         doc_tfidf[keyword] = tf * idf
  41.     documents_tfidf.append(doc_tfidf)
  42. # 计算余弦相似度
  43. def cosine_similarity(vec1, vec2):
  44.     intersection = set(vec1.keys()) & set(vec2.keys())
  45.     numerator = sum(vec1[x] * vec2[x] for x in intersection)
  46.     sum1 = sum(vec1[x] ** 2 for x in vec1)
  47.     sum2 = sum(vec2[x] ** 2 for x in vec2)
  48.     denominator = math.sqrt(sum1) * math.sqrt(sum2)
  49.     if not denominator:
  50.         return 0.0
  51.     else:
  52.         return float(numerator) / denominator
  53. # 计算文档与查询的相似度
  54. similarities = []
  55. for doc_tfidf in documents_tfidf:
  56.     similarity = cosine_similarity(query_tfidf, doc_tfidf)
  57.     similarities.append(similarity)
  58. # 按相似度排序并返回结果
  59. sorted_documents = sorted(zip(documents, similarities), key=lambda x: x[1], reverse=True)
  60. # 打印结果
  61. for i, (doc, score) in enumerate(zip(documents, similarities)):
  62.     print(f"Document {i+1}: {doc}\nScore: {score}\n")
复制代码
总结

关键词匹配是RAG搜刮中的一个很告急的方法之一,但是关键词匹配的缺点也很明显,就是关键词匹配的召回率很低,由于关键词匹配只匹配了关键词,而没有匹配到关键词的上下文。所以一样平常需要结合语义搜刮去一起举行。可以参考我的另一片先容语义搜刮的文章去举行双路召回搜刮。【AIGC】AI怎样匹配RAG知识库: Embedding实践,语义搜刮
在上面我们的实践中,我们使用jieba库去举行分词,然后通过TF-IDF算法去盘算关键词的权重,然后通过余弦相似度去盘算文档和查询的相似度,最后通过相似度去排序,返回结果。基本上这个一个比较通用的关键词匹配RAG数据库的方法。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我可以不吃啊

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表