首页 > 编程语言 >python实战(七)——基于LangChain的RAG实践

python实战(七)——基于LangChain的RAG实践

时间:2024-11-10 10:45:20浏览次数:3  
标签:RAG prompt python text langchain LangChain template pdf import

一、任务目标

        基于之前的RAG实战,相信大家对RAG的实现已经有了一定的了解了。这篇文章将使用LangChain作为辅助,实现一个高效、便于维护的RAG程序。

二、什么是LangChain

        LangChain是一个用于构建大模型应用程序的开源框架,它内置了多个模块化组件。通过这些组件,我们能够快速且便捷地搭建一个强大的大模型应用程序。首先,我们来看一下如何通过LangChain来调用大语言模型:

from langchain_community.chat_models.openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
import os


API_SECRET_KEY = "your api key"
BASE_URL = "your api base"
os.environ["OPENAI_API_KEY"] = API_SECRET_KEY
os.environ["OPENAI_API_BASE"] = BASE_URL


# 这里的temperature参数控制答案生成的随机性,0表示按照概率最大的结果生成,也就是最稳定
# 如果温度设置为1则表示生成极富随机性的结果
# 由于我们没有指定调用哪个openai模型,默认会是gpt-3.5-turbo
chat = ChatOpenAI(temperature=0.0)

# 定义template字符串,这里不需要使用f字符串来赋值
template = """请将下面的中文文本翻译为{language}。\
文本:'''{text}'''
"""

# 将template字符串转换为langchain模板,这时候会自动识别prompt模板需要的参数,即{}中的内容
prompt_template = ChatPromptTemplate.from_template(template)

customer_language = '英文'
customer_text = '你好,我来自中国。'

# 传入相应字符串生成符合大模型输入要求的prompt
customer_messages = prompt_template.format_messages(language=customer_language, text=customer_text)
print(customer_messages[0])

# 调用大语言模型
customer_response = chat.invoke(customer_messages, temperature=0.0)
print(customer_response.content)

        相比起我们直接使用openai库调用大模型的方式,LangChain库调用大语言模型要更加结构化和模块化,尤其是prompt模板的构建部分。这样做的好处是,我们可以很方便地进行程序的复用。另外,LangChain内置了多个常用场景的Prompt模板,可以拿来即用,省去了我们重新设计和构造prompt的时间。

三、RAG流程构建

1、文档加载

        LangChain支持多种文档格式的加载,比如doc、pdf、markdown甚至html等。这里,我们加载几个pdf文档(文档中的内容是调用大模型生成的关于各个西游记主角的人物特征):

from langchain_community.document_loaders.pdf import PyPDFLoader

# 这里会逐页加载文档
loaders = [PyPDFLoader('孙悟空.pdf'), PyPDFLoader('猪八戒.pdf'), PyPDFLoader('沙和尚.pdf'), PyPDFLoader('唐僧.pdf')]
docs = []
for loader in loaders:
    pages = loader.load()
    # 打印pages的元素个数
    print(len(pages))
    # 打印第一个元素,也就是第一页的一部分文字看看
    print(pages[0].page_content[:10])
    # 打印第一个元素的元数据
    print(pages[0].metadata)
    docs.extend(pages)

2、文档分割

        加载后的文档可能很大,我们需要将文档分割成一个一个的小块进行存储。在进行检索的时候,也能够直接返回相关的文档块,而不需要整个文档都传给大模型。LangChain提供字符级别的文档分隔、token级别的文档分隔等多个工具。这里我们使用字符分割:

from langchain.text_splitter import RecursiveCharacterTextSplitter

# chunk_size用于设置每个文本块的大小,chunk_overlap用于设置每个文本块直接的重叠部分大小
text_splitter = RecursiveCharacterTextSplitter(chunk_size=50, chunk_overlap=10)
blocks = text_splitter.split_documents(docs)

3、文本向量化存储

        为了便于后续使用,我们把文本转化成向量并存储到本地。向量化的意义在于可以很方便地比较文本相似度,从而检索出与query相关的信息返回给大模型。

from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma

# 定义向量化工具
embedding_model = OpenAIEmbeddings(model='text-embedding-3-small')

directory = './save_folder'
# Chroma是一个轻量级的向量存储库,langchain提供了数十个向量存储库,这里我们使用高效的Chroma
vectordb = Chroma.from_documents(
    documents=blocks,
    embedding=embedding_model,
    persist_directory=directory
)
# 永久化存储
vectordb.persist()

# 打印文本向量数
print('文本向量数:', vectordb._collection.count())

# 可以进行相似性检索,k指定返回结果数量
query = '请介绍一下唐僧的性格特点'
search_results = vectordb.similarity_search(query, k=3)
print('相似文本示例:', search_results[0])

        这里,我们使用了similarity_search方法检索相关的文本向量,这是纯相似度比较的方式,返回结果将高度相关,但也会减少多样性。如果希望在查询的相关性和多样性之间保持平衡,也可以使用max_marginal_relevance_search方法进行向量检索

4、问答

        这里,我们构造一个检索式问答链,并让程序返回它所用到的检索结果:

from langchain_community.chat_models import ChatOpenAI
from langchain.chains.retrieval_qa.base import RetrievalQA
from langchain.prompts import PromptTemplate

llm = ChatOpenAI(model_name='gpt-3.5-turbo', temperature=0.0)
template = '请根据上下文回答以下问题。上下文:{context},问题:{question}'
qa_prompt = PromptTemplate.from_template(template)

qa_chain = RetrievalQA.from_chain_type(
    llm,
    retriever=vectordb.as_retriever(),
    return_source_documents=True,
    chain_type_kwargs={'prompt':qa_prompt}
)

question = '请介绍一下唐僧的性格特点'
response = qa_chain({'query':question})
# 打印模型响应
print(response['result'])
# 打印第一个相关的检索结果
print(response['source_documents'][0])

        上面的代码中,{context}是检索结果,{question}是指我们的提问,这两个变量不可缺少,变量命名和相对位置也应当与上面一致,至于放置的绝对位置则无特别要求

四、完整代码

        代码运行过程中如果存在报错是因为一些依赖库没有安装,pip install就可以了。如果是无报错退出且状态码是00005结尾的,那么应该是Chroma读取内存数据的时候报错了,persist存储到本地之后,使用Chroma(persist_directory='你的存储地址', embedding_function='初始化之后的embedding模型')即可正常运行。

from langchain_community.document_loaders.pdf import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.chat_models import ChatOpenAI
from langchain.chains.retrieval_qa.base import RetrievalQA
from langchain.prompts import PromptTemplate
import os


API_SECRET_KEY = "your api key"
BASE_URL = "your api base"
os.environ["OPENAI_API_KEY"] = API_SECRET_KEY
os.environ["OPENAI_API_BASE"] = BASE_URL


# 这里会逐页加载文档
loaders = [PyPDFLoader('孙悟空.pdf'), PyPDFLoader('猪八戒.pdf'), PyPDFLoader('沙和尚.pdf'), PyPDFLoader('唐僧.pdf')]
docs = []
for loader in loaders:
    pages = loader.load()
    docs.extend(pages)

# chunk_size用于设置每个文本块的大小,chunk_overlap用于设置每个文本块直接的重叠部分大小
text_splitter = RecursiveCharacterTextSplitter(chunk_size=50, chunk_overlap=10)
blocks = text_splitter.split_documents(docs)

# 定义向量化工具
embedding_model = OpenAIEmbeddings(model='text-embedding-3-small')
directory = 'save_folder'
# Chroma是一个轻量级的向量存储库,langchain提供了数十个向量存储库,这里我们使用高效的Chroma
vectordb = Chroma.from_documents(
    documents=blocks,
    embedding=embedding_model,
    persist_directory=directory
)
# 永久化存储
vectordb.persist()

# 指定模型
llm = ChatOpenAI(model_name='gpt-3.5-turbo', temperature=0.0)
# 构建模板
template = '请根据上下文回答以下问题。上下文:{context},问题:{question}'
qa_prompt = PromptTemplate.from_template(template)

# 构建检索式问答链
qa_chain = RetrievalQA.from_chain_type(
    llm,
    retriever=vectordb.as_retriever(),
    return_source_documents=True,
    chain_type_kwargs={'prompt':qa_prompt}
)

quest = '请介绍一下唐僧的性格特点'
response = qa_chain({'query':quest})
# 打印模型响应
print('模型响应:', response['result'])
# 打印第一个相关的检索结果
print('第一个相关的检索结果:', response['source_documents'][0])

五、总结

        本文实现了基于LangChain的RAG问答助手程序,但是其中仍然有许多值得打磨的细节,例如目前的问答助手只能支持一问一答的互动形式,如果需要基于历史聊天记录进行问答,则需要使用LangChain中其他的模块化工具进行聊天记录的存储和调用,这些内容将在后续的博文中讨论。

标签:RAG,prompt,python,text,langchain,LangChain,template,pdf,import
From: https://blog.csdn.net/ChaneMo/article/details/143568524

相关文章

  • 综合能源系统分析的统一能路理论(三):《稳态与动态潮流计算》(Python代码实现)
     ......
  • Google Earth Engine Python——PyGEE-SWToolbox地表水分析工具箱
    目录简介功能安装使用方法代码引用BibTeXifrequired:致谢简介一个用于使用GoogleEarthEngine进行交互式地表水映射和分析的PythonJupyter笔记本工具箱        PyGEE-SWToolbox是一个Python-GoogleEarthEngine(GEE)地表水分析工具箱,开发于Jupyter......
  • 100种算法【Python版】第60篇——滤波算法之粒子滤波
    本文目录1算法步骤2算法示例:多目标跟踪3算法应用:多维非线性系统状态模拟粒子滤波(ParticleFilter)是一种基于随机采样的贝叶斯滤波方法,广泛应用于动态系统的状态估计。它通过在状态空间中使用一组随机粒子(样本)来表示后验分布,从而处理非线性和非高斯的状态估计问......
  • 【PAT_Python解】1120 买地攻略
    原题链接:PTA|程序设计类实验辅助教学平台Tips:以下Python代码仅个人理解,非最优算法,仅供参考!多学习其他大佬的AC代码!defcount_purchase_options(N,M,prices):start=0current_sum=0total_count=0forendinrange(N):current_sum+=......
  • 【PAT_Python解】1115 裁判机
    原题链接:PTA|程序设计类实验辅助教学平台Tips:以下Python代码仅个人理解,非最优算法,仅供参考!多学习其他大佬的AC代码!测试点5:passd有9994个不同的有效数值测试点6:is_given有157386个不同的差值AC代码:importsysdefis_pass(num,is_given,passed_numbers,passed_en......
  • 计算机毕业设计Python+大模型动漫推荐系统 动漫视频推荐系统 机器学习 协同过滤推荐算
    作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待与各位高校教师、企业......
  • 计算机毕业设计Python+大模型农产品价格预测 ARIMA自回归模型 农产品可视化 农产品爬
    作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待与各位高校教师、企业......
  • [LeetCode] 1343. Number of Sub-arrays of Size K and Average Greater than or Equa
    Givenanarrayofintegersarrandtwointegerskandthreshold,returnthenumberofsub-arraysofsizekandaveragegreaterthanorequaltothreshold.Example1:Input:arr=[2,2,2,2,5,5,5,8],k=3,threshold=4Output:3Explanation:Sub-arrays[2......
  • jsonargparse python cli 开发库
    jsonargparse是一个pythoncli库,尽管不如其他库火(click)目前Lightningcli就使用了此库包含的特性自动创建cli类似Fire,typer,Clize以及Tyro支持类型校验支持通过配置文件或者环境变量的配置解析(集成confuse,configargparse,dynaconf,omegaconf)dataclass支持说明jsonargpa......
  • 华为OD机试2024年E卷-MVP争夺战[100分]( Java | Python3 | C++ | C语言 | JsNode | Go
    题目描述在星球争霸篮球赛对抗赛中,最大的宇宙战队希望每个人都能拿到MVP,MVP的条件是单场最高分得分获得者。可以并列所以宇宙战队决定在比赛中尽可能让更多队员上场,并且让所有得分的选手得分都相同,然而比赛过程中的每1分钟的得分都只能由某一个人包揽。输入描述输入第一行......