文章目录
前言
随着人工智能的不断发展,大语言模型这门技术也越来越重要,很多人和企业都开始将大语言模型投入生产之中,本文就将从理论知识介绍了如何构建一个以RAG技术为核心功能的基于自建知识库的本地大模型,并提供一些思路。
一、什么是RAG
检索增强生成RAG(Retrieval- Augmented Generation)在2020年Facebook AI Research(FAIR)团队所写的《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》中被首次提及。
RAG技术是一种在自然语言处理领域(NLP)的关键方法,通过改进问题表述来提升回答质量及效率。它广泛应用于问答系统、对话管理、机器人助手、在线教育、医疗健康、金融服务、法律咨询、学术研究等多个领域,能够帮助用户获取更准确和个性化的答案或解决方案。随着人工智能的发展,RAG的应用范围将持续扩展并深度影响这些领域的信息处理与决策支持过程。
二、为什么使用RAG
众所周知,训练一个通用大模型需要大量的数据并且消耗很大的算力和财力。这对于中小型企业尤其是非互联网企业来说并不具有性价比,且企业存在大量独有的知识资料,这使通用大模型在该领域的泛化能力较弱,存在严重的大模型幻觉问题。而RAG技术很好的缓解了这两个问题。打一个通俗易懂的比方,通用大模型就像接受了九年制义务教育的高中生,配合了RAG技术,他就变成了对每一领域有一定研究的大学生。
三、RAG流程
图片来自NVIDIA,相关链接: 大模型结合 RAG 构建客服场景自动问答系统
我将进行简单的展示具体的环境搭建和代码请看之后的实践部分
1. 数据处理
文件录入
pdf文件
代码如下(示例):
from langchain_community.document_loaders import PyPDFLoader
loader = PyPDFLoader("test.pdf")
documents = loader.load_and_split()
txt文件
from langchain.document_loaders import TextLoader
loader = TextLoader("test.txt")
documents = loader.load()
其他文件
文件类型 | 包 |
---|---|
文件夹 | DirectoryLoader |
Azure 存储 | AzureBlobStorageContainerLoader |
CSV文件 | CSVLoader |
印象笔记 | EverNoteLoader |
Google网盘 | GoogleDriveLoader |
任意的网页 | UnstructuredHTMLLoader |
S3 | S3DirectoryLoader/S3FileLoader、 |
Youtube | YoutubeLoader |
…… | …… |
文件分割
RecursiveCharacterTextSplitter
from langchain_text_splitters import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size = 500, chunk_overlap = 100)
#chunk_size 表示分割块的大小(可以简单理解为一个分割块的字数)
#chunk_overlap表示分割块的重复部分。(重复部分是为了减少中间中断句子对语义的影响)
也可以通过分隔符分割
text_splitter = RecursiveCharacterTextSplitter(separators=["\n\n"])
分隔符 | 含义 |
---|---|
“\n” | 单次换行 |
“\n\n" | 两次换行 |
" " | 空格换行 |
“.” | "."换行 |
“,” | ","换行 |
“\u200b”, | 零宽空格(零宽空格是一种不可打印的Unicode字符,用于可能需要换行处) |
“\uff0c”, | # 全角逗号 |
“\u3001”, | # Ideographic comma |
“\uff0e”, | # 全角句号 |
“\u3002”, | # Ideographic full stop |
CharacterTextSplitter
from langchain_text_splitters import CharacterTextSplitter
text_splitter = CharacterTextSplitter(separator="\n\n", chunk_size=40, chunk_overlap=10, length_function=len, is_separator_regex=False)
与 RecursiveCharacterTextSplitter 的区别是:
CharacterTextSplitter 分隔符只能传递字符串,RecursiveCharacterTextSplitter 可以传分隔符数组。
CharacterTextSplitter 在指定分割符后,如果基于分隔符分割后的文本大于指定的 chunk_size,则会保持文本的完整性,此时 chunk_size、chunk_overlap 失效。
2.嵌入(Embedding)
什么是嵌入?
可以简单理解为向量化。这涉及到了大语言模型的底层架构——Transformer模型。
如果感兴趣可以看这篇文章 Transformer 模型详解
向量数据库推荐
向量数据库 | 是否开源 | 特点 |
---|---|---|
FAISS | 是 | 速度快,但不能永久储存 |
Chorma | 是 | python易用性强 |
Milvus | 是 | 在FAISS的基础上加入了永久储存 |
Weaviate | 是 | 提供了GraphQL-based API |
Pinecone | 否 | —— |
声明:以上仅为博主的个人理解,具体差异建议自行了解
嵌入模型推荐
由于API限制的问题因此我个人不建议使用OpenAIEmbeddings,如果你能获得也是不错的选择。
开源大模型推荐使用Ollama。其中如果是嵌入中文文档可以使用 herald/dmeta-embedding-zh,英文文档可以使用nomic-embed-text。也可以在HuggingFace上找相关的嵌入模型,例如有道的bce-embedding-vase-v1。
商业大模型可以使用百度开发的文心一言或者字节的千问。但这两个都需要access_token。具体使用方法见之后的文章。
3.模型精调
模型精调主要可以分成三种方法:Post-Pretrain,STF,偏好对齐
Post-Pretrain
预训练( Post-Pretrain)适用于训练数据量较大涉及范围较广的项目,例如各类通用大模型的训练。
SFT
监督微调(Supervised Fine-Tuning)适用于训练数据量较小的项目,例如各类垂类大模型
全量更新 :指对矩阵中的所有参数一起进行调整,效果可能会更显著
LoRA:指对矩阵中的部分参数进行调整,一定程度上可以缓解大模型失忆
无法确定哪个的效果会更好,可以两者皆用进行比较。
偏好对齐
RLHF(Reinforcement Learning from Human Feedback) 基于人类反馈的强化学习方法,基于成对的偏好标注数据训练奖励模型,并使用近端策略优化方法最大化奖励来调优大模型,使得大模型与人类偏好和价值观对齐。
KTO(Knowledge Transfer Objective) KTO 是一种知识转移的优化方法,主要用于将一个大型预训练模型的知识转移到另一个较小、更特定任务的模型上
DPO(Distributed Proximal Policy Optimization):DPO 是一种用于多智能体系统中政策优化的方法。在大型语言模型的背景下,它可能被用来协调多个模型或部分(如分布式架构中的不同节点)之间的决策过程
总结
本文主要讲了RAG的主要流程并提供了相关模型和可能的方向。具体的代码实现请看下一篇文章。