百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

【AIGC】AI如何匹配RAG知识库:关键词搜索

liebian365 2024-11-02 13:33 32 浏览 0 评论

引言

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库实现关键词搜索RAG,搜索text2中最适配text1的文档。

例子

# Example text
text = "发到顺丰"

# Example text2
text2 = "您好,是您拨打的客服电话吗;你好,我的这个货想要通过顺丰去发;订单号发我一下;xxxxxx;好的我这边给您发顺丰"

用jieba库提取关键词

# 切割 text2 并将其作为文档
documents = text2.split(';')

# 提取关键词的函数
def extract_keywords(text):
    return jieba.analyse.extract_tags(text)

# 提取查询关键词
query_keywords = extract_keywords(text)

# 提取文档关键词
documents_keywords = [extract_keywords(doc) for doc in documents]

计算TF-IDF

# 计算查询关键词的词频 (TF)
query_keyword_counts = Counter(query_keywords)

# 总文档数
total_documents = len(documents)

# 计算所有关键词的逆文档频率 (IDF)
all_keywords = set()
for doc_keywords in documents_keywords:
    all_keywords.update(doc_keywords)

keyword_idf = {}
for keyword in all_keywords:
    doc_count_containing_keyword = sum(1 for doc_keywords in documents_keywords if keyword in doc_keywords)
    keyword_idf[keyword] = math.log((1 + total_documents) / (1 + doc_count_containing_keyword)) + 1

# 计算查询关键词的 TF-IDF
query_tfidf = {}
for keyword, count in query_keyword_counts.items():
    tf = count
    idf = keyword_idf.get(keyword, 0)
    query_tfidf[keyword] = tf * idf

# 计算所有文档的 TF-IDF
documents_tfidf = []
for doc_keywords in documents_keywords:
    doc_keyword_counts = Counter(doc_keywords)
    doc_tfidf = {}
    for keyword, count in doc_keyword_counts.items():
        tf = count
        idf = keyword_idf.get(keyword, 0)
        doc_tfidf[keyword] = tf * idf
    documents_tfidf.append(doc_tfidf)

计算文档和查询相似度

# 计算余弦相似度
def cosine_similarity(vec1, vec2):
    intersection = set(vec1.keys()) & set(vec2.keys())
    numerator = sum(vec1[x] * vec2[x] for x in intersection)
    sum1 = sum(vec1[x] ** 2 for x in vec1)
    sum2 = sum(vec2[x] ** 2 for x in vec2)
    denominator = math.sqrt(sum1) * math.sqrt(sum2)
    if not denominator:
        return 0.0
    else:
        return float(numerator) / denominator

# 计算文档与查询的相似度
similarities = []
for doc_tfidf in documents_tfidf:
    similarity = cosine_similarity(query_tfidf, doc_tfidf)
    similarities.append(similarity)

# 按相似度排序并返回结果
sorted_documents = sorted(zip(documents, similarities), key=lambda x: x[1], reverse=True)

# 打印结果
for i, (doc, score) in enumerate(zip(documents, similarities)):
    print(f"Document {i+1}: {doc}\nScore: {score}\n")

结果

Score得分越高,则文档越匹配查询词,可以看到,我们根据关键词搜索,找到了最适配text1的文档,Document 2。

Document 1: 您好,是您拨打的客服电话吗
Score: 0.0

Document 2: 你好,我的这个货想要通过顺丰去发
Score: 0.4472135954999579

Document 3: 订单号发我一下
Score: 0.0

Document 4: xxxxxx
Score: 0.0

Document 5: 好的我这边给您发顺丰
Score: 0.0

完整代码:

import jieba
from jieba.analyse import default_tfidf
from collections import Counter
import math

# Example text
text = "发到顺丰"

# Example text2
text2 = "您好,是您拨打的客服电话吗;你好,我的这个货想要通过顺丰去发;订单号发我一下;xxxxxx;好的我这边给您发顺丰"

# 切割 text2 并将其作为文档
documents = text2.split(';')

# 提取关键词的函数
def extract_keywords(text):
    return jieba.analyse.extract_tags(text)

# 提取查询关键词
query_keywords = extract_keywords(text)

# 提取文档关键词
documents_keywords = [extract_keywords(doc) for doc in documents]

# 计算查询关键词的词频 (TF)
query_keyword_counts = Counter(query_keywords)

# 总文档数
total_documents = len(documents)

# 计算所有关键词的逆文档频率 (IDF)
all_keywords = set()
for doc_keywords in documents_keywords:
    all_keywords.update(doc_keywords)

keyword_idf = {}
for keyword in all_keywords:
    doc_count_containing_keyword = sum(1 for doc_keywords in documents_keywords if keyword in doc_keywords)
    keyword_idf[keyword] = math.log((1 + total_documents) / (1 + doc_count_containing_keyword)) + 1

# 计算查询关键词的 TF-IDF
query_tfidf = {}
for keyword, count in query_keyword_counts.items():
    tf = count
    idf = keyword_idf.get(keyword, 0)
    query_tfidf[keyword] = tf * idf

# 计算所有文档的 TF-IDF
documents_tfidf = []
for doc_keywords in documents_keywords:
    doc_keyword_counts = Counter(doc_keywords)
    doc_tfidf = {}
    for keyword, count in doc_keyword_counts.items():
        tf = count
        idf = keyword_idf.get(keyword, 0)
        doc_tfidf[keyword] = tf * idf
    documents_tfidf.append(doc_tfidf)

# 计算余弦相似度
def cosine_similarity(vec1, vec2):
    intersection = set(vec1.keys()) & set(vec2.keys())
    numerator = sum(vec1[x] * vec2[x] for x in intersection)
    sum1 = sum(vec1[x] ** 2 for x in vec1)
    sum2 = sum(vec2[x] ** 2 for x in vec2)
    denominator = math.sqrt(sum1) * math.sqrt(sum2)
    if not denominator:
        return 0.0
    else:
        return float(numerator) / denominator

# 计算文档与查询的相似度
similarities = []
for doc_tfidf in documents_tfidf:
    similarity = cosine_similarity(query_tfidf, doc_tfidf)
    similarities.append(similarity)

# 按相似度排序并返回结果
sorted_documents = sorted(zip(documents, similarities), key=lambda x: x[1], reverse=True)

# 打印结果
for i, (doc, score) in enumerate(zip(documents, similarities)):
    print(f"Document {i+1}: {doc}\nScore: {score}\n")

总结

关键词匹配是RAG搜索中的一个很重要的方法之一,但是关键词匹配的缺点也很明显,就是关键词匹配的召回率很低,因为关键词匹配只匹配了关键词,而没有匹配到关键词的上下文。所以一般需要结合语义搜索去一起进行。 在上面我们的实践中,我们使用jieba库去进行分词,然后通过TF-IDF算法去计算关键词的权重,然后通过余弦相似度去计算文档和查询的相似度,最后通过相似度去排序,返回结果。基本上这个一个比较通用的关键词匹配RAG数据库的方法。

相关推荐

4万多吨豪华游轮遇险 竟是因为这个原因……

(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...

“菜鸟黑客”必用兵器之“渗透测试篇二”

"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...

科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白

作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...

麦子陪你做作业(二):KEGG通路数据库的正确打开姿势

作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...

知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势

智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...

每日新闻播报(September 14)_每日新闻播报英文

AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...

香港新巴城巴开放实时到站数据 供科技界研发使用

中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...

5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper

本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...

Qt动画效果展示_qt显示图片

今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...

如何从0到1设计实现一门自己的脚本语言

作者:dong...

三年级语文上册 仿写句子 需要的直接下载打印吧

描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...

C++|那些一看就很简洁、优雅、经典的小代码段

目录0等概率随机洗牌:1大小写转换2字符串复制...

二年级上册语文必考句子仿写,家长打印,孩子照着练

二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...

一年级语文上 句子专项练习(可打印)

...

亲自上阵!C++ 大佬深度“剧透”:C++26 将如何在代码生成上对抗 Rust?

...

取消回复欢迎 发表评论: