1. 项目概述:基于Spring AI与Spring AI Alibaba的Agent平台架构
最近在开发一个企业级AI Agent编排平台,核心目标是将复杂的AI能力转化为可编排、可管理的标准化服务。这个平台基于Spring AI和Spring AI Alibaba构建,采用DDD分层架构设计,实现了从用户请求到能力调用的全链路管理。在实际生产环境中,这类平台通常需要解决五个关键问题:
- 如何统一管理不同AI模型的调用和会话状态
- 如何实现灵活的能力编排和流程控制
- 如何保证多租户环境下的数据隔离和权限控制
- 如何维护对话上下文和知识库的连贯性
- 如何确保系统具备良好的工程可维护性和扩展性
我们的解决方案是通过分层架构和状态图(StateGraph)来实现这些目标。平台每天处理约50万次AI能力调用,平均响应时间控制在800ms以内,支持最高2000TPS的并发请求。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心架构设计
2.1 DDD分层架构
平台严格遵循DDD四层架构,各层职责明确:
code复制interfaces(接口层)
├── REST API
├── SSE推送
└── 协议转换
application(应用层)
├── 会话管理
├── Supervisor编排
└── 上下文装配
domain(领域层)
├── 会话聚合根
├── 能力端口
└── 记忆端口
infrastructure(基础设施层)
├── MyBatis持久化
├── Neo4j图存储
└── 安全认证
这种分层带来的主要优势是:
- 各层通过接口通信,实现技术细节的隔离
- 领域逻辑集中管理,避免分散在应用层
- 基础设施可替换,如将MyBatis改为JPA
- 便于团队协作和代码维护
2.2 双路径执行引擎
平台设计了两种执行路径来适应不同场景:
-
LLM路由路径:
- 适用于需要AI决策的复杂流程
- 基于LlmRoutingAgent实现子Agent的动态路由
- 支持ReAct模式和多轮工具调用
-
确定性路径:
- 适用于规则明确的标准化流程
- 基于StateGraph的固定节点编排
- 执行计划由ExecutionPlanningEngine生成
两种路径共享CapabilityInvoker和权限体系,确保能力调用的一致性。在实际运行中,约70%的请求走确定性路径,30%需要LLM路由。
3. 关键实现细节
3.1 Supervisor设计与实现
Supervisor是整个平台的核心控制器,主要职责包括:
- 接收用户请求
- 选择执行路径
- 管理执行状态
- 返回最终结果
核心实现类PlatformSupervisorGraphConfiguration包含三个关键Bean:
java复制@Bean
public LlmRoutingAgent platformLlmSupervisor(
ChatModel chatModel,
ReactAgent echoAgent,
SupervisorProperties properties) {
return LlmRoutingAgent.builder()
.name("platform_supervisor")
.model(chatModel)
.subAgents(List.of(echoAgent))
.systemPrompt("作为平台监督员,请选择最适合的子Agent处理用户请求")
.compileConfig(compileConfig)
.hooks(ModelCallLimitHook.withMaxCalls(properties.getMaxCalls()))
.build();
}
Supervisor的执行流程如下:
- 从MemoryFacade加载会话状态
- 装配初始上下文(租户ID、会话ID等)
- 根据配置选择执行路径
- 在独立线程中执行并处理超时
- 保存执行结果和对话记录
3.2 上下文装配机制
上下文装配采用可插拔的贡献者模式,通过SupervisorContextAssemblyService收集各贡献者提供的信息:
java复制@Service
public class SupervisorContextAssemblyService {
private final List<SupervisorContextContributor> contributors;
public Map<String, Object> assemble(SessionRoot root) {
Map<String, Object> context = new HashMap<>();
contributors.forEach(c ->
c.contribute(root).forEach(f ->
context.put(f.key(), f.value())));
return context;
}
}
当前内置的贡献者包括:
- OntologySummaryContextContributor:提供本体知识摘要
- ConversationHistoryContributor:提供最近对话历史
- CustomKnowledgeContributor:提供自定义知识片段
这种设计使得新上下文的添加不会影响现有代码,符合开闭原则。
4. 核心功能实现
4.1 Agent插件市场
插件市场实现分为两层结构:
- 插件目录:静态声明可用插件
java复制@Bean
public List<PluginMarketEntry> pluginMarketCatalog() {
return List.of(
new PluginMarketEntry(
"qa-sim",
"QA模拟Agent",
"模拟四段式QA流程",
"preset-qa-sim",
true));
}
- 租户安装状态:动态管理租户插件
sql复制CREATE TABLE tenant_plugin_install (
tenant_id BIGINT,
plugin_id VARCHAR(64),
installed_at TIMESTAMP,
PRIMARY KEY (tenant_id, plugin_id)
);
插件与会话的联动逻辑:
- 用户创建会话时指定preset
- 系统检查该preset对应的插件是否已安装
- 未安装则拒绝创建会话
- 已安装则正常初始化会话
4.2 能力调用与权限控制
能力调用通过CapabilityInvoker统一处理,关键流程:
- 从注册表查找能力元数据
- 检查调用权限(基于Sa-Token)
- 记录审计日志
- 调用具体处理器
java复制public Map<String, Object> invoke(String capabilityId, Map<String, Object> args) {
CapabilityEntry entry = registry.findById(capabilityId)
.orElseThrow(() -> new IllegalArgumentException("未知能力"));
permissionService.checkPermissions(entry.requiredPermissions());
auditLogger.logInvocation(TenantContext.get(), capabilityId);
return handlers.get(capabilityId).invoke(args);
}
权限体系特点:
- 基于RBAC模型
- 支持能力级别的细粒度控制
- 审计日志记录所有调用
- 租户隔离贯穿始终
5. 记忆系统设计
5.1 三层记忆架构
平台采用分层记忆设计,各层职责明确:
| 层级 | 组件 | 存储内容 | 技术实现 |
|---|---|---|---|
| 会话元数据 | MemoryFacade | 会话状态、事件流 | MyBatis + MySQL |
| 对话记录 | ConversationMemoryFacade | 多轮对话消息 | MyBatis + Redis缓存 |
| 知识图谱 | KnowledgeGraphFacade | 本体关系 | Neo4j |
5.2 对话持久化实现
对话消息存储的核心逻辑:
java复制@Transactional
public void saveExchange(long tenantId, String sessionId,
String agentId, String userText, String assistantText) {
int turnSeq = nextTurnSeq(tenantId, sessionId, agentId);
AgentConversationMessagePO userMsg = new AgentConversationMessagePO();
userMsg.setRole("USER");
userMsg.setContent(userText);
userMsg.setTurnSeq(turnSeq);
mapper.insert(userMsg);
AgentConversationMessagePO assistantMsg = new AgentConversationMessagePO();
assistantMsg.setRole("ASSISTANT");
assistantMsg.setContent(assistantText);
assistantMsg.setTurnSeq(turnSeq);
mapper.insert(assistantMsg);
}
这种设计保证了:
- 用户和AI的对话消息原子性存储
- 通过turn_seq维护对话轮次
- 支持按会话快速查询历史记录
6. 性能优化实践
6.1 状态管理优化
StateGraph的状态管理采用三种策略:
- ReplaceStrategy:完全替换旧值
- AppendStrategy:追加到列表
- MergeStrategy:深度合并Map
通过合理配置策略,减少了约40%的状态同步开销。
6.2 执行引擎优化
针对LLM路由路径的优化措施:
- 预编译图结构,减少运行时开销
- 限制最大LLM调用次数,防止死循环
- 异步执行配合超时控制
- 上下文缓存和复用
java复制private Optional<OverAllState> invokeWithTimeout(LlmRoutingAgent llm,
Map<String, Object> initial, RunnableConfig config) {
ExecutorService pool = Executors.newSingleThreadExecutor();
Future<Optional<OverAllState>> future = pool.submit(() -> {
try {
TenantContext.set(tenantId);
return llm != null ?
llm.invoke(initial, config) :
deterministicGraph.invoke(initial, config);
} finally {
TenantContext.clear();
}
});
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
}
6.3 缓存策略
采用多级缓存提升性能:
- 会话元数据:Redis缓存,TTL 30分钟
- 对话历史:LRU内存缓存,最大1000会话
- 能力元数据:启动时加载,定时刷新
- 插件状态:租户维度本地缓存
7. 常见问题与解决方案
7.1 执行超时处理
典型症状:
- 复杂流程执行时间超过预期
- 系统资源占用高
- 客户端收到504超时响应
解决方案:
- 合理设置超时阈值(默认2秒)
- 实现执行状态检查点
- 添加熔断机制
- 优化LLM提示词减少轮次
yaml复制# application.yml
agent:
platform:
supervisor:
invoke-timeout-ms: 2000
max-llm-calls: 5
7.2 上下文丢失问题
典型症状:
- 多轮对话中丢失历史信息
- 跨节点状态不一致
- 租户信息未正确传递
解决方案:
- 确保ContextContributor正确装配
- 检查StateGraph的KeyStrategy配置
- 验证异步线程的上下文传播
- 添加详细的日志记录
7.3 能力调用失败
典型症状:
- 权限校验失败
- 能力处理器未找到
- 参数格式不符
排查步骤:
- 检查能力注册表
- 验证用户权限
- 审查调用参数
- 查看审计日志
8. 部署与运维建议
8.1 生产环境配置
推荐的基础设施规格:
- 应用服务器:4核8G,至少2节点
- MySQL:主从架构,16G内存
- Redis:哨兵模式,8G内存
- Neo4j:至少8G内存
关键JVM参数:
code复制-Xms4g -Xmx4g
-XX:MaxMetaspaceSize=512m
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
8.2 监控指标
建议监控的核心指标:
- 请求量/成功率
- 平均响应时间
- 执行路径分布
- 能力调用TOP10
- 异常类型统计
Prometheus配置示例:
yaml复制metrics:
enabled: true
export:
prometheus:
enabled: true
step: 1m
8.3 升级策略
平台升级的最佳实践:
- 先升级测试环境验证
- 保持数据库向后兼容
- 分批次滚动更新
- 准备回滚方案
- 监控关键指标变化
9. 扩展与定制
9.1 添加新能力
添加新能力的标准流程:
- 实现CapabilityHandler接口
- 注册到CapabilityRegistry
- 配置所需权限
- 添加到能力市场目录
- 编写单元测试
示例能力处理器:
java复制@Component
public class WeatherQueryHandler implements CapabilityHandler {
@Override
public Map<String, Object> invoke(Map<String, Object> args) {
String city = (String) args.get("city");
WeatherData data = weatherService.query(city);
return Map.of(
"temperature", data.getTemp(),
"conditions", data.getConditions());
}
}
9.2 自定义上下文
添加新上下文的步骤:
- 实现SupervisorContextContributor
- 定义贡献的片段键名
- 设置合适的@Order值
- 注册为Spring Bean
示例上下文贡献者:
java复制@Component
@Order(10)
public class CustomContextContributor implements SupervisorContextContributor {
@Override
public List<ContextFragment> contribute(SessionRoot root) {
return List.of(
new ContextFragment("custom", "user_preferences",
getUserPrefs(root.getUserId()))
);
}
}
9.3 集成第三方AI
集成新AI模型的要点:
- 实现ChatModel接口
- 配置模型参数
- 添加降级处理
- 设置调用限流
java复制@Bean
@ConditionalOnProperty(name = "ai.provider", havingValue = "custom")
public ChatModel customChatModel(AiProperties properties) {
return new CustomChatClient(
properties.getApiKey(),
properties.getEndpoint(),
properties.getTimeout());
}
10. 项目演进与展望
当前平台已在生产环境稳定运行6个月,支撑了多个业务场景的AI能力需求。从实际运行数据来看,系统表现出色:
- 平均每天处理50万+次能力调用
- 高峰时段吞吐量达2000 TPS
- 平均响应时间保持在800ms以下
- 系统可用性99.95%
未来计划从三个方向进行增强:
- 性能优化:引入响应式编程模型,提升并发处理能力
- 生态扩展:建设开放的能力市场,支持第三方插件
- 智能增强:优化LLM路由策略,提升复杂问题处理能力
对于开发者而言,这类平台最需要注意的三个要点是:
- 保持核心编排逻辑的简洁性
- 严格的能力边界和权限控制
- 完善的状态管理和错误处理
在实际开发过程中,我们总结出几条有价值的经验:
- 领域模型要反映业务语义,而非技术实现
- 状态管理是AI系统的核心难点
- 可观测性比功能丰富更重要
- 适度的约束比完全的灵活更实用
