本文档目的:
- 快速了解RAG的背景与原理
- 使用langchain框架快速搭建问答系统
大模型RAG 问答的背景
随着自然语言处理技术的不断发展,问答系统作为一种重要的应用形式,已经得到了广泛的关注和研究。传统的问答系统通常依赖于手动编写的规则和模板,这种方式不仅效率低下,而且难以适应复杂多变的自然语言表达方式。
为了解决这些问题,人们开始研究基于深度学习的问答系统。其中,大语言模型(LLM)的出现改变了自然语言处理(NLP)的格局。这些模型具有极高的语言理解能力,可以处理各式各样的自然语言任务,例如文本生成、知识问答、推理计算、阅读理解等。其中,问答系统是一种常见的 NLP 应用,它允许用户提出问题,并根据预训练的知识或信息库提供答案。
近几年出现了大量的预训练模型(Bert[1]、Gpt3[2]、RoBERTa[3]、T5[4])。这些大型预训练模型大都基于公开语料(书籍、维基百科等),导致模型都是基于先前训练过的数据进行内容的生成,会产生幻觉问题(胡言乱语或答非所问),当用户的查询超出范围时,例如在训练数据中未见过的内容或需要最新信息来回答时,LLM会产生较差的性能。对于实时数据以及保存在企业私有文档或数据库中的内容进行问答,一般都是通过微调的方法,但此方法费时费力,为了解决这个问题,研究人员提出了检索增强生成(RAG)的方法。RAG 是一种基于生成式模型的问答方法,它首先从私有数据文档或数据库中对提问进行检索,然后再将检索到的数据送入LLM中,最大可能的消除了模型的幻觉问题。LLM可以利用来自外部数据源的额外相关信息来增强文本生成能力。
未来大模型的发展趋势:大模型就像一个基座,可以基于此开发多种应用,类似于电脑中的CPU。
暂时无法在飞书文档外展示此内容
什么是RAG(Retrieval Augmented Generation)
RAG,全称检索增强生成(Retrieval-Augmented Generation),是一种优化大型语言模型(LLM)输出的方法,使其能够在生成响应之前引用权威知识库。它结合了语言模型和信息检索技术,可以在多种自然语言处理任务中提高质量和准确性。
RAG是一种利用向量数据库和大模型结合的应用方案,可以解决大模型的知识局限性、幻觉问题和数据安全性等问题。它是一种基于向量数据库的文本检索技术,能够快速找到相似的文本。
检索增强生成的通用流程
暂时无法在飞书文档外展示此内容
检索增强生成的最先进流程
- 查询重写技术(query translation)
- 查询路由(Routing)
- 查询构建(query construction)
- 索引(Indexing)
- 检索(Retrieval)
- 生成(Generation)
什么是Langchain
LangChain 是一个强大的框架,旨在帮助开发人员使用语言模型构建端到端的应用程序。它提供了一套工具、组件和接口,可简化创建由大型语言模型(LLM)和聊天模型提供支持的应用程序的过程。
简单来说,可以将 LangChain 理解为开源版的 GPT 插件,它提供了丰富的大语言模型工具,支持在开源模型的基础上快速增强模型的能力。
深入学习了解可参考官方文档: langchain官方文档
实践
环境安装配置
安装langchian的相关依赖包
# 安装包
! pip install langchain_community tiktoken langchain-openai langchainhub chromadb langchain
我们可以选择大模型的api调用或者本地有显卡 自己部署开源大模型进行问答生成,如果选择大模型api调用,则一般需要申请相关大模型的api key,根据自己的需要选择所需的模型。
gemini Api key :需特定地区
chatgpt key :需信用卡
(可选,用来追踪问答的过程和结果)LangSmith 配置: api-key获取链接需在下方链接
import os
os.environ['LANGCHAIN_TRACING_V2'] = 'true'
os.environ['LANGCHAIN_ENDPOINT'] = 'https://api.smith.langchain.com'
os.environ['LANGCHAIN_API_KEY'] = <your-api-key>
配置open api key 用来访问openai 的api
os.environ['OPENAI_API_KEY'] = <your-api-key>
-
通用流程
下面这个代码是使用langchain框架最通用的一个过程
import bs4
from langchain import hub
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.vectorstores import Chroma
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
#### 索引 ####
# 1. 加载文档 : 使用的langchain自带的web库 解析网页
loader = WebBaseLoader(
web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
bs_kwargs=dict(
parse_only=bs4.SoupStrainer(
class_=("post-content", "post-title", "post-header")
)
),
)
# 加载文档
docs = loader.load()
# 2. 分割 : 使用langchain的文本分割库 参数:chunk_size 分割的文档块大小 chunk_overlap 相邻文档块的重叠数字
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)
# 3. 嵌入 : 使用Openai的embed模型将分割好的文档块进行向量化,并将向量存储
vectorstore = Chroma.from_documents(documents=splits,
embedding=OpenAIEmbeddings())
# 4. 创建检索器:k是参数 可调 用来控制查到的块个数
retriever = vectorstore.as_retriever(search_kwargs={"k": 1})
#### 检索并生成 ####
# 5. 提示词
prompt = hub.pull("rlm/rag-prompt")
# 6. 调用了gpt-3.5的 api
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
# 文档前处理 用来拼接文档的所有页
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
# 构建调用链
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
# 开始提问
rag_chain.invoke("What is Task Decomposition?")
-
查询重写技术 (Query Transformations)
基于距离的矢量数据库在高维空间中查询并根据“距离”寻找相似的嵌入文档。但是,检索可能会根据查询语义的微妙变化产生不同的结果,所以,我们可以对用户的查询进行重写操作,从而自动化调优提示过程。
2.1 多重查询(Multi Query)
多重查询是将问题使用模型再生成几个不同的版本,这几个版本并行去查向量数据库,把检索到的文档全部送到大模型中去生成答案。
流程:
暂时无法在飞书文档外展示此内容
2.2 查询结果融合(Rag-Fusion)[7]
RAG-Fusion 的工作流程包括:首先,通过 LLM 将用户的查询转换为相似但不同的查询;然后,对原始查询及其新生成的同级查询执行矢量搜索;接着,使用倒数排名融合来聚合和细化所有结果;最后,将精心挑选的结果与新查询配对,引导大型语言模型精心设计输出,考虑所有查询和重新排序的结果列表。
相比于上一小节的部分,只多了将查询到的文档集进行融合的一个过程,而不是把查到的所有文档送到LLM中。
暂时无法在飞书文档外展示此内容
2.3 查询分解(Quert Decomposition)
查询分解是将用户的问题
参考
[1] Devlin, Jacob, et al. "Bert: Pre-training of deep bidirectional transformers for language understanding." arXiv preprint arXiv:1810.04805 (2018).
[2] Brown, Tom, et al. "Language models are few-shot learners." Advances in neural information processing systems 33 (2020): 1877-1901.
[3] Liu, Yinhan, et al. "Roberta: A robustly optimized bert pretraining approach." arXiv preprint arXiv:1907.11692 (2019).
[4] Raffel, Colin, et al. "Exploring the limits of transfer learning with a unified text-to-text transformer." Journal of machine learning research 21.140 (2020): 1-67.
[5] www.youtube.com/watch?v=wd7…
[7] Rackauckas, Zackary. "RAG-Fusion: a New Take on Retrieval-Augmented Generation." arXiv preprint arXiv:2402.03367 (2024).