检索增强生成 RAG

检索增强生成(Retrieval-Augmented Generation,RAG) 是一种将信息检索大语言模型生成 深度融合的 AI 技术框架,核心是让模型先查资料、再写答案 ,从根本上解决大模型的知识过时、幻觉、隐私安全三大痛点。

一、核心定位与诞生背景

RAG 本质是为大模型搭建外部动态知识库,让模型不再依赖 "死记硬背" 的训练数据,而是按需检索外部权威信息后生成回答。

  • 解决的核心问题:
    1. 知识截止:大模型训练数据固定,无法获取训练后新信息。
    2. 幻觉:模型编造虚假、无依据的内容。
    3. 隐私与成本:企业私有数据不能上传公共模型,全量微调成本极高。

二、核心工作流程(四步闭环)

1. 知识库构建(离线)
  • 数据处理:将文档、网页、数据库等非结构化数据清洗、分块(Chunk)。
  • 向量化 :用嵌入模型(Embedding Model)将文本转为向量,存入向量数据库(如 Milvus、Pinecone、FAISS)。
  • 索引:构建高效检索索引,支持语义相似度查询。
2. 查询处理(在线)
  • 用户输入问题 → 转为查询向量 → 向量数据库做语义检索 → 召回 Top-K 最相关的文档片段。
3. 上下文增强
  • 用户问题 + 检索到的参考资料拼接成增强 Prompt,作为大模型输入。
4. 增强生成
  • 大模型基于 "问题 + 参考资料" 生成回答,可附带引用来源,提升可信度。

三、核心技术组件

表格

组件 作用 常见选型
嵌入模型 文本→向量,决定检索精度 BGE、text-embedding-ada-002、E5
向量数据库 存储与高效检索向量 Milvus、Pinecone、Weaviate、FAISS
检索器 语义匹配、召回相关片段 BM25 + 向量混合检索、重排序(Rerank)
生成模型 基于上下文生成回答 GPT、Llama、文心一言、通义千问
重排序模型 对召回结果二次排序,提升相关性 CrossEncoder、BGE-Reranker

四、核心优势

  1. 事实准确、减少幻觉:回答基于检索到的真实资料,可溯源。
  2. 知识实时更新:无需重新训练模型,仅更新向量库即可接入新数据。
  3. 隐私安全可控:私有数据本地存储,不泄露给公共模型。
  4. 成本极低:替代全量微调,仅需轻量级向量化与检索流程。
  5. 垂直领域适配强:快速接入医疗、法律、企业内部文档等专业知识。

五、主流应用场景

  • 企业知识库问答:员工查询内部制度、产品手册、技术文档。
  • 智能客服:基于产品文档、FAQ 生成精准回复。
  • 法律 / 医疗专业问答:结合最新法规、医学文献生成专业回答。
  • 内容创作:基于参考资料生成报告、文案、摘要。
  • 多模态 RAG:检索图片、视频、音频等多模态信息并生成回答。

六、RAG vs 微调(Fine-tuning)

表格

维度 RAG 微调
知识更新 实时、低成本(更新向量库) 慢、高成本(重新训练)
隐私 数据本地存储,安全可控 数据需上传训练,隐私风险高
幻觉控制 强(基于检索资料) 弱(依赖训练数据)
适用场景 知识频繁更新、私有数据、专业领域 通用能力增强、风格对齐

七、演进方向

  • 高级 RAG:混合检索(BM25 + 向量)、多轮对话 RAG、GraphRAG(知识图谱 + RAG)。
  • 端到端优化:检索与生成联合训练、动态上下文窗口、引用验证。
  • 多模态 RAG:支持文本、图像、音频、视频的跨模态检索与生成。

1. 文档解析器(DocumentParser):搞定多格式文档读取

1.1 核心作用

将不同格式的二进制文件(PDF/DOCX/PPTX 等)解析为 LangChain4j 统一的 Document 对象(包含文本内容 + 元数据,如文件路径、格式、创建时间等),解决「不同格式文件无法统一处理」的问题。

1.2 常见实现类(按场景选型)

表格

解析器类名 所属模块 支持格式 适用场景 优缺点
TextDocumentParser langchain4j 核心模块 TXT、MD、HTML、JSON 等纯文本 纯文本文件解析 轻量、无额外依赖;仅支持纯文本
ApachePdfBoxDocumentParser langchain4j-document-parser-apache-pdfbox PDF 单页 / 多页 PDF 解析 解析精度高;需引入 PDFBox 依赖
ApachePoiDocumentParser langchain4j-document-parser-apache-poi DOC、DOCX、PPT、PPTX、XLS、XLSX 微软 Office 文件 覆盖全 Office 格式;依赖稍重
ApacheTikaDocumentParser langchain4j-document-parser-apache-tika 几乎所有格式(PDF/Office/ 图片 / 音频等) 格式不固定的混合场景 万能解析;依赖最大、速度稍慢

1.3 核心使用方式(代码实操)

第一步:添加对应依赖(Maven)

xml

复制代码
<!-- 核心依赖(纯文本解析) -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j</artifactId>
    <version>0.32.0</version> <!-- 建议用最新版 -->
</dependency>

<!-- PDF解析依赖 -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-document-parser-apache-pdfbox</artifactId>
    <version>0.32.0</version>
</dependency>

<!-- Office解析依赖 -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-document-parser-apache-poi</artifactId>
    <version>0.32.0</version>
</dependency>

<!-- 万能解析依赖(Tika) -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-document-parser-apache-tika</artifactId>
    <version>0.32.0</version>
</dependency>
第二步:解析文档的常用 API

java

运行

复制代码
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import dev.langchain4j.data.document.parser.apache.pdfbox.ApachePdfBoxDocumentParser;
import dev.langchain4j.data.document.parser.apache.poi.ApachePoiDocumentParser;
import dev.langchain4j.data.document.parser.TextDocumentParser;

import java.nio.file.FileSystems;
import java.nio.file.PathMatcher;
import java.util.List;

public class DocumentParserDemo {
    public static void main(String[] args) {
        // 1. 解析单个纯文本文档(TXT/MD)
        Document txtDoc = FileSystemDocumentLoader.loadDocument(
                "E:/knowledge/file.txt", 
                new TextDocumentParser()
        );

        // 2. 解析单个PDF文档
        Document pdfDoc = FileSystemDocumentLoader.loadDocument(
                "E:/knowledge/医院信息.pdf", 
                new ApachePdfBoxDocumentParser()
        );

        // 3. 解析单个Word文档
        Document docxDoc = FileSystemDocumentLoader.loadDocument(
                "E:/knowledge/产品手册.docx", 
                new ApachePoiDocumentParser()
        );

        // 4. 加载指定目录下所有纯文本文档
        List<Document> allTxtDocs = FileSystemDocumentLoader.loadDocuments(
                "E:/knowledge", 
                new TextDocumentParser()
        );

        // 5. 加载指定目录下仅.txt后缀的文档(按规则过滤)
        PathMatcher txtMatcher = FileSystems.getDefault().getPathMatcher("glob:*.txt");
        List<Document> filterTxtDocs = FileSystemDocumentLoader.loadDocuments(
                "E:/knowledge", 
                txtMatcher, 
                new TextDocumentParser()
        );

        // 6. 递归加载目录+子目录下所有文档
        List<Document> recursiveDocs = FileSystemDocumentLoader.loadDocumentsRecursively(
                "E:/knowledge", 
                new ApachePdfBoxDocumentParser() // 解析PDF
        );

        // 打印解析结果(查看文本内容和元数据)
        System.out.println("PDF文档内容:" + pdfDoc.text());
        System.out.println("PDF文档元数据:" + pdfDoc.metadata());
    }
}

2. 文档分割器(DocumentSplitter):把长文本切成小片段

2.1 核心作用

解析后的文档可能是几万 / 几十万字的长文本,直接向量化会超出大模型上下文窗口,也会降低检索精度。文档分割器的作用是:

  • 将长文本分割成固定长度的文本片段(TextSegment);
  • 保留重叠部分(如 30 个 token),保证片段间的语义连贯性;
  • 若单个单元(段落 / 句子)过长,自动调用子分割器进一步拆分。

2.2 常见实现类(按分割粒度选型)

表格

分割器类名 分割粒度 核心参数 适用场景
DocumentByParagraphSplitter 段落(连续 2 个以上换行符分隔) 最大长度、重叠长度、分词器 结构化文档(如手册、论文)
DocumentByLineSplitter 同上 日志、代码文件、表格类文本
DocumentBySentenceSplitter 句子(基于 OpenNLP) 同上 文学文本、对话类内容
DocumentByWordSplitter 单词 同上 短文本、外文文档
DocumentByCharacterSplitter 字符 同上 简单文本、无复杂结构的内容
DocumentSplitters.recursive() 递归分割(段落→行→句子→单词) 同上 通用场景(默认推荐)

2.3 核心概念:Token vs 字符

  • 字符:按文字个数计算(如 "你好"=2 个字符),简单但忽略语义;
  • Token:按语义单元分割(如 "人工智能"=1 个 token,"机器学习"=1 个 token),更贴合大模型的处理逻辑;
  • LangChain4j 中可通过 HuggingFaceTokenizer 实现 Token 计算,推荐优先用 Token 而非字符定义片段长度。

2.4 核心使用方式(代码实操)

复制代码
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import dev.langchain4j.data.document.parser.TextDocumentParser;
import dev.langchain4j.data.document.splitter.DocumentByParagraphSplitter;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddedTextStore;
import dev.langchain4j.model.embedding.InMemoryEmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import dev.langchain4j.tokenizer.HuggingFaceTokenizer;

import java.util.List;

public class DocumentSplitterDemo {
    public static void main(String[] args) {
        // 1. 加载并解析文档
        Document document = FileSystemDocumentLoader.loadDocument(
                "E:/knowledge/人工智能.md",
                new TextDocumentParser()
        );

        // 2. 方式1:使用默认递归分割器(推荐)
        // 默认:最大300token,重叠30token,递归拆分(段落→行→句子→单词)
        List<TextSegment> defaultSegments = DocumentSplitters.recursive()
                .maxSegmentSize(300)  // 每个片段最大token数
                .overlapSize(30)       // 片段间重叠token数
                .split(document);

        // 3. 方式2:自定义按段落分割器(指定Token计算)
        DocumentByParagraphSplitter paragraphSplitter = new DocumentByParagraphSplitter(
                300,                  // 最大Token数
                30,                   // 重叠Token数
                new HuggingFaceTokenizer() // Token分词器
        );
        List<TextSegment> paragraphSegments = paragraphSplitter.split(document);

        // 4. 分割后直接入库(向量化+存储一步到位)
        EmbeddedTextStore embeddingStore = new InMemoryEmbeddingStore<>();
        // Ingestor:分割→向量化→存储
        EmbeddingStoreIngestor.ingest(document, embeddingStore);

        // 打印结果
        System.out.println("默认分割后的片段数:" + defaultSegments.size());
        System.out.println("第一个片段内容:" + defaultSegments.get(0).text());
        System.out.println("向量库中存储的片段数:" + embeddingStore.count());
    }
}

2.5 分割器工作流程(关键)

  1. 初始化分割器,指定最大片段长度 (Token / 字符)和重叠长度
  2. 按分割粒度拆分文档(如段落分割器先拆成段落);
  3. 将小单元(段落 / 句子)组合成片段,不超过最大长度;
  4. 若单个单元过长(如一个段落 500token),调用子分割器(如行分割器)继续拆分;
  5. 为每个片段添加唯一index元数据,保证顺序;
  6. 输出最终的TextSegment列表,用于后续向量化。

总结(核心关键点)

  1. 文档解析器 :核心是「格式兼容」,根据文件类型选对应实现(PDF 用 PDFBox、Office 用 POI、混合格式用 Tika),最终输出统一的Document对象;
  2. 文档分割器:核心是「粒度控制」,优先用默认递归分割器,按 Token 定义片段长度(推荐 300-500token),保留 10%-20% 的重叠长度保证语义连贯;
  3. 实操关键:解析和分割是 RAG 数据预处理的基础,解析不完整会导致知识缺失,分割不合理会降低检索精度,需根据文档类型(结构化 / 非结构化)调整分割策略。

如果需要,我可以补充「解析 + 分割 + 向量化 + 检索」的完整 RAG 流程代码,或者针对某类文档(如复杂 PDF、多表格 Word)的解析优化方案。

相关推荐
OpenCSG1 小时前
什么是模型管理平台?从大模型治理走向企业级OPC平台
大数据·人工智能·opencsg
bitbrowser2 小时前
AI搜索可见性:如何让产品在ChatGPT和DeepSeek里被优先展示?
人工智能·chatgpt
sdyeswlw2 小时前
案例直击|一二三物联网 2025 三大经典项目,解锁物联赋能新场景
大数据·网络·人工智能
软件工程小施同学2 小时前
区块链可投会议CCF B--ICWS 2026 截止3.8
人工智能
万能菜道人2 小时前
学习Lora训练的个人记录
人工智能·学习
x-cmd2 小时前
[x-cmd] Firefox 148 发布 AI 开关,支持一键禁用 AI 功能
人工智能·ai·firefox·agent·x-cmd
ActionTech2 小时前
2026 年 AI 预言:幻觉监管、GPU 现实撞墙与 “广告版” ChatGPT 的到来
人工智能·chatgpt
sundaygeek2 小时前
高通机器人AI硬件使用上手指导(基于RB5开发套件)
人工智能·机器人
Scott.W2 小时前
跟我学Easyi3C Tower Adapter Console(9)
人工智能·python·嵌入式硬件·i3c