课堂笔记
1. LLM应用开发范式
通用的大语言模型(Large Language Model,LLM)往往具备比较好的语义理解能力,以此理解能力为基础,可以开发出众多基于LLM的智能应用。在两个月以前,OpenAI宣布GPTs,可以直接使用对话的方式构建一个个性化的GPT,近日OpenAI开放了GPT商店,用户可以分享自己的经过个性化调试以后的GPT,将GPT应用到了多种场景里面。1
LLM的训练过程极其漫长,所以在应用时往往存在知识时效性受限、专业能力有限、个人化定制化成本高的缺点,如何继续扩展已经训练好的模型的能力显得极为重要。目前基于大模型进行应用开发有两种核心范式:检索增强生成(RAG)和模型微调(Finetune)。
RAG是给模型外挂一个知识库,在用户提问时,将知识库和用户提问同时输入给大模型,大模型可以基于知识库完成本次回答;Finetune是使用新数据集对模型参数进行微调,使模型在新的数据集上具备理解能力。RAG优势在于成本低,可以实时更新,但是能力上限由基座模型所决定,外挂知识库会占用大量上下文;Finetune的个性化微调数据覆盖面更广,对于非可见知识,如回答风格的模拟效果非常好,但是需要重新训练,依旧对GPU资源的需求量大,而且无法做到实时更新知识,更新时需要重新微调模型参数。
LangChain是主流的RAG开发框架之一,本次课程介绍如何使用LangChain实现RAG应用。可能内容包括RAG开发的常规流程:使用个人私域数据构建向量数据库;基于LLM大语言模型搭建知识库助手;使用Gradio将知识库助手部署为网页交互界面。
本次课程所展示的知识库助手基于InternLM模型,该模型是上海人工智能实验室开源的大语言模型,能够理解用户自然语言的指令,具有强大的知识储备和逻辑推理能力,可以作为应用开发的基座模型。2
2. RAG开发
2.1 基本原理
RAG的原理是:对于每个用户输入,使用向量模型将其转换为向量,并在向量数据库中匹配相似的文本段(被认为与输入请求相关,包含对应答案),将用户输入和相似文本段一起嵌入到Prompt中,将Prompt传递给LLM,得到模型的回答。
2.2 LangChain开发框架
LangChain是一个为各种LLM提供通用接口,简化应用开发流程的开源工具,LangChain包含各种组件,组件之间的组合可以开发出各种LLM应用,例如将自己的私域数据嵌入到LangChain的组件中,构建适用于相关场景的RAG应用。LangChain最核心的组件是链(Chains):将组件组合实现端到端应用,例如检索问答链覆盖实现RAG的全部流程,可以直接将自己的数据库和大模型引入到检索问答链中,高效搭建自己的RAG应用。
下图是知识助手的检索问答链工作流程,LangChain需要使用SentenceTransformers分别对用户的输入和附加数据库向量化,在向量数据库中可以匹配向量之间的相似度,基于用户输入和相似文本生成Prompt交给InternLM获得回答结果。图片中虚线框内的流程已经封装在LangChain中,基于LangChain构建自己的RAG应用变得更加简单。
2.3 构建向量数据库
实现RAG应用的第一步是构建自己的知识数据库,构建流程包括加载源文件、文档分块和文档向量化。源文件加载的实现过程需要确定文档类型,针对不同的类型选择相对应的加载器,将源数据转化为无格式的字符串。然后对字符串进行分块,避免单个文档超过大模型上下文的上限,一般根据字符串长度进行分割,可以手动控制分割长度和重叠长度,后续的检索将以每个分割块为基本单元。使用Embedding模型将本文数据向量化以支持文本之间的语义匹配,本次课程使用SentenceTransformers作为本文向量化的模型。向量化以后的数据可以组成向量数据库,本次课程使用轻量级的Chroma来组织向量数据库,Chroma是支持语义检索的向量数据库框架。
2.4 搭建知识库助手
LangChain框架支持自定义LLM,部署在本地的InternLM可以被封装为自定义LLM类,然后由LangChain框架调用来构建检索问答链。通过将自定义向量数据库和自定义LLM接入到检索问答链,用户只需要输入问题,即可获得LLM基于知识库的回答,实现知识库助手的核心功能。
这种方法无需修改模型的参数,构建起来方便快捷,为了进一步提高RAG知识库助手的能力,未来工作中可以考虑在文本分割步骤时于文本的语义进行分割,或者对每个分割块生成概括性索引,保证更优的检索精度,亦可在Prompt的生成阶段选择更优的策略,让LLM可以给出更加符合要求的回到。
2.5 Web Demo部署
基于RGA构建的LLM知识库助手可以部署在Web端,目前有很多支持简易Web应用的工具,例如Gradio、Streamlit等。本次课程将使用Gradio部署知识库助手的Web界面,实现更加直观的交互方式。
3. 开发工具
本次课程的知识库助手需要用到多种开发工具,以下是对相关开发工具的简单介绍。
3.1 SentenceTransformer
SentenceTransformers是一个可以将句子、文本等数据提取为向量特征的方法,该方法最早公开于Sentence-BERT论文中3,方法支持超过100种语言的本文嵌入,本文之间的嵌入特征能够用Cosine相似度来进行语义度量。4
SentenceTransformers提供基于Pytorch和Transformers的多种预训练模型,本次课程将要用到的预训练模型为下图所示模型。
3.2 Chroma
Chroma是向量数据库框架,在LLM应用开发阶段,可以更好地把需要用到的文本数据整合起来,特别契合RAG应用的开发过程,如下图所示,Chroma可以将知识库的文本和嵌入保存为数据库,当用户提出一个请求时,使用Embedding模型提取请求的嵌入特征,然后从数据库中检索相似的文本数据,用户请求和相似文本数据一同生成Prompt输入给LLM。
3.3 Gradio
Gradio是一个可以帮助开发者快速部署深度学习网页应用的框架,本次作业使用该框架完成网页端的模型部署,使用Chatbot
类在网页上显示整个对话过程中的用户输入和模型输出信息。5
Chatbot
可以接收Markdown的部分语法,而且可以在聊天过程中直接显示图片、音频和视频。当Chatbot
作为输入使用时,可以将当前的每一轮对话的输入输出作为一个列表,用于LLM的上下文判断;当Chatbot
作为输出使用时,其接受一个对话列表,列表中每个元素是一个[user message, response message]
的对话,然后将所有的对话显示在网页上。
以下Python代码使用Chatbot
的简单样例,可以看到chatbot
变量分别作为respond
函数的输入(给出内容)和输出(接收内容),在该代码中,respond
函数中的chat_history.append((message, bot_message))
语句是用来更新Chatbot
的内容。
import gradio as gr
import random
import time
with gr.Blocks() as demo:
chatbot = gr.Chatbot(height=500)
msg = gr.Textbox()
clear = gr.ClearButton([msg, chatbot])
def respond(message, chat_history):
bot_message = random.choice(["How are you?", "I love you", "I'm very hungry"])
chat_history.append((message, bot_message))
time.sleep(2)
return "", chat_history
msg.submit(respond, [msg, chatbot], [msg, chatbot])
if __name__ == "__main__":
demo.launch()
安装好Gradio以后,运行以上Python代码,得到的结果如下图所示,模型可以接受每次用户的收入,随机从