一、 引言:从调用API到构建智能体
单纯调用大模型API只能解决通用问题。真正的企业级AI应用需要模型能够理解和处理外部知识,如公司内部文档、数据库记录等。这就是AI智能体的用武之地——它能感知环境、使用工具(如数据库)、并执行复杂任务。
RAG是构建此类智能体的关键技术栈。其核心思想是:在向大模型提问前,先从私有知识库中检索出最相关的信息片段,并将其作为上下文与问题一同提交给模型,从而得到基于特定知识的精准回答。
本文将对比介绍两个Java领域的AI框架:Spring AI(Spring官方新项目,提供抽象层)和LangChain4j(灵感源于Python的LangChain,功能丰富),并分别展示如何用它们实现RAG流水线。
二、 技术选型与项目初始化
- 框架简介
Spring AI(选学):致力于为AI应用开发提供熟悉的Spring范式(如AIClient抽象、PromptTemplate)。目前仍在早期阶段,但背靠Spring生态,前景可观。
LangChain4j(主打):一个功能强大、设计优雅的Java库,提供了大量现成的组件(文档加载器、工具、链),用于构建AI应用,是目前Java生态中最接近Python LangChain成熟度的选择。
- 项目依赖
本例我们以LangChain4j为主进行构建。在pom.xml中引入以下依赖:
xml
0.29.0
org.springframework.boot
spring-boot-starter-web
<!-- LangChain4j 核心 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- LangChain4j 用于OpenAI集成 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- LangChain4j 本地向量库(暂存嵌入向量) -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-embeddings-all-minilm-l6-v2</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- 用于从文件系统加载文档 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-document-parser-apache-poi</artifactId>
<version>${langchain4j.version}</version>
</dependency>
- 配置信息(application.yml)
yaml
langchain4j:
openai:
chat-model:
api-key: ${OPENAI_API_KEY}
model-name: "gpt-3.5-turbo"
embedding-model:
api-key: ${OPENAI_API_KEY}
model-name: "text-embedding-ada-002"
知识库文档路径
app:
knowledge-base-path: "./knowledge-base"
三、 核心实现:四步构建RAG流水线
一个完整的RAG系统包含四个关键步骤:文档摄入、向量化与存储、检索和生成。
- 文档摄入与分块(Ingestion)
首先,我们需要将原始文档(如PDF、Word、TXT)加载进来,并切割成适合处理的小片段(chunks)。
java
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentParser;
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import dev.langchain4j.data.document.parser.TextDocumentParser;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.nio.file.Paths;
import java.util.List;
@Configuration
public class DocumentIngestionConfig {
@Bean
public EmbeddingStore<TextSegment> embeddingStore() {
// 使用内存向量库作为示例。生产环境可换为ChromaDB、PgVector等持久化方案。
return new InMemoryEmbeddingStore<>();
}
@Bean
public EmbeddingStoreIngestor embeddingStoreIngestor(EmbeddingStore<TextSegment> embeddingStore, EmbeddingModel embeddingModel) {
// EmbeddingStoreIngestor 是一个工具类,封装了分块、向量化、存储的流水线
return EmbeddingStoreIngestor.builder()
.documentSplitter(DocumentSplitters.recursive(500, 100)) // 递归分块,最大500字符,重叠100字符
.embeddingModel(embeddingModel)
.embeddingStore(embeddingStore)
.build();
}
// 应用启动时加载知识库的Bean
@Bean
public Boolean loadKnowledgeBase(EmbeddingStoreIngestor ingestor, @Value("${app.knowledge-base-path}") String path) {
List<Document> documents = FileSystemDocumentLoader.loadDocuments(Paths.get(path), new TextDocumentParser());
ingestor.ingest(documents);
System.out.println("知识库文档加载完毕!");
return true;
}
}
- 创建AI服务(智能体)
接下来,我们定义一个AI服务接口。LangChain4j会通过动态代理自动为我们实现它。
java
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
// 定义智能体的“大脑”
public interface KnowledgeBaseAssistant {
@SystemMessage("""
你是一个专业的客服助手,专门回答关于公司产品和服务的问题。
请严格根据提供的信息来源进行回答。如果信息来源中没有相关答案,请明确告知"根据现有资料,我暂时无法回答这个问题。"
请保持回答友好、简洁且准确。
""")
String answerQuestion(@UserMessage @V("question") String question);
}
- 装配智能体(将检索与生成连接)
这是最核心的一步,我们将检索器(Retriever)和聊天模型(ChatModel)组装成一个具备RAG能力的AI服务。
java
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.service.AiServices;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AIConfig {
@Bean
public KnowledgeBaseAssistant knowledgeBaseAssistant(
ChatLanguageModel chatLanguageModel,
EmbeddingStore<TextSegment> embeddingStore,
EmbeddingModel embeddingModel) {
// 1. 创建内容检索器
EmbeddingStoreContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(embeddingStore)
.embeddingModel(embeddingModel)
.maxResults(2) // 每次检索最相关的2个片段
.build();
// 2. 使用AiServices将检索器与AI模型绑定到接口上
return AiServices.builder(KnowledgeBaseAssistant.class)
.chatLanguageModel(chatLanguageModel)
.contentRetriever(retriever) // 关键:注入RAG能力!
.build();
}
}
- 提供REST API
最后,我们创建一个简单的控制器来暴露服务。
java
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/assistant")
public class AssistantController {
private final KnowledgeBaseAssistant assistant;
public AssistantController(KnowledgeBaseAssistant assistant) {
this.assistant = assistant;
}
@PostMapping("/ask")
public String askQuestion(@RequestBody QuestionRequest request) {
return assistant.answerQuestion(request.question());
}
public record QuestionRequest(String question) {}
}
四、 测试与进阶探讨
测试:
在./knowledge-base目录下放入你的公司手册、API文档等文本文件。
启动应用后,提问:“我们公司的主要产品是什么?” 智能体会自动检索知识库中的相关内容并生成回答。
进阶探讨:
向量数据库升级:内存向量库重启后数据丢失。生产环境应集成PostgreSQL(pgvector扩展)、RedisStack或ChromaDB等专业向量数据库。
更复杂的智能体:LangChain4j支持让AI智能体“使用工具”。例如,可以定义一个工具方法@Tool("查询用户订单信息"),让智能体在回答关于订单的问题时,自动调用后端服务查询真实数据。
与Spring AI的对比:Spring AI提供了类似的抽象,例如VectorStore接口和AiClient。其开发体验更“Spring化”,但当前版本(如1.0.0-M5)的文档和社区生态尚不如LangChain4j成熟。长期来看,两者都值得关注。
五、 总结
通过LangChain4j框架,Java开发者能够以声明式、模块化的方式高效构建功能强大的AI智能体。本文演示的RAG应用只是一个起点。通过组合不同的工具、模型和记忆机制,我们可以创造出能够理解复杂指令、与外部系统交互并完成闭环任务的下一代Java应用。随着Spring AI等官方项目的持续发力,Java在AI应用工程领域的地位必将愈发巩固,为开发者提供坚实可靠的智能底层架构。