多智能体系统入门到精通:基于Spring AI Alibaba实战,收藏这篇就够了!

多智能体系统入门到精通:基于Spring AI Alibaba实战,收藏这篇就够了!svg xmlns http www w3 org 2000 svg style display none svg

大家好,我是讯享网,很高兴认识大家。这里提供最前沿的Ai技术和互联网信息。



 
  
    
     
      
     

在很多团队的实际落地过程中,“多智能体”很容易停留在 Demo 层面:

  • • 能跑通几个 Agent 互相调用
  • • 能生成一段看起来不错的内容
  • • 能在单机环境完成一次链路演示

但一旦进入真实业务环境,问题会马上出现:

  • • 请求量上来后,模型调用延迟和成本不可控
  • • 多个智能体之间上下文不一致,生成结果互相冲突
  • • 缺少编排、限流、重试、降级、缓存、可观测,系统无法稳定运行
  • • 代码层面只展示了简单样例,距离生产级实现差距很大

本文不再停留在“如何写一个多 Agent Demo”,而是从架构师和资深工程师视角,系统讲清楚如何基于 Spring AI Alibaba 构建一个真正可落地的 故事创作多智能体系统。文章重点包括:

  • • 多智能体协作的原理与架构设计
  • • 面向高并发场景的工程化方案
  • • 生产级代码实现与核心设计模式
  • • 缓存、异步化、限流、降级、可观测与部署方案
  • • 一个贴近业务的完整案例:在线故事创作平台

如果你希望的不只是“能生成故事”,而是“能支撑业务上线”,这篇文章会更接近你真正需要的答案。


2.1 目标业务场景

我们假设要建设一个在线 AI 创作平台,面向 C 端作者、内容社区、教育平台或互动小说应用,提供如下能力:

  • • 用户输入主题、风格、受众、篇幅、角色偏好
  • • 系统自动完成故事策划、角色设定、场景设计、章节生成、风格统一
  • • 支持大批量并发生成
  • • 支持流式返回和异步任务模式
  • • 支持作品二次编辑、续写、重写

典型请求示例:

 

2.2 为什么适合用多智能体

故事创作天然不是一个单点能力问题,而是一个复杂任务分解问题。一个高质量故事至少包含:

  • • 世界观和主线冲突设计
  • • 角色目标、动机与成长弧
  • • 场景和章节推进
  • • 文风统一和润色
  • • 结果校验与质量评估

如果把所有任务交给一个“大一统 Prompt”,常见问题是:

  • • 输出长度不稳定
  • • 结构松散
  • • 风格漂移
  • • 人物设定前后矛盾
  • • 场景信息遗漏

因此更合理的方式是:将复杂创作任务拆解为多个专业化智能体,由编排层协调执行,再由汇总智能体整合输出。

2.3 真实工程挑战

当系统进入生产环境,真正难的不是“写 Prompt”,而是解决以下问题:

  • • 如何定义智能体职责边界,避免重复劳动和上下文污染
  • • 如何保证多个智能体之间的数据契约一致
  • • 如何让模型调用具备超时、重试、熔断、限流能力
  • • 如何应对高并发下的线程池、连接池、消息积压与缓存击穿
  • • 如何支持同步、流式、异步三种调用模式
  • • 如何沉淀监控指标,定位慢调用、坏输出和成本异常

3.1 从“Prompt 拼接”到“任务编排”

多智能体系统的本质不是多个 LLM 实例,而是 面向复杂任务的分工协作系统。它通常由四层组成:

  1. 接入层:接收用户请求,做鉴权、限流、参数校验
  2. 编排层:负责任务拆解、执行顺序、并行控制、超时控制
  3. 智能体层:执行具体任务,如情节设计、人物塑造、风格统一
  4. 基础设施层:模型网关、缓存、数据库、MQ、监控、日志、追踪

3.2 多智能体协作模式

常见协作模式有三种:

模式一:串行链式协作

适合强依赖型流程,例如:

  • • 先生成故事大纲
  • • 再基于大纲生成人物
  • • 再基于人物和大纲生成章节

优点:

  • • 结果可控
  • • 上下文依赖明确

缺点:

  • • 总耗时较长
  • • 某一步失败会阻塞整体
模式二:并行协作

适合弱依赖或可提前拆分的任务,例如:

  • • 角色设定
  • • 场景设定
  • • 风格约束

优点:

  • • 总时延低
  • • 适合高并发优化

缺点:

  • • 汇总阶段复杂
  • • 容易出现结果不一致
模式三:评审闭环协作

适合质量要求高的场景:

  • • 生成智能体产出初稿
  • • 评审智能体检查逻辑、风格、重复率、敏感内容
  • • 修订智能体进行再加工

优点:

  • • 内容质量更稳定

缺点:

  • • Token 成本更高
  • • 处理链路更长

实际生产中,往往是“串行 + 并行 + 评审闭环”的组合。

3.3 本文采用的协作拓扑

用户请求

API Gateway

Story Application Service

Workflow Orchestrator

Plot Agent

Character Agent

Scene Agent

Chapter Agent

Shared Story Context

Style Agent

Review Agent

质量达标?

持久化/缓存/MQ

Rewrite Agent

这里有三个关键设计思想:

  • 共享上下文对象:避免每个 Agent 自己拼 Prompt,导致上下文失真
  • 编排层控制执行:Agent 只关注能力,不关心调度细节
  • 评审闭环:将质量控制前置,而不是把低质量输出直接交给用户

4.1 系统总体架构

Web/App/开放API

API Gateway

Story Service

Agent Orchestrator

Spring AI Alibaba Model Gateway

Redis

MySQL

Kafka/RocketMQ

Prometheus + Grafana + Trace

Async Story Worker

4.2 分层职责

1)API Gateway

职责:

  • • Token 校验与租户隔离
  • • 接口限流和黑白名单
  • • 请求透传 traceId
  • • 路由同步接口与异步接口
2)应用服务层

职责:

  • • 参数校验
  • • 幂等控制
  • • 返回任务单或流式响应
  • • 选择合适执行模式
3)编排层 Orchestrator

职责:

  • • 任务拆解
  • • 并行编排
  • • 超时控制
  • • 审核闭环
  • • 失败补偿
4)Agent 能力层

职责:

  • • 只负责领域任务
  • • 不耦合数据库、MQ、控制器
  • • 输入输出通过 DTO/Domain Object 约束
5)基础设施层

职责:

  • • 模型调用适配
  • • 缓存
  • • 消息驱动异步执行
  • • 数据持久化
  • • 监控和审计

4.3 为什么不建议直接在 Controller 里串 Agent

很多初学者实现是这样的:

  • • Controller 接收请求
  • • 直接 new/注入多个 Agent
  • • 顺序调用模型
  • • 拼一个结果返回

这种做法在 Demo 阶段没问题,但在生产环境存在明显风险:

  • • 缺少职责分离,无法扩展
  • • 无法复用编排逻辑
  • • 无法做统一超时、熔断、重试
  • • 测试困难
  • • 后续难以接入异步任务、审核流、回调机制

正确方式应该是:

  • • Controller 只做接入
  • • Application Service 只做用例编排入口
  • • Orchestrator 负责业务级工作流
  • • Agent 负责纯能力实现

组件 技术选型 作用 选型理由 Web 框架 Spring Boot 3.x 服务承载 生态成熟,便于整合监控、配置、数据层 AI 框架 Spring AI Alibaba 模型接入 统一抽象 ChatModel、Prompt、Advisor、Tool 等能力 服务治理 Spring Cloud Alibaba 配置/注册发现 与 Nacos、Sentinel 等整合较强 缓存 Redis 结果缓存/幂等/热点保护 高性能,适合分布式场景 数据库 MySQL 8.x 请求、作品、审计持久化 事务与结构化查询能力稳定 MQ Kafka 或 RocketMQ 异步生成、削峰填谷 解耦同步链路与离线生成 限流熔断 Sentinel / Resilience4j 流量治理 保护模型网关和下游服务 可观测 Micrometer + Prometheus + Grafana + Zipkin/Tempo 监控与追踪 便于定位慢调用和异常链路 容器化 Docker + Kubernetes 部署与扩缩容 生产环境标准配置

  1. 领域建模:先把数据结构设计对

多智能体系统最容易失控的点之一,就是各 Agent 输入输出随意定义。生产环境里,必须先做 统一领域对象建模

6.1 核心请求对象

package com.example.story.domain;import jakarta.validation.constraints.Max;import jakarta.validation.constraints.Min;import jakarta.validation.constraints.NotBlank;import jakarta.validation.constraints.NotEmpty;import java.util.List;public record StoryRequest( @NotBlank String requestId, @NotBlank String theme, @NotBlank String genre, @NotBlank String style, @NotBlank String targetAudience, @Min(1) @Max(20) int chapters, @NotEmpty List 
        
    
          
            keywords, String language) {} 
          

6.2 共享上下文对象

package com.example.story.domain;import java.time.Instant;import java.util.ArrayList;import java.util.List;public class StoryContext { private final String requestId; private final StoryRequest request; private StoryOutline outline; private List 
        
    
          
            characters = new ArrayList<>(); private List 
           
             scenes = new ArrayList<>(); private List 
            
              chapters = new ArrayList<>(); private StoryReview review; private Instant startedAt = Instant.now(); public StoryContext(String requestId, StoryRequest request) { this.requestId = requestId; this.request = request; } public String requestId() { return requestId; } public StoryRequest request() { return request; } public StoryOutline outline() { return outline; } public void setOutline(StoryOutline outline) { this.outline = outline; } public List 
             
               characters() { return characters; } public void setCharacters(List 
              
                characters) { this.characters = characters; } public List 
               
                 scenes() { return scenes; } public void setScenes(List 
                
                  scenes) { this.scenes = scenes; } public List 
                 
                   chapters() { return chapters; } public void setChapters(List 
                  
                    chapters) { this.chapters = chapters; } public StoryReview review() { return review; } public void setReview(StoryReview review) { this.review = review; } public Instant startedAt() { return startedAt; }} 
                   
                  
                 
                
               
              
             
            
          

6.3 统一输出对象

package com.example.story.domain;import java.time.Instant;import java.util.List;public record StoryResult( String requestId, String title, StoryOutline outline, List 
        
    
          
            characters, List 
           
             chapters, StoryReview review, Instant createdAt) {} 
            
          

6.4 为什么共享上下文是关键

如果没有 StoryContext 这种共享领域对象,系统很容易出现:

  • • PlotAgent 输出大纲字段 A
  • • CharacterAgent 需要字段 B
  • • ChapterAgent 又拼接另一套 Prompt
  • • 最后 StyleAgent 根本拿不到完整语义

本质上,上下文对象就是多智能体系统里的“状态中枢”。它让多 Agent 从“无序 Prompt 串联”变成“有约束的数据驱动编排”。


7.1 设计目标

我们不希望业务代码直接散落大量模型调用细节,而是封装统一的 LLM Gateway,负责:

  • • Prompt 构造
  • • 模型参数设置
  • • 超时与重试
  • • 结构化输出解析
  • • 调用日志记录
  • • Token 与耗时指标上报

7.2 模型网关封装

package com.example.story.infrastructure.ai;import io.micrometer.core.instrument.MeterRegistry;import io.micrometer.core.instrument.Timer;import java.time.Duration;import java.util.Map;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.springframework.ai.chat.client.ChatClient;import org.springframework.ai.chat.prompt.Prompt;import org.springframework.ai.chat.prompt.PromptTemplate;import org.springframework.stereotype.Component;@Slf4j@Component@RequiredArgsConstructorpublic class StoryModelGateway { private final ChatClient chatClient; private final MeterRegistry meterRegistry; public String call(String template, Map 
         
    
           
             variables, StoryModelOptions options) { Timer.Sample sample = Timer.start(meterRegistry); try { Prompt prompt = new PromptTemplate(template).create(variables); String content = chatClient.prompt(prompt) .advisors(advisorSpec -> advisorSpec.param("requestId", options.requestId())) .options(options.toChatOptions()) .call() .content(); sample.stop(Timer.builder("story.ai.call.latency") .tag("scene", options.scene()) .tag("model", options.model()) .register(meterRegistry)); meterRegistry.counter("story.ai.call.success", "scene", options.scene(), "model", options.model()).increment(); return content; } catch (Exception ex) { meterRegistry.counter("story.ai.call.error", "scene", options.scene(), "model", options.model()).increment(); log.error("LLM call failed, requestId={}, scene={}", options.requestId(), options.scene(), ex); throw ex; } } public record StoryModelOptions( String requestId, String scene, String model, Double temperature, Integer maxTokens, Duration timeout ) { public org.springframework.ai.openai.OpenAiChatOptions toChatOptions() { return org.springframework.ai.openai.OpenAiChatOptions.builder() .model(model) .temperature(temperature) .maxTokens(maxTokens) .build(); } }} 
           

7.3 为什么需要统一网关

如果每个 Agent 都自己直接调 ChatClient,后果通常是:

  • • 参数风格不统一
  • • 超时策略不一致
  • • 指标无法汇总
  • • 故障排查困难

统一网关的价值是:将“模型调用”从业务实现细节提升为平台能力。


8.1 Agent 接口抽象

package com.example.story.agent;import com.example.story.domain.StoryContext;public interface StoryAgent 
          
    
            
              { T execute(StoryContext context); String name();} 
            

8.2 情节设计智能体

职责:

  • • 生成世界观
  • • 生成主线冲突
  • • 给出章节纲要
package com.example.story.agent;import com.example.story.domain.StoryContext;import com.example.story.domain.StoryOutline;import com.example.story.infrastructure.ai.StoryModelGateway;import com.fasterxml.jackson.databind.ObjectMapper;import java.util.Map;import lombok.RequiredArgsConstructor;import org.springframework.stereotype.Component;@Component@RequiredArgsConstructorpublic class PlotAgent implements StoryAgent 
          
    
            
              { private static final String PROMPT = """ 你是资深小说策划编辑,请基于以下信息输出故事大纲。 主题: {theme} 类型: {genre} 风格: {style} 目标读者: 章节数: {chapters} 关键词: {keywords} 输出要求: 1. 给出标题 2. 给出世界观设定 3. 给出主线冲突 4. 给出章节级大纲 5. 严格输出 JSON """; private final StoryModelGateway modelGateway; private final ObjectMapper objectMapper; @Override public StoryOutline execute(StoryContext context) catch (Exception ex) { throw new IllegalStateException("Failed to parse outline JSON", ex); } } @Override public String name() { return "PlotAgent"; }} 
            

8.3 人物塑造智能体

职责:

  • • 根据大纲生成角色
  • • 明确人物关系、目标、秘密、成长弧
package com.example.story.agent;import com.example.story.domain.StoryCharacter;import com.example.story.domain.StoryContext;import com.example.story.infrastructure.ai.StoryModelGateway;import com.fasterxml.jackson.core.type.TypeReference;import com.fasterxml.jackson.databind.ObjectMapper;import java.util.List;import java.util.Map;import lombok.RequiredArgsConstructor;import org.springframework.stereotype.Component;@Component@RequiredArgsConstructorpublic class CharacterAgent implements StoryAgent 
          
    
            
              > { private static final String PROMPT = """ 你是角色设定专家,请根据故事大纲生成核心人物列表。 故事标题: {title} 世界观: {world} 主线冲突: {conflict} 输出要求: 1. 至少 3 个角色 2. 每个角色包含:name、age、identity、personality、goal、arc、relationship 3. 严格输出 JSON 数组 """; private final StoryModelGateway modelGateway; private final ObjectMapper objectMapper; @Override public List 
             
               execute(StoryContext context) { var outline = context.outline(); String content = modelGateway.call( PROMPT, Map.of( "title", outline.title(), "world", outline.worldSetting(), "conflict", outline.mainConflict() ), new StoryModelGateway.StoryModelOptions( context.requestId(), "character", "qwen-plus", 0.8, 1800, java.time.Duration.ofSeconds(20) ) ); try { List 
              
                characters = objectMapper.readValue(content, new TypeReference<>() {}); context.setCharacters(characters); return characters; } catch (Exception ex) { throw new IllegalStateException("Failed to parse characters JSON", ex); } } @Override public String name() { return "CharacterAgent"; }} 
               
              
            

8.4 章节生成智能体

职责:

  • • 按章节落地内容
  • • 对齐大纲和人物弧线

8.5 风格统一智能体

职责:

  • • 消除不同章节文风漂移
  • • 统一叙事视角、语言节奏和修辞风格

8.6 评审智能体

职责:

  • • 检查逻辑冲突
  • • 检查人物行为一致性
  • • 检查重复片段
  • • 检查敏感内容

这里的核心思想是:

  • 生成型 Agent 负责创造
  • 评审型 Agent 负责约束

这和真实编辑部工作流是高度一致的。


很多文章讲多智能体时,重点都在 Agent 本身;但在工程实践中,真正决定系统上限的是 编排层

9.1 编排层职责

  • • 决定哪些步骤串行,哪些步骤并行
  • • 控制每一步超时
  • • 控制失败重试次数
  • • 聚合结果并形成共享上下文
  • • 根据质量评审结果进入修订分支

9.2 生产级 Orchestrator 实现

package com.example.story.workflow;import com.example.story.agent.ChapterAgent;import com.example.story.agent.CharacterAgent;import com.example.story.agent.PlotAgent;import com.example.story.agent.ReviewAgent;import com.example.story.agent.SceneAgent;import com.example.story.agent.StyleAgent;import com.example.story.domain.StoryContext;import com.example.story.domain.StoryRequest;import com.example.story.domain.StoryResult;import java.time.Instant;import java.util.concurrent.CompletableFuture;import java.util.concurrent.Executor;import java.util.concurrent.TimeUnit;import lombok.RequiredArgsConstructor;import org.springframework.stereotype.Component;@Component@RequiredArgsConstructorpublic class StoryWorkflowOrchestrator return new StoryResult( request.requestId(), context.outline().title(), context.outline(), context.characters(), context.chapters(), context.review(), Instant.now() ); }} 

9.3 这里的关键点

1)大纲先串行

因为角色和场景都依赖大纲,所以先串行生成大纲。

2)角色和场景并行

这两者依赖大纲,但彼此之间弱依赖,可以并行,降低整体 RT。

3)章节生成放在并行任务之后

章节需要综合大纲、角色、场景,所以必须在聚合之后执行。

4)评审失败进入修订闭环

这是保证质量稳定的关键机制。


如果系统只做少量请求,以上架构已经够用;但如果进入真正的高并发场景,还必须进行系统级工程化升级。

10.1 同步接口与异步接口分层

建议将故事生成拆成两类接口:

同步接口

适合:

  • • 短篇内容
  • • 大纲生成
  • • 角色设定
  • • 轻量润色

特征:

  • • 直接返回结果
  • • 接口超时控制在 3 秒到 15 秒
异步接口

适合:

  • • 长篇故事
  • • 多章节创作
  • • 多轮修订

特征:

  • • 返回任务 ID
  • • 后台工作流异步执行
  • • 通过轮询/WebSocket/回调获取状态

10.2 异步任务化设计

package com.example.story.application;import com.example.story.domain.StoryRequest;import com.example.story.infrastructure.messaging.StoryCreationProducer;import java.util.UUID;import lombok.RequiredArgsConstructor;import org.springframework.stereotype.Service;@Service@RequiredArgsConstructorpublic class AsyncStoryApplicationService { private final StoryCreationProducer producer; private final StoryTaskRepository storyTaskRepository; public String submit(StoryRequest request) { String taskId = UUID.randomUUID().toString(); storyTaskRepository.create(taskId, request.requestId(), "PENDING"); producer.send(taskId, request); return taskId; }} 

消费者异步处理:

package com.example.story.infrastructure.messaging;import com.example.story.domain.StoryRequest;import com.example.story.workflow.StoryWorkflowOrchestrator;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.springframework.kafka.annotation.KafkaListener;import org.springframework.stereotype.Component;@Slf4j@Component@RequiredArgsConstructorpublic class StoryCreationConsumer { private final StoryWorkflowOrchestrator orchestrator; private final StoryTaskRepository storyTaskRepository; private final StoryResultRepository storyResultRepository; @KafkaListener(topics = "story-create-topic", groupId = "story-worker-group") public void consume(StoryCreateMessage message) { try { storyTaskRepository.updateStatus(message.taskId(), "RUNNING"); var result = orchestrator.execute(message.request()); storyResultRepository.save(message.taskId(), result); storyTaskRepository.updateStatus(message.taskId(), "SUCCESS"); } catch (Exception ex) { log.error("Async story create failed, taskId={}", message.taskId(), ex); storyTaskRepository.updateStatus(message.taskId(), "FAILED"); } }} 

10.3 为什么异步化是必须的

模型调用本质是高延迟 IO 任务,并且存在不确定性。如果所有请求都同步阻塞:

  • • Web 容器线程会被长期占用
  • • 突发流量下线程池很快打满
  • • 用户体验会因为长尾请求显著恶化

异步化的本质价值是:

  • 把高耗时任务从用户主请求链路中剥离出来
  • 通过 MQ 做削峰填谷
  • 提高系统在高并发场景下的稳定性

10.4 线程池配置

不要直接用 CompletableFuture.supplyAsync() 默认线程池,必须显式声明业务线程池。

package com.example.story.config;import java.util.concurrent.Executor;import java.util.concurrent.ThreadPoolExecutor;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;@Configurationpublic class ExecutorConfig } 

线程池参数建议根据以下因素评估:

  • • CPU 核数
  • • 平均模型响应时间
  • • 峰值并发数
  • • 下游模型网关限额

对于 AI 场景,线程池不是越大越好。更大的线程池可能带来:

  • • 上游请求更多
  • • 模型网关被打爆
  • • 平均延迟上升
  • • 失败率增加

因此要配合 限流与背压 一起使用。

10.5 限流、熔断、降级

生产系统一定要有“保护模型服务”的能力。

建议策略:

  • • 单租户限流
  • • 单接口 QPS 限流
  • • 模型调用超时熔断
  • • 下游异常率过高时快速失败
  • • 降级到“小模型生成大纲 + 大模型润色”

Resilience4j 示例:

package com.example.story.infrastructure.resilience;import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;import io.github.resilience4j.retry.annotation.Retry;import io.github.resilience4j.timelimiter.annotation.TimeLimiter;import java.util.concurrent.CompletableFuture;import lombok.RequiredArgsConstructor;import org.springframework.stereotype.Service;@Service@RequiredArgsConstructorpublic class ResilientStoryAiService { private final StoryAiDelegate delegate; @Retry(name = "story-ai") @CircuitBreaker(name = "story-ai", fallbackMethod = "fallback") @TimeLimiter(name = "story-ai") public CompletableFuture 
            
    
              
                generate(String prompt) { return CompletableFuture.supplyAsync(() -> delegate.generate(prompt)); } public CompletableFuture 
               
                 fallback(String prompt, Throwable throwable) { return CompletableFuture.completedFuture("当前生成服务繁忙,请稍后重试。"); }} 
                
              

10.6 缓存设计

AI 场景中,缓存不只是“提高速度”,更重要的是 降低成本和保护下游模型资源

可以缓存的对象包括:

  • • 热门题材大纲
  • • 常见角色模板
  • • 风格模板
  • • Prompt 渲染结果
  • • 异步任务状态
  • • 幂等请求结果

缓存键设计示例:

story:outline:{hash(theme+genre+style+keywords)}story:task:{taskId}story:result:{taskId}story:idempotent:{requestId} 

缓存注意点:

  • • 不要缓存未审核内容太久
  • • 大文本建议压缩后缓存
  • • 防止缓存雪崩和击穿
  • • 对热点 Key 做互斥重建

11.1 同步接口

package com.example.story.web;import com.example.story.application.StoryApplicationService;import com.example.story.domain.StoryRequest;import com.example.story.domain.StoryResult;import jakarta.validation.Valid;import lombok.RequiredArgsConstructor;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestHeader;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/api/v1/stories")@RequiredArgsConstructorpublic class StoryController { private final StoryApplicationService storyApplicationService; @PostMapping("/generate") public StoryResult generate( @Valid @RequestBody StoryRequest request, @RequestHeader(value = "X-Request-Id", required = false) String requestId) { return storyApplicationService.generate(requestId, request); }} 

11.2 异步接口

package com.example.story.web;import com.example.story.application.AsyncStoryApplicationService;import com.example.story.domain.StoryRequest;import jakarta.validation.Valid;import java.util.Map;import lombok.RequiredArgsConstructor;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/api/v1/story-tasks")@RequiredArgsConstructorpublic class StoryTaskController { private final AsyncStoryApplicationService asyncStoryApplicationService; private final StoryTaskQueryService storyTaskQueryService; @PostMapping public Map 
             
    
               
                 submit(@Valid @RequestBody StoryRequest request) { String taskId = asyncStoryApplicationService.submit(request); return Map.of("taskId", taskId, "status", "PENDING"); } @GetMapping("/{taskId}") public StoryTaskResponse get(@PathVariable String taskId) { return storyTaskQueryService.query(taskId); }} 
               

11.3 幂等控制

AI 生成接口非常适合做幂等,尤其是用户网络重试、网关重试、客户端超时重发时。

推荐做法:

  • • 要求客户端传 requestId
  • • 服务端使用 Redis SETNX
  • • 已存在则直接返回历史结果或任务状态

12.1 场景描述

某互动小说平台希望提供“输入一句话,自动生成 6 章短篇小说”的能力,要求:

  • • 首屏 2 秒内返回受理结果
  • • 普通用户并发 300 QPS
  • • 峰值活动时并发 1200 QPS
  • • 生成成功率不低于 99%
  • • 章节内容前后设定一致

12.2 方案拆解

系统采用以下执行策略:

快速响应层
  • • 用户请求进入 API Gateway
  • • 参数校验和幂等检查通过后
  • • 直接写入任务表和 Kafka
  • • 立即返回 taskId
异步工作层
  • • Worker 消费任务消息
  • • 先生成大纲
  • • 并行生成人物、场景设定
  • • 生成章节
  • • 风格统一
  • • 评审与必要重写
  • • 落库并刷新缓存
结果分发层
  • • 前端轮询任务状态
  • • 或通过 WebSocket 推送完成事件

12.3 为什么这个方案有效

因为它把用户感知时延与模型真实执行时延做了拆分:

  • • 用户只需等待任务受理
  • • 模型复杂生成在后台完成
  • • 峰值流量被 MQ 平滑吸收

12.4 容量估算示例

假设:

  • • 平均生成一次完整故事耗时 18 秒
  • • 单个 Worker Pod 稳定并发处理 20 个任务
  • • 峰值每分钟 3600 个请求

则至少需要:

  • • 每秒请求 60
  • • 在 18 秒平均处理时长下,系统在途任务约 1080 个
  • • 若每 Pod 处理 20 个在途任务,则至少需要约 54 个 Worker 并发槽位

如果每个 Worker Pod 配置 2 个并发执行线程,则大约需要 27 个 Pod,实际部署建议再留 20% 到 30% 冗余。

这就是为什么 AI 系统容量规划不能只看 QPS,必须看“平均耗时 × 在途任务数”


多智能体系统的另一个重点不是“能生成”,而是“稳定生成”。

13.1 结构化输出优先

尽量要求各 Agent 输出 JSON 或明确结构,而不是长篇自由文本。原因是:

  • • 更易解析
  • • 更易校验
  • • 更易供下游 Agent 使用

13.2 审核规则前置

评审智能体应至少检查:

  • • 人物数量与主角关系是否完整
  • • 章节是否都有明确推进事件
  • • 是否存在人物名称漂移
  • • 是否存在世界观矛盾
  • • 是否存在重复段落
  • • 是否触发敏感内容策略

13.3 规则引擎 + LLM 双校验

不要把所有质量判断都交给模型。建议采用:

  • • 规则引擎做强约束校验
  • • LLM 做语义质量评估

例如:

  • • 章节数不匹配,用规则直接判失败
  • • 人物成长弧是否自然,用 LLM 做评审

13.4 Prompt 模板化

不要把 Prompt 写死在代码里到处散落。建议:

  • • 统一模板目录
  • • 模板版本化
  • • 支持灰度发布

这样可以做到:

  • • A/B 测试不同提示词
  • • 不改代码快速调整效果
  • • 不同租户使用不同模板

如果没有监控,多智能体系统出现问题时几乎无法定位。

14.1 必须监控的指标

系统层指标
  • • CPU
  • • 内存
  • • JVM GC
  • • 线程池活跃线程数
  • • Kafka Lag
应用层指标
  • • 接口 QPS
  • • P95/P99 响应时间
  • • 错误率
  • • 限流次数
  • • 熔断次数
AI 层指标
  • • 每个 Agent 调用耗时
  • • 各模型成功率/失败率
  • • 平均 Token 消耗
  • • 单请求模型成本
  • • 审核失败率
  • • 重写率

14.2 日志设计

日志至少要带:

  • • requestId
  • • taskId
  • • tenantId
  • • agentName
  • • modelName
  • • latency
  • • tokenUsage
  • • resultStatus

14.3 链路追踪

建议每次生成请求从入口开始透传 traceId,贯穿:

  • • Gateway
  • • 应用服务
  • • 编排层
  • • Agent 调用
  • • MQ 消费
  • • 结果持久化

这样当用户反馈“这个故事生成了 40 秒”,你才能快速定位是:

  • • Kafka 堆积
  • • 某个 Agent 超时
  • • 模型接口抖动
  • • 数据库写入慢

15.1 建议的表设计

至少需要三类核心表:

story_task

用于记录异步任务状态:

  • • task_id
  • • request_id
  • • status
  • • created_at
  • • updated_at
  • • error_message
story_result

用于保存最终作品:

  • • task_id
  • • title
  • • outline_json
  • • character_json
  • • chapter_json
  • • review_json
  • • model_info
story_agent_audit

用于记录 Agent 级调用审计:

  • • request_id
  • • task_id
  • • agent_name
  • • model_name
  • • prompt_version
  • • latency_ms
  • • success_flag
  • • error_message

15.2 为什么审计日志很重要

当出现以下问题时,审计日志是核心依据:

  • • 某一版 Prompt 效果突然变差
  • • 某个模型版本出错率升高
  • • 某租户生成内容质量异常
  • • 成本突然上涨

16.1 application.yml

server: port: 8080 tomcat: threads: max: 300 min-spare: 20 accept-count: 200spring: application: name: story-agent-service datasource: url: jdbc:mysql://mysql:3306/story_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: story_user password: ${DB_PASSWORD} hikari: maximum-pool-size: 30 minimum-idle: 10 connection-timeout: 3000 validation-timeout: 1000 data: redis: host: redis port: 6379 lettuce: pool: max-active: 64 max-idle: 16 min-idle: 8 kafka: bootstrap-servers: kafka:9092 listener: concurrency: 6 producer: acks: all retries: 3 consumer: group-id: story-worker-group max-poll-records: 50management: endpoints: web: exposure: include: health,info,prometheus,metrics metrics: tags: application: ${spring.application.name}story: ai: default-model: qwen-plus timeout-seconds: 20 review-threshold: 0.75 

16.2 Kubernetes Deployment

apiVersion: apps/v1kind: Deploymentmetadata: name: story-agent-servicespec: replicas: 4 selector: matchLabels: app: story-agent-service template: metadata: labels: app: story-agent-service spec: containers: - name: app image: registry.example.com/story-agent-service:1.0.0 ports: - containerPort: 8080 env: - name: DB_PASSWORD valueFrom: secretKeyRef: name: story-secret key: db-password resources: requests: cpu: "1000m" memory: "2Gi" limits: cpu: "2000m" memory: "4Gi" readinessProbe: httpGet: path: /actuator/health/readiness port: 8080 initialDelaySeconds: 20 periodSeconds: 10 livenessProbe: httpGet: path: /actuator/health/liveness port: 8080 initialDelaySeconds: 30 periodSeconds: 20---apiVersion: autoscaling/v2kind: HorizontalPodAutoscalermetadata: name: story-agent-service-hpaspec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: story-agent-service minReplicas: 4 maxReplicas: 20 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 

16.3 部署建议

  • • Web 接入层和异步 Worker 分开部署
  • • Worker 建议单独设置 HPA
  • • 大文本结果不要只放内存,及时落 Redis/MySQL/对象存储
  • • 配置中心统一管理 Prompt 版本和模型参数

17.1 为什么生成结果前后不一致

常见原因:

  • • Agent 之间没有共享统一上下文
  • • Prompt 模板风格不一致
  • • 章节生成时没有明确约束人物设定

解决方案:

  • • 引入 StoryContext
  • • 统一 Prompt 规范
  • • 在章节生成阶段明确引用角色设定与大纲

17.2 为什么高峰期 RT 飙升

常见原因:

  • • 同步请求过多
  • • 默认线程池失控
  • • 模型下游限额触发排队
  • • Kafka 消费能力不足

解决方案:

  • • 长任务异步化
  • • 显式线程池 + 队列长度控制
  • • 增加 Worker 副本
  • • 引入限流与熔断

17.3 为什么成本失控

常见原因:

  • • 所有环节都使用大模型
  • • 重复请求没有缓存
  • • Prompt 冗长,导致 Token 浪费
  • • 评审失败频繁触发重写

解决方案:

  • • 大纲/分类用中等模型,润色用大模型
  • • 建立缓存体系
  • • 精简上下文
  • • 对质量阈值做动态调优

17.4 为什么异步任务堆积严重

常见原因:

  • • 入队速度远高于消费速度
  • • 单个任务执行时间过长
  • • 重试策略过于激进

解决方案:

  • • 扩容 Worker
  • • 拆分任务颗粒度
  • • 控制最大重试次数
  • • 对超大任务启用排队或预约生成

建议按四个阶段推进:

第一阶段:单体验证

目标:

  • • 跑通主流程
  • • 验证 Agent 分工是否合理
  • • 验证 Prompt 模板效果

技术形态:

  • • 单体 Spring Boot
  • • 同步接口
  • • 本地缓存

第二阶段:服务化改造

目标:

  • • 引入统一编排层
  • • 加入 Redis、MySQL
  • • 实现基本监控和审计

技术形态:

  • • 分层服务
  • • 结构化输出
  • • 线程池治理

第三阶段:高并发升级

目标:

  • • 支持异步任务化
  • • 引入 Kafka/RocketMQ
  • • 接入限流、熔断、降级

技术形态:

  • • Web/Worker 分离
  • • HPA 自动扩缩容
  • • 多副本部署

第四阶段:平台化能力沉淀

目标:

  • • Prompt 配置中心化
  • • 模型路由能力
  • • 成本分析
  • • 多租户隔离

技术形态:

  • • Agent 平台化
  • • 模型网关平台化
  • • 运营化仪表盘

基于 Spring AI Alibaba 构建多智能体故事创作系统,真正难的从来不是“把几个 Agent 连起来”,而是把它做成一个 可编排、可扩展、可治理、可观测、可上线 的生产系统。

从架构上看,核心是四件事:

  • • 用 统一上下文对象 管理多智能体共享状态
  • • 用 编排层 管理串并行流程、超时、重试和闭环修订
  • • 用 异步化、缓存、限流、熔断 支撑高并发稳定性
  • • 用 监控、审计、追踪 保证系统可运维

从工程实践看,建议你牢记一句话:

多智能体系统不是 Prompt 的堆砌,而是一个带有 AI 能力的分布式业务系统。

只有当你用分布式系统的方法去设计它,才有可能真正支撑业务落地。


如果继续往前演进,这个系统还可以进一步升级:

  • • 增加记忆智能体,支持角色长期设定继承
  • • 增加编辑智能体,支持“续写、改写、缩写、扩写”
  • • 接入向量检索,支持故事设定库和风格库召回
  • • 引入多模型路由,根据任务类型自动选择模型
  • • 增加成本控制中心,实现租户级 Token 预算治理
  • • 引入人工反馈闭环,持续优化 Prompt 与审核策略

当这些能力逐步补齐后,你得到的就不再只是一个“写故事工具”,而是一套真正具备商业化潜力的 内容创作智能体平台

🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!

有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!

就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

在这里插入图片描述

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇

学习路线:

以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!

我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

小讯
上一篇 2026-04-09 14:06
下一篇 2026-04-09 14:04

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/253728.html