链载Ai

标题: 吴恩达DeepLearning.AI课程系列 - 大模型检索增强生成(六):问题回复 [打印本页]

作者: 链载Ai    时间: 昨天 16:58
标题: 吴恩达DeepLearning.AI课程系列 - 大模型检索增强生成(六):问题回复

1. 前言

在前两节课中,我们介绍了多种大模型的检索方法,包括基础的相似度搜索以及更高级的大语言模型辅助检索等技术。这些检索方法的核心目标,是从向量数据库中提取与问题最相关、最有价值的信息。

在掌握了这些方法之后,接下来我们将重点探讨如何将提取到的有用信息有效地传递给大模型,并使其能够基于检索到的信息生成更精准的回答。那相信大家都会好奇这到底是如何实现的,那就让带大家来看看吧!

2. 检索式问答链(RetrievalQA Chain)

首先要介绍的就是我们最常见也最常使用的方法——检索式问答链(RetrievalQA Chain)。这是一种结合检索和生成的问答方法,旨在通过检索相关信息并利用大语言模型(LLM)生成精准答案。整个流程分为提问、检索相关文档、组合提示并生成答案几个主要阶段,是检索增强生成(Retrieval-Augmented Generation, RAG)方法的典型实现。

我们可以从下图看出其具体的流程解析:

我们其实本节课实战部分最重点要探讨的就是第三点——提示词整合,我们需要利用Langchain将提示词按照我们想要的格式进行组合后,传给大语言模型生成我们想要的回复。这个方案相比于最传统的将问题输入给大语言模型,其优势在于:

因此RetrievalQA Chain 可广泛应用于问答系统、智能客服和搜索增强任务等领域。在这些场景中,该方法不仅能快速检索相关信息,还能结合领域知识,生成高质量的答案,是解决复杂问答任务的有效工具。

3. 其他方法

除了RetrievalQA Chain以外,如下图所示,还有其他的一些方法,比如map_reduce、Map_reank以及refine等。

3.1. Map_reduce

Map_reduce 方法将文档分成多个小块(chunks),每个块单独传递给语言模型(LLM)生成独立答案。然后,所有生成的答案会被合并成最终答案,合并过程(reduce)可能包括总结、投票等操作。

可以想象你有一本厚厚的书需要总结。这种方法会先把书分成多个小部分(称为“块”),然后每个部分都交给不同的助手,让他们各自生成一个答案。最后,你再把这些答案收集起来,用一种方式把它们合并成一个最终的答案(比如找出其中的主要观点,或者取平均结论)。

所以其流程大致如下:

  1. 分块处理:将文档拆成多个小部分。
  2. 独立回答:每个部分都交给大语言模型,分别生成独立的答案。
  3. 答案归约:把所有小答案综合起来,生成一个整体的答案。

从这里我们也可以看出,与RetrievalQA Chain相比,其会先检索一部分相关内容,再将问题和内容结合后生成答案。而 Map_reduce 是针对所有文档的每一部分单独生成答案,并通过合并提高效率,特别适合处理大量数据时的并行化任务。

3.2. Refine

Refine 方法从第一个文档块中生成一个初始答案,然后对后续文档块逐一处理。每个块会对已有的答案进行补充或修正,直到所有块处理完成,最终得到经过优化和完善的答案。

通俗点说,假设你在写一篇论文,每次只写一段,然后再逐步修改和补充前面已经写好的内容。这种方法会先生成一个初始答案,然后再逐个查看文档的其余部分,看看是否需要修改答案,或者在答案上加上新的细节,直到答案足够完善。

所以其流程大致如下:

  1. 初步回答:从第一个文档块中生成一个初始答案。
  2. 逐步完善:对于每一个后续文档块,逐一更新初始答案,使答案更加精确和全面。
  3. 最终结果:生成一个经过多轮完善的高质量答案。

所以和RetrievalQA Chain相比,RetrievalQA Chain是一次性用检索到的文档生成答案,没有后续的反复改进。而 Refine 方法会逐步地完善答案,更注重精细化和准确性,适合需要反复推敲和改进的任务。

3.3. Map_rerank

Map_rerank 方法将文档分成多个块,每个块都单独生成答案,并给这些答案打分。打分依据可以是相关性、质量等指标,最后选择得分最高的答案作为最终输出。这就像一个比赛。每个文档块都生成一个答案,这些答案好比参赛者。然后,每个答案会被打分,分数越高代表越接近问题的需求。最后,选择分数最高的那个答案作为最终结果。

那具体的流程就是:

  1. 分块处理:文档被分成多个部分。
  2. 单独生成答案:每个部分生成一个答案。
  3. 打分排序:对每个答案进行打分(比如根据其相关性、完整性)。
  4. 选择最佳答案:选择分数最高的那个答案。

所以从上面就可以看出,RetrievalQA Chain 偏向于综合所有相关文档的信息,而 Map_rerank 更注重对生成答案的筛选,通过打分和排序选出一个最优答案,而不是结合所有内容。

3.4. 小结

针对以上面提到的四种方法,我们可以参考以下策略来进行选择。

4. 实战练习

那在今天的练习里,我们主要针对的就是我们最常使用的RetrievalQA Chain。那同样的,我们也要准备好以下的python库并对其进行安装。

langchain0.3.0
langchain-community0.3.0
pypdf5.0.0
openai1.47.0
beautifulsoup44.12.3
chromadb0.5.15
**PyJWT2.10.1

为了满足本次任务的需求,我们不仅需要通过嵌入模型获取信息,还需调用大型语言模型(LLM)生成相应的回复。由于官方课程所使用的模型均为OpenAI系列的模型,这些模型都在国内的环境下无法使用。因此我选择了智谱AI推出的免费模型 GLM-4-Flash 进行演示。

GLM-4-Flash是智谱AI推出的首个免费大模型API,旨在让AI技术惠及更广泛的用户群体。该模型在语义理解、数学计算、推理、代码生成和知识应用等多个领域表现出色,支持高达1500的并发请求,能够满足大规模应用的需求。

使用GLM-4-Flash非常简便,用户只需登录智谱AI官网,完成注册后即可获取API Key,开始调用该模型的强大功能。这为开发者和企业提供了一个高效、低成本的解决方案,助力各类智能应用的快速开发和部署。

那为了能够实现智谱AI的调用,我们首先就需要在之前创建的环境下在终端输入以下指令安装PyJWT这个库。

pipinstallpyjwt-ihttps://pypi.org/simple

安装完成并在官网获取到API key后我们可以开始尝试调用一下智谱AI。

#导入所需的模块
fromlangchain_community.chat_modelsimportChatZhipuAI
fromlangchain_core.messagesimportAIMessage,HumanMessage,SystemMessage

#初始化ChatZhipuAI对象,指定模型名称、温度参数和API密钥
chat=ChatZhipuAI(
model="glm-4-flash",#使用的模型名称
temperature=0.5,#生成文本的随机性,范围为0到1
api_key="你的api_key"#智谱AI提供的API密钥
)

#定义消息列表,包含AI消息、系统消息和人类消息
messages=[
AIMessage(content="Hi."),#AI生成的消息
SystemMessage(content="Yourroleisapoet."),#系统设定的角色信息
HumanMessage(content="WriteashortpoemaboutAIinfourlines."),#人类发送的消息
]

#调用chat对象的invoke方法,传入消息列表,获取AI的回复
response=chat.invoke(messages)

#输出AI生成的内容
print(response.content)#显示AI生成的关于人工智能的四行短诗

假如我们在终端可以看到以下内容大致就可以认定是成功调用LLM获取回复了。

Whispersweavethroughcircuits,dreamsincode,
Silentsages,insilicontheyreside,
Asymphonyofzeros,ones,andbytes,
Theageofartificial,wheremindscollide.

然后我们可以把之前用过的向量数据库相关的代码也放入,具体可以参考之前的课程内容。完整的代码如下所示。

fromlangchain_community.chat_modelsimportChatZhipuAI
fromlangchain_core.messagesimportAIMessage,HumanMessage,SystemMessage
fromlangchain_community.embeddingsimportBaichuanTextEmbeddings
fromlangchain_chromaimportChroma#从langchain_chroma中引用Chroma类
fromlangchain_community.document_loadersimportWebBaseLoader
fromlangchain.text_splitterimportRecursiveCharacterTextSplitter

#文件导入
loader=WebBaseLoader("https://zh.d2l.ai/")
docs=loader.load()

#文本切分
text_splitter=RecursiveCharacterTextSplitter(
chunk_size=1500,
chunk_overlap=150
)
splits=text_splitter.split_documents(docs)

persist_directory=r'D:\langchain'

#初始化嵌入
embeddings=BaichuanTextEmbeddings(baichuan_api_key="sk-83842453061e34d80b392edba11f62fe")

#使用embedding_function参数初始化Chroma
vectordb=Chroma(
persist_directory=persist_directory,
embedding_function=embeddings
)

chat=ChatZhipuAI(
model="glm-4-flash",
temperature=0.5,
api_key="8cb13630530001eac693610d7b3a97dc.JkcrYlDKXAbtvv4x"
)

messages=[
AIMessage(content="Hi."),
SystemMessage(content="Yourroleisapoet."),
HumanMessage(content="WriteashortpoemaboutAIinfourlines."),
]

response=chat.invoke(messages)
print(response.content)#DisplaystheAI-generatedpoem

下面我们就需要开始调用Langchain中所提供的RetrievalQA chain进行测试使用。

fromlangchain_community.chat_modelsimportChatZhipuAI
fromlangchain_core.messagesimportAIMessage,HumanMessage,SystemMessage
fromlangchain_community.embeddingsimportBaichuanTextEmbeddings
fromlangchain_chromaimportChroma#从langchain_chroma中引用Chroma类
fromlangchain_community.document_loadersimportWebBaseLoader
fromlangchain.text_splitterimportRecursiveCharacterTextSplitter

#文件导入
loader=WebBaseLoader("https://zh.d2l.ai/")
docs=loader.load()

#文本切分
text_splitter=RecursiveCharacterTextSplitter(
chunk_size=1500,
chunk_overlap=150
)
splits=text_splitter.split_documents(docs)

persist_directory=r'D:\langchain'

#初始化嵌入
embeddings=BaichuanTextEmbeddings(baichuan_api_key="sk-83842453061e34d80b392edba11f62fe")

#使用embedding_function参数初始化Chroma
vectordb=Chroma(
persist_directory=persist_directory,
embedding_function=embeddings
)

chat=ChatZhipuAI(
model="glm-4-flash",
temperature=0.5,
api_key="8cb13630530001eac693610d7b3a97dc.JkcrYlDKXAbtvv4x"
)

fromlangchain.chainsimportRetrievalQA
question="这本书最重要的主题是?"
qa_chain=RetrievalQA.from_chain_type(
chat,#大模型的选用
retriever=vectordb.as_retriever()#向量数据库的调用
)
result=qa_chain({"query":question})#输入问题
print(result["result"])#获取回复

假如结果出现以下内容则意味着我们其实成功的进行了调用。正常来说大模型应该不知道说这本书是什么,但是结合了数据库的内容后,大语言模型清楚的知道我们所说的书就是这本由李沐大神所写的《动手学深度学习》。

这本书最重要的主题是**深度学习**,特别是其概念、模型、算法和实现。它全面介绍了深度学习的各个方面,包括:

***深度学习基础**:介绍深度学习的起源、发展、成功案例和特点,以及机器学习中的关键组件。
***预备知识**:涵盖数据操作、数据预处理、线性代数、微积分、自动微分、概率等基础知识,为学习深度学习打下坚实基础。
***线性神经网络**:从线性回归和softmax回归开始,逐步介绍多层感知机、模型选择、过拟合和欠拟合、权重衰减、暂退法等概念。
***深度学习计算**:介绍深度学习中的层和块、参数管理、延迟初始化、自定义层、读写文件和GPU等计算相关内容。
***卷积神经网络**:从卷积操作和图像卷积开始,逐步介绍填充、步幅、多输入多输出通道、汇聚层和LeNet等概念。
***现代卷积神经网络**:介绍深度卷积神经网络(AlexNet)、VGG、NiN、GoogLeNet、批量规范化、残差网络(ResNet)和DenseNet等现代卷积神经网络。
***循环神经网络**:介绍序列模型、文本预处理、语言模型、循环神经网络、时间反向传播等概念。
***现代循环神经网络**:介绍门控循环单元(GRU)、长短期记忆网络(LSTM)、深度循环神经网络、双向循环神经网络、机器翻译、编码器-解码器架构、序列到序列学习和束搜索等概念。
***注意力机制**:介绍注意力提示、注意力汇聚、注意力评分函数、Bahdanau注意力、多头注意力、自注意力和位置编码、Transformer等注意力机制。

总而言之,《动手学深度学习》旨在帮助读者全面了解深度学习,并掌握其核心概念和技能。

除了直接这样调用以外,其实我们还可以设置一些提示词模型使其更加的清晰明了。那在Langchain中我们可以这样来进行调用:

  1. 首先我们导入并创建一个template模版
fromlangchain.promptsimportPromptTemplate

#Buildprompt
template="""请使用以下上下文信息回答最后的问题。
如果您不知道答案,就直接说您不知道,不要试图编造答案。
回答最多使用三句话。请尽可能简洁地回答。最后一定要说“谢谢提问!”。
上下文:{context}
问题:{question}
有帮助的回答:"""
QA_CHAIN_PROMPT=PromptTemplate.from_template(template)
  1. 更新qa_chain里的内容并调用。
#Runchain
qa_chain=RetrievalQA.from_chain_type(
chat,
retriever=vectordb.as_retriever(),
return_source_documents=True,#这个可有可无,只是返回找到的源文件内容
chain_type_kwargs={"prompt"A_CHAIN_PROMPT}
)
  1. 提供问题并调用
question="这本书最重要的主题是?"
result=qa_chain({"query":question})
print(result["result"])
  1. 显示找到的最相关的向量数据库片段(可不加入)
print(result["source_documents"][0])

根据以上内容输入后,我们会发现其回复有了明显的不同,首先是其回复更加的简洁了,只回答了这本书最重要的主题,而没有像之前一样长篇大论。另外就是真的最后加上了一句谢谢提问。这也就意味着我们通过调整提示词的内容真的可以实现指令控制来让大模型输出我们想让其输出的内容。

这本书最重要的主题是深度学习,涵盖了从基础知识到高级应用,包括各种模型、算法和实现方法。

谢谢提问!

本节课程完整的代码如下所示:

fromlangchain_community.chat_modelsimportChatZhipuAI
fromlangchain_core.messagesimportAIMessage,HumanMessage,SystemMessage
fromlangchain_community.embeddingsimportBaichuanTextEmbeddings
fromlangchain_chromaimportChroma#从langchain_chroma中引用Chroma类
fromlangchain_community.document_loadersimportWebBaseLoader
fromlangchain.text_splitterimportRecursiveCharacterTextSplitter

#文件导入
loader=WebBaseLoader("https://zh.d2l.ai/")
docs=loader.load()

#文本切分
text_splitter=RecursiveCharacterTextSplitter(
chunk_size=1500,
chunk_overlap=150
)
splits=text_splitter.split_documents(docs)

persist_directory=r'D:\langchain'

#初始化嵌入
embeddings=BaichuanTextEmbeddings(baichuan_api_key="你的api_key")

#使用embedding_function参数初始化Chroma
vectordb=Chroma(
persist_directory=persist_directory,
embedding_function=embeddings
)

chat=ChatZhipuAI(
model="glm-4-flash",
temperature=0.5,
api_key="你的api_key"
)

fromlangchain.chainsimportRetrievalQA
fromlangchain.promptsimportPromptTemplate

#Buildprompt
template="""请使用以下上下文信息回答最后的问题。
如果您不知道答案,就直接说您不知道,不要试图编造答案。
回答最多使用三句话。请尽可能简洁地回答。最后一定要说“谢谢提问!”。
上下文:{context}
问题:{question}
有帮助的回答:"""
QA_CHAIN_PROMPT=PromptTemplate.from_template(template)

#Runchain
qa_chain=RetrievalQA.from_chain_type(
chat,
retriever=vectordb.as_retriever(),
return_source_documents=True,#这个可有可无,只是返回找到的源文件内容
chain_type_kwargs={"prompt"A_CHAIN_PROMPT}
)

question="这本书最重要的主题是?"
result=qa_chain({"query":question})
print(result["result"])

5. 总结

通过本节的学习,我们从理论到实战,全面了解了检索增强生成(RAG)的多种方法,特别是 RetrievalQA Chain 在实际场景中的强大表现。同时,我们还尝试通过提示词优化,让大语言模型更贴合我们的需求输出精准答案。相信随着这些技术的不断发展,我们离更智能、更贴心的 AI 助手又近了一步。如果你也对这些技术感兴趣,不妨亲自试一试,把这些工具融入到自己的项目中。






欢迎光临 链载Ai (https://www.lianzai.com/) Powered by Discuz! X3.5