Administrator
Published on 2026-04-26 / 15 Visits
0
0

RAG笔记

RAG步骤

理解(用自己的话)

RAG是提示词工程的一种,分为离线阶段-- 建立向量库和在线阶段 -- 查询阶段
这里的离线指我们拿到了所有数据,然后处理;而在线是指我们需要实时响应,只能知道用户之前和现在query
离线阶段分为:

  1. 加载文档,变成LLM能处理的纯文本

  2. 切分文档。 因为模型输入长度限制,以及向量计算中长文本的细节会消失

切分文档要保持语义,切分方案有

  1. 按照字符切分

r_splitter = RecursiveCharacterTextSplitter(
    chunk_size=150,
    chunk_overlap=0,
    separators=["\n\n", "\n", "(?<=\. )", " ", ""]
)

这样会首先尝试用\n\n分割文档,如果长度太长,再尝试用\n,然后尝试用. 然后" " 然后""
对应分割段落, 分割段内换行,分割句子 分割单词 分割字母

  1. 按照token切分
    使用token分词器会在每个chunks中加入文档metadata

  2. 向量化

  3. 入库 向量和对应chunk一起入库

代码片段(关键点)

from langchain.document_loaders import PyPDFLoader

# Load PDF
loaders = [
    # Duplicate documents on purpose - messy data
    PyPDFLoader("docs/cs229_lectures/MachineLearning-Lecture01.pdf"),
    PyPDFLoader("docs/cs229_lectures/MachineLearning-Lecture01.pdf"),
    PyPDFLoader("docs/cs229_lectures/MachineLearning-Lecture02.pdf"),
    PyPDFLoader("docs/cs229_lectures/MachineLearning-Lecture03.pdf")
]
# 加载文档
docs = []
for loader in loaders:
    docs.extend(loader.load())
# 切分文档
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size = 1500,
    chunk_overlap = 150
)
splits = text_splitter.split_documents(docs)
# 向量化文档并持久化
from langchain.vectorstores import Chroma
persist_directory = 'docs/chroma/'
!rm -rf ./docs/chroma  # remove old database files if any
vectordb = Chroma.from_documents(
    documents=splits,
    embedding=embedding,
    persist_directory=persist_directory
)

# 查询
question = "is there an email i can ask for help"
docs = vectordb.similarity_search(question,k=3)
docs[0].page_content

遇到的坑

重复文件如何去重
向量搜索是基于semantic, 因此一些硬性要求并不会被识别出来,比如:
question = "what did they say about regression in the third lecture?"
实际上并不会识别出"the third lecture"然后去除不是"the third lecture" 的文档

解决方案:

MMR(Maximal Marginal Relevance)

\text{Score}(D_i) = \lambda \cdot \text{Sim}(D_i, Q) - (1-\lambda) \cdot \max_{D_j \in S} \text{Sim}(D_i, D_j)

  • 第一项 (加分项): 与 Query 的向量点积

  • 第二项 (扣分项): 与已选集  中最像的一个的向量点积。
    \lambda 是要调节的参数

  1. Self-Querying Retriever

  2. Contextual Compression
    MMR可以解决重复文件的问题,同时可以提升回答质量

self-query retriever

重构查询语句,把查询分成语义查询 + 结构化信息过滤两步
我们把结构化信息包含在metadata中,比如第几讲,第几页
重构方法:让LLM从query中提取出metadata,我们给LLM提供metadata语义讲解,LLM把query中的语义与metadata语义对比,输出结构化metadata过滤语言和去掉限制条件的语义语言
比如 "第三章中对注意力机制的解释"变成
{
"query": "注意力机制是怎么解释的",
"filter": {"lecture": 3}
}

compression

然后在加入历史对话,AI就能理解上下文,chatbot就产生了

相关链接

LangChain Chat with Your Data - DeepLearning.AI
Advanced Techniques in RAG: A Deep Dive into MMR, Self-Querying Retrievers, Contextual Compression, and Ensemble Retrieval - DEV Community

Fine-tuning和RAG 类似 重构和打补丁


Comment