Spring AI 多模型智能协作工作流实现指南

Spring AI 多模型智能协作工作流实现指南

说明

本文档旨在指导开发者基于 Spring AI 框架,在 Spring Boot 2 环境下集成多种主流大语言模型(如 OpenAI ChatGPT、Deepseek、阿里云通义千问等),并提供从环境配置、模型调用、流式输出到提示模板与异常处理的完整使用示例。文中示例适配 Spring AI 进行开发。本教程适用于对 LLM 应用开发有一定基础的 Java 工程师,亦可作为企业多模型接入与管理的实现参考。

1. 系统架构概述

本方案基于 Spring AI 框架,构建了一个多模型协作的工作流系统,通过 ChatGPT、Deepseek 和通义千问三大模型的优势互补,实现从原始输入到高质量输出的完整处理流程。

以下是基于Mermaid语法的工作流架构图,您可以直接复制到支持Mermaid的Markdown编辑器(如Typora、VS Code插件等)中查看:
异常处理 模型协作工作流 成功 失败 JSON格式 生成草稿 降级处理 使用默认关键词 解析JSON结果 ChatGPT关键词提取 通义千问文本润色 Deepseek内容生成 用户输入文本 最终输出结果

架构图说明:

  1. 流程图元素

    • 矩形框:表示处理步骤
    • 菱形框:表示判断/解析节点
    • 子图:标识不同处理阶段
    • 样式:区分输入/输出节点
  2. 工作流步骤

    A B C D F G E

  3. 带详细说明的版本

原始文本 JSON格式 成功 失败 初稿内容 用户输入 ChatGPT处理器 解析结果? 提取关键词+意图 使用默认值 Deepseek生成器 通义千问润色器 最终输出

关键路径说明:

  1. 正常流程

    复制代码
    用户输入 → ChatGPT提取 → 解析JSON → Deepseek生成 → 通义千问润色 → 输出
  2. 异常流程

    复制代码
    解析失败 → 使用默认关键词 → 继续后续流程
  3. 组件职责

    • ChatGPT:结构化理解输入文本
    • Deepseek:基于结构化数据生成内容
    • 通义千问:优化表达质量

部署架构图(补充)

云服务 HTTP请求 API调用 API调用 API调用 OpenAI Cloud Deepseek API 阿里云通义千问 客户端 Spring Boot API Redis缓存 数据库

2. 环境配置

2.1 Maven 依赖配置

xml 复制代码
<dependencies>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.7.18</version>
    </dependency>

    <!-- Spring AI Core -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-core</artifactId>
        <version>0.8.1</version>
    </dependency>

    <!-- OpenAI Starter -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
        <version>0.8.1</version>
    </dependency>

    <!-- 阿里云通义千问 -->
    <dependency>
        <groupId>com.alibaba.cloud.ai</groupId>
        <artifactId>spring-ai-alibaba-starter</artifactId>
        <version>1.0.0-M2</version>
    </dependency>

    <!-- JSON 处理 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>

    <!-- 日志记录 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-logging</artifactId>
    </dependency>
</dependencies>

2.2 应用配置 (application.yml)

yaml 复制代码
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      model: gpt-4-turbo
      temperature: 0.7
      max-tokens: 1000
    
    alibaba:
      dashscope:
        api-key: ${TONGYI_API_KEY}
        model: qwen-max
        temperature: 0.8

deepseek:
  api-key: ${DEEPSEEK_API_KEY}
  base-url: https://api.deepseek.com/v1
  model: deepseek-chat

app:
  workflow:
    max-retries: 3
    retry-delay: 1000
    timeout: 30000

3. 核心组件实现

3.1 模型任务定义

java 复制代码
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ModelTask {
    private String taskId;
    private TaskType type;
    private String input;
    private Map<String, Object> params;
    
    public enum TaskType {
        KEYWORD_EXTRACTION, // 关键词提取
        CONTENT_GENERATION, // 内容生成
        TEXT_POLISHING      // 文本润色
    }
}

3.2 模型执行器接口

java 复制代码
public interface ModelExecutor {
    /**
     * 执行模型任务
     * @param task 模型任务
     * @return 执行结果
     * @throws ModelExecutionException 模型执行异常
     */
    String execute(ModelTask task) throws ModelExecutionException;
    
    /**
     * 支持的模型类型
     */
    ModelTask.TaskType supportedType();
}

3.3 ChatGPT 执行器实现 (关键词提取)

java 复制代码
@Service
@Slf4j
public class ChatGPTExecutor implements ModelExecutor {
    
    @Autowired
    private OpenAiChatClient chatClient;
    
    @Override
    public String execute(ModelTask task) throws ModelExecutionException {
        try {
            String prompt = buildExtractionPrompt(task.getInput());
            log.info("Executing ChatGPT task with prompt: {}", prompt);
            
            String response = chatClient.call(prompt);
            log.info("ChatGPT response: {}", response);
            
            return parseJsonResponse(response);
        } catch (Exception e) {
            log.error("ChatGPT execution failed", e);
            throw new ModelExecutionException("ChatGPT processing failed", e);
        }
    }
    
    private String buildExtractionPrompt(String input) {
        return """
            请从以下文本中提取结构化信息,按JSON格式返回:
            {
              "keywords": ["关键词1", "关键词2", ...],  // 5-10个核心关键词
              "intent": "用户意图描述",              // 用户的主要目的
              "sentiment": "positive/neutral/negative" // 情感倾向
            }
            
            输入文本:
            """ + input;
    }
    
    private String parseJsonResponse(String response) {
        // 简化的JSON解析,实际项目中应使用Jackson等库
        if (response.startsWith("{") && response.endsWith("}")) {
            return response;
        }
        // 处理非标准JSON响应
        return response.replaceFirst(".*?(\\{.*\\}).*", "$1");
    }
    
    @Override
    public ModelTask.TaskType supportedType() {
        return ModelTask.TaskType.KEYWORD_EXTRACTION;
    }
}

3.4 Deepseek 执行器实现 (内容生成)

java 复制代码
@Service
@Slf4j
public class DeepseekExecutor implements ModelExecutor {
    
    @Value("${deepseek.api-key}")
    private String apiKey;
    
    @Value("${deepseek.base-url}")
    private String baseUrl;
    
    @Value("${deepseek.model}")
    private String model;
    
    private final RestClient restClient;
    
    public DeepseekExecutor() {
        this.restClient = RestClient.builder()
                .baseUrl(baseUrl)
                .defaultHeader("Authorization", "Bearer " + apiKey)
                .build();
    }
    
    @Override
    public String execute(ModelTask task) throws ModelExecutionException {
        try {
            Map<String, Object> requestBody = buildRequest(task);
            log.info("Sending request to Deepseek: {}", requestBody);
            
            ResponseEntity<Map> response = restClient.post()
                    .uri("/chat/completions")
                    .body(requestBody)
                    .retrieve()
                    .toEntity(Map.class);
            
            return extractContent(response.getBody());
        } catch (Exception e) {
            log.error("Deepseek API call failed", e);
            throw new ModelExecutionException("Deepseek processing failed", e);
        }
    }
    
    private Map<String, Object> buildRequest(ModelTask task) {
        return Map.of(
            "model", model,
            "messages", List.of(
                Map.of("role", "system", "content", "你是一个专业的内容生成助手"),
                Map.of("role", "user", "content", task.getInput())
            ),
            "temperature", 0.7,
            "max_tokens", 2000
        );
    }
    
    private String extractContent(Map<String, Object> response) {
        // 简化处理,实际项目需要更健壮的解析
        return ((Map)((List)response.get("choices")).get(0))
                .get("message").toString();
    }
    
    @Override
    public ModelTask.TaskType supportedType() {
        return ModelTask.TaskType.CONTENT_GENERATION;
    }
}

3.5 通义千问执行器实现 (文本润色)

java 复制代码
@Service
@Slf4j
public class TongyiExecutor implements ModelExecutor {
    
    @Autowired
    private TongyiChatClient chatClient;
    
    @Override
    public String execute(ModelTask task) throws ModelExecutionException {
        try {
            String polishPrompt = buildPolishPrompt(task.getInput());
            log.info("Executing Tongyi polishing with prompt: {}", polishPrompt);
            
            String response = chatClient.call(polishPrompt);
            log.info("Tongyi polished response: {}", response);
            
            return response;
        } catch (Exception e) {
            log.error("Tongyi polishing failed", e);
            throw new ModelExecutionException("Tongyi polishing failed", e);
        }
    }
    
    private String buildPolishPrompt(String input) {
        return """
            请对以下文本进行专业的中文润色,要求:
            1. 保持原意不变
            2. 优化表达流畅度
            3. 使用更专业的词汇
            4. 适当调整句式结构
            5. 确保语法正确
            
            需要润色的文本:
            """ + input;
    }
    
    @Override
    public ModelTask.TaskType supportedType() {
        return ModelTask.TaskType.TEXT_POLISHING;
    }
}

4. 工作流协调器

java 复制代码
@Service
@Slf4j
public class WorkflowCoordinator {
    
    @Autowired
    private List<ModelExecutor> executors;
    
    @Value("${app.workflow.max-retries}")
    private int maxRetries;
    
    @Value("${app.workflow.retry-delay}")
    private long retryDelay;
    
    @Value("${app.workflow.timeout}")
    private long timeout;
    
    private final Map<ModelTask.TaskType, ModelExecutor> executorMap = new HashMap<>();
    
    @PostConstruct
    public void init() {
        executors.forEach(executor -> 
            executorMap.put(executor.supportedType(), executor));
    }
    
    @Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000))
    public String processWorkflow(String userInput) throws WorkflowException {
        long startTime = System.currentTimeMillis();
        String taskId = UUID.randomUUID().toString();
        
        try {
            // 阶段1: 关键词提取
            ModelTask extractionTask = new ModelTask(
                taskId, 
                ModelTask.TaskType.KEYWORD_EXTRACTION,
                userInput,
                Map.of("format", "json")
            );
            
            String extractionResult = executeWithTimeout(
                executorMap.get(ModelTask.TaskType.KEYWORD_EXTRACTION),
                extractionTask
            );
            
            // 阶段2: 内容生成
            String generationPrompt = buildGenerationPrompt(extractionResult);
            ModelTask generationTask = new ModelTask(
                taskId,
                ModelTask.TaskType.CONTENT_GENERATION,
                generationPrompt,
                Map.of("length", "medium")
            );
            
            String generatedContent = executeWithTimeout(
                executorMap.get(ModelTask.TaskType.CONTENT_GENERATION),
                generationTask
            );
            
            // 阶段3: 文本润色
            ModelTask polishingTask = new ModelTask(
                taskId,
                ModelTask.TaskType.TEXT_POLISHING,
                generatedContent,
                Map.of("style", "professional")
            );
            
            String finalResult = executeWithTimeout(
                executorMap.get(ModelTask.TaskType.TEXT_POLISHING),
                polishingTask
            );
            
            log.info("Workflow completed in {} ms", 
                System.currentTimeMillis() - startTime);
            
            return finalResult;
        } catch (TimeoutException e) {
            throw new WorkflowException("Workflow timed out", e);
        } catch (Exception e) {
            throw new WorkflowException("Workflow execution failed", e);
        }
    }
    
    private String executeWithTimeout(ModelExecutor executor, ModelTask task) 
            throws Exception {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Future<String> future = executorService.submit(() -> executor.execute(task));
        
        try {
            return future.get(timeout, TimeUnit.MILLISECONDS);
        } finally {
            executorService.shutdown();
        }
    }
    
    private String buildGenerationPrompt(String extractionResult) {
        try {
            JSONObject json = new JSONObject(extractionResult);
            String keywords = String.join(", ", json.getJSONArray("keywords").toList());
            String intent = json.getString("intent");
            
            return String.format("根据以下关键词和意图生成专业内容:\n关键词: %s\n意图: %s", 
                keywords, intent);
        } catch (Exception e) {
            log.warn("Failed to parse extraction result, using raw input");
            return "根据以下信息生成专业内容:\n" + extractionResult;
        }
    }
}

5. REST 控制器

java 复制代码
@RestController
@RequestMapping("/api/ai-workflow")
@Slf4j
public class WorkflowController {
    
    @Autowired
    private WorkflowCoordinator workflowCoordinator;
    
    @PostMapping("/process")
    public ResponseEntity<?> processInput(@RequestBody String userInput) {
        try {
            log.info("Received processing request: {}", userInput);
            String result = workflowCoordinator.processWorkflow(userInput);
            return ResponseEntity.ok(result);
        } catch (WorkflowException e) {
            log.error("Workflow processing error", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(Map.of(
                        "error", "Processing failed",
                        "message", e.getMessage()
                    ));
        }
    }
    
    @GetMapping("/status")
    public ResponseEntity<?> getStatus() {
        return ResponseEntity.ok(Map.of(
            "status", "operational",
            "models", List.of("ChatGPT", "Deepseek", "Tongyi")
        ));
    }
}

6. 异常处理

java 复制代码
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    
    @ExceptionHandler(WorkflowException.class)
    public ResponseEntity<?> handleWorkflowException(WorkflowException ex) {
        log.error("Workflow error occurred: {}", ex.getMessage());
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(Map.of(
                    "error", "AI Workflow Error",
                    "message", ex.getMessage(),
                    "timestamp", Instant.now()
                ));
    }
    
    @ExceptionHandler(ModelExecutionException.class)
    public ResponseEntity<?> handleModelException(ModelExecutionException ex) {
        log.error("Model execution failed: {}", ex.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_GATEWAY)
                .body(Map.of(
                    "error", "Model Execution Error",
                    "message", "One of the AI models failed to process the request",
                    "timestamp", Instant.now()
                ));
    }
}

7. 测试用例

java 复制代码
@SpringBootTest
@ActiveProfiles("test")
@Slf4j
public class WorkflowIntegrationTest {
    
    @Autowired
    private WorkflowCoordinator workflowCoordinator;
    
    @Test
    public void testFullWorkflow() {
        String input = "用户反馈:新版App的语音识别功能很准确,但耗电量较大,希望优化电池使用效率";
        
        try {
            String result = workflowCoordinator.processWorkflow(input);
            log.info("Workflow result:\n{}", result);
            
            assertNotNull(result);
            assertTrue(result.length() > 50);
            assertTrue(result.contains("语音识别") || result.contains("耗电"));
        } catch (WorkflowException e) {
            fail("Workflow execution failed: " + e.getMessage());
        }
    }
    
    @Test
    public void testTimeoutHandling() {
        // 模拟超时场景的测试
        assertThrows(WorkflowException.class, () -> {
            workflowCoordinator.processWorkflow("test timeout");
        });
    }
}

8. 部署与监控建议

8.1 Prometheus 监控配置

yaml 复制代码
# application.yml 添加监控配置
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  metrics:
    export:
      prometheus:
        enabled: true
    tags:
      application: ai-workflow

8.2 关键指标监控

  1. 工作流执行时间
  2. 各模型调用成功率
  3. API响应时间
  4. 错误率统计
  5. Token使用量

9. 性能优化建议

  1. 缓存层:对常见查询结果实现缓存

    java 复制代码
    @Cacheable(value = "aiResponses", key = "#userInput.hashCode()")
    public String processWorkflow(String userInput) { ... }
  2. 批量处理:支持批量输入处理

  3. 异步处理:对耗时任务实现异步API

    java 复制代码
    @Async
    public CompletableFuture<String> processAsync(String input) { ... }
  4. 连接池配置:优化HTTP连接池

    yaml 复制代码
    spring:
      ai:
        openai:
          rest:
            connection-timeout: 5000
            read-timeout: 30000
            max-connections: 100

10. 安全建议

  1. API密钥轮换:定期更新各模型API密钥

  2. 输入过滤:防止Prompt注入攻击

    java 复制代码
    public String sanitizeInput(String input) {
        return input.replaceAll("[<>\"']", "");
    }
  3. 访问控制:实现API访问认证

  4. 请求限流:防止滥用

总结

本实现方案展示了如何利用 Spring AI 框架构建一个多模型协作的智能工作流系统,具有以下特点:

  1. 模块化设计:各模型执行器相互独立,易于扩展
  2. 弹性处理:完善的错误处理和重试机制
  3. 性能可控:超时管理和异步支持
  4. 可观测性:完善的日志和监控支持
  5. 生产就绪:包含安全、缓存等生产环境所需功能

通过这种架构,您可以灵活地替换或添加新的AI模型,同时保持业务逻辑的一致性,为构建企业级AI应用提供了可靠的基础框架。

相关推荐
peerless_fu1 小时前
rabbitmq AI复习
spring·rabbitmq
人生导师yxc2 小时前
SpringCloud基础知识
后端·spring·spring cloud
烟沙九洲2 小时前
@ModelAttribute、@RequestBody、@RequestParam、@PathVariable 注解对比
java·spring
ademen4 小时前
spring4第4课-ioc控制反转-详解如何注入参数
java·后端·spring
weixin_579732105 小时前
dto vo类为什么要序列化?
spring
劲爽小猴头7 小时前
Spring MVC + Tomcat 8.5 踩坑实录:Servlet 版本引发的部署失败
java·spring·mvc
程序猿DD7 小时前
Spring官方的在线教程也可以用中文观看了
java·数据库·spring
hello_ejb38 小时前
聊聊Tomato Architecture
java·spring
学境思源AcademicIdeas9 小时前
ChatGPT + 知网 + 知乎,如何高效整合信息写出一篇专业内容?
人工智能·chatgpt
编程乐学(Arfan开发工程师)10 小时前
28、请求处理-【源码分析】-请求映射原理
java·前端·spring boot·后端·spring