欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 艺术 > python实战(四)——RAG预热实践

python实战(四)——RAG预热实践

2024/11/29 8:43:06 来源:https://blog.csdn.net/ChaneMo/article/details/143300217  浏览:    关键词:python实战(四)——RAG预热实践

一、任务目标

        为了清晰直观地展示RAG(检索增强生成)方法的有效性,我们手搓一套RAG的流程进行演示,作为后续LangChain等技术的预热。本文编程实践的目的是展示RAG的工作原理及流程(科普为主),不过多关注技术实现的效果和效率,因此如果是奔着代码拿来即用的目的阅读本文的话,那可能不会有什么大的收获。

二、常规的大模型问答

        这里直接给出本文的示例Query:

“请告诉我,花花是一个怎么样的人”

        下面,调用gpt-3.5-turbo大模型回答这个问题。我们使用openai的大模型接口,在这个过程中需要用到你个人的api_key等信息:

import openai# 可以去openai官网或者国内某些镜像网站注册一个
openai.api_key = "你的api key"
openai.api_base = "你的api base"
query = '请告诉我,花花是一个怎么样的人'
chat_completion = openai.ChatCompletion.create(model="gpt-3.5-turbo",messages=[{"role": "user", "content": query}])
response = chat_completion.choices[0].message.content
print(response)

        下面是大模型的回答,很明显,大模型也没办法在没有任何背景知识的情况下回答这个问题:

三、基于RAG的大模型问答

1、知识库构建

        首先,我们需要有一个存储着各类信息的知识库,里面需要有花花相关的内容。有了基本的知识储备,才能够正确回答问题。这里给出一个简单的知识库示例,其中包含了磊磊、花花、明明三个人各自性格、特长等信息:

dataBase = [
"磊磊是一个充满活力的北京小伙子,性格外向,总是人群中的焦点。他对生活充满了热情,喜欢与人交流,总是能够轻松地与陌生人打成一片。磊磊的运动爱好广泛,尤其擅长篮球和游泳,他经常参加各种体育活动,不仅锻炼了身体,也结交了许多志同道合的朋友。",
"磊磊的特长之一是公共演讲,无论是在学校的辩论赛还是公司的年会上,磊磊总能用他那富有感染力的言辞吸引听众的注意。此外,磊磊还对摄影有着浓厚的兴趣,喜欢捕捉生活中的美好瞬间,他的社交媒体上充满了他拍摄的风景和人物照片。",
"在人际交往方面,磊磊有着广泛的社交圈,他善于倾听,乐于助人,这使得他在朋友中非常受欢迎。磊磊总是能够用他的幽默感和积极态度为周围的人带来正能量。尽管磊磊的朋友众多,但磊磊也非常重视与家人的关系,经常抽时间陪伴家人,享受家庭的温暖。",
"花花是一个温柔而细腻的女孩,她的性格内向,喜欢安静和独处。花花来自江南的一个小镇,那里的宁静和美丽深深地影响了她的性格和审美。花花的爱好是绘画和写作,她喜欢用画笔捕捉自然的美丽,用文字记录内心的感受。",
"花花在社交场合可能显得有些害羞和保守,但她的真诚和善良总能赢得他人的尊重和喜爱。她更倾向于深度交流而非表面的寒暄,这使得她的友谊往往更加长久和稳固。在业余时间,花花喜欢阅读和研究心理学,这不仅帮助她更好地理解自己,也让她在与人交往时更加敏感和体贴。尽管她不常成为聚会的中心,但花花的存在总能为周围的人带来一份宁静和安慰。",
"明明,一个性格外向的年轻人,总是带着阳光般的笑容,他的热情和活力很容易感染周围的人。他出生在繁华的上海,这个城市的快节奏和多元文化塑造了他开朗和包容的性格。",
"明明的爱好多种多样,他特别喜欢户外运动,如徒步旅行和自行车骑行,这些活动不仅让他保持了健康的体魄,也让他有机会结识来自不同背景的朋友。明明还是各种社交活动的常客,无论是公司的团队建设还是朋友间的聚会,他总能成为调动气氛的关键人物。",
"在工作之余,明明也热衷于公益事业,他经常参与志愿者活动,帮助那些需要帮助的人。明明的这种乐于助人的精神,让他在社区中也赢得了良好的声誉。"
]

2、知识检索

        我们的示例知识库规模很小,但是实际业务过程中,数据的规模可能非常大,我们不可能把整个知识库同时作为prompt输入给大模型。那一个基本的方案就是去检索跟Query相关的知识来辅助大模型理解,例如我们可以通过计算余弦相似度的方式来选择跟Query最相似的Top N条知识,然后合并这些知识到Prompt中。

        由于我们这是一个简易版RAG,秉着简易的原则,我们在这里使用Word2Vec进行文本的向量化。这里,Word2Vec模型的训练语料就是dataBase,完成训练之后直接对dataBase中的每一句话进行向量化(Word2Vec句向量由所有词向量按位取平均所得)。

from gensim.models import Word2Vec
import numpy as np
import jiebatexts_cut = [list(jieba.cut(text)) for text in dataBase]
model = Word2Vec(sentences=texts_cut, vector_size=100, window=10, min_count=1, sg=1, epochs=100)
sentence_vectors = []
for sentence in texts_cut:vector = np.mean([model.wv[word] for word in sentence if word in model.wv], axis=0)sentence_vectors.append(vector)

        现在,我们已经实现了知识库的向量化,接下来就是检索Query与知识库中的每一条知识的相似度了。这里我们直接使用Word2Vec对Query进行向量化,并比对Query向量和知识向量表示的相似度,由于数据量不大,这里直接使用for循环。

from scipy.spatial import distancequery_emb = np.mean([model.wv[word] for word in list(jieba.cut('请告诉我,花花是一个怎么样的人')) if word in model.wv], axis=0)
most_relative = -1
max_sims = -1
for idx, vec in enumerate(sentence_vectors):cosine_similarity = 1 - distance.cosine(query_emb, vec)print("向量ID:{}, 余弦相似度:{}".format(idx, cosine_similarity))if cosine_similarity>max_sims:max_sims = cosine_similaritymost_relative = idx

      结果如下:

        由于知识库数据量太小,这里我们只选择Top 1最相关的知识。可以看到,最相似的为ID为3的知识表示,对应文本为:

        “花花是一个温柔而细腻的女孩,她的性格内向,喜欢安静和独处。花花来自江南的一个小镇,那里的宁静和美丽深深地影响了她的性格和审美。花花的爱好是绘画和写作,她喜欢用画笔捕捉自然的美丽,用文字记录内心的感受。”

3、大模型问答

        我们把上述文本加入到prompt中并让大模型回答我们的问题:

query = '请告诉我,花花是一个怎么样的人。'
prompt = f"以下是一些相关的可用信息:{dataBase[most_relative]}"
chat_completion = openai.ChatCompletion.create(model="gpt-3.5-turbo",messages=[{"role": "user", "content": query+prompt}])
response = chat_completion.choices[0].message.content
print(response)

        结果如下,是否优雅了许多?

四、完整代码

import openai
from gensim.models import Word2Vec
import numpy as np
import jieba
from scipy.spatial import distance# api配置
openai.api_key = "你的api key"
openai.api_base = "你的api base"dataBase = [
"磊磊是一个充满活力的北京小伙子,性格外向,总是人群中的焦点。他对生活充满了热情,喜欢与人交流,总是能够轻松地与陌生人打成一片。磊磊的运动爱好广泛,尤其擅长篮球和游泳,他经常参加各种体育活动,不仅锻炼了身体,也结交了许多志同道合的朋友。",
"磊磊的特长之一是公共演讲,无论是在学校的辩论赛还是公司的年会上,磊磊总能用他那富有感染力的言辞吸引听众的注意。此外,磊磊还对摄影有着浓厚的兴趣,喜欢捕捉生活中的美好瞬间,他的社交媒体上充满了他拍摄的风景和人物照片。",
"在人际交往方面,磊磊有着广泛的社交圈,他善于倾听,乐于助人,这使得他在朋友中非常受欢迎。磊磊总是能够用他的幽默感和积极态度为周围的人带来正能量。尽管磊磊的朋友众多,但磊磊也非常重视与家人的关系,经常抽时间陪伴家人,享受家庭的温暖。",
"花花是一个温柔而细腻的女孩,她的性格内向,喜欢安静和独处。花花来自江南的一个小镇,那里的宁静和美丽深深地影响了她的性格和审美。花花的爱好是绘画和写作,她喜欢用画笔捕捉自然的美丽,用文字记录内心的感受。",
"花花在社交场合可能显得有些害羞和保守,但她的真诚和善良总能赢得他人的尊重和喜爱。她更倾向于深度交流而非表面的寒暄,这使得她的友谊往往更加长久和稳固。在业余时间,花花喜欢阅读和研究心理学,这不仅帮助她更好地理解自己,也让她在与人交往时更加敏感和体贴。尽管她不常成为聚会的中心,但花花的存在总能为周围的人带来一份宁静和安慰。",
"明明,一个性格外向的年轻人,总是带着阳光般的笑容,他的热情和活力很容易感染周围的人。他出生在繁华的上海,这个城市的快节奏和多元文化塑造了他开朗和包容的性格。",
"明明的爱好多种多样,他特别喜欢户外运动,如徒步旅行和自行车骑行,这些活动不仅让他保持了健康的体魄,也让他有机会结识来自不同背景的朋友。明明还是各种社交活动的常客,无论是公司的团队建设还是朋友间的聚会,他总能成为调动气氛的关键人物。",
"在工作之余,明明也热衷于公益事业,他经常参与志愿者活动,帮助那些需要帮助的人。明明的这种乐于助人的精神,让他在社区中也赢得了良好的声誉。"
]# 知识库文本向量化
texts_cut = [list(jieba.cut(text)) for text in dataBase]
model = Word2Vec(sentences=texts_cut, vector_size=100, window=10, min_count=1, sg=1, epochs=100)
sentence_vectors = []
for sentence in texts_cut:vector = np.mean([model.wv[word] for word in sentence if word in model.wv], axis=0)sentence_vectors.append(vector)
print(sentence_vectors)# query
query = '请告诉我,花花是一个怎么样的人。'# 余弦相似度匹配/知识检索
query_emb = np.mean([model.wv[word] for word in list(jieba.cut(query)) if word in model.wv], axis=0)
most_relative = -1
max_sims = -1
for idx, vec in enumerate(sentence_vectors):cosine_similarity = 1 - distance.cosine(query_emb, vec)print("向量ID:{}, 余弦相似度:{}".format(idx, cosine_similarity))if cosine_similarity>max_sims:max_sims = cosine_similaritymost_relative = idx# 结合知识库知识的大模型问答
prompt = f"以下是一些相关的可用信息:{dataBase[most_relative]}"
chat_completion = openai.ChatCompletion.create(model="gpt-3.5-turbo",messages=[{"role": "user", "content": query+prompt}])
response = chat_completion.choices[0].message.content
print(response)

五、总结

        本文使用极其简单的流程实现了一个简易版RAG。可见,结合RAG技术,大模型能够轻松回答原先无法回答的一些需要知识背景的问题。RAG的概念非常简单,但是它对于提升大模型的表现却非常有效。本文只是进行了一个科普性质的讲解,后续将会详细介绍RAG技术的实现。毕竟,实际业务知识库的规模可能达到了大数据的量级,因此必然无法直接逐条知识和Query比较相似度,这使得我们需要进行一些必要的检索优化;另外,将知识文本添加到Prompt中的方式也较为原始,实际上有更加高效的知识应用策略;最后,RAG的链路也早就有诸如LangChain等开源解决方案帮助我们进行开发了,无需人工重复造轮子。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com