跳到主要内容 Spring AI Alibaba 实战示例与最佳实践 | 极客日志
Java AI java
Spring AI Alibaba 实战示例与最佳实践 本文介绍了 Spring AI Alibaba 框架的实战示例与最佳实践,涵盖核心对话、ReactAgent、多智能体编排、RAG Agent、SQL Agent、Voice Agent 及工作流配置。内容包括基础对话、多轮记忆、流式响应、自定义工具、结构化输出、顺序/并行/路由/循环执行模式,以及知识检索、数据库交互和语音助手的具体实现。最后提供了完整的配置文件、依赖项及工具设计、Agent 设计、错误处理等最佳实践建议。
氛围 发布于 2026/3/29 更新于 2026/4/13 1 浏览Spring AI Alibaba 实战示例与最佳实践
汇总 Spring AI Alibaba 框架的完整示例代码和最佳实践。
第一部分:核心对话示例
1.1 最简对话
@RestController
public {
ChatClient chatClient;
{
.chatClient = builder.build();
}
String {
chatClient.prompt(query).call().content();
}
}
class
ChatController
private
final
public
ChatController
(ChatClient.Builder builder)
this
@GetMapping("/chat")
public
chat
(@RequestParam String query)
return
1.2 多轮对话 List<Message> messages = List.of(
new SystemMessage ("你是一个 Java 专家" ),
new UserMessage ("什么是 Spring Boot?" ),
new AssistantMessage ("Spring Boot 是..." ),
new UserMessage ("它有什么优势?" )
);
Prompt prompt = new Prompt (messages);
ChatResponse response = chatModel.call(prompt);
1.3 流式响应 Flux<ChatResponse> responseStream = chatModel.stream(new Prompt ("解释 Spring Boot 自动配置" ));
responseStream.subscribe(chatResponse -> {
System.out.print(chatResponse.getResult().getOutput().getText());
});
1.4 带记忆的对话 @RestController
@RequestMapping("/advisor/memory")
public class ChatMemoryController {
private final ChatClient chatClient;
private final MessageWindowChatMemory chatMemory;
public ChatMemoryController (ChatClient.Builder builder, ChatMemoryRepository repository) {
this .chatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(repository)
.maxMessages(100 )
.build();
this .chatClient = builder
.defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
.build();
}
@GetMapping("/call")
public String call (@RequestParam String query, @RequestParam String conversationId) {
return chatClient.prompt(query)
.advisors(a -> a.param(CONVERSATION_ID, conversationId))
.call().content();
}
@GetMapping("/messages")
public List<Message> messages (@RequestParam String conversationId) {
return chatMemory.get(conversationId);
}
}
第二部分:ReactAgent 完整示例
2.1 基础配置 @Configuration
public class AgentConfiguration {
private final ChatModel chatModel;
@Bean
public ReactAgent reactAgent () throws GraphStateException {
return ReactAgent.builder()
.name("agent" )
.description("This is a react agent" )
.model(chatModel)
.saver(new MemorySaver ())
.tools(new FileReadTool ().toolCallback(), new FileWriteTool ().toolCallback())
.hooks(HumanInTheLoopHook.builder()
.approvalOn("file_write" , "Write File should be approved" )
.build())
.interceptors(new LogToolInterceptor ())
.build();
}
}
2.2 自定义工具 @Component
public class FileWriteTool implements BiFunction <FileWriteTool.Request, ToolContext, String> {
@Override
public ToolCallback toolCallback () {
return FunctionToolCallback.builder("file_write" , this )
.description("Tool for write files" )
.inputType(Request.class)
.build();
}
@Override
public String apply (Request request, ToolContext toolContext) {
try {
String safePath = Paths.get(System.getProperty("user.dir" ))
.resolve(request.filePath)
.normalize()
.toString();
Files.writeString(Paths.get(safePath), request.content);
return "Successfully wrote to file: " + request.filePath;
} catch (IOException e) {
return "Error writing to file: " + e.getMessage();
}
}
@JsonClassDescription("Request for writing a file")
public record Request (
@JsonProperty(value = "file_path", required = true )
@JsonPropertyDescription("The path of the file to write")
String filePath,
@JsonProperty(value = "content", required = true)
@JsonPropertyDescription("The content to write to the file")
String content
) {}
}
2.3 结构化输出
public class ContactInfo {
private String name;
private String email;
private String phone;
}
ReactAgent agent = ReactAgent.builder()
.name("contact_extractor" )
.model(chatModel)
.outputType(ContactInfo.class)
.build();
AssistantMessage result = agent.call("提取联系人信息:张三,[email protected] ,(555) 123-4567" );
第三部分:多智能体示例
3.1 研究团队(顺序执行) @Configuration
public class ResearchTeamConfig {
@Bean
public ReactAgent researcher (ChatModel model) {
return ReactAgent.builder()
.name("researcher" )
.model(model)
.systemPrompt("你是一个研究专家,负责收集和整理信息。" )
.tools(new WebSearchTool (), new DocumentReaderTool ())
.build();
}
@Bean
public ReactAgent analyst (ChatModel model) {
return ReactAgent.builder()
.name("analyst" )
.model(model)
.systemPrompt("你是一个分析专家,负责分析研究数据并提取洞察。" )
.build();
}
@Bean
public ReactAgent writer (ChatModel model) {
return ReactAgent.builder()
.name("writer" )
.model(model)
.systemPrompt("你是一个写作专家,负责将分析结果整理成报告。" )
.build();
}
@Bean
public SequentialAgent researchPipeline (ReactAgent researcher, ReactAgent analyst, ReactAgent writer) {
return SequentialAgent.builder()
.name("research-pipeline" )
.addAgent(researcher)
.addAgent(analyst)
.addAgent(writer)
.build();
}
}
3.2 并行执行 ParallelAgent parallel = ParallelAgent.builder()
.name("multi-research" )
.addAgent(techResearchAgent)
.addAgent(marketResearchAgent)
.addAgent(competitorResearchAgent)
.aggregator(results -> String.join("\n\n" , results))
.build();
String result = parallel.call("分析 AI 市场趋势" );
3.3 路由选择 RoutingAgent router = RoutingAgent.builder()
.name("support-router" )
.router((input, agents) -> {
if (input.contains("技术" )) {
return "tech-support" ;
} else if (input.contains("账单" )) {
return "billing-support" ;
}
return "general-support" ;
})
.addAgent("tech-support" , techAgent)
.addAgent("billing-support" , billingAgent)
.addAgent("general-support" , generalAgent)
.build();
3.4 循环执行 LoopAgent loop = LoopAgent.builder()
.name("refinement-loop" )
.agent(refinementAgent)
.maxIterations(5 )
.terminationCondition((input, output) -> {
return output.contains("完成" ) || output.contains("满意" );
})
.build();
第四部分:RAG Agent 示例
4.1 知识检索工具 @Component
public class KnowledgeRetrievalTool implements BiFunction <Request, ToolContext, String> {
private final SimpleVectorStore vectorStore;
public KnowledgeRetrievalTool (EmbeddingModel embeddingModel) {
this .vectorStore = SimpleVectorStore.builder(embeddingModel).build();
}
@PostConstruct
void initKnowledgeBase () {
for (String url : knowledgeSourceUrls) {
JsoupDocumentReader reader = new JsoupDocumentReader (url);
List<Document> documents = reader.get();
TokenTextSplitter splitter = new TokenTextSplitter ();
vectorStore.add(splitter.apply(documents));
}
}
@Override
public String apply (Request request, ToolContext toolContext) {
SearchRequest searchRequest = SearchRequest.builder()
.query(request.query())
.topK(request.topK() != null ? request.topK() : 4 )
.build();
List<Document> documents = vectorStore.similaritySearch(searchRequest);
return documents.stream()
.map(doc -> "---\n" + doc.getFormattedContent() + "\n---" )
.collect(Collectors.joining("\n\n" ));
}
public ToolCallback toolCallback () {
return FunctionToolCallback.builder("knowledge_retrieval" , this )
.description("Retrieves relevant information from the knowledge base" )
.inputType(Request.class)
.build();
}
public record Request (
@JsonProperty(value = "query", required = true )
String query,
@JsonProperty(value = "top_k")
Integer topK
) {}
}
4.2 RAG Agent 配置 @Configuration
public class RagAgentConfiguration {
@Bean
public ReactAgent ragAgent (ChatModel model, EmbeddingModel embeddingModel) {
KnowledgeRetrievalTool knowledgeTool = new KnowledgeRetrievalTool (embeddingModel);
return ReactAgent.builder()
.name("rag-agent" )
.description("你是一个知识库问答助手,使用知识检索工具回答问题。" )
.model(model)
.tools(knowledgeTool.toolCallback())
.saver(new MemorySaver ())
.build();
}
}
第五部分:SQL Agent 示例 @Configuration
public class SqlAgentConfiguration {
private final ChatModel chatModel;
private final JdbcTemplate jdbcTemplate;
@Bean
public ReactAgent sqlAgent () throws GraphStateException {
return ReactAgent.builder()
.name("sql-agent" )
.description("""
You are an agent designed to interact with a SQL database. DO NOT make any DML statements (INSERT, UPDATE, DELETE, DROP etc.). Only SELECT queries are allowed. Remember to:
1. First call list_tables
2. Then call get_schema
3. Then call check_query
4. Finally call execute_query
""" )
.model(chatModel)
.tools(
newListTablesTool(jdbcTemplate).toolCallback(),
new GetSchemaTool (jdbcTemplate).toolCallback(),
new QueryCheckerTool ().toolCallback(),
new ExecuteQueryTool (jdbcTemplate).toolCallback()
)
.build();
}
}
第六部分:Voice Agent 示例 @Configuration
public class VoiceAgentConfiguration {
@Bean
public ReactAgent voiceReactAgent (ChatModel chatModel, BookingTool bookingTool, FlightChangeTool flightChangeTool) {
return ReactAgent.builder()
.name("voice-assistant" )
.description("""
你是一个专业的航空公司语音助手。
你的能力:
1. 查询航班预订详情
2. 更改航班日期
重要输出规则:
- 只用纯文本,不要用 Markdown、列表符号或表情符号
- 保持回复简短,最多 2-3 句话
- 用自然口语化的中文回复,像电话交流一样
""" )
.model(chatModel)
.saver(new MemorySaver ())
.tools(bookingTool.toolCallback(), flightChangeTool.toolCallback())
.build();
}
}
第七部分:工作流示例
7.1 StateGraph 配置 @Configuration
public class GraphConfiguration {
@Bean
public CompiledGraph workflowGraph () {
StateGraph stateGraph = new StateGraph (OverAllState.class);
stateGraph.addNode("node1" , new ProcessNode ());
stateGraph.addNode("node2" , new TransformNode ());
stateGraph.addNode("node3" , new OutputNode ());
stateGraph.addEdge(START, "node1" );
stateGraph.addEdge("node1" , "node2" );
stateGraph.addEdge("node2" , "node3" );
stateGraph.addEdge("node3" , END);
return stateGraph.compile();
}
}
7.2 条件边 stateGraph.addConditionalEdge("detectUpgrade" , new DetectUpgradeDispatcher (), Map.of(
"upgrade" , "upgrade" ,
"continue" , "generateReply" ,
"end" , END
));
第八部分:最佳实践
8.1 工具设计
职责单一 :每个工具专注单一功能
描述清晰 :提供准确的工具描述和参数说明
错误处理 :优雅处理异常,返回友好错误信息
安全控制 :敏感操作添加审批机制
8.2 Agent 设计
系统提示词 :明确角色和行为规范
记忆管理 :使用 MemorySaver 保持对话状态
迭代控制 :设置合理的迭代次数限制
结构化输出 :定义可预测的响应格式
8.3 多智能体编排 场景 推荐模式 简单流程 SequentialAgent 独立任务 ParallelAgent 条件分支 RoutingAgent 迭代优化 LoopAgent
8.4 RAG 优化
文档处理 :chunk 大小 500-1000 tokens,保持适当 overlap
检索优化 :使用混合检索提高召回,实施重排序提高精度
生成优化 :提供清晰的上下文格式,要求标注来源
8.5 错误处理
设置超时和重试
实现降级策略
记录执行日志
使用拦截器统一处理
第九部分:完整配置 spring:
application:
name: spring-ai-alibaba-demo
ai:
dashscope:
api-key: ${AI_DASHSCOPE_API_KEY}
chat:
options:
model: qwen-max
temperature: 0.7
max-tokens: 2000
embedding:
options:
model: text-embedding-v3
vectorstore:
pgvector:
dimensions: 1536
index-type: hnsw
memory:
redis:
host: localhost
port: 6379
timeout: 5000
rag:
knowledge:
sources:
- https://example.com/docs/
chunk-size: 500
chunk-overlap: 50
第十部分:依赖配置 <dependencies >
<dependency >
<groupId > com.alibaba.cloud.ai</groupId >
<artifactId > spring-ai-alibaba-agent-framework</artifactId >
<version > 1.1.2.0</version >
</dependency >
<dependency >
<groupId > com.alibaba.cloud.ai</groupId >
<artifactId > spring-ai-alibaba-starter-dashscope</artifactId >
<version > 1.1.2.0</version >
</dependency >
<dependency >
<groupId > com.alibaba.cloud.ai</groupId >
<artifactId > spring-ai-alibaba-graph</artifactId >
<version > 1.1.2.0</version >
</dependency >
<dependency >
<groupId > org.redisson</groupId >
<artifactId > redisson</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-jdbc</artifactId >
</dependency >
</dependencies >
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
Mermaid 预览与可视化编辑 基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online