首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【大模型学习 | RAG & DeepSeek 实战(二)】

【大模型学习 | RAG & DeepSeek 实战(二)】

原创
作者头像
九年义务漏网鲨鱼
发布2025-07-20 15:17:48
发布2025-07-20 15:17:48
75900
代码可运行
举报
运行总次数:0
代码可运行

Deepseek & RAG 实战(二)

【大模型学习 | RAG & DeepSeek 实战】-腾讯云开发者社区-腾讯云文章中,已经实现了基于RAG建立了本地知识库,通过检索相似度最高的知识来辅助大模型的问答系统。但是,在知识检索和向量存储方面,依然存在着许多不足。例如,在检索向量方面,原文只采用了向量召回的方式,无法满足对于关键词的检索;在存储方面,原文是没有采用任何存储策略的,这也意味着每次加载pdf知识库时都需要重新向量化。为此,基于以上问题,本章对问答系统实现进一步的优化。

🧩 检索优化

原始代码(向量召回),属于单阶段的检索
代码语言:python
代码运行次数:0
运行
复制
def retrieve_docs(query, k=3):
    """检索最相关的k个段落"""
    query_vec = model.encode([query])
    D, I = index.search(query_vec, k=k)  # D是距离,I是索引
    return [paragraphs[i] for i in I[0]]

✅ 能理解语义:能找到与 query 相近含义的段落,即使不含相同词语

❌ 容易忽略语义不相近,但有明显的关键词重合;语义相似≠语用相近,尤其在法律、金融等领域问题突出

因此,向量召回可能遇到以下问题:

用户输入

单向量召回可能错在哪

“2024年湖北省大学生竞赛奖金是多少?”

文中提的是“省部级奖励金额”,但向量模型可能找不到这段

“我想了解奖助学金政策”

向量模型找“奖学金”段落,但“助学金”是关键词

“获得奖项后的政策支持?”

多个段落提到奖项,但真正写“支持”措施的段落可能被漏掉

🔍 BM25(关键词召回)

BM25是一个词项的检索匹配算法,通过对比查询与目标段落之间的词项,相同词项越多越相关,但例如the、a等关键词会频繁出现,因此在关键词出现太多时贡献度也会衰减。是TF-IDF算法的改进版。

  • 代码
代码语言:python
代码运行次数:0
运行
复制
def retrieve(self, query, k=5, bm25_k=10):
    bm25_scores = self.bm25.get_scores(query.split())
    bm25_topk_idx = np.argsort(bm25_scores)[::-1][:bm25_k]
🧱 Rerank(重排序)

目前可以分别从两个召回器(Faiss + BM25)拿到了不同或者相同的段落,从原先的单通道召回变成了多通道召回。但是,还需要分别从两个召回器中判断哪几段是“最适合回答 query 的。这时候引入rerank 模型(如 BGE-Reranker、ColBERT),对多个段落的得分进行重排序,具体实现:

1️⃣ 将 (query, paragraph) 成对送入 BERT/Transformer 分类器

2️⃣ 得到语义相关性分数

3️⃣ 排序并只保留前几条

  • 代码
代码语言:python
代码运行次数:0
运行
复制
def retrieve(self, query, k=5, bm25_k=10):
    # 向量召回
    query_vec = model.encode([query])
    D, I = index.search(query_vec, k=k)  # D是距离,I是索引
    vec_topk_idx = I[0]
    # return [paragraphs[i] for i in I[0]]
    
    bm25_scores = self.bm25.get_scores(query.split())
    bm25_topk_idx = np.argsort(bm25_scores)[::-1][:bm25_k]
    
    candidate_idxs = list(set(bm25_topk_idx.tolist() + vec_topk_idx.tolist()))
    candidate_vecs = self.embeddings[candidate_idxs]
    query_vec = query_vec / np.linalg.norm(query_vec)  # 归一化
    candidate_vecs = candidate_vecs / np.linalg.norm(candidate_vecs, axis=1, keepdims=True)
    scores = np.dot(candidate_vecs, query_vec.T).squeeze()

    sorted_idx = np.argsort(scores)[::-1]
    reranked_idxs = [candidate_idxs[i] for i in sorted_idx[:k]]

    return [self.paragraphs[i] for i in reranked_idxs]

模块

能力

Faiss 向量检索

找泛义相近文本(Recall 全面)

BM25 检索

找关键词重合文本(Recall 准确)

Reranker

对 Recall 候选排序,挑出真正语义匹配(Precision

🧩 存储优化

原始代码(向量未缓存保存与加载)

🔴 每次都要重新 encode → 慢、重复。

代码语言:python
代码运行次数:0
运行
复制
doc_embeddings = model.encode(paragraphs)
index.add(doc_embeddings)
🔍 保存为本地向量库
代码语言:python
代码运行次数:0
运行
复制
import pickle

with open("docs.pkl", "wb") as f:
    pickle.dump({"paragraphs": paragraphs, "embeddings": doc_embeddings}, f)

# 加载
with open("docs.pkl", "rb") as f:
    cache = pickle.load(f)
    paragraphs = cache["paragraphs"]
    doc_embeddings = cache["embeddings"]
index = faiss.IndexFlatL2(dimension)
index.add(doc_embeddings)
🧠 存储优化

当保存的向量超过几千上万条,内存和查询速度都成问题. 为此,需要对存储向量进行压缩.在原来的代码中,我们没有采用任何的向量压缩,采用了最简单和最基础的检索方式IndexFlatL2,通过欧氏距离进行相似度计算,为了加快检索速度, faiss提供了多种压缩方式:

必须了解底层原理(尤其你是大模型工程师/向量检索方向):

算法

核心思想

应用场景

PQ(Product Quantization)

将向量拆分成多个子向量 → 用 8bit 表示每个子块

超大数据量,压缩向量

IVF(Inverted File)

建立多个“中心点”(聚类),每次只在最近的几个中心中搜索

百万级向量库

HNSW(Hierarchical Navigable Small World)

建图搜索 → 多层邻居结构加速搜索

实时性高、近似搜索

OPQ(优化 PQ)

比 PQ 更强的压缩(旋转+重组)

更高精度压缩

1️⃣ Faiss 的压缩索引(PQ)
  • 将向量拆分成多个子向量 → 用 8bit 表示每个子块
代码语言:python
代码运行次数:0
运行
复制
index = faiss.IndexPQ(d, M=8, nbits=8)
  • d: 向量维度(如 384)
  • M: 子向量数量(压缩块)
  • nbits: 每块用几位表示(8bit)
2️⃣ Faiss 的 HNSW/IVF 加速结构: 建图结构用于近似快速检索(不是压缩,但更快),可与压缩同时用
  • IVF : 建立多个“中心点”(聚类),每次只在最近的几个中心中搜索
  • HNSW : 建图搜索 → 多层邻居结构加速搜索
代码语言:python
代码运行次数:0
运行
复制
quantizer = faiss.IndexFlatL2(d)
index = faiss.IndexIVFFlat(quantizer, d, nlist=100)
# index = faiss.IndexIVFPQ(quantizer, dimension, nlist, m, nbits) 压缩 + 近似
index.train(doc_embeddings)
index.add(doc_embeddings)

写在最后:

✅ 本章中实现了对检索和存储方面的优化, 加强了问答系统的检索能力以及存储能力;

✅ 若有该项目的代码需求,可以三连获取 ❗❗❗

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Deepseek & RAG 实战(二)
    • 🧩 检索优化
      • 原始代码(向量召回),属于单阶段的检索
      • 🔍 BM25(关键词召回)
      • 🧱 Rerank(重排序)
    • 🧩 存储优化
      • 原始代码(向量未缓存保存与加载)
      • 🔍 保存为本地向量库
      • 🧠 存储优化
    • 写在最后:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档