第三章-RAG知识库基础

100 阅读6分钟

本文仅用于记录学习笔记,知识来源:程序员鱼皮的超级智能体课程

一、AI问答常见场景

  • 电商场景、商品推荐
  • 教育场景
  • 法律咨询、基础法律条例
  • 金融行业、个性化理财
  • 医疗行业、病情初步诊断参考
  • 科研、资料查询、研究建议

二、RAG概念

对于AI问答,我们可以考虑一下,AI如何回答我们的问题,他的依据是什么,来源就是知识,AI本身具有一些通用知识,对于不会的问题可以联网查询,如何让AI的回答更有专业性和个性,这就需要知识库的存在,AI利用知识库进行问答效果更好更个性化。

如何让AI利用自己的知识库来进行问答呢? 这就要用到AI主流技术——RAG

1.什么是RAG

RAG(检索增强生成)是结合检索技术和AI内容生成的混合框架,可以解决大模型的知识时效性限制幻觉问题,可以保证AI根据知识库来回答而不是凭空捏制造

RAG与传统AI模型的区别: image.png

2.RAG的工作流程

  • 文档收集和切割
  • 向量转换和存储
  • 文档过滤和检索
  • 查询增强和关联

屏幕截图 2025-07-20 010912.png

3.RAG相关技术

Embedding和Embedding模型

Embedding嵌入是将高维的离散数据(如文字图片)在转换为低纬度的连续向量的过程。这些向量在数学空间中能表示原始数据的语义特征,使得计算机可以理解数据之间的相似性

Embedding模型是执行着这种算法的机器学习模型,如Word2Vec、ResNet等。不同的Embedding模型产生的向量表示和维度数不同,一般纬度越高表达能力越强,可以捕获更丰富的与语义和细微的差别,但是同样更占存储空间。

image.png

向量数据库

用来专门存储和检索向量数据的数据库系统,通过高效的索引算法实现快速相似性搜索,传统数据库也可以存储向量数据,不过向量数据库优化了向量数据的存储和检索。 常用的向量数据库有Milvus、Pinecone等

image.png

精排和Rank模型

精排是搜索/推荐系统的最后阶段,使用计算复杂度更高的算法,考虑更多特征和业务规则,对少量选项进行复杂精细的排序 Rank模型及排序模型负责对召回阶段筛选出的候选集进行精确排序,考虑多种特征评估相关性。现代Rank模型通常基于深度学习,如BERT、MART等,综合考虑查询与候选项的相关性、用户历史等行为因素,如电商推荐,系统会根据商品特征用户偏好点击率等给每个会选商品打分并排序

image.png

混合检索策略

混合检索策略结合多种检索方法的优势,提高搜索效果,常见的组合包括关键词检索、语义检索、知识图谱等

三、RAG实战

其实想要应用RAG很简单,就按照上面提到的开发步骤就行 屏幕截图 2025-07-20 010912.png

对其进行简化:

  • 文档准备
  • 文档读取
  • 向量转换和存储
  • 查询增强

SpringAI + 本地知识库

1.文档准备

提供给AI的知识库最好满足结构化的特点,而markdown格式的文档非常符合,所以说可以准备几篇markdown格式的文档作为知识库,做demo熟悉技术时甚至可以使用AI来生成md文档

帮我生成 3 篇 Markdown 文章,主题是【恋爱常见问题和回答】,3 篇文章的问题分别针对单身、恋爱、已婚的状态,内容形式为 11 答,每个问题标题使用 4 级标题,每篇内容需要有至少 5 个问题,要求每个问题中推荐一个相关的课程,课程链接都是 https://www.codefather.cn

2.文档读取

该环节需要对文档进行处理,然后转化为向量存入向量数据库,即ETL(抽取、转换、加载),SpringAI对ETL提供了支持,官方文档如下:官方文档

ETL有3大核心组件:

image.png

SpringAI支持多种DocumentReaders,用于加载json、text、html、md、pdf、doc等类型的文件,这里我们使用MarkdownDocumentReader来读取md文档

(1)首先就需要引入maven依赖

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-markdown-document-reader</artifactId>
    <version>1.0.0-M6</version>
</dependency>

(2)编写一个文档加载器类

大致流程为:

  • 获取资源路径
  • 获取一个配置类MarkdownDocumentReaderConfig的对象,设置好参数
  • MarkdownDocumentReader类带上资源参数和配置参数加载文档
  • 获取最终分割好的文档结果
@Component
@Slf4j
class LoveAppDocumentLoader {

    private final ResourcePatternResolver resourcePatternResolver;

    LoveAppDocumentLoader(ResourcePatternResolver resourcePatternResolver) {
        this.resourcePatternResolver = resourcePatternResolver;
    }

    public List<Document> loadMarkdowns() {
        List<Document> allDocuments = new ArrayList<>();
        try {
            // 这里可以修改为你要加载的多个 Markdown 文件的路径模式
            Resource[] resources = resourcePatternResolver.getResources("classpath:document/*.md");
            for (Resource resource : resources) {
                String fileName = resource.getFilename();
                MarkdownDocumentReaderConfig config = MarkdownDocumentReaderConfig.builder()
                        .withHorizontalRuleCreateDocument(true)
                        .withIncludeCodeBlock(false)
                        .withIncludeBlockquote(false)
                        .withAdditionalMetadata("filename", fileName)
                        .build();
                MarkdownDocumentReader reader = new MarkdownDocumentReader(resource, config);
                allDocuments.addAll(reader.get());
            }
        } catch (IOException e) {
            log.error("Markdown 文档加载失败", e);
        }
        return allDocuments;
    }
}

可通过MarkdownDocumentReaderConfig类来指定一些读取文档的细节和元信息配置,如提取文档的文件名作为文档的metadata,可便于后续知识库实现更精确的检索。

3.向量转换和存储

我们先使用SpringAI内置的基于内存读写的向量数据库来保存文档 大致流程也很简单:

  • 首先就是要确定Embedding模型,这里选用dashscopeEmbeddingModel,这里是使用Resource注解进行注入的要注意变量名必须正确
  • 将Embedding模型作为参数new一个SimpleVectorStore对象即可
  • 使用上面定义的文档读取类来读取文档
  • 调用add方法存储文档 核心代码就这一行: SimpleVectorStore simpleVectorStore = SimpleVectorStore.builder(dashscopeEmbeddingModel) .build();
@Configuration
public class LoveAppVectorStoreConfig {

    @Resource
    private LoveAppDocumentLoader loveAppDocumentLoader;
    
    @Bean
    VectorStore loveAppVectorStore(EmbeddingModel dashscopeEmbeddingModel) {
        SimpleVectorStore simpleVectorStore = SimpleVectorStore.builder(dashscopeEmbeddingModel)
                .build();
        // 加载文档
        List<Document> documents = loveAppDocumentLoader.loadMarkdowns();
        simpleVectorStore.add(documents);
        return simpleVectorStore;
    }
}

4.增强查询

SpringAI通过Advisor特性提供了开箱即用的RAG功能,主要是QuestionAnswerAdvisor问答拦截器和RetrievalAugmentationAdvisor检索增强拦截器,前者简单易用,后者灵活强大

QuestionAnswerAdvisor源码如下: image.png

QuestionAnswerAdvisor会先在向量数据库中查询与用户问题相关的文档,这段文档会被拼接到用户的提问中,下面有给出了一段提示词可以看到让AI根据文档来回答用户的问题,如果没有相关文档则不能回答问题

(1)引入依赖

<dependency>
   <groupId>org.springframework.ai</groupId>
   <artifactId>spring-ai-advisors-vector-store</artifactId>
</dependency>

(2)这里选用QuestionAnswerAdvisor来实验检索增强功能 大致流程如下:

  • 使用对话客户端来调用大模型进行对话
  • 使用QuestionAnswerAdvisor来增强检索 很简单指定个参数就行了
@Resource
private VectorStore loveAppVectorStore;

public String doChatWithRag(String message, String chatId) {
    ChatResponse chatResponse = chatClient
            .prompt()
            .user(message)
            .advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId)
                    .param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
            // 开启日志,便于观察效果
            .advisors(new MyLoggerAdvisor())
            // 应用知识库问答
            .advisors(new QuestionAnswerAdvisor(loveAppVectorStore))
            .call()
            .chatResponse();
    String content = chatResponse.getResult().getOutput().getText();
    log.info("content: {}", content);
    return content;
}

SpringAI+云知识库

不做过多介绍比较简单,代码也比较简单,着重看手动配置,可以使用阿里云百炼平台,官方文档很详细: java2ai.com/docs/1.0.0-…