RAG 检索增强生成(Retrieval-Augmented Generation,RAG)

RAG的基本结构有哪些呢?

RAG流程
RAG = “先把相关文档搜出来,再让大模型照着读”;流程固定为 编码→检索→拼装→生成→后处理 五步,离线再配套切块、建索引、存元数据即可上线。

RAG(检索增强生成)是通过“外部知识库检索+大模型生成”解决幻觉问题的技术,核心是让模型回答基于指定事实。

我的项目拆解(技术深度体现):

1. 多文档格式解析: 针对多种不同类型的文档包括表格、PPT、PDF 和流程说明相关的图片信息等,结合格式特性

进行差异化解析与切分,PDF/PPT 用专用库提取文本(PyPDF2、python-pptx),表格类转换为结构化数据(如
Pandas)或 Markdown 保留逻辑关系,图片类通过 OCR(PaddleOCR)提取和提炼成文字信息,最后按语义或固定长度分块,确保信息完整性和检索适配性。

  1. 混合检索+Rerank层精排
    关键词(BM25+)+语义(Embedding)互补,解决专业术语OOV问题;
    两阶段排序
    阶段一是混合检索,先用BM25+做文本召回(就是关键词匹配),使用BGE-large-1.5对长查询重点使用向量检索,对两者取并集后再去重,以确保关键字匹配和语义近似的文档都能被召回。Top5
    召回率(所有该找出来的正确项,我实际找出来了多少)从 0.6 提升至 0.78,MRR(用途:衡量排序类任务(检索、推荐、问答)的首条正确结果平均有多靠前)从 0.52 提高至 0.63;

BM25以及BM25+区别:
BM25 只认字面 token,BM25+ 先“拼写-拼音-子词-同义词”四轮扩展,再 BM25 打分,从而把「字面不同但意思一样」的文档也捞回来。

Details

维度 经典 BM25 BM25+
输入单元 精确分词 token token + 子词 + 拼音 + 同义词
OOV 专业词 查无此词 → 0 分 拼音/子词仍能命中
同义表达 必须关键词相同 同义词词典自动归一
实现成本 零,开箱即用 轻量预处理 < 5 ms
召回效果 易漏同义/拼写变体 同义/拼写/缩写全覆盖

BM25+ 不是改公式,而是给 BM25 前加一层“泛化 token”生成器,让它在关键词通道里就能初步解决同义和 OOV 问题,再与向量路并集互补。

pip install rank-bm25 hanlp jieba pypinyin
import jieba, pypinyin, json, hanlp
from rank_bm25 import BM25Okapi
from pypinyin import lazy_pinyin
from typing import List

# 1. 同义词典(金融示例)
synonym = {
    "信用卡": ["贷记卡", "credit card"],
    "逾期": ["违约", "欠款未还"]
}

# 2. 预处理:子词 + 拼音 + 同义词
def expand(text: str) -> str:
    # 同义词替换
    for k, v in synonym.items():
        for w in v:
            text = text.replace(w, k)
    # 拼音(首字母)
    py = "".join(lazy_pinyin(text, style=pypinyin.FIRST_LETTER))
    # 子词(2-gram)
    tokens = list(jieba.cut(text))
    sub_words = ["".join(tokens[i:i+2]) for i in range(len(tokens)-1)]
    return tokens + sub_words + list(py)   # 三路融合

# 3. 建库(假设已清洗)
docs = ["信用卡逾期后利息如何计算",
        "贷记卡违约金收费标准",
        "信用卡最低还款额说明"]
corpus = [expand(d) for d in docs]
bm25 = BM25Okapi(corpus)

# 4. 查询
query = "credit card 违约利息"
query_tokens = expand(query)
scores = bm25.get_scores(query_tokens)
topk = sorted(enumerate(scores), key=lambda x: x[1], reverse=True)[:5]
print("BM25+ Top5:", [(docs[i], s) for i, s in topk])

embedding模型:

Details

Embedding层优化

  • 模型选型:轻量级通用句向量模型:BERT-base(通用语义)与Sentence-BERT(句向量专项),多语言MiniLM-L6-v2(量化后仅80MB),在业务数据集上召回率提升12%(余弦相似度阈值0.75→0.82)。 long-context 模型:BGE-large-1.5、Conan-embedding-v2

  • 工程优化:通过FAISS的IVF_HNSW索引将检索延迟从500ms压至80ms,支持100万级文档库(分块策略:按标点+滑动窗口100字符,重叠20字符避免语义割裂)。

第二阶段是用Cross-Encoder,也就是rerank模型做语义精排,综合语义、上下文和任务特征,将最相关的文档排到前列,减少噪声干扰。效果是Top10准确率从78%→91%(对比单Embedding检索),MRR 从 0.52 提高至 0.78。

上面的rerank模型,可以是bge-small,或者为了追求更高精度,可把 rerank 模型换成 BGE-reranker-large(+2 % MRR,-10 QPS)。

  1. 多轮对话上下文管理: 为解决原有系统上下文对话能力弱的情况,设计 Context Injection 机制,对用户的跟进提 问自动关联上下文实体并替换代词,这种实体识别 + 指代消解 + 语义桥接(HanLP(NER命名实体识别。) + bert-coref-chinese(指代) + 规则桥接)的策略显著提升了多轮对话的连贯性。
Details

#NER
pip install hanlp
import hanlp
hanlp_ner = hanlp.load(hanlp.pretrained.ner.MSRA_NER_BERT_BASE_ZH)
spans = hanlp_ner("我想查下我的信用卡账单")   # [{'text':'信用卡','type':'PROD'}]
中文 13 类实体人名/机构/产品/金额/日期等),F194%GPU  5 ms#指代消解
pip install coref-hoi==1.0   # 已打包模型
from coref_hoi import pipeline
coref = pipeline("zh-coref-bert-base")
clusters = coref("我的信用卡逾期了,它还能用吗?")   # 返回 [[(0,3),(7,8)]]  # 信用卡-它
单句 10 ms若置信度 < 0.6 自动回退最近实体规则防止误链#语义桥接(替换/补全)
纯规则 + 依存检查不跑模型-  HanLP 依存句法判断主语/宾语空缺- 实体池权重 = 出现次数 + 时间衰减 Top1 实体- 原地字符串替换或句首插入生成新 query

  1. 业务闭环验证

F1计算公式:
Precision = TP / (TP + FP) → 生成的事实里多少是对的
Recall = TP / (TP + FN) → 所有该说的事实里说了多少
F1 = 2 · P · R / (P + R)

TP = 命中事实数
FP = 生成答案里多出来的虚假/错误事实数
FN = 金标准里未被召回的事实数

提升23%原因:与纯大模型对比
纯大模型常“自由发挥”→ FP 高、遗漏关键点 → FN 也高;本项目用检索+重排+引用限制,先生成有出处的答案,再算事实 F1,因此 FP 大幅下降,F1 提升 23 个百分点。

LLM Agent

Agent 的工作流程如下:

接收用户输入。
调用大模型(如 Qwen),并告知其可用的工具及其 Schema。
如果模型决定调用工具,Agent 会解析请求,执行相应的 Python 函数。
Agent 将工具的执行结果返回给模型。
模型根据工具结果生成最终回复。
Agent 将最终回复返回给用户。

agent如何记住历史信息:
「在线用向量/Key-Value 做短时检索 → 定期摘要/结构化转长时记忆 → 必要时把高价值数据再喂回模型权重」