大模型虽好,但不知道你公司的内部数据。
RAG (Retrieval Augmented Generation) 是目前解决这个问题的最佳方案。
简单来说,就是先把你的文档切碎、存起来;等用户提问时,先搜出相关片段,再喂给 AI。
Spring AI 专门提供了一套 ETL Pipeline 来处理这个流程,就像处理大数据一样标准。
1. 核心流程
- Extract (读取):从 PDF、Word、网页读取文本。
- Transform (转换):把长文本切分成小块 (Token Splitting)。
- Load (加载):把文本块变成向量,存入向量数据库。
- 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 的大脑。下一阶段,你可以尝试更换更强大的向量数据库,或者调整切分策略来优化检索效果。