一、pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.8</version>
<relativePath/>
</parent>
<groupId>com.zhan.agent</groupId>
<artifactId>agent-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>agent-demo</name>
<description>agent demo</description>
<properties>
<java.version>17</java.version>
<spring-ai-alibaba.version>1.1.0.0-M5</spring-ai-alibaba.version>
<spring-ai.version>1.1.0-M4</spring-ai.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-bom</artifactId>
<version>${spring-ai-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Agent Framework -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-agent-framework</artifactId>
</dependency>
<!-- Dash5cope(阿里云百炼) -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
<version>${spring-ai-alibaba.version}</version>
</dependency>
<!-- Graph Core -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-graph-core</artifactId>
</dependency>
<!-- Spring Boot Starter Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
二、yml配置文件
spring:
ai:
dashscope:
api-key: sk-09c7b571687b46d5a2e25a03fbddxxxx
application:
name: spring-ai-alibaba-demo
server:
port: 8080
logging:
level:
com.alibaba.cloud.ai: DEBUG
三、agentConfig
package com.zhan.agent.config;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AgentConfig {
@Bean
public ChatClient chatBotAgent(ChatModel chatModel) {
return ChatClient.builder(chatModel).defaultSystem("你是一个友好的AI助手,能够回答用户的问题。请用中文回答,保持回答简洁明了。").build();
}
@Bean
public ChatClient calculatorAgent(ChatModel chatModel) {
return ChatClient.builder(chatModel).defaultSystem("你是一个数学计算助手,能够处理各种数学计算问题。请用中文回答。").build();
}
@Bean
public ChatClient creativeWriterAgent(ChatModel chatModel) {
return ChatClient.builder(chatModel).defaultSystem("你是一个创意写作助手,擅长创作各种文体的内容。请用中文回答。").build();
}
}
四、workflowController
package com.zhan.agent.controller;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/workflow")
public class WorkflowController {
@Autowired
private ChatModel chatModel;
@GetMapping("/execute")
public String executeWorkflow(@RequestParam String input) {
try {
//模拟工作流:分类->处理->输出结果
String classification = classifyInput(input);
String result = processClassification(classification);
return result;
} catch (Exception e) {
return "工作流执行错误:" + e.getMessage();
}
}
private String classifyInput(String input) {
String prompt = "请将以下文本分类为:积极、消极或中性。只返回分类结果,不要其他解释。\n\n文本:" + input;
return ChatClient.builder(chatModel)
.build()
.prompt()
.user(prompt)
.call()
.content();
}
private String processClassification(String classification) {
String prompt = "根据分类结果生成相应的回复。分类:" + classification + "\n请生成一个简洁的回复。";
return ChatClient.builder(chatModel)
.build()
.prompt()
.user(prompt)
.call()
.content();
}
@GetMapping("/simple")
public String simpleWorkflow(@RequestParam String input) {
try {
String result = ChatClient.builder(chatModel)
.build()
.prompt()
.user("请处理以下请求:" + input)
.call()
.content();
return "工作流结果:" + result;
} catch (Exception e) {
return "工作流执行错误:" + e.getMessage();
}
}
@GetMapping("/info")
public String getWorkflowInfo() {
return "简单工作流演示:输入文本->自动分类->处理结果";
}
}
五、chatController
package com.zhan.agent.controller;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
@RestController
@RequestMapping("/api")
public class ChatController {
@Autowired
@Qualifier("chatBotAgent")
private ChatClient chatBotAgent;
@Autowired
@Qualifier("calculatorAgent")
private ChatClient calculatorAgent;
@Autowired
@Qualifier("creativeWriterAgent")
private ChatClient creativeWriterAgent;
@Autowired
private ChatModel chatModel;
@GetMapping("/chat")
public String chat(@RequestParam String query) {
try {
String response = chatBotAgent.prompt()
.user(query)
.call()
.content();
return response;
} catch (Exception e) {
return "抱歉,处理请求时出现错误:" + e.getMessage();
}
}
@GetMapping("/calculator")
public String calculator(@RequestParam String query) {
try {
String response = calculatorAgent.prompt()
.user(query)
.call()
.content();
return response;
} catch (Exception e) {
return "抱歉,计算出现错误:" + e.getMessage();
}
}
@GetMapping("/creative")
public String creative(@RequestParam String query) {
try {
String response = creativeWriterAgent.prompt()
.user(query)
.call()
.content();
return response;
} catch (Exception e) {
return "抱歉,创作出现错误:" + e.getMessage();
}
}
@GetMapping(value = "/stream", produces = "text/event-stream")
public Flux<String> streamChat(@RequestParam String query) {
return chatBotAgent.prompt()
.user(query)
.stream()
.content()
.onErrorReturn("抱歉,流式响应出现错误");
}
@GetMapping("/models")
public String getModelInfo() {
return "当前使用的模型:DashScope Qwen系列模型";
}
}
六、index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Spring AI Alibaba演示平台</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/daisyui/4.12.10/full.min.css" rel="stylesheet">
<link href="https://cdn.bootcdn.net/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
</head>
<body class="bg-gray-50 min-h-screen">
<!--导航栏-->
<div class="navbar bg-gradient-to-r from-blue-600 to-purple-600 text-white shadow-lg">
<div class="navbar-start">
<div class="dropdown">
<label tabindex="0" class="btn btn-ghost lg:hidden">
<i class="fas fa-bars text-xl"></i>
</label>
<ul tabindex="0" class="menu menu-compact dropdown-content mt-3 p-2 shadow bg-base-100 rounded-box w-52">
<li><a href="#chat" class="text-gray-800">智能对话</a></li>
<li><a href="#workflow" class="text-gray-800">工作流</a></li>
<li><a href="#features" class="text-gray-800">特性展示</a></li>
</ul>
</div>
<a class="btn btn-ghost normal-case text-xl">
<i class="fas fa-robot mr-2"></i>Spring AI Alibaba
</a>
</div>
<div class="navbar-center hidden lg:flex">
<ul class="menu menu-horizontal px-1">
<li><a href="#chat" class="text-white hover:bg-white/20">智能对话</a></li>
<li><a href="#workflow" class="text-white hover:bg-white/20">工作流</a></li>
<li><a href="#features" class="text-white hover:bg-white/20">特性展示</a></li>
</ul>
</div>
<div class="navbar-end">
<button class="btn btn-ghost btn-circle">
<i class="fas fa-cog text-xl"></i>
</button>
</div>
</div>
<!--主要内容区域-->
<div class="container mx-auto px-4 py-8">
<!--欢迎区域-->
<div class="hero bg-gradient-to-r from-blue-50 to-purple-50 rounded-2xl mb-8">
<div class="hero-content text-center py-12">
<div class="max-w-2xl">
<h1 class="text-5xl font-bold text-gray-800 mb-4">
<i class="fas fa-brain text-blue-600 mr-3"></i>Spring AI Alibaba
</h1>
<p class="text-xl text-gray-600 mb-6">
基于ReactAgent设计理念,的智能Agent开发框架,支持多Agent编排、工作流管理和人在回路交互
</p>
<div class="flex justify-center space-x-4">
<div class="badge badge-primary badge-lg p-4">
<i class="fas fa-robot mr-2"></i>ReactAgent
</div>
<div class="badge badge-secondary badge-lg p-4">
<i class="fas fa-project-diagram mr-2"></i>Graph Core
</div>
<div class="badge badge-accent badge-lg p-4">
<i class="fas fa-users mr-2"></i>Agent
</div>
</div>
</div>
</div>
</div>
<!--功能区域-->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<!--智能对话区域-->
<div id="chat" class="card bg-white shadow-xl">
<div class="card-body">
<h2 class="card-title text-2xl text-gray-800">
<i class="fas fa-comments text-blue-600 mr-2"></i>智能对话
</h2>
<p class="text-gray-60mb-4">体验基于ReactAgent的智能对话能力</p>
<div class="tabs tabs-boxed mb-4">
<a class="tab tab-active" onclick="switchChatMode('general')">通用对话</a>
<a class="tab" onclick="switchChatMode('calculator')">计算器</a>
<a class="tab" onclick="switchChatMode('writer')">创意写作</a>
</div>
<div class="form-control">
<label class="label">
<span class="label-text">输入您的问题</span>
</label>
<textarea id="chatInput" class="textarea textarea-bordered h-24"
placeholder="请输入您想询问的问题.."></textarea>
</div>
<div class="card-actions justify-end mt-4">
<button onclick="streamChat()" class="btn btn-outline btn-primary">
<i class="fas fa-stream mr.-2"></i>流式对话
</button>
<button onclick="sendChat()" class="btn btn-primary">
<i class="fas fa-paper-plane mr-2"></i>发送
</button>
</div>
</div>
<div id="chatResponse" class="mt-4 p-4 bg-gray-50 rounded-lg hidden">
<div class="flex items-center mb-2">
<i class="fas fa-robot text-blue-600 mr-2"></i>
<span class="font-semibold">AI▣复:</span>
</div>
<div id="chatContent" class="text-gray-700"></div>
</div>
</div>
<!--工作流演示区域-->
<div id="workflow" class="card bg-white shadow-xl">
<div class="card-body">
<h2 class="card-title text-2xl text-gray-800">
<i class="fas fa-project-diagram text-purple-600 mr-2"></i>工作流演示
</h2>
<p class="text-gray-600 mb-4">体验基于Graph Core的工作流编排</p>
<div class="form-control">
<label class="label">
<span class="label-text">输入文本进行分类</span>
</label>
<input id="workflowInput" type="text" class="input input-bordered" placeholder="请输入需要分类的文本..">
</div>
<div class="card-actions justify-end mt-4">
<button onclick="executeWorkflow()" class="btn btn-secondary">
<i class="fas fa-play mr-2"></i>执行工作流
</button>
</div>
<div id="workflowResult" class="mt-4 p-4 bg-purple-50 rounded-lg hidden">
<div class="flex items-center mb-2">
<i class="fas fa-chart-line text-purple-600 mr-2"></i>
<span class=-"font-semibold">工作流结果:</span>
</div>
<div id="workflowContent" class="text-gray-700 whitespace-pre-line"></div>
</div>
</div>
</div>
</div>
<!--特性展示区域-->
<div id="features" class="mt-12">
<h2 class="text-3xl font-bold text-center text-gray-800 mb-8">
<i class="fas fa-star text-yellow-500 mr-3"></i>核心特性展示
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<div class="card bg-gradient-to-br from-blue-500 to-blue-600 text-white">
<div class="card-body text-center">
<i class="fas fa-brain text-4xl mb-4"></i>
<h3 class="card-title justify-center">ReactAgent</h3>
<p>基于ReAct范式的智能Agent,支持推理和行动能力</p>
</div>
</div>
<div class="card bg-gradient-to-br from-purple-500 to-purple-600 text-white">
<div class="card-body text-center">
<i class="fas fa-sitemap text-4xl mb-4"></i>
<h3 class="card-title justify-center'">多Agent编排</h3>
<p>支持Sequential、Parallel、Routing、Loop等多种编排模式</p>
</div>
</div>
<div class="card bg-gradient-to-br from-green-500 to-green-600 text-white">
<div class="card-body text-center">
<i class="fas fa-project-diagram text-4xl mb-4"></i>
<h3 class="card-title justify-center">Graph Core</h3>
<p>基于图的工作流运行时,支持条件路由和状态管理</p>
</div>
</div>
<div class="card bg-gradient-to-br from-orange-500 to-orange-600 text-white">
<div class="card-body text-center">
<i class="fas fa-user-check text-4xl mb-4"></i>
<h3 class="card-title justify-center">人在回路</h3>
<p>支持Human-in-the-loop交互,人工参与关键决策</p>
</div>
</div>
</div>
</div>
<!--架构图展示-->
<div class="mt-12 card bg-white shadow-xl">
<div class="card-body">
<h2 class="card-title text-2xl text-gray-800 mb-6">
<i class="fas fa-layer-group text-indigo-600 mr-2"></i>架构层次
</h2>
<div class="space-y-4">
<div class="p-4 bg-gradient-to-r from-blue-100 to-blue-200 rounded-lg border-l-4 border-blue-500">
<h4 class="font-bold text-blue-800">Agent Framework(高级抽象层)</h4>
<p class="text-blue-700">ReactAgent,SequentialAgent,ParallelAgent,LlmRoutingAgent,LoopAgent</p>
</div>
<div class="text-center text-gray-400">
<i class="fas fa-arrow-down text-2xl"></i>
</div>
<div class="p-4 bg-gradient-to-r from-purple-100 to-purple-200 rounded-lg border-l-4 border-purple-500">
<h4 class="font-bold text-purple-800">Graph Core(工作流运行时)</h4>
<p class="text-purple-700">StateGraph,Node,Edge,OverAllState,CompiledGraph</p>
</div>
<div class="text-center text-gray-400">
<i class="fas fa-arrow-down text-2xl"></i>
</div>
<div class="p-4 bg-gradient-to-r from-green-100 to-green-200 rounded-lg border-l-4 border-green-500">
<h4 class="font-bold text-green-800">Spring AI(基础抽象层)</h4>
<p class="text-green-700">ChatModel,Tool,Message,MCP</p>
</div>
</div>
</div>
</div>
</div>
<!--页脚-->
<footer class="footer footer-center p-10 bg-gray-800 text-white mt-16">
<div>
<p class="text-lg">Spring AI Alibaba演示平台</p>
<p class="text-sm opacity-7">基于ReactAgent设计理念,的智能Agent开发框架</p>
<p class="text-xs opacity-50 mt-2">
参考文档:<a href="https://blog.csdn.net/Traitsw/article/details/155613644" target="_blank"
class="link link-hover">CSDN-Spring AI Alibaba:智能Agent;开发实战指南</a>
</p>
</div>
</footer>
<script>
let currentChatMode ='general';
function switchChatMode(mode){
currentChatMode = mode;
document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('tab-active'));
event.target.classList.add('tab-active');
const input = document.getElementById('chatInput');
switch(mode){
case 'general':
input.placeholder='请输入您想询问的问题..';
break;
case 'calculator':
input.placeholder='请输入数学计算问题,如:计算15+27*3';
break;
case 'writer':
input.placeholder='请输入创作需求,如:写一篇关于春天的短文';
break;
}
}
async function sendChat() {
const input = document.getElementById('chatInput').value.trim();
if (!input) return;
const responseDiv = document.getElementById('chatResponse');
const contentDiv = document.getElementById('chatContent');
responseDiv.classList.remove('hidden');
contentDiv.innerHTML='<div class="loading loading-spinner loading-md"></div>正在处理..';
try {
let endpoint ='/api/chat';
if (currentChatMode === 'calculator') endpoint = '/api/calculator';
if (currentChatMode === 'writer') endpoint = '/api/creative';
const response = await fetch(`${endpoint}?query=${encodeURIComponent(input)}`);
const result = await response.text();
contentDiv.innerHTML = result;
} catch (error) {
contentDiv.innerHTML='抱歉,请求失败:' + error.message;
}
}
async function streamChat() {
const input = document.getElementById('chatInput').value.trim();
if (!input) return;
const responseDiv = document.getElementById('chatResponse');
const contentDiv = document.getElementById('chatContent');
responseDiv.classList.remove('hidden');
contentDiv.innerHTML='<div class="loading loading-spinner loading-md"></div>正在流式处理..';
try {
const response = await fetch(`/api/stream?query=${encodeURIComponent(input)}`);
const reader = response.body.getReader();
const decoder = new TextDecoder();
let result ='';
while (true) {
const { done,value } = await reader.read();
if (done) break;
result += decoder.decode(value);
contentDiv.innerHTML = result;
}
} catch (error){
contentDiv.innerHTML='抱歉,流式请求失败:' + error.message;
}
}
async function executeWorkflow(){
const input = document.getElementById('workflowInput').value.trim();
if (!input) return;
const resultDiv = document.getElementById('workflowResult');
const contentDiv = document.getElementById('workflowContent')
resultDiv.classList.remove('hidden');
contentDiv.innerHTML='<div class="loading loading-spinner loading-md"></div>正在执行工作流..';
try {
const response = await fetch(`/api/workflow/execute?input=${encodeURIComponent(input)}`);
const result = await response.text();
contentDiv.innerHTML = result;
} catch (error){
contentDiv.innerHTML='抱歉,工作流执行失败:' + error.message;
}
}
//回车发送
document.getElementById('chatInput').addEventListener('keypress',function(e){
if (e.key === 'Enter' && !e.shiftKey){
e.preventDefault();
sendChat();
}
});
document.getElementById('workflowInput').addEventListener('keypress',function(e){
if (e.key === 'Enter'){
e.preventDefault();
executeWorkflow();
}
});
</script>
</body>
</html>
七、效果