同一需求三套写法:用 Spring AI、LangChain4j、AgentScope Java 各实现一个带工具调用的 RAG 助手(实战对比)
📚 本文是「Java 大模型框架专题」系列第 5 篇(实战收尾篇)。全系列 5 篇,建议按序阅读:
- 总纲 2026 Java 大模型框架选型终极指南:Spring AI vs LangChain4j vs AgentScope Java 深度横评
- 深度 Spring AI 2.0 深度解析
- 深度 LangChain4j 深度解析
- 深度 AgentScope Java 深度解析
- 实战 同一需求三套写法(本篇)
(发布后请把每行标题替换为对应文章的超链接,形成专题矩阵互导闭环)
一、需求定义:一个"技术问答助手"
前四篇都在讲"是什么、怎么选"。这篇反过来,用一个真实需求把三家拉出来遛一遛。
需求:一个技术问答助手,要求:
- 用户问一个技术问题;
- 先从知识库检索相关文档(RAG);
- 需要时能调用工具(比如查当前时间);
- 以流式方式输出带依据的回答。

说明:以下代码为示意实现,突出各框架的编程范式与代码量差异;具体 API 以官方文档为准(文末附链接)。
二、Spring AI 2.0 实现
java
// 配置:RAG 检索器挂进 Advisor 链
@Configuration
class AiConfig {
@Bean
ChatClient chatClient(ChatClient.Builder builder, VectorStore store) {
return builder
.defaultAdvisors(QuestionAnswerAdvisor.builder(store).build())
.build();
}
}
// 工具:@Tool 声明,被 ToolCallingAdvisor 自动发现
@Component
class TimeTools {
@Tool(description = "返回当前 UTC 时间")
String now() { return Instant.now().toString(); }
}
@RestController
class AssistantController {
private final ChatClient chatClient;
AssistantController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping(value = "/ask", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
Flux<String> ask(@RequestParam String q) {
return chatClient.prompt()
.system("你是技术问答助手,优先依据检索到的上下文回答")
.user(q)
.stream()
.content(); // 流式输出
}
}
特点 :命令式 + Fluent;RAG 靠 QuestionAnswerAdvisor 挂载;工具靠 @Tool 自动发现;流式返回 Flux<String>。
三、LangChain4j 实现
java
interface Assistant {
@SystemMessage("你是技术问答助手,优先依据检索到的上下文回答")
Flux<String> answer(@UserMessage String question); // 流式
}
// 检索器
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(store) // pgvector / InMemory 等
.embeddingModel(embeddingModel)
.maxResults(3)
.build();
// 工具
class TimeTools {
@Tool("返回当前 UTC 时间")
String now() { return Instant.now().toString(); }
}
// 装配
Assistant assistant = AiServices.builder(Assistant.class)
.chatLanguageModel(model)
.contentRetriever(retriever) // 自动把检索结果注入上下文
.tools(new TimeTools())
.build();
Flux<String> answer = assistant.answer("Spring AI 2.0 需要哪个 Boot 版本?");
特点 :声明式 @AiService;RAG 靠 ContentRetriever 自动注入;工具靠 @Tool 注入;流式靠方法返回类型 Flux 自动切换。
四、AgentScope Java 实现
java
// 把"检索知识库"封装成一个工具,交给 Agent 自主调用
class KnowledgeTools {
@Tool("在技术知识库中检索相关文档")
String search(@ToolParam String query) { return vectorSearch(query); }
}
// 用 HarnessAgent 承载生产级 Agent(长期记忆 / 会话持久化 / 沙箱)
HarnessAgent assistant = HarnessAgent.builder()
.name("技术问答助手")
.model(model) // Qwen / OpenAI / Claude / Gemini...
.tools(new KnowledgeTools(), new TimeTools())
.build();
Response resp = assistant.run("Spring AI 2.0 需要哪个 Boot 版本?");
特点 :Agent 编排式;RAG 不是内建抽象,而是封装成一个 @Tool 让 Agent 自主决定何时调用 ;用 HarnessAgent 直接获得记忆、持久化、沙箱能力。
五、三份代码并排对比
| 维度 | Spring AI | LangChain4j | AgentScope Java |
|---|---|---|---|
| 代码风格 | 命令式 Fluent | 声明式接口 | Agent 编排式 |
| RAG 方式 | QuestionAnswerAdvisor |
ContentRetriever 自动注入 |
@Tool 封装检索,Agent 自主调 |
| 工具接入 | @Tool Bean |
@Tool 注入 |
@Tool + @ToolParam |
| 流式 | Flux<String> |
Flux<String>(返回类型即语义) |
事件系统(32 类事件) |
| 心智模型 | "给 Spring 服务加 AI 能力" | "把 AI 服务当接口实现" | "编排一个会自己干活的 Agent" |
| 额外白拿 | 观测/自动配置 | 记忆/护栏/非阻塞 | 记忆/持久化/沙箱/HITL |
读法:三者都能完成这个需求,但**"舒服程度"取决于你的心智模型**------Spring 团队觉得第一列最顺,Quarkus/纯 Java 团队觉得第二列最顺,做多智能体的人觉得第三列才是正解。
六、真实跑起来会遇到什么
| 坑 | 说明 | 规避 |
|---|---|---|
| Boot 版本 | Spring AI 2.0 跑不了 Boot 3.x | 迁 Boot 4,或先用 LangChain4j 双 Starter |
| 依赖数量 | LangChain4j 模块多,容易引错 | 按需引,别一把梭 * |
| 心智成本 | AgentScope 抽象高,Demo 与生产的 API 不同 | 先 ReActAgent 跑通,再上 HarnessAgent |
| RAG 效果 | 三家都依赖"检索质量"上限 | 切块策略 + 相似度阈值是真正的胜负手 |
七、结论
回到系列第 1 篇的那句话:三个框架不在同一层。
- 做单体智能 (本场景就是)→ Spring AI (Spring 栈 / Boot 4)或 LangChain4j(跨框架 / 生态最全);
- 做多智能体自治系统 → AgentScope Java。
这个"技术问答助手"恰好是"单体智能"的典型,所以 Spring AI 与 LangChain4j 是更贴合的答案 ;但如果你要把它升级成"研究-写作-评审分工的 AI 团队",AgentScope 的 HarnessAgent + 子智能体编排就是更优解。
你正在做的项目,是"单体智能"还是"多智能体协作"?评论区聊聊,我帮你对号入座。
系列矩阵导航
- 🔗 第 1 篇·总纲 三框架选型深度横评(含分层定位图 + 决策树)
- 🔗 第 2 篇·深度 Spring AI 2.0 深度解析
- 🔗 第 3 篇·深度 LangChain4j 深度解析
- 🔗 第 4 篇·深度 AgentScope Java 深度解析
本文数据截至 2026-11-02;代码为示意实现,API 细节分别以 Spring AI、LangChain4j、AgentScope Java 官方文档为准。