一、本章介绍
通过编写功能验证代码,分别基于 Spring AI、LangChain4j、Google ADK 等框架完成对 AI 服务的接入与调用测试,验证各技术方案在模型连接、能力适配、流程编排等方面的可行性与实现效果。
该阶段的目标在于通过实际案例完成关键能力预研与技术验证,为后续 AI Agent 智能体脚手架 的技术选型、架构设计与工程化落地奠定基础。
二、环境配置
- JDK 17
- Maven 3.8.x - Maven 教程
- IntelliJ IDEA 社区版(免费) IntelliJ IDEA 教程
- Git - 安装后会配置到 IntelliJ IDEA 这样才能向服务端推送或者拉取代码。
三、框架介绍
1. Spring AI
官网:https://docs.spring.io/spring-ai/reference/index.html
Spring AI 项目旨在简化集成人工智能功能的应用程序的开发,避免不必要的复杂性。
该项目在设计理念上借鉴了 LangChain、LlamaIndex 等知名 Python 项目的经验与思路,但 Spring AI 并不是对这些项目的简单迁移或直接复刻。其诞生的核心出发点在于:下一代生成式人工智能应用的构建不应局限于 Python 生态,而应面向更广泛的开发群体与多语言技术体系。
也正因如此,Spring AI 更强调在 Java / Spring 生态 下构建适用于企业级场景的生成式 AI 应用基础设施,致力于为不同编程语言背景下的开发模式提供可借鉴的工程化实践与统一抽象能力。
2. LangChain4J
官网:https://docs.langchain4j.info/
LangChain4j 的核心目标,是降低 LLM 集成到 Java 应用程序中的实现门槛,让开发者能够以更简洁、更工程化的方式构建基于大语言模型的应用能力。
LangChain4j 诞生于 2023 年初 ChatGPT 快速兴起的阶段。项目团队当时注意到,相较于 Python 和 JavaScript 生态中已较为丰富的 LLM 工具库与开发框架,Java 领域仍缺少一个具有代表性的对应方案,因此推动了 LangChain4j 的设计与实现。
虽然项目名称中包含“LangChain”,但 LangChain4j 并不是对 LangChain 的单一复刻,而是综合吸收了 LangChain、Haystack、LlamaIndex 以及更广泛社区中的设计思想与实践经验,并在此基础上结合 Java 生态特点进行了扩展与创新,形成了更适合 Java 开发者使用的 LLM 应用开发框架。
3. Google ADK
官网:https://google.github.io/adk-docs/get-started/java/#
代理开发工具包(ADK)是一套灵活、模块化的 AI Agent 开发与部署框架,用于支持各类智能体应用的构建、组织与运行。ADK 虽然针对 Gemini 及 Google 生态体系进行了较深度的优化,但其整体设计并不依赖特定模型或固定部署方式,同时也具备与其他框架和技术体系进行兼容集成的能力。
ADK 的设计理念,是让智能体开发过程尽可能接近传统软件工程开发方式,使开发者能够以更加标准化、工程化的方式构建、部署与编排智能体系统。基于这一能力,开发人员既可以实现面向单一任务的轻量级代理,也可以组织支持复杂流程、多阶段协作与多智能体编排的高级代理架构。
三、功能测试
1. 工程结构

ai-agent-scaffold-lite是本次创建的整体脚手架工程。在这一节中,我们主要在app模块下进行功能测试,以熟悉各个框架 API 的使用方式。在使用过程中,需要先在
pom.xml中引入相关依赖,包括:Spring AI、LangChain4J、Google ADK,以及设计模式相关框架。在
test/api目录下,我们新增了tool和model两部分内容,并分别基于 Spring AI 和 LangChain4J 两个框架进行功能验证。最后,在agent目录下,完成对 Google ADK 的相关验证。
2. 接口说明
curl https://gpt.xxxx.xyz/v1/chat/completions -H "Content-Type: application/json" -H "Authorization: Bearer sk-x5RwPi42uhXyazTK5eFf4c49499d4dE**** *你的完整apikey" -d '{
"model": "gpt-5.5",
"messages": [
{
"role": "user",
"content": "1+1"
}
]
}'- 无论是 OpenAI、Google、智谱、阿里还是百度,这些大模型本质上都提供了类似的请求接口。而我们常用的框架,如
Spring AI、LangChain4J、Google ADK,可以看作是在这些基础接口之上的一层封装,并在此基础上进一步扩展了更多功能。
3. 功能测试
因为我们开发的是一个脚手架项目,很多配置和组件都需要根据实际场景动态创建。因此,在实现上需要采用编码方式进行处理,而不能完全依赖 Starter 通过 YML 配置完成初始化。
例如,Spring AI 可以通过 YML 配置快速启动,但在脚手架场景下,我们需要支持更灵活的动态化能力,所以必须了解并掌握如何通过编码方式完成相关配置和组件创建。
3.1 模型服务
3.1.1 Spring AI
package cn.cactusli.ai.test.api.model;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.openai.api.OpenAiApi;
/**
* Spring AI Test
* 文档:<a href="https://docs.spring.io/spring-ai/reference/1.0/api/advisors.html">spring ai</a>
*/
@Slf4j
public class SpringAiApiTest {
public static void main(String[] args) {
OpenAiApi openAiApi = OpenAiApi.builder()
.baseUrl("https://api1.oaipro.com")
.apiKey("sk-xxxx")
.completionsPath("v1/chat/completions")
.embeddingsPath("v1/embeddings")
.build();
ChatModel chatModel = OpenAiChatModel.builder()
.openAiApi(openAiApi)
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-5.4-mini")
.build())
.build();
String call = chatModel.call("hi 你是哪个模型?");
log.info("测试结果:{}", call);
}
}3.1.2 LangChain4J
package cn.cactusli.ai.test.api.model;
import dev.langchain4j.model.openai.OpenAiChatModel;
import lombok.extern.slf4j.Slf4j;
/**
* LangChain4j
* <p>
* 文档:<a href="https://docs.langchain4j.info/">langchain4j</a>
* 案例:<a href="https://github.com/langchain4j/langchain4j-examples">langchain4j-examples</a>
**/
@Slf4j
public class LangChain4jApiTest {
public static void main(String[] args) {
OpenAiChatModel chatModel = OpenAiChatModel.builder()
.baseUrl("https://api1.oaipro.com/v1")
.apiKey("sk-FtZfc3Lyr2RjMkT1TDMTuY73t2NDvyU5dDgqjt4ZqwdMAdNk3xAW")
.modelName("gpt-5.4-mini")
.build();
String chat = chatModel.chat("hi 你是哪个模型?");
log.info("测试结果:{}", chat);
}
}Langchain4j 的对接方式与 Spring AI 基本类似——掌握了核心用法后,其他功能也可以对照查找。正如 Spring AI 所述,该项目汲取了 LangChain、LlamaIndex 等知名 Python 项目的设计理念。
在后续的脚手架开发中,我们会更多地基于 Spring AI 框架来构建 Langchain4j 的案例,目的主要是为了增强相关知识储备和实战经验。
3.2 工具对接(MCP)
3.2.1 Spring AI:cn.cactusli.ai.test.api.agent.LoopAgentTest
public static void main(String[] args) {
OpenAiApi openAiApi = OpenAiApi.builder()
.baseUrl("https://api1.oaipro.com/")
.apiKey("sk-xxxx")
.completionsPath("v1/chat/completions")
.embeddingsPath("v1/embeddings")
.build();
ChatModel chatModel = OpenAiChatModel.builder()
.openAiApi(openAiApi)
.defaultOptions(OpenAiChatOptions.builder()
.model("gpt-5.4-mini")
.build())
.build();
// STEP 1: Initial Writer Agent (Runs ONCE at the beginning)
LlmAgent initialWriterAgent =
LlmAgent.builder()
.model(new SpringAI(chatModel))
.name("InitialWriterAgent")
.description(
"Writes the initial document draft based on the topic, aiming for some initial"
+ " substance.")
.instruction(
"""
You are a Creative Writing Assistant tasked with starting a story.
Write the *first draft* of a short story (aim for 2-4 sentences).
Base the content *only* on the topic provided below. Try to introduce a specific element (like a character, a setting detail, or a starting action) to make it engaging.
Output *only* the story/document text. Do not add introductions or explanations.
""")
.outputKey(STATE_CURRENT_DOC)
.includeContents(NONE)
.build();
// STEP 2a: Critic Agent (Inside the Refinement Loop)
LlmAgent criticAgentInLoop =
LlmAgent.builder()
.model(new SpringAI(chatModel))
.name("CriticAgent")
.description(
"Reviews the current draft, providing critique if clear improvements are needed,"
+ " otherwise signals completion.")
.instruction(
"""
You are a Constructive Critic AI reviewing a short document draft (typically 2-6 sentences). Your goal is balanced feedback.
**Document to Review:**
```
{{current_document}}
```
**Task:**
Review the document for clarity, engagement, and basic coherence according to the initial topic (if known).
IF you identify 1-2 *clear and actionable* ways the document could be improved to better capture the topic or enhance reader engagement (e.g., "Needs a stronger opening sentence", "Clarify the character's goal"):
Provide these specific suggestions concisely. Output *only* the critique text.
ELSE IF the document is coherent, addresses the topic adequately for its length, and has no glaring errors or obvious omissions:
Respond *exactly* with the phrase "No major issues found." and nothing else. It doesn't need to be perfect, just functionally complete for this stage. Avoid suggesting purely subjective stylistic preferences if the core is sound.
Do not add explanations. Output only the critique OR the exact completion phrase.
""")
.outputKey(STATE_CRITICISM)
.includeContents(NONE)
.build();
// STEP 2b: Refiner/Exiter Agent (Inside the Refinement Loop)
LlmAgent refinerAgentInLoop =
LlmAgent.builder()
.model(new SpringAI(chatModel))
.name("RefinerAgent")
.description(
"Refines the document based on critique, or calls exitLoop if critique indicates"
+ " completion.")
.instruction(
"""
You are a Creative Writing Assistant refining a document based on feedback OR exiting the process.
**Current Document:**
```
{{current_document}}
```
**Critique/Suggestions:**
{{criticism}}
**Task:**
Analyze the 'Critique/Suggestions'.
IF the critique is *exactly* "No major issues found.":
You MUST call the 'exitLoop' function. Do not output any text.
ELSE (the critique contains actionable feedback):
Carefully apply the suggestions to improve the 'Current Document'. Output *only* the refined document text.
Do not add explanations. Either output the refined document OR call the exitLoop function.
""")
.outputKey(STATE_CURRENT_DOC)
.includeContents(NONE)
.tools(FunctionTool.create(LoopAgentTest.class, "exitLoop"))
.build();
// STEP 2: Refinement Loop Agent
LoopAgent refinementLoop =
LoopAgent.builder()
.name("RefinementLoop")
.description("Repeatedly refines the document with critique and then exits.")
.subAgents(criticAgentInLoop, refinerAgentInLoop)
.maxIterations(5)
.build();
// STEP 3: Overall Sequential Pipeline
SequentialAgent iterativeWriterAgent =
SequentialAgent.builder()
.name(APP_NAME)
.description(
"Writes an initial document and then iteratively refines it with critique using an"
+ " exit tool.")
.subAgents(initialWriterAgent, refinementLoop)
.build();
// Create an InMemoryRunner
InMemoryRunner runner = new InMemoryRunner(iterativeWriterAgent, APP_NAME);
// InMemoryRunner automatically creates a session service. Create a session using the service
Session session = runner.sessionService().createSession(APP_NAME, USER_ID).blockingGet();
Content userMessage = Content.fromParts(Part.fromText("Write a document about a cat"));
// Run the agent
Flowable<Event> eventStream = runner.runAsync(USER_ID, session.id(), userMessage);
// Stream event response
eventStream.blockingForEach(
event -> {
if (event.finalResponse()) {
System.out.println(event.stringifyContent());
}
});
}在 Google ADK 中,单个智能体是通过
LlmAgent类来构建的。构建过程中,需要实例化 Spring AI 中的Model对象进行封装。每个
LlmAgent智能体都可以进一步通过LoopAgent进行包装,从而支持配置subAgents。这个包装过程相当于让智能体执行一个“分析 → 决策 → 执行”的循环流程。为了防止无限执行,需要设置最大迭代次数maxIterations(例如 5 次)。
3.3.2 并行 :cn.cactusli.ai.test.api.agent.ParallelAgentTest
ParallelAgent parallelResearchAgent =
ParallelAgent.builder()
.name("ParallelWebResearchAgent")
.subAgents(researcherAgent1, researcherAgent2, researcherAgent3)
.description("Runs multiple research agents in parallel to gather information.")
.build();- ParallelAgent 可以组装 LlmAgent、LoopAgent,当然你也可以嵌套组合更复杂的智能体。
3.3.3 串行:cn.cactusli.ai.test.api.agent.SequentialAgentTest
SequentialAgent codePipelineAgent =
SequentialAgent.builder()
.name("CodePipelineAgent")
.description("Executes a sequence of code writing, reviewing, and refactoring.")
// The agents will run in the order provided: Writer -> Reviewer -> Refactorer
.subAgents(codeWriterAgent(chatModel), codeReviewerAgent(chatModel), codeRefactorerAgent(chatModel))
.build();- SequentialAgent 则可以把 LlmAgent、LoopAgent、ParallelAgent 进行组合使用。