【总结01】简单实现RAG的完整流程
目录
一、什么是 RAG?
1.1 核心定义
1.2 技术原理
二、完整流程代码实现
一、什么是 RAG?
1.1 核心定义
从本质上讲,RAG(Retrieval-Augmented Generation)是一种旨在解决大语言模型(LLM)“知其然不知其所以然”问题的技术范式。它的核心是将模型内部学到的“参数化知识”(模型权重中固化的、模糊的“记忆”),与来自外部知识库的“非参数化知识”(精准、可随时更新的外部数据)相结合。其运作逻辑就是在 LLM 生成文本前,先通过检索机制从外部知识库中动态获取相关信息,并将这些“参考资料”融入生成过程,从而提升输出的准确性和时效性 。
💡一句话总结:RAG 就是让 LLM 学会了“开卷考试”,它既能利用自己学到的知识,也能随时查阅外部资料。
1.2 技术原理
那么,RAG 系统是如何实现“参数化知识”与“非参数化知识”的结合呢?如下图所示,其架构主要通过两个阶段来完成这一过程:
(1)检索阶段:寻找“非参数化知识”
- 知识向量化:嵌入模型(Embedding Model)充当了“连接器”的角色。它将外部知识库编码为向量索引(Index),存入向量数据库。
- 语义召回:当用户发起查询时,检索模块利用同样的嵌入模型将问题向量化,并通过相似度搜索(Similarity Search),从海量数据中精准锁定与问题最相关的文档片段。
(2)生成阶段:融合两种知识
- 上下文整合:生成模块接收检索阶段送来的相关文档片段以及用户的原始问题。
- 指令引导生成:该模块会遵循预设的Prompt指令,将上下文与问题有效整合,并引导 LLM(如 DeepSeek)进行可控的、有理有据的文本生成。
二、完整流程代码实现
知识库准备:
【代码】
from langchain_community.document_loaders import UnstructuredMarkdownLoader, UnstructuredPDFLoader from langchain_core.prompts import ChatPromptTemplate from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_community.embeddings import HuggingFaceEmbeddings, DashScopeEmbeddings from langchain_core.vectorstores import InMemoryVectorStore from langchain.chat_models import init_chat_model from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough from dotenv import load_dotenv load_dotenv() # 1.加载本地文档 fil_path = "C:/Users/Administrator/Desktop/英雄联盟英雄芸阿娜全面介绍.pdf" loader = UnstructuredPDFLoader(fil_path) docs = loader.load() print(docs) # 2.文档切割 spliter = RecursiveCharacterTextSplitter( chunk_size=300, # 分段的最大字符数 chunk_overlap=5, # 分段之间允许重叠的字符数 separators=["\n\n", "\n", ",","。", "!", "?", ";", ":", "…", "—", "~"], # 分段的依据 length_function=len # 字符统计依据(函数) ) split_docs_chunks = spliter.split_documents(docs) print(split_docs_chunks) # 3.构建中文嵌入模型 # embeddings = HuggingFaceEmbeddings( # model_name="BAAI/bge-small-zh-v1.5", # model_kwargs={"device": "cpu"}, # 默认使用cpu # encode_kwargs={'normalize_embeddings': True} # 对生成的向量进行 L2 归一化 # ) # 这边使用DashScopeEmbeddings embeddings = DashScopeEmbeddings( model="text-embedding-v2" ) # 4.构建向量存储 vectorstore = InMemoryVectorStore(embeddings) vectorstore.add_documents(split_docs_chunks) # 添加文档到向量存储中: 将文档转换为向量并存储在内存中 retriever = vectorstore.as_retriever( search_kwargs={"k": 3} # 搜索时返回的向量数量 ) # 5.构建提示词 prompt = ChatPromptTemplate.from_messages( messages=[ {"role": "system", "content": "你是一个AI助手,请根据参考资料: {context},回答用户的问题"}, {"role": "human", "content": "我的问题是{questions}"}, ], ) # 6.初始化模型 model = init_chat_model( model="deepseek-chat", ) # 7. 构建链 str_parser = StrOutputParser() def format_docs(docs_list): reference_text = '[' for doc in docs_list: reference_text += doc.page_content reference_text += ']' return reference_text chain = {"context": retriever | format_docs, "questions": RunnablePassthrough()} | prompt | model | str_parser # 8.调用链 response = chain.stream(input="介绍一下芸阿娜的基础属性?") for chunk in response: print(chunk, end="", flush=True)生成结果:
