20260108_142519_AGI(十二):RAG技术基础及企业级RAG系统打造
本文详解大模型应用开发三大模式:提示工程、RAG检索增强生成和微调,重点解析RAG技术的原理、流程及优势,并通过DeepSeek+Faiss案例展示本地知识库检索系统搭建。同时介绍Query改写技术提升检索质量,以及结合互联网搜索扩展RAG系统功能,为开发者提供完整的大模型应用开发指南。
一、大模型应用开发的三种模式
提示工程(Prompt Engineering)、RAG(检索增强生成)和微调(Fine-tuning)分别代表了不同维度的优化手段。
提示工程 (Prompt Engineering):不改变模型,通过优化输入(Prompt)来引导输出。一般用于:
- 快速原型开发:需要立即看到效果。
- 通用任务:总结、翻译、改写、简单的逻辑推理。
- 改变语气或格式:如“请以专业律师的口吻回复”或“输出 JSON 格式”。
- 预算极低:几乎没有额外成本。
RAG (检索增强生成):在模型回答前,先去外部数据库(如公司文档、实时新闻)检索相关知识,再把知识喂给模型。一般用于:
- 需要准确的事实:需要模型回答特定的、私有的或最新的信息(如“我公司去年的差旅报销规定”)。
- 知识库频繁更新:数据每天甚至每小时都在变,微调无法跟上这种速度。
- 需要引用来源:用户需要知道答案是从哪篇文档里找出来的(减少“幻觉”)。
- 长文本处理:数据量巨大,超出了单个提示词的长度限制。
微调 (Fine-tuning):使用特定领域的数据集对模型进行二次训练,改变其内部参数(权重)。一般用于:
- 特定的行为/风格习惯:你需要模型极度符合某种特定风格(如模仿某个作家的文风)。
- 极度专业的术语:模型在理解特定垂直领域(如病理学影像报告、底层代码库)的特殊表达时表现不佳。
- 为了降本增效:通过微调一个小模型(如 Llama-3-8B),使其表现接近大模型(如 GPT-4),从而降低推理成本和延迟。
- 遵循复杂指令:当提示工程无法让模型稳定遵循某些及其复杂的输出规则时。

二、RAG的核心原理与流程
1、什么是RAG?
RAG (Retrieval-Augmented Generation,检索增强生成) 是目前大模型应用中最火热的技术架构之一。RAG是一种结合信息检索(Retrieval)和文本生 成(Generation)的技术,RAG技术通过实时检索相关文档或信息,并将其作为上下文输入到生成模型中,从而提高生成结果的时效性和准确性。简单来说,RAG 就是给大模型配了一个“外部知识库”。当用户提问时,系统先去知识库里查资料,把查到的资料和问题一起喂给模型,让模型参考这些资料来回答。
RAG的优势:
- 解决知识时效性问题:大模型的训练数据通常是静态的,无法涵盖最新信息,而RAG可以检索外部知识库实时更新信息。
- 减少模型幻觉:通过引入外部知识,RAG能够减少模型生成虚假或不准确内容的可能性。
- 提升专业领域回答质量:RAG能够结合垂直领域的专业知识 库,生成更具专业深度的回答。
2、RAG的核心原理与流程
RAG 的核心思想是将检索(Retrieval)能力与生成(Generation)能力结合。
- 传统生成 (LLM Only): 靠模型脑子里记的知识回答(闭卷考试)。如果知识点没学过或记错了,就会胡说八道(幻觉)。
- RAG 生成: 先找资料,再根据资料组织语言回答(开卷考试)。这样回答更准确,且能通过引文溯源。
一个完整的 RAG 流程通常分为两个阶段:数据准备阶段(离线)和检索生成阶段(在线)。
第一阶段:数据准备
- 文档加载 (Load): 读取各种格式的私人文档(PDF、Word、Markdown、数据库等)。
- 文本切割 (Split/Chunking): 将长文章切成一小块一小块的“语义片段”(比如每段 500 字),因为模型的输入窗口有限。
- 向量化 (Embedding): 利用 Embedding 模型将这些文字片段转化成一串数字(向量)。这些数字代表了文字的“语义含义”。
- 存入向量数据库 (Store): 将这些向量存入专门的向量数据库(如 Milvus, Pinecone, FAISS 等)。
第二阶段:检索与生成
这是当用户输入问题后的实时处理过程:
- 问题向量化: 把用户的提问(比如“公司出差报销标准是什么?”)也转化成向量。
- 语义检索 (Retrieve): 在向量数据库中进行“相似度搜索”,找出与问题语义最接近的几个文档片段(Top-K)。
- 提示词增强 (Augment): 将“用户问题”和“搜到的片段”塞进一个模板里。 * 模板示例: “请参考以下背景资料:资料A,回答用户的问题:[用户问题]。如果资料中没有提到,请回答不知道。”
- 模型生成 (Generate): 大模型阅读这些“背景资料”,生成一个准确且有据可依的回答。
RAG 流程图解:
用户问题 ➔ 向量化 ➔ 去数据库捞资料 ➔ 问题+资料组合 ➔ 大模型 ➔ 最终答案

3、RAG的核心优势与局限性
核心优势:
- 解决“幻觉”问题: 模型必须参考给定的资料回答,大大降低了瞎编的概率。
- 知识实时性: 不需要重新训练模型。只要把最新的新闻或文档存入数据库,模型立刻就能掌握新知识。
- 私有数据安全: 企业不需要把敏感数据传给云端模型进行微调,只需在本地检索后,将相关片段传给模型。
- 可解释性: 模型的回答可以标注出处(例如:“根据《2023年财务手册》第三章…”),方便人工核对。
虽然 RAG 很强,但也有挑战:
- 检索质量: 如果搜出来的片段本身就不相关,模型就会被带偏。
- 上下文长度: 如果需要参考的资料太多,超出了模型的处理能力,效果会打折。
三、DeepSeek + Faiss搭建本地知识库检索
该系统的核心逻辑是将文档向量化并存入 Faiss,查询时通过相似度匹配找出相关内容,最后交给 DeepSeek 进行总结回答。
技术栈选择:
- 向量数据库:Faiss作为高效的向量检索
- 嵌入模型:阿里云DashScope的text-embedding-v1
- 大语言模型:deepseek-v3
- 文档处理:PyPDF2用于PDF文本提取
1、环境准备
首先安装必要的 Python 库:
pip install dashscope faiss-cpu PyPDF2 openai numpy langchain_community
2、核心代码实现
整个流程分为:文档预处理(PDF文本提取、文本分割、页码映射处理)→ 知识库构建(向量数据库构建、数据持久化)→ 问答查询(相似度检索、问答链处理、答案生成与展示)
from PyPDF2 import PdfReader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_community.vectorstores import FAISS
from typing import List, Tuple
import os
import pickle
DASHSCOPE_API_KEY = os.getenv('DASHSCOPE_API_KEY')
if not DASHSCOPE_API_KEY:
raise ValueError("请设置环境变量 DASHSCOPE_API_KEY")
def extract_text_with_page_numbers(pdf) -> Tuple[str, List[Tuple[str, int]]]:
"""
从PDF中提取文本并记录每个字符对应的页码
参数:
pdf: PDF文件对象
返回:
text: 提取的文本内容
char_page_mapping: 每个字符对应的页码列表
"""
text = ""
char_page_mapping = []
for page_number, page in enumerate(pdf.pages, start=1):
extracted_text = page.extract_text()
if extracted_text:
text += extracted_text
# 为当前页面的每个字符记录页码
char_page_mapping.extend([page_number] * len(extracted_text))
else:
print(f"No text found on page {page_number}.")
return text, char_page_mapping
def process_text_with_splitter(text: str, char_page_mapping: List[int], save_path: str = None) -> FAISS:
"""
处理文本并创建向量存储
参数:
text: 提取的文本内容
char_page_mapping: 每个字符对应的页码列表
save_path: 可选,保存向量数据库的路径
返回:
knowledgeBase: 基于FAISS的向量存储对象
"""
# 创建文本分割器,用于将长文本分割成小块
text_splitter = RecursiveCharacterTextSplitter(
separators=["\n\n", "\n", ".", " ", ""],
chunk_size=1000,
chunk_overlap=200,
length_function=len,
)
# 分割文本
chunks = text_splitter.split_text(text)
print(f"文本被分割成 {len(chunks)} 个块。")
# 创建嵌入模型
embeddings = DashScopeEmbeddings(
model="text-embedding-v1",
dashscope_api_key=DASHSCOPE_API_KEY,
)
# 从文本块创建知识库
knowledgeBase = FAISS.from_texts(chunks, embeddings)
print("已从文本块创建知识库。")
# 为每个文本块找到对应的页码信息
page_info = {}
current_pos = 0
for chunk in chunks:
chunk_start = current_pos
chunk_end = current_pos + len(chunk)
# 找到这个文本块中字符对应的页码
chunk_pages = char_page_mapping[chunk_start:chunk_end]
# 取页码的众数(出现最多的页码)作为该块的页码
if chunk_pages:
# 统计每个页码出现的次数
page_counts = {}
for page in chunk_pages:
page_counts[page] = page_counts.get(page, 0) + 1
# 找到出现次数最多的页码
most_common_page = max(page_counts, key=page_counts.get)
page_info[chunk] = most_common_page
else:
page_info[chunk] = 1 # 默认页码
current_pos = chunk_end
knowledgeBase.page_info = page_info
print(f'页码映射完成,共 {len(page_info)} 个文本块')
# 如果提供了保存路径,则保存向量数据库和页码信息
if save_path:
# 确保目录存在
os.makedirs(save_path, exist_ok=True)
# 保存FAISS向量数据库
knowledgeBase.save_local(save_path)
print(f"向量数据库已保存到: {save_path}")
# 保存页码信息到同一目录
with open(os.path.join(save_path, "page_info.pkl"), "wb") as f:
pickle.dump(page_info, f)
print(f"页码信息已保存到: {os.path.join(save_path, 'page_info.pkl')}")
return knowledgeBase
def load_knowledge_base(load_path: str, embeddings = None) -> FAISS:
"""
从磁盘加载向量数据库和页码信息
参数:
load_path: 向量数据库的保存路径
embeddings: 可选,嵌入模型。如果为None,将创建一个新的DashScopeEmbeddings实例
返回:
knowledgeBase: 加载的FAISS向量数据库对象
"""
# 如果没有提供嵌入模型,则创建一个新的
if embeddings is None:
embeddings = DashScopeEmbeddings(
model="text-embedding-v1",
dashscope_api_key=DASHSCOPE_API_KEY,
)
# 加载FAISS向量数据库,添加allow_dangerous_deserialization=True参数以允许反序列化
knowledgeBase = FAISS.load_local(load_path, embeddings, allow_dangerous_deserialization=True)
print(f"向量数据库已从 {load_path} 加载。")
# 加载页码信息
page_info_path = os.path.join(load_path, "page_info.pkl")
if os.path.exists(page_info_path):
with open(page_info_path, "rb") as f:
page_info = pickle.load(f)
knowledgeBase.page_info = page_info
print("页码信息已加载。")
else:
print("警告: 未找到页码信息文件。")
return knowledgeBase
# 读取PDF文件
pdf_reader = PdfReader('./浦发上海浦东发展银行西安分行个金客户经理考核办法.pdf')
# 提取文本和页码信息
text, char_page_mapping = extract_text_with_page_numbers(pdf_reader)
print(f"提取的文本长度: {len(text)} 个字符。")
# 处理文本并创建知识库,同时保存到磁盘
save_dir = "./vector_db"
knowledgeBase = process_text_with_splitter(text, char_page_mapping, save_path=save_dir)
# 示例:如何加载已保存的向量数据库
from langchain_community.llms import Tongyi
llm = Tongyi(model_name="deepseek-v3", dashscope_api_key=DASHSCOPE_API_KEY) # qwen-turbo
# 设置查询问题
query = "客户经理被投诉了,投诉一次扣多少分"
if query:
# 执行相似度搜索,找到与查询相关的文档
docs = knowledgeBase.similarity_search(query,k=10)
# 构建上下文
context = "\n\n".join([doc.page_content for doc in docs])
# 构建提示
prompt = f"""根据以下上下文回答问题:{context} 问题: {query}"""
# 直接调用 LLM
response = llm.invoke(prompt)
print(response)
print("来源:")
# 记录唯一的页码
unique_pages = set()
# 显示每个文档块的来源页码
for doc in docs:
text_content = getattr(doc, "page_content", "")
source_page = knowledgeBase.page_info.get(
text_content.strip(), "未知"
)
if source_page not in unique_pages:
unique_pages.add(source_page)
print(f"文本块页码: {source_page}")
五、Query改写
RAG 的核心在于“检索-生成”。如果第一步“检索”就走偏了,那么后续的“生成”质量也会降低。
用户提出的问题往往是口语化的、承接上下文的、模糊的,甚至是包含了情绪的。 而知识库里的文本(切片/Chunks)通常是陈述性的、客观的。因此,需要一个翻译官的角色,将用户的“口语化查询”转换成“书面化、精确的检索语句”
1、上下文依赖型Query改写
instruction = “”" 你是一个智能的查询优化助手。请分析用户的当前问题以及前序对话历史,判断当前问题是否依赖于上下文。 如果依赖,请将当前问题改写成一个独立的、包含所有必要上下文信息的完整问题。 如果不依赖,直接返回原问题。 “”"
prompt = f"“”
###指令###
{instruction}
###对话历史###
{conversation_history}
###当前问题###
{current_query}
###改写后的问题###
“”"
例如:

2、对比型Query改写
instruction = “”" 你是一个查询分析专家。请分析用户的输入和相关的对话上下文,识别出问题中需要进行比较的多个对象。然后,将原始问题改写成一个更明确、更适合在知识库中检索的对比性查询。 “”"
prompt = 同上

3、模糊指代型Query改写
instruction = “”" 你是一个消除语言歧义的专家。请分析用户的当前问题和对话历史,找出问题中"都"、“它”、“这个” 等模糊指代词具体指 向的对象。 然后,将这些指代词替换为明确的对象名称,生成一个清晰、无歧义的新问题。 “”"
prompt = 同上

如何学习大模型 AI ?
由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。
但是具体到个人,只能说是:
“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。
这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。
我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

第一阶段(10天):初阶应用
该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。
- 大模型 AI 能干什么?
- 大模型是怎样获得「智能」的?
- 用好 AI 的核心心法
- 大模型应用业务架构
- 大模型应用技术架构
- 代码示例:向 GPT-3.5 灌入新知识
- 提示工程的意义和核心思想
- Prompt 典型构成
- 指令调优方法论
- 思维链和思维树
- Prompt 攻击和防范
- …
第二阶段(30天):高阶应用
该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。
- 为什么要做 RAG
- 搭建一个简单的 ChatPDF
- 检索的基础概念
- 什么是向量表示(Embeddings)
- 向量数据库与向量检索
- 基于向量检索的 RAG
- 搭建 RAG 系统的扩展知识
- 混合检索与 RAG-Fusion 简介
- 向量模型本地部署
- …
第三阶段(30天):模型训练
恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。
到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?
- 为什么要做 RAG
- 什么是模型
- 什么是模型训练
- 求解器 & 损失函数简介
- 小实验2:手写一个简单的神经网络并训练它
- 什么是训练/预训练/微调/轻量化微调
- Transformer结构简介
- 轻量化微调
- 实验数据集的构建
- …
第四阶段(20天):商业闭环
对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。
- 硬件选型
- 带你了解全球大模型
- 使用国产大模型服务
- 搭建 OpenAI 代理
- 热身:基于阿里云 PAI 部署 Stable Diffusion
- 在本地计算机运行大模型
- 大模型的私有化部署
- 基于 vLLM 部署大模型
- 案例:如何优雅地在阿里云私有部署开源大模型
- 部署一套开源 LLM 项目
- 内容安全
- 互联网信息服务算法备案
- …
学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。
如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。
这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

更多推荐

所有评论(0)