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 依赖配置

<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)

spring:ai:openai:api-key: ${OPENAI_API_KEY}model: gpt-4-turbotemperature: 0.7max-tokens: 1000alibaba:dashscope:api-key: ${TONGYI_API_KEY}model: qwen-maxtemperature: 0.8deepseek:api-key: ${DEEPSEEK_API_KEY}base-url: https://api.deepseek.com/v1model: deepseek-chatapp:workflow:max-retries: 3retry-delay: 1000timeout: 30000

3. 核心组件实现

3.1 模型任务定义

@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 模型执行器接口

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

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

@Service
@Slf4j
public class ChatGPTExecutor implements ModelExecutor {@Autowiredprivate OpenAiChatClient chatClient;@Overridepublic 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");}@Overridepublic ModelTask.TaskType supportedType() {return ModelTask.TaskType.KEYWORD_EXTRACTION;}
}

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

@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();}@Overridepublic 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();}@Overridepublic ModelTask.TaskType supportedType() {return ModelTask.TaskType.CONTENT_GENERATION;}
}

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

@Service
@Slf4j
public class TongyiExecutor implements ModelExecutor {@Autowiredprivate TongyiChatClient chatClient;@Overridepublic 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;}@Overridepublic ModelTask.TaskType supportedType() {return ModelTask.TaskType.TEXT_POLISHING;}
}

4. 工作流协调器

@Service
@Slf4j
public class WorkflowCoordinator {@Autowiredprivate 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<>();@PostConstructpublic 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 控制器

@RestController
@RequestMapping("/api/ai-workflow")
@Slf4j
public class WorkflowController {@Autowiredprivate 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. 异常处理

@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. 测试用例

@SpringBootTest
@ActiveProfiles("test")
@Slf4j
public class WorkflowIntegrationTest {@Autowiredprivate WorkflowCoordinator workflowCoordinator;@Testpublic 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());}}@Testpublic void testTimeoutHandling() {// 模拟超时场景的测试assertThrows(WorkflowException.class, () -> {workflowCoordinator.processWorkflow("test timeout");});}
}

8. 部署与监控建议

8.1 Prometheus 监控配置

# application.yml 添加监控配置
management:endpoints:web:exposure:include: health,info,metrics,prometheusmetrics:export:prometheus:enabled: truetags:application: ai-workflow

8.2 关键指标监控

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

9. 性能优化建议

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

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

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

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

    spring:ai:openai:rest:connection-timeout: 5000read-timeout: 30000max-connections: 100
    

10. 安全建议

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

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

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

  4. 请求限流:防止滥用

总结

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/84841.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言中清空缓存区到底写到哪里比较好

文章目录 问题背景%d和%c读取缓冲区的差别清空缓存区 问题背景 在写C语言的命令行程序时&#xff0c;我们经常会用到用户输入和标准输出&#xff0c;特别的&#xff0c;当用户输入后&#xff0c;我们发现程序运行不是我们要的样子&#xff0c;这个时候&#xff0c;很可能就是输…

计算机视觉与深度学习 | 基于 YOLOv8 + BeautyGAN + CodeFormer + Face Parsing 实现简单的人脸美颜

人脸美颜 **一、算法流程图****二、完整代码实现**1. 环境准备2. 完整代码(face_beautify.py)**三、核心算法公式**1. YOLOv8检测损失函数2. BeautyGAN损失函数3. CodeFormer图像重建公式**四、关键实现细节**1. 多尺度人脸处理2. 颜色校正策略**五、模型下载清单****六、性能…

如何在WordPress中选择最佳Elementor主题:专家指南

当你在WordPress建站过程中逐步积累了经验&#xff0c;你可能会发觉&#xff0c;基础和进阶主题已难以完全满足你的需求。如果你需要更复杂的功能、更灵活的布局设计&#xff0c;甚至高级定制效果&#xff0c;那么就需要选择更加专业的主题。在这篇文章中&#xff0c;我将为你推…

FPGA高速接口 mipi lvds cameralink hdml 千兆网 sdi

mipi: https://blog.csdn.net/SDJ_success/article/details/146541776 cameralink CameraLink协议 CameraLink协议是一种专门针对机器视觉应用领域的串行通信协议&#xff0c;它使用低压差分信号(LVDS)进行数据的传输和通信。CameraLink标准是在ChannelLink标准的基础上多加了…

手机收不到WiFi,手动输入WiFi名称进行连接不不行,可能是WiFi频道设置不对

以下是电脑上分享WiFi后&#xff0c;部分手机可以看到并且能连接&#xff0c;部分手机不行&#xff0c;原因是&#xff1a;频道设置为5GHz&#xff0c;修改成&#xff0c;任何可用频率&#xff0c;则可

12.Java 对象冷冻术:从用户登录到游戏存档的序列化实战

目录 一、引言 二、用户登录存档&#xff1a;让账号信息「冻龄」不变 1. 给对象贴「冷冻标签」&#xff1a;实现 Serializable 2. 冷冻与解冻实战&#xff1a;把用户存进文件 3. 演示场景 三、游戏存档复活&#xff1a;让角色进度「穿越时空」 1. 复杂对象冷冻&#xff…

conda 环境中opencv 报错以及其他报错

如题&#xff0c;通过 conda install opencv 然后遇到 ImportError: DLL load failed while importing cv2: 找不到指定的模块。 参考网络相关答案 通过conda 卸载 然后通过 pip3 安装opencv-pyhton https://stackoverflow.com/questions/75387197/anaconda-importerror-dll-…

(已开源-CVPR2024) RadarDistill---NuScenes数据集Radar检测第一名

本文介绍一篇Radar 3D目标检测模型&#xff1a;RadarDistill。雷达数据固有的噪声和稀疏性给3D目标检测带来了巨大挑战。在本文中&#xff0c;作者提出了一种新的知识蒸馏(KD)方法RadarDistill&#xff0c;它可以通过利用激光雷达数据来提高雷达数据的表征。RadarDistill利用三…

创建型设计模式之Singleton(单例)设计模式

创建型设计模式之Singleton&#xff08;单例&#xff09;设计模式 摘要&#xff1a; Singleton&#xff08;单例&#xff09;设计模式确保一个类仅有一个实例&#xff0c;并提供全局访问点。其结构包含一个静态方法getInstance()用于获取唯一实例&#xff0c;构造方法私有化防…

C++11:系统类型增强

C11&#xff1a;系统类型增强 强枚举类型作用域限定隐式类型转换指定类型前置声明 类型别名 using模板别名复杂指针别名 auto限制性 auto注意事项 nullptrdecltype 强枚举类型 在C98的枚举设计中&#xff0c;存在很多缺陷&#xff0c;为此C11推出了强枚举来代替旧版的枚举&…

linux 内核warn_on/Bug_on

1,warn_on() warn_on() 是 Linux 内核中用于报告潜在问题或警告的宏。与 bug_on() 不同&#xff0c;bug_on() 通常用于报告严重错误&#xff0c;其触发往往会导致内核Oops或panic&#xff0c;而 warn_on() 则用于报告不太严重的、可能只是潜在问题或预期外情况的情况。它的触…

SQL输出20个9

在SQL Server中要输出20个连续的9&#xff0c;可以使用以下几种方法&#xff1a; 使用REPLICATE函数重复生成字符&#xff1a; SELECT REPLICATE(9, 20) AS Result 2. 使用UNION ALL联合查询生成多行&#xff1a; SELECT 9 AS Number FROM (VALUES (1),(1),(1),(1),(1),(1),…

懒人云电脑方案:飞牛NAS远程唤醒 + 节点小宝一键唤醒、远程控制Windows!

后台高频问题解答&#xff1a; “博主&#xff0c;飞牛NAS能定时开关机了&#xff0c;能不能让它顺便把家里Windows电脑也远程唤醒控制&#xff1f;最好点一下就能连&#xff0c;不用记IP端口那种&#xff01;” 安排&#xff01;今天这套方案完美实现&#xff1a; ✅ 飞牛NAS…

Linux特殊符号

1 管道符| 管道符号 | 用于将一个命令的输出作为另一个命令的输入。这种机制允许将多个命令组合在一起&#xff0c;形成一个数据处理链&#xff0c;每个命令处理前一个命令的输出&#xff0c;从而实现复杂的数据处理任务。示例 # 查询/var/log目录下所有的log文件,并进行分页…

初识Docker:容器化技术的入门指南

初识Docker&#xff1a;容器化技术的入门指南 一、Docker是什么&#xff1a;容器化技术的核心概念二、Docker的核心优势2.1 环境一致性2.2 高效部署与快速迭代2.3 资源利用率高 三、Docker的安装与基本使用3.1 安装Docker3.2 Docker基本概念3.3 第一个Docker容器体验 四、Docke…

商务风企业公司推广培训计划PPT模版分享

商务风企业公司推广培训计划PPT模版分享&#xff1a;商务培训推广计划PPT模版https://pan.quark.cn/s/063282eaf739 第1套PPT模版&#xff0c;绿橙配色&#xff0c;几何图形拼接背景&#xff0c;有中英文标题和占位文本。 第2套PPT模版是黑金高端商务风格&#xff0c;有汇报人…

深入理解Nginx:详尽配置手册

Nginx是一款高性能的HTTP和反向代理服务器&#xff0c;广泛应用于负载均衡、缓存和Web服务器等场景。随着互联网应用的快速发展&#xff0c;掌握Nginx的配置和优化技巧显得尤为重要。在本篇文章中&#xff0c;我们将深入探讨Nginx的配置&#xff0c;帮助你更好地理解和使用这款…

每日leetcode

1572. 矩阵对角线元素的和 - 力扣&#xff08;LeetCode&#xff09; 题目 给你一个正方形矩阵 mat&#xff0c;请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例 1&#xff1a; 输入&#xff1a;mat [[1,2,3], …

Server 9 ,在 VMware 虚拟机上安装 Windows 系统完整指南

目录 前言 一、准备工作 1.1 准备安装文件 1.2 安装VMware软件 1.3 创建新的虚拟机 1.4 开启虚拟机 二、注意事项 2.1 调整硬件设置 2.2 启动顺序配置 2.3 固件类型选择 2.4 安全启动配置 三、安装优化 3.1 安装VMware Tools 3.2 系统更新与激活 四、更多操作 ​…

最终章:终焉之塔 · 前端之道

第一章&#xff1a;HTML基石现实的骨架 第二章&#xff1a;CSS秘典 色彩与布局的力量 第三章&#xff1a;JavaScript引擎 行为之火 第四章&#xff1a;DOM迷宫 掌控页面之心 第五章&#xff1a;异步幻境 时间与数据的秘密 第六章&#xff1a;事件风暴 用户的意志 第七章&a…