一、RAG是什么
前面的AI文章,我们看到了大模型(如文心一言、通义千问等)的对话能力,这些大模型的能力是依赖预训练阶段所学的知识来进行文本生成任务的,如问答,翻译等。然而这些模型的知识是静态的,受限于预训练数据的时间点,无法动态获取最新的知识内容。大模型的预训练数据更多来自公开的通用知识,它们并不能访问个人或企业的私有数据,因此我们可以发现大模型缺乏对特定领域知识的响应能力。同时因为大模型的训练数据很多且很广,它的回答容易产生不准确的答案,大家称这种现象为幻觉。
检索增强生成RAG(Retrieval-Augmented Generation)的引入解决了这些问题。它允许生成模型在生成文本时动态地从外部知识库中检索相关信息,并将这些信息整合到生成过程中。这样一来,生成模型不仅能够利用其内部的知识,还能实时地从外部资源中获取最新的、最相关的信息,从而提高了生成内容的准确性和时效性。具体来说,RAG的工作流程如下:
Retrieval(检索):
在这个阶段,系统从外部知识库中检索与当前任务相关的文档或片段。检索的目标是找出最相关的背景信息,以便为生成模型提供额外的支持。
Augmentation(增强):
在检索到相关信息之后,这些信息需要与原始输入进行融合。这一步骤被称为“增强”,因为它通过加入检索到的高相关性信息,增强了生成模型的输入上下文,使其能够更好地生成高质量的文本。
Generation(生成):
最后,增强后的上下文被输入到生成模型中,生成模型根据增强后的信息生成最终的文本。这个过程利用了检索到的信息,确保生成的内容更加准确和相关。
二、使用LangChain实现RAG
下面是我们使用千帆大模型的RAG示例,代码如下(示例):
import os
from langchain.schema.runnable import RunnablePassthrough, RunnableMap, RunnableLambda
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain_community.embeddings import ModelScopeEmbeddings
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate
from langchain.callbacks.manager import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
from langchain.schema import StrOutputParser
from langchain_community.llms import QianfanLLMEndpoint
# 加载文档内容
with open("./背影.txt", encoding="utf-8") as file:
full_txt = file.read()
# 将大块数据分成更小的块数据
text_splitter = CharacterTextSplitter(
separator="\n\n", chunk_size=30, chunk_overlap=8, length_function=len
)
currentDocuments = text_splitter.split_text(full_txt)
# 将拆分好的小块数据转化为向量并存入向量数据库中
model_id = "damo/nlp_corom_sentence-embedding_chinese-base"
embeddings_model = ModelScopeEmbeddings(model_id=model_id)
db = Chroma.from_texts(currentDocuments, embeddings_model)
retriever = db.as_retriever(search_kwargs={"k":1})
# 设置环境变量
os.environ["QIANFAN_ACCESS_KEY"] = "********************************"
os.environ["QIANFAN_SECRET_KEY"] = "********************************"
# 定义模型
qinfanLLM = QianfanLLMEndpoint(temperature=0.9,print_prompt=True)
# 单个示例的 PromptTemplate
example_prompt = PromptTemplate(
input_variables=["context", "question"],
template="上下文: {context}\n问题:{question}\n答案:",
)
# 定义 form_docs 函数
def form_docs(docs):
return "\n\n".join([d.page_content for d in docs])
qa = RetrievalQA.from_chain_type(
llm=qinfanLLM,
chain_type="stuff",
retriever=retriever,
return_source_documents=True,
chain_type_kwargs={"prompt": example_prompt},
)
query = "文章中提到几次背影?"
result = qa({"query": query})
print(result["result"])
上面我放入了中学课文朱自清的《背影》作为RAG的专有知识,然后我们可以看到模型的回答如下:
三、RAG实践考虑
上面我们只是按照RAG的工作流程做了一个简单的示例,实际过程中还会遇到很多问题如:
- 怎么把office文件(如docx、ppt、excel等)以及pdf文件等内容读取并切割嵌入到向量数据库?
- 不同场景使用什么样的嵌入模型合适?
- 检索过程会返回很多内容,如何提高检索的精确度?
- 上面的代码示例并未实现检索内容的排序或重排,如何实现呢?
四、总结
通过RAG模型,企业和组织可以充分利用私有知识库中的信息,生成更加准确、专业和丰富的文本。这不仅提高了生成内容的质量,还增加了模型的透明度和可信度,从而更好地服务于不同的应用场景。RAG模型为企业和组织提供了一种有效的手段,将内部积累的专业知识转化为实际应用,提升工作效率和服务质量。