news 2026/8/27 15:42:17

【干货收藏】RAG技术详解:让本地大模型不再“凭空捏造“,实时检索生成答案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【干货收藏】RAG技术详解:让本地大模型不再“凭空捏造“,实时检索生成答案

前言

RAG =「先查资料,再写答案」的 AI 工作模式。

它把「检索系统」和「大模型」结合起来,让模型不用全靠记忆,而是实时查找外部知识再生成回答,从而更准确、更可信。为什么建议在本地化的大模型中增加RAG叠加,就是这样原因。在Deepseek使用过程中,也会有联网查询这一个功能,如果本地化部署没有增加数据库训练和RAG叠加,后续的回答只能基于原来训练的内容进行回答,会导致回答空洞、无法接入企业/个人知识,没有达到本地化部署、细分领域专用的效果。

RAG的工作流程可以总结如下:

核心结构:用户问题 → 检索器(Vector DB / BM25)→ 文本片段 → 组装 Prompt → 大模型 → 回答

目前RAG的检索方式主要为以下三种:

举个简单的例子:

问题:“写一个R函数,按组计算均值和95%CI。”

传统模型 → 可能瞎写,也可能不是很准确,存在一定的误差

RAG → 检索数据库中已有的 R 代码片段(如 dplyr / broom / summarise 函数示例)

然后拼接 Prompt:

参考以下代码片段: [1] file/path/stats_utils.R#3 #' 计算均值和置信区间 calc_ci <- function(vec, conf=0.95) { ... } 现在回答问题: 写一个R函数,按组计算 mean 和 95% CI(输入 dataframe 和 group 列)

→ 模型输出会更加准确 + 风格一致 + 易维护;特别是个人使用时,越用越贴近自己的风格(前提是提供RAG的内容是个人的代码或者个人风格的内容)。

接下来举例LLM-Coder,代码助手的RAG叠加的操作:

流程:语料收集 → 清洗切块 → 向量化(+BM25)→ 检索 → 交叉重排 → 拼接上下文 → 本地小模型生成

第 1 步:准备语料(代码 + 文档)

1.拉你要用的 GitHub 仓库(或拷贝企业内部仓)

2.只保留:.py、.R、.ipynb(抽代码单元)、.md、.Rmd、设计文档 / 指南 PDF(可先转文本)

3.去重:同内容哈希;过滤:dist/ build/ .ipynb_checkpoints/ 之类生成物

代码分块原则(很重要):按“函数/类/文件内标题”切块,而不是盲目固定长度;每块附文件路径+起止行号元数据;R 的 roxygen2 注释、Python 的 docstring 作为上下文优先保留;

第 2 步:创建本地向量库(FAISS)

安装必要的库:

pip install sentence-transformers faiss-cpu rank_bm25 unstructured pypdf

接下来使用python脚本进行创建:

# build_index.py import os, json, re, faiss from pathlib import Path from rank_bm25 import BM25Okapi from sentence_transformers import SentenceTransformer from tqdm import tqdm SRC_DIR = "corpus" # 你整理好的语料根目录 IDX_DIR = "rag_index" # 索引输出目录 EMB_NAME = "BAAI/bge-small-zh-v1.5" # 中文场景;英文用 bge-small-en-v1.5 os.makedirs(IDX_DIR, exist_ok=True) # -------- 1) 收集并“按函数/段落”切块 -------- def split_code_blocks(text, lang): # 极简切块:按函数/类/roxygen 标题等;你可换成更强的 AST 切块器 if lang == "python": pat = r"(?m)^(def |class )" elif lang == "r": pat = r"(?m)^(#'|[a-zA-Z0-9_]+\s*<-function)" else: pat = r"(?m)^#{1,6}\s|^$" chunks, buf = [], [] for line in text.splitlines(): if re.search(pat, line) and buf: chunks.append("\n".join(buf)); buf=[line] else: buf.append(line) if buf: chunks.append("\n".join(buf)) # 限长再切 out=[] for c in chunks: if len(c) < 2000: out.append(c) else: for i in range(0, len(c), 1500): out.append(c[i:i+1800]) return out def walk_corpus(): docs=[] for p in Path(SRC_DIR).rglob("*"): if p.suffix.lower() in [".py",".r",".md",".rmd",".txt"]: txt = p.read_text(errors="ignore", encoding="utf-8", newline=None) lang = "python" if p.suffix==".py" else ("r" if p.suffix==".r" else "md") blocks = split_code_blocks(txt, lang) for bi, b in enumerate(blocks): docs.append({ "text": b.strip(), "meta": {"path": str(p), "block_id": bi, "lang": lang} }) return docs docs = walk_corpus() with open(f"{IDX_DIR}/corpus.jsonl","w",encoding="utf-8") as f: for d in docs: f.write(json.dumps(d,ensure_ascii=False)+"\n") print("chunks:", len(docs)) # -------- 2) 向量化 + FAISS -------- model = SentenceTransformer(EMB_NAME) # 默认走 CPU,可用 .to("cuda")(显存允许) embs = model.encode([d["text"] for d in docs], batch_size=64, show_progress_bar=True, normalize_embeddings=True) d = embs.shape[1] index = faiss.IndexFlatIP(d) # 归一化后用内积=余弦 index.add(embs) faiss.write_index(index, f"{IDX_DIR}/faiss.index") with open(f"{IDX_DIR}/meta.json","w",encoding="utf-8") as f: json.dump({"emb_model":EMB_NAME, "count":len(docs)}, f, ensure_ascii=False, indent=2) # -------- 3) BM25(可选混合检索)-------- bm25 = BM25Okapi([d["text"].split() for d in docs]) import pickle; pickle.dump({"bm25":bm25, "docs":docs}, open(f"{IDX_DIR}/bm25.pkl","wb")) print("done.")

第 3 步:检索 + 重排 + 调用本地 LLM

先装一个轻量重排器(可关掉以换速度):

pip install cross-encoder

查询脚本(支持向量检索 + 可选 BM25 混合 + 重排):

# query_rag.py import json, faiss, numpy as np, pickle from sentence_transformers import SentenceTransformer, CrossEncoder from pathlib import Path import requests IDX_DIR = "rag_index" OLLAMA_URL = "http://localhost:11434/api/generate" # 先启动 ollama meta = json.load(open(f"{IDX_DIR}/meta.json","r",encoding="utf-8")) docs = [json.loads(l) for l in open(f"{IDX_DIR}/corpus.jsonl","r",encoding="utf-8")] index = faiss.read_index(f"{IDX_DIR}/faiss.index") emb_model = SentenceTransformer(meta["emb_model"]) try: bm25_pack = pickle.load(open(f"{IDX_DIR}/bm25.pkl","rb")) bm25, bm_docs = bm25_pack["bm25"], bm25_pack["docs"] except: bm25=None # 可选重排(CPU 也能跑,慢时可关闭) try: reranker = CrossEncoder("BAAI/bge-reranker-base") except: reranker = None def retrieve(query, topk=6, mix_bm25=True): qv = emb_model.encode([query], normalize_embeddings=True) D,I = index.search(qv, topk) cand = [docs[i] for i in I[0]] if mix_bm25 and bm25: bm = bm25.get_top_n(query.split(), bm_docs, n=topk) cand = cand + bm # 重排 if reranker: pairs = [(query, c["text"]) for c in cand] scores = reranker.predict(pairs) ranked = [c for _,c in sorted(zip(scores,cand), key=lambda x:-x[0])] return ranked[:topk] return cand[:topk] PROMPT = """你是代码助手。请仅依据“参考上下文”,用{lang}给出解决方案,并简短解释。 问题:{question} 参考上下文(可能不完整,请择要引用文件路径): {context} 要求: 1) 先给核心代码;2) 再解释关键点;3) 如引用到文件,请标注 path#blockid。 """ def ask_llm(model_tag, prompt): resp = requests.post(OLLAMA_URL, json={"model": model_tag, "prompt": prompt, "stream": False}) return resp.json()["response"] if __name__=="__main__": question = "用R写一个函数:分组计算均值和95%CI,并返回整洁表(tidy)。" lang = "R" cands = retrieve(question, topk=8, mix_bm25=True) ctx = "\n\n---\n".join([f"[{i}] {c['meta']['path']}#b{c['meta']['block_id']}\n{c['text'][:1200]}" for i,c in enumerate(cands)]) prompt = PROMPT.format(lang=lang, question=question, context=ctx) print(ask_llm("deepseek-r1:1.5b", prompt))

先起 LLM:

# (个人电脑安装的1.5B模型)CMD输入: ollama pull deepseek-r1:1.5b ollama run deepseek-r1:1.5b

第 4 步:提高检索高命中

  • Hybrid 检索:向量 + BM25 混合(上面已示范);代码类问题对关键字很敏感
  • 代码块切分更智能:有余力的话用 AST/语法树分块器(按函数、类、导出对象)
  • 去噪与权重:README、示例/测试、roxygen/docstring 给予更高“候选优先级”
  • 重排器可选:小型交叉编码器离线即可;嫌慢就把重排改成轻量(如 Cosine + Heuristic)
  • Prompt 模板固定:始终要求“先代码、后解释、引用路径”,可极大降低幻觉
  • 缓存:对 embeddings 和检索结果做本地缓存(SQLite/磁盘),多次问答更快

第 5 步:评估与迭代

  • 小题集:自建 50–200 条“问题→期望代码/断言”的集合(Python 用pytest,R 用testthat
  • 三类指标
  1. 检索命中率(是否找到包含答案的块)
  2. 重排质量(相关块是否排在前 3)
  3. 执行通过率(生成代码跑单测是否通过)
  • 闭环:错误样本加入“补充语料/FAQ/模板代码” → 重新嵌入 → 索引刷新

最后

为什么要学AI大模型

当下,⼈⼯智能市场迎来了爆发期,并逐渐进⼊以⼈⼯通⽤智能(AGI)为主导的新时代。企业纷纷官宣“ AI+ ”战略,为新兴技术⼈才创造丰富的就业机会,⼈才缺⼝将达 400 万!

DeepSeek问世以来,生成式AI和大模型技术爆发式增长,让很多岗位重新成了炙手可热的新星,岗位薪资远超很多后端岗位,在程序员中稳居前列。

与此同时AI与各行各业深度融合,飞速发展,成为炙手可热的新风口,企业非常需要了解AI、懂AI、会用AI的员工,纷纷开出高薪招聘AI大模型相关岗位。

最近很多程序员朋友都已经学习或者准备学习 AI 大模型,后台也经常会有小伙伴咨询学习路线和学习资料,我特别拜托北京清华大学学士和美国加州理工学院博士学位的鲁为民老师给大家这里给大家准备了一份涵盖了AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频全系列的学习资料,这些学习资料不仅深入浅出,而且非常实用,让大家系统而高效地掌握AI大模型的各个知识点。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

AI大模型系统学习路线

在面对AI大模型开发领域的复杂与深入,精准学习显得尤为重要。一份系统的技术路线图,不仅能够帮助开发者清晰地了解从入门到精通所需掌握的知识点,还能提供一条高效、有序的学习路径。

但知道是一回事,做又是另一回事,初学者最常遇到的问题主要是理论知识缺乏、资源和工具的限制、模型理解和调试的复杂性,在这基础上,找到高质量的学习资源,不浪费时间、不走弯路,又是重中之重。

AI大模型入门到实战的视频教程+项目包

看视频学习是一种高效、直观、灵活且富有吸引力的学习方式,可以更直观地展示过程,能有效提升学习兴趣和理解力,是现在获取知识的重要途径


光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

海量AI大模型必读的经典书籍(PDF)

阅读AI大模型经典书籍可以帮助读者提高技术水平,开拓视野,掌握核心技术,提高解决问题的能力,同时也可以借鉴他人的经验。对于想要深入学习AI大模型开发的读者来说,阅读经典书籍是非常有必要的。

600+AI大模型报告(实时更新)

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

AI大模型面试真题+答案解析

我们学习AI大模型必然是想找到高薪的工作,下面这些面试题都是总结当前最新、最热、最高频的面试题,并且每道题都有详细的答案,面试前刷完这套面试题资料,小小offer,不在话下

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/27 15:40:37

大疆热红外影像转温度GeoTIFF的R-JPEG解析与Pix4D合成实践

简介&#xff1a;无人机遥感中的热红外成像技术常被用于地表温度监测与农业植保&#xff0c;而大疆H20T、XT2等相机输出的R-JPEG格式并非普通图像&#xff0c;温度数据以私有元数据形式封装在JPEG容器内。要获得真实温度&#xff0c;需解析JPEG中的Ancillary Data&#xff0c;提…

作者头像 李华
网站建设 2026/8/27 15:39:32

AI Agent工具调用安全:预执行门禁的设计与实现

如果你正在把一个 AI Agent 接进生产环境&#xff0c;有一件事迟早会拦在你面前&#xff1a;你怎么确认模型生成的工具调用不会删库、发邮件、写坏文件&#xff0c;或者把敏感数据暴露给不该看的人&#xff1f;靠提示词约束&#xff0c;靠模型自觉&#xff0c;靠事后审计&#…

作者头像 李华
网站建设 2026/8/27 15:39:20

4399手游模拟器推荐 玩4399手游用什么模拟器好

不少情怀玩家偏爱游玩4399系列手游&#xff0c;手机游玩却常受发热、运行卡顿等问题困扰&#xff0c;选对适配的4399手游模拟器&#xff0c;就能彻底改善这类游玩体验。市面上多数模拟器对4399手游适配优化不足&#xff0c;容易出现兼容出错、画面模糊等问题&#xff0c;哪款43…

作者头像 李华
网站建设 2026/8/27 15:39:06

基于ONNXRuntime的YOLOv8 C++部署:检测、分割、旋转框全攻略

简介&#xff1a;深度学习模型的工程落地往往面临跨语言、跨平台的挑战&#xff0c;而推理引擎的选择直接决定部署效率与兼容性。ONNXRuntime作为跨平台推理框架&#xff0c;能够统一加载目标检测、实例分割等任务模型&#xff0c;配合OpenCV完成图像预处理与结果可视化&#x…

作者头像 李华
网站建设 2026/8/27 15:37:31

用 JPEXS Free Flash Decompiler 做 SWF 反编译与资源提取

用 JPEXS Free Flash Decompiler 做 SWF 反编译与资源提取 【免费下载链接】jpexs-decompiler JPEXS Free Flash Decompiler 项目地址: https://gitcode.com/gh_mirrors/jp/jpexs-decompiler JPEXS Free Flash Decompiler&#xff08;社区常简称为 FFDec&#xff09;是一…

作者头像 李华