Spring AI RAG 实战:让 AI 读懂你的私有文档

大模型虽好,但不知道你公司的内部数据。R.

大模型虽好,但不知道你公司的内部数据。
RAG (Retrieval Augmented Generation) 是目前解决这个问题的最佳方案。
简单来说,就是先把你的文档切碎、存起来;等用户提问时,先搜出相关片段,再喂给 AI。

Spring AI 专门提供了一套 ETL Pipeline 来处理这个流程,就像处理大数据一样标准。

1. 核心流程

  1. Extract (读取):从 PDF、Word、网页读取文本。
  2. Transform (转换):把长文本切分成小块 (Token Splitting)。
  3. Load (加载):把文本块变成向量,存入向量数据库。
  4. Retrieve (检索):根据用户问题找答案。

2. 读取文档 (Document Readers)

Spring AI 内置了非常丰富的阅读器。

读取 JSON

适合读取结构化数据。

JsonReader jsonReader = new JsonReader(new ClassPathResource("bikes.json"));
List<Document> documents = jsonReader.get();

读取 PDF

需要引入 spring-ai-pdf-document-reader 依赖。

PagePdfDocumentReader pdfReader = new PagePdfDocumentReader(
    new ClassPathResource("manual.pdf"),
    PdfDocumentReaderConfig.builder()
        .withPagesPerDocument(1)
        .build());
List<Document> docs = pdfReader.read();

读取万能格式 (Tika)

如果你不知道文件是什么格式(Word, PPT, HTML…),直接用 Apache Tika。

TikaDocumentReader reader = new TikaDocumentReader(new ClassPathResource("contract.docx"));
List<Document> docs = reader.read();

3. 切分文档 (Splitters)

AI 的上下文窗口有限,而且文本越长,语义越稀释。所以我们需要把文档切成小块。
最常用的是 TokenTextSplitter

// 默认每块 800 Token,重叠 350 Token(保持上下文连贯)
var splitter = new TokenTextSplitter();
List<Document> splitDocs = splitter.apply(docs);

4. 存入向量数据库 (Vector Store)

这里我们使用简单的 SimpleVectorStore(内存存储)作为演示。生产环境建议用 PGVector, Redis, Chroma 等。

@Bean
VectorStore vectorStore(EmbeddingModel embeddingModel) {
    return new SimpleVectorStore(embeddingModel);
}

// 在某个初始化方法里
vectorStore.add(splitDocs); // 这一步会自动调用 EmbeddingModel 生成向量

5. 检索与问答

现在,当用户提问时,我们不再直接调 ChatClient,而是先问 VectorStore。

// 1. 检索相似文档
List<Document> similarDocs = vectorStore.similaritySearch(
    SearchRequest.query("如何申请年假?").withTopK(2)); // 找最相关的2段

// 2. 构造提示词
String context = similarDocs.stream()
    .map(Document::getContent)
    .collect(Collectors.joining("\n"));

String prompt = """
    基于以下信息回答问题:
    %s

    问题:如何申请年假?
    """.formatted(context);

// 3. 问 AI
String answer = chatClient.prompt().user(prompt).call().content();

简化写法:QuestionAnswerAdvisor

Spring AI 封装了一个 QuestionAnswerAdvisor,帮你自动完成“检索+拼接”这步。

chatClient.prompt()
    .advisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults()))
    .user("如何申请年假?")
    .call()
    .content();

总结

这就是 RAG 的完整闭环。
通过 Spring AI 的 ETL 管道,你可以轻松地把企业的知识库变成 AI 的大脑。下一阶段,你可以尝试更换更强大的向量数据库,或者调整切分策略来优化检索效果。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注