汕头站扩建,免费的个人简历模板 简约,做网站多少钱 网络服务,台州网站建设维护检索增强生成(Retrieval-augmented generation#xff0c;RAG)使得我们可以让大型语言模型(LLMs)访问外部知识库数据(如pdf,word、text等)#xff0c;从而让人们可以更加方便的通过LLM来学习外部数据的知识。今天我们将利用之前学习到的RAG方法#xff0c;谷歌Gemini模型和l… 
检索增强生成(Retrieval-augmented generationRAG)使得我们可以让大型语言模型(LLMs)访问外部知识库数据(如pdf,word、text等)从而让人们可以更加方便的通过LLM来学习外部数据的知识。今天我们将利用之前学习到的RAG方法谷歌Gemini模型和langchain框架来快速开发一个能够和pdf文件对话的机器人之所以要选择Gemini模型是因为它的API目前是免费调用的而OpenAI的API则是要收费的而我没有那么多银子所以只能选择免费的。 
一、什么是检索增强生成 (Retrieval-augmented generationRAG) 
检索增强生成 (RAG) 是一种使用来自私有或专有数据源的信息来辅助文本生成的技术。 它将检索模型设计用于搜索大型数据集或知识库和生成模型例如 大型语言模型 (LLM) 此类模型会使用检索到的信息生成可供阅读的文本回复结合在一起。一个基本的RAG检索过程主要包含以下这些步骤 一个典型的RAG系统一般包含两个主要的部件 
检索器组件根据用户问题从外部数据源(如pdf,word,text等)检索相关信息并提供给LLM 以便回答用户问题。生成器组件LLM根据检索到的相关信息生成正确的、完整的对用户友好的答案。 
我之前写过一系列的关于使用langchain与文档对话的博客如果想详细了解RAG的基本过程可以先看一下我写的这些博客。 
在本次的与PDF文档对话的系统中我们使用的检索器组件是基于Langchain框架的父文档检索器如果对它还不熟悉朋友可以先看一下我之前写的父文档检索器这篇博客至于生成器组件我们使用的是基于谷歌的Gemini大模型。对于如何开发一个基于web页面的聊天机器人程序还不熟悉的朋友可以查看我之前写的使用python快速开发各种聊天机器人应用这篇博客以便可以快速上手开发机器人应用程序。对谷歌gemini模型还不熟悉的朋友可以查看我之前写的谷歌Gemini API 应用(一)基础应用这篇博客以便可以快速了解Gemini API的使用方法。 
在本文的最后我会给大家分享完整的代码大家可以在此基础上不断的完善代码开发出符合你们自己需求的机器人。 
一环境配置 
这里我们主要使用的是panel和langchain这两个python包 
pip install google-generativeai
pip install panel
pip install langchain
pip install chroma 
如果在安装过程中报错请根据报错信息安装其他必要的python包。 
二、组件介绍 
这里我们会使用谷歌Gemini模型组件以及基于langchain的检索器组件其中包括文档分割器组件、父文档检索器组件、向量数据库组件、另外我们还需要使用python的web框架组件panel等。下面我们导入这些组件的python包 
import tempfile
import panel as pn
import param
from langchain.document_loaders import PyPDFLoader
from langchain.embeddings import HuggingFaceBgeEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.retrievers import ParentDocumentRetriever
from langchain.storage import InMemoryStore
from langchain.vectorstores import Chroma
from panel_chat_examples import EnvironmentWidgetBase
import google.generativeai as genai 
这里需要说明的是我们使用的LLM是谷歌原生的Gemini模型组件而非由langchain非封装的gemini组件之所以使用谷歌原生组件是因为我发现langchain的gemini组件存在一些bug, 它不能设置谷歌模型的安全策略导致机器人在回答问题的时候经常会报用户问题存在安全性问题的异常这可能是由于目前这个langchain的gemini组件还是早期版本估计后面会完善这些问题。 
三、功能模块介绍 
31. Embedding模型的选择 
如果对Embedding模型还不太熟悉的朋友可以查看我之前写的Embedding模型的选择这篇博客因为本次实验使用的是中文内容的文档所以我还是选择了BAAI的bge-small-zh-v1.5, 如果大家使用的是英文的pdf文档则可以将Embedding模型切换为了BAAI的bge-small-en-v1.5: 
#支持中文的BAAI embedding模型
bge_embeddings  HuggingFaceBgeEmbeddings(model_nameBAAI/bge-small-zh-v1.5,cache_folderD:\\models) 
这里的cache_folder指的是存放Embedding模型的文件夹当首次执行机器人程序的时候系统会自动从HuggingFace的网站下载Embedding模型并将它存放到默认的cache_folder文件夹下(C盘)所以这里我们可以指定cache_folder文件夹的路径把Embedding模型存储在C盘以外的地方。 
3.2 Gemini模型的安全策略 
Gemini模型在回答用户问题的时候有一套严格的关于内容的安全审查机制以防止出现违反道德伦理色情暴力等内容。由于本次实验我使用的PDF文档是阿凡提故事大全.pdf它是一个中文文档,当机器人在回答问题的时候不知为何经常出现内容违规的提示这可能是由于gemini模型的默认安全审查策略的阈值设置的太高引起的因此当我把安全审查策略的阈值调到无以后就不再出现违规提示了: 
generation_config  {temperature: 0.0,top_p: 1,top_k: 1,max_output_tokens: 2048,
}safety_settings  [{category: HARM_CATEGORY_HARASSMENT,threshold: BLOCK_NONE},{category: HARM_CATEGORY_HATE_SPEECH,threshold: BLOCK_NONE},{category: HARM_CATEGORY_SEXUALLY_EXPLICIT,threshold: BLOCK_NONE},{category: HARM_CATEGORY_DANGEROUS_CONTENT,threshold: BLOCK_NONE}] 
这里我们设置了模型参数generation_config 和安全策略参数safety_settings 在模型参数中我们设置了temperature为0该参数的取值范围为0-1参数值越低llm给出的答案越精准参数值越高给出的答案变化性越大因此为了让llm不要产生多样化的结果我们应尽量调低temperature的值设置为0或0.1都可以。另外我们将所有安全策略的阈值都设置为BLOCK_NONE即不做安全性审查。 
3.3父文档检索器 
如果对langchain的父文档检索器策略还不熟悉的朋友可以先看一下我之前写的父文档检索器这篇博客下面是我们在panel中定义父文档检索器的一些组件 
#加载文档
pn.cache(ttlTTL)
def _get_docs(pdf):# load documentswith tempfile.NamedTemporaryFile(wb, deleteFalse) as f:f.write(pdf)file_name  f.nameloader  PyPDFLoader(file_name)docs  loader.load()return docs#创建父文档切割器
pn.cache(ttlTTL)
def _get_parent_splitter():return RecursiveCharacterTextSplitter(chunk_size1000)
#创建子文档切割器
pn.cache(ttlTTL)
def _get_child_splitter():return RecursiveCharacterTextSplitter(chunk_size400)
#创建内存存储组件
pn.cache(ttlTTL)
def _get_MemoryStore():return InMemoryStore()
#创建向量数据库   
pn.cache(ttlTTL)
def _get_vector_db():        vectorstore  Chroma(collection_namesplit_parents, embedding_function  bge_embeddings)return vectorstore
#创建父文档检索器
pn.cache(ttlTTL)
def _get_retriever(pdf, number_of_chunks: int):docs_get_docs(pdf)vectorstore _get_vector_db()store_get_MemoryStore()child_splitter_get_child_splitter()parent_splitter_get_parent_splitter()#创建父文档检索器retriever  ParentDocumentRetriever(vectorstorevectorstore,docstorestore,child_splitterchild_splitter,parent_splitterparent_splitter,search_kwargs{k: number_of_chunks})#添加文档集retriever.add_documents(docs)return retriever 
3.4创建gemini模型对象 
下面是在panel中定义gemini模型对象和模型生成内容的方法 
#创建gemini模型对象
pn.cache(ttlTTL)
def _get_model():#创建gemini modelmodel  genai.GenerativeModel(model_namegemini-pro,generation_configgeneration_config,safety_settingssafety_settings)return modeldef _get_response(contents):retriever_get_retriever(state.pdf, state.number_of_chunks)model_get_model()relevant_docsretriever.get_relevant_documents(contents)contexts\n\n.join([w.page_content for w in relevant_docs])#prompt模板template  f请根据下面给出的上下文来回答下面的问题,并给出完整的答案:
上下文:{contexts}问题: {contents}
response  model.generate_content(template)chunks  []for chunk in relevant_docs:name  fChunk {chunk.metadata[page]}content  chunk.page_contentchunks.insert(0, (name, content))return response.text, chunks 
3.5创建panel页面组件 
这里我们还需要创建panel的页面组件和设置环境变量等全局变量以便设置谷歌的api_key和callback函数这里我们我们仍然使用的是panel的chat_interface作为我们的页面聊天组件对应panel还不熟悉的朋友可以查看我之前写的使用python快速开发各种聊天机器人应用以及panel的官方文档 
# 定义应用程序全局变量
class EnvironmentWidget(EnvironmentWidgetBase):GOOGLE_API_KEY: str  param.String()class State(param.Parameterized):pdf: bytes  param.Bytes()number_of_chunks: int  param.Integer(default2, bounds(1, 5), step1)environ  EnvironmentWidget()
state  State()# 定义页面组件
pdf_input  pn.widgets.FileInput.from_param(state.param.pdf, accept.pdf, height50)
text_input  pn.widgets.TextInput(placeholderFirst, upload a PDF!)# 定义和配置 panel ChatInterface
def _get_validation_message():pdf  state.pdfgoogle_api_key  environ.GOOGLE_API_KEYif not pdf and not google_api_key:return 请在左侧侧边栏中输入谷歌api key 然后上传PDF文件!if not pdf:return 请先上传pdf 文件if not google_api_key:return 请先输入谷歌api keygenai.configure(api_keygoogle_api_key,transportrest)return def _send_not_ready_message(chat_interface) - bool:message  _get_validation_message()if message:chat_interface.send({user: System, object: message}, respondFalse)return bool(message)async def respond(contents, user, chat_interface):if _send_not_ready_message(chat_interface):returnif chat_interface.active  0:chat_interface.active  1chat_interface.active_widget.placeholder  在这里输入您的问题!yield {user: Gemini, object: 现在可以开始和pdf对话了}returnresponse, documents  _get_response(contents)pages_layout  pn.Accordion(*documents, sizing_modestretch_width, max_width800)answers  pn.Column(response, pages_layout)yield {user: Gemini, object: answers}chat_interface  pn.chat.ChatInterface(callbackrespond,sizing_modestretch_width,widgets[pdf_input, text_input],disabledTrue,
)pn.depends(state.param.pdf, environ.param.GOOGLE_API_KEY, watchTrue)
def _enable_chat_interface(pdf, google_api_key):if pdf and google_api_key:chat_interface.disabled  Falseelse:chat_interface.disabled  True_send_not_ready_message(chat_interface)## Wrap the app in a nice templatetemplate  pn.template.BootstrapTemplate(titlePDF文档对话机器人,sidebar[environ,state.param.number_of_chunks],main[chat_interface],
)
template.servable() 
四、机器人使用方法介绍 
我们需要在命令行窗口中执行机器人的源代码程序 
panel serve gemini_pdf_bot.py 在浏览器中打开访问机器人的链接 完成输入谷歌api key和上传pdf文件以后就可以开始和机器人聊天了 五、总结 
今天我们主要介绍了如何开发一个简单的RAG系统:基于pdf文档问答的机器人应用其中我们应用了langchain的父文档检索策略panel的页面聊天组件chat_interface以及谷歌的Gemini大模型。希望今天的内容对大家学习RAG和聊天机器人程序有所帮助。 
六、完整代码 
链接https://pan.baidu.com/s/1w6MzGDflLF7N3-NlENKj8w 提取码tllt