从 0 到 1:Spring Boot 与 Spring AI 深度实战(基于DeepSeek)
在人工智能技术与企业级开发深度融合的今天,传统软件开发模式与 AI 工程化开发的差异日益显著。作为 Spring 生态体系中专注于 AI 工程化的核心框架,通过标准化集成方案大幅降低 AI 应用开发门槛。本文将以国产大模型代表 ** 深度求索(DeepSeek)** 为例,完整演示从环境搭建到核心机制解析的全流程,带您掌握企业级 AI 应用开发的核心能力。
在人工智能技术与企业级开发深度融合的今天,传统软件开发模式与 AI 工程化开发的差异日益显著。作为 Spring 生态体系中专注于 AI 工程化的核心框架,Spring AI通过标准化集成方案大幅降低 AI 应用开发门槛。本文将以国产大模型代表 ** 深度求索(DeepSeek)** 为例,完整演示从环境搭建到核心机制解析的全流程,带您掌握企业级 AI 应用开发的核心能力。
一、传统开发 vs AI 工程化:范式革命与技术挑战
1. 开发模式对比
维度
传统软件开发
AI 工程化开发
核心驱动
业务逻辑与算法实现
数据驱动的模型训练与推理
输出特性
确定性结果(基于固定规则)
概率性结果(基于统计学习)
核心资产
业务代码与数据结构
高质量数据集与训练好的模型
迭代方式
功能模块增量开发
数据标注→模型训练→推理优化的闭环迭代
2. AI 工程化核心挑战
- 数据治理难题:需解决数据采集(如爬虫反爬)、清洗(异常值处理)、标注(实体识别)等全链路问题
- 模型工程复杂度:涉及模型选型(如选择 DeepSeek-R1 还是 Llama 系列)、训练调优(超参数搜索)、量化压缩(模型轻量化)
- 生产级部署要求:需支持高并发推理(如 Token 级流输出)、多模型管理(A/B 测试)、实时监控(延迟 / 成功率指标)
传统 Spring Boot 的 MVC 架构难以直接应对这些挑战,而Spring AI通过标准化接口封装与生态整合,将 AI 能力转化为可插拔的工程组件。
二、Spring AI x DeepSeek:国产化 AI 工程解决方案
1. DeepSeek 模型优势
作为国内领先的 AGI 公司,深度求索(DeepSeek)提供:
- 高性能推理引擎:支持长上下文(8K/32K tokens 可选)与流式输出
- 企业级安全合规:数据本地化部署方案(支持私有化云)
- 多模态能力扩展:后续可无缝集成图像 / 语音处理模块

通过spring-ai-deepseek模块,Spring Boot 应用可通过注解驱动方式调用 DeepSeek 模型,底层自动处理 HTTP 连接池管理、请求重试、响应解析等工程化问题。
三、实战开发:基于 DeepSeek 的智能文本生成系统
1. 项目搭建
目录结构

通过 Spring Initializr 创建项目时,添加 DeepSeek 专用依赖:
xml
体验AI代码助手
代码解读
复制代码
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-ai-deepseek</artifactId> </dependency>

或在 pom.xml 中手动添加上述依赖,Maven 会自动解析 DeepSeek 集成所需的全部组件。
2. 配置 DeepSeek
在 application.yml 中配置 DeepSeek 服务信息(含注册指引):
yaml
体验AI代码助手
代码解读
复制代码
# DeepSeek 服务配置(官方文档:https://docs.spring.io/spring-ai/reference/api/chat/deepseek-chat.html) spring: ai: deepseek: # 必需:在DeepSeek控制台申请的API密钥(注册地址:https://platform.deepseek.com/register) api-key: ${DEEPSEEK_API_KEY:your-deepseek-api-key} # API基础地址(私有化部署需修改) base-url: https://api.deepseek.com # 聊天模型配置 chat: enabled: true options: model: deepseek-chat # 使用deepseek-chat模型 temperature: 0.8 # 生成随机性控制(0.0-1.0,值越高越随机) max-tokens: 512 # 单次生成最大Token数 top-p: 0.9 # Nucleus采样参数(0.0-1.0,控制生成词汇的概率分布) frequency-penalty: 0.0 # 频率惩罚(-2.0到2.0) presence-penalty: 0.0 # 存在惩罚(-2.0到2.0) stop: ["###", "END"] # 生成停止序列 # 重试配置 retry: max-attempts: 3 # 最大重试次数 backoff: initial-interval: 2s # 初始重试间隔 multiplier: 2 # 重试间隔倍数 max-interval: 10s # 最大重试间隔 on-client-errors: false # 是否对4xx错误重试 # 应用服务器配置 server: port: 8080 # 服务端口 servlet: context-path: / # 上下文路径 encoding: charset: UTF-8 # 字符编码 force: true # 强制编码 # 日志配置 logging: level: root: INFO com.example.demo: DEBUG org.springframework.ai: DEBUG org.springframework.ai.deepseek: DEBUG pattern: console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" # 管理端点配置 management: endpoints: web: exposure: include: health,info,metrics,env base-path: /actuator endpoint: health: show-details: always server: port: 8080

3. 编写代码
(1)DeepSeek 服务封装(SmartGeneratorService.java)
ini
体验AI代码助手
代码解读
复制代码
package com.example.demo.service; import com.example.demo.dto.AiRequest; import com.example.demo.dto.AiResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.chat.prompt.PromptTemplate; import org.springframework.ai.deepseek.DeepSeekChatOptions; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import java.util.Map; /** * 智能生成服务 * 提供营销文案生成、代码生成、智能问答等功能 * * @author Spring AI Demo */ @Service public class SmartGeneratorService { private static final Logger logger = LoggerFactory.getLogger(SmartGeneratorService.class); private final ChatModel chatModel; public SmartGeneratorService(ChatModel chatModel) { this.chatModel = chatModel; } /** * 生成营销文案 * * @param request 请求参数 * @return AI响应 */ public AiResponse generateMarketingContent(AiRequest request) { logger.info("开始生成营销文案,输入:{}", request.getContent()); long startTime = System.currentTimeMillis(); try { String systemPrompt = """ 你是一位专业的营销文案专家,擅长创作吸引人的营销内容。 请根据用户的需求,生成具有以下特点的营销文案: 1. 吸引眼球的标题 2. 突出产品/服务的核心价值 3. 使用情感化的语言 4. 包含明确的行动号召 5. 语言简洁有力,易于理解 请用中文回复,格式清晰,内容富有创意。 """; PromptTemplate promptTemplate = new PromptTemplate(systemPrompt + "\n\n用户需求:{content}"); Prompt prompt = promptTemplate.create(Map.of("content", request.getContent())); // 设置营销文案生成的参数(创意性较高) DeepSeekChatOptions options = DeepSeekChatOptions.builder() .temperature(request.getTemperature() != null ? request.getTemperature() : 1.3) .maxTokens(request.getMaxTokens() != null ? request.getMaxTokens() : 800) .build(); var response = chatModel.call(new Prompt(prompt.getInstructions(), options)); String content = response.getResult().getOutput().getText(); long processingTime = System.currentTimeMillis() - startTime; logger.info("营销文案生成完成,耗时:{}ms", processingTime); AiResponse aiResponse = AiResponse.success(content, "deepseek-chat"); aiResponse.setProcessingTimeMs(processingTime); return aiResponse; } catch (Exception e) { logger.error("营销文案生成失败", e); return AiResponse.error("营销文案生成失败:" + e.getMessage()); } } /** * 生成代码 * * @param request 请求参数 * @return AI响应 */ public AiResponse generateCode(AiRequest request) { logger.info("开始生成代码,需求:{}", request.getContent()); long startTime = System.currentTimeMillis(); try { String systemPrompt = """ 你是一位资深的软件工程师,精通多种编程语言和技术栈。 请根据用户的需求,生成高质量的代码,要求: 1. 代码结构清晰,逻辑合理 2. 包含必要的注释说明 3. 遵循最佳实践和编码规范 4. 考虑错误处理和边界情况 5. 如果需要,提供使用示例 请用中文注释,代码要完整可运行。 """; PromptTemplate promptTemplate = new PromptTemplate(systemPrompt + "\n\n编程需求:{content}"); Prompt prompt = promptTemplate.create(Map.of("content", request.getContent())); // 设置代码生成的参数(准确性优先) DeepSeekChatOptions options = DeepSeekChatOptions.builder() .temperature(request.getTemperature() != null ? request.getTemperature() : 0.1) .maxTokens(request.getMaxTokens() != null ? request.getMaxTokens() : 1500) .build(); var response = chatModel.call(new Prompt(prompt.getInstructions(), options)); String content = response.getResult().getOutput().getText(); long processingTime = System.currentTimeMillis() - startTime; logger.info("代码生成完成,耗时:{}ms", processingTime); AiResponse aiResponse = AiResponse.success(content, "deepseek-chat"); aiResponse.setProcessingTimeMs(processingTime); return aiResponse; } catch (Exception e) { logger.error("代码生成失败", e); return AiResponse.error("代码生成失败:" + e.getMessage()); } } /** * 智能问答 * * @param request 请求参数 * @return AI响应 */ public AiResponse answerQuestion(AiRequest request) { logger.info("开始智能问答,问题:{}", request.getContent()); long startTime = System.currentTimeMillis(); try { String systemPrompt = """ 你是一位知识渊博的AI助手,能够回答各种领域的问题。 请根据用户的问题,提供准确、详细、有用的回答: 1. 回答要准确可靠,基于事实 2. 解释要清晰易懂,层次分明 3. 如果涉及专业术语,请适当解释 4. 如果问题复杂,可以分步骤说明 5. 如果不确定答案,请诚实说明 请用中文回复,语言友好专业。 """; PromptTemplate promptTemplate = new PromptTemplate(systemPrompt + "\n\n用户问题:{content}"); Prompt prompt = promptTemplate.create(Map.of("content", request.getContent())); // 设置问答的参数(平衡准确性和流畅性) DeepSeekChatOptions options = DeepSeekChatOptions.builder() .temperature(request.getTemperature() != null ? request.getTemperature() : 0.7) .maxTokens(request.getMaxTokens() != null ? request.getMaxTokens() : 1000) .build(); var response = chatModel.call(new Prompt(prompt.getInstructions(), options)); String content = response.getResult().getOutput().getText(); long processingTime = System.currentTimeMillis() - startTime; logger.info("智能问答完成,耗时:{}ms", processingTime); AiResponse aiResponse = AiResponse.success(content, "deepseek-chat"); aiResponse.setProcessingTimeMs(processingTime); return aiResponse; } catch (Exception e) { logger.error("智能问答失败", e); return AiResponse.error("智能问答失败:" + e.getMessage()); } } /** * 通用聊天 * * @param request 请求参数 * @return AI响应 */ public AiResponse chat(AiRequest request) { logger.info("开始聊天对话,消息:{}", request.getContent()); long startTime = System.currentTimeMillis(); try { String systemPrompt = request.getSystemPrompt() != null ? request.getSystemPrompt() : """ 你是一位友好、有帮助的AI助手。 请以自然、亲切的方式与用户对话: 1. 保持友好和礼貌的语调 2. 根据上下文提供有用的回复 3. 如果用户需要帮助,尽力提供支持 4. 保持对话的连贯性和趣味性 请用中文回复,语言自然流畅。 """; PromptTemplate promptTemplate = new PromptTemplate(systemPrompt + "\n\n用户:{content}"); Prompt prompt = promptTemplate.create(Map.of("content", request.getContent())); // 设置聊天的参数(自然对话) DeepSeekChatOptions options = DeepSeekChatOptions.builder() .temperature(request.getTemperature() != null ? request.getTemperature() : 0.9) .maxTokens(request.getMaxTokens() != null ? request.getMaxTokens() : 800) .build(); var response = chatModel.call(new Prompt(prompt.getInstructions(), options)); String content = response.getResult().getOutput().getText(); long processingTime = System.currentTimeMillis() - startTime; logger.info("聊天对话完成,耗时:{}ms", processingTime); AiResponse aiResponse = AiResponse.success(content, "deepseek-chat"); aiResponse.setProcessingTimeMs(processingTime); return aiResponse; } catch (Exception e) { logger.error("聊天对话失败", e); return AiResponse.error("聊天对话失败:" + e.getMessage()); } } /** * 流式聊天 * * @param message 用户消息 * @return 流式响应 */ public Flux<String> streamChat(String message) { logger.info("开始流式聊天,消息:{}", message); try { String systemPrompt = """ 你是一位友好、有帮助的AI助手。 请以自然、亲切的方式与用户对话,用中文回复。 """; PromptTemplate promptTemplate = new PromptTemplate(systemPrompt + "\n\n用户:{content}"); Prompt prompt = promptTemplate.create(Map.of("content", message)); DeepSeekChatOptions options = DeepSeekChatOptions.builder() .temperature(0.9) .maxTokens(800) .build(); return chatModel.stream(new Prompt(prompt.getInstructions(), options)) .map(response -> response.getResult().getOutput().getText()) .doOnNext(chunk -> logger.debug("流式响应块:{}", chunk)) .doOnComplete(() -> logger.info("流式聊天完成")) .doOnError(error -> logger.error("流式聊天失败", error)); } catch (Exception e) { logger.error("流式聊天启动失败", e); return Flux.error(e); } } }

(2)Web 控制器实现(AiController.java)
less
体验AI代码助手
代码解读
复制代码
package com.example.demo.controller; import com.example.demo.dto.AiRequest; import com.example.demo.dto.AiResponse; import com.example.demo.service.SmartGeneratorService; import jakarta.validation.Valid; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; /** * AI功能控制器 * 提供营销文案生成、代码生成、智能问答、聊天对话等API * * @author Spring AI Demo */ @RestController @RequestMapping("/api/ai") @CrossOrigin(origins = "*") public class AiController { private static final Logger logger = LoggerFactory.getLogger(AiController.class); private final SmartGeneratorService smartGeneratorService; public AiController(SmartGeneratorService smartGeneratorService) { this.smartGeneratorService = smartGeneratorService; } /** * 营销文案生成API * * @param request 请求参数 * @return 生成的营销文案 */ @PostMapping("/marketing") public ResponseEntity<AiResponse> generateMarketingContent(@Valid @RequestBody AiRequest request) { logger.info("收到营销文案生成请求:{}", request.getContent()); try { AiResponse response = smartGeneratorService.generateMarketingContent(request); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("营销文案生成API调用失败", e); return ResponseEntity.internalServerError() .body(AiResponse.error("服务器内部错误:" + e.getMessage())); } } /** * 代码生成API * * @param request 请求参数 * @return 生成的代码 */ @PostMapping("/code") public ResponseEntity<AiResponse> generateCode(@Valid @RequestBody AiRequest request) { logger.info("收到代码生成请求:{}", request.getContent()); try { AiResponse response = smartGeneratorService.generateCode(request); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("代码生成API调用失败", e); return ResponseEntity.internalServerError() .body(AiResponse.error("服务器内部错误:" + e.getMessage())); } } /** * 智能问答API * * @param request 请求参数 * @return 问题的答案 */ @PostMapping("/qa") public ResponseEntity<AiResponse> answerQuestion(@Valid @RequestBody AiRequest request) { logger.info("收到智能问答请求:{}", request.getContent()); try { AiResponse response = smartGeneratorService.answerQuestion(request); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("智能问答API调用失败", e); return ResponseEntity.internalServerError() .body(AiResponse.error("服务器内部错误:" + e.getMessage())); } } /** * 聊天对话API * * @param request 请求参数 * @return 聊天回复 */ @PostMapping("/chat") public ResponseEntity<AiResponse> chat(@Valid @RequestBody AiRequest request) { logger.info("收到聊天对话请求:{}", request.getContent()); try { AiResponse response = smartGeneratorService.chat(request); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("聊天对话API调用失败", e); return ResponseEntity.internalServerError() .body(AiResponse.error("服务器内部错误:" + e.getMessage())); } } /** * 简单文本生成API(GET方式,用于快速测试) * * @param message 用户消息 * @param temperature 温度参数(可选) * @return 生成的回复 */ @GetMapping("/simple") public ResponseEntity<AiResponse> simpleChat( @RequestParam String message, @RequestParam(required = false) Double temperature) { logger.info("收到简单聊天请求:{}", message); try { AiRequest request = new AiRequest(message, temperature); AiResponse response = smartGeneratorService.chat(request); return ResponseEntity.ok(response); } catch (Exception e) { logger.error("简单聊天API调用失败", e); return ResponseEntity.internalServerError() .body(AiResponse.error("服务器内部错误:" + e.getMessage())); } } /** * 健康检查API * * @return 服务状态 */ @GetMapping("/health") public ResponseEntity<String> health() { return ResponseEntity.ok("AI服务运行正常 ✅"); } /** * 获取支持的功能列表 * * @return 功能列表 */ @GetMapping("/features") public ResponseEntity<Object> getFeatures() { var features = new Object() { public final String[] supportedFeatures = { "营销文案生成 (POST /api/ai/marketing)", "代码生成 (POST /api/ai/code)", "智能问答 (POST /api/ai/qa)", "聊天对话 (POST /api/ai/chat)", "简单对话 (GET /api/ai/simple?message=你好)", "流式聊天 (GET /api/stream/chat?message=你好)" }; public final String model = "deepseek-chat"; public final String version = "1.0.0"; public final String description = "Spring AI + DeepSeek 智能文本生成服务"; }; return ResponseEntity.ok(features); } }

(3)流式响应处理(StreamController.java)
typescript
体验AI代码助手
代码解读
复制代码
package com.example.demo.controller; import com.example.demo.service.SmartGeneratorService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; import java.time.Duration; import java.util.HashMap; import java.util.Map; /** * 流式响应控制器 * 提供Server-Sent Events (SSE) 流式聊天功能 * * @author Spring AI Demo */ @RestController @RequestMapping("/api/stream") @CrossOrigin(origins = "*") public class StreamController { private static final Logger logger = LoggerFactory.getLogger(StreamController.class); private final SmartGeneratorService smartGeneratorService; public StreamController(SmartGeneratorService smartGeneratorService) { this.smartGeneratorService = smartGeneratorService; } /** * 流式聊天API * 使用Server-Sent Events (SSE) 实现实时流式响应 * * @param message 用户消息 * @return 流式响应 */ @GetMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> streamChat(@RequestParam String message) { logger.info("收到流式聊天请求:{}", message); return smartGeneratorService.streamChat(message) .filter(chunk -> chunk != null && !chunk.trim().isEmpty()) // 过滤空内容 .doOnNext(chunk -> logger.debug("原始数据块: '{}'", chunk)) .map(chunk -> chunk.trim()) // 只清理空白字符 .filter(chunk -> !chunk.isEmpty()) // 再次过滤空内容 .concatWith(Flux.just("[DONE]")) .doOnSubscribe(subscription -> logger.info("开始流式响应")) .doOnComplete(() -> logger.info("流式响应完成")) .doOnError(error -> logger.error("流式响应出错", error)) .onErrorReturn("[ERROR] 流式响应出现错误"); } /** * 流式聊天API(JSON格式) * 返回JSON格式的流式数据 * * @param message 用户消息 * @return JSON格式的流式响应 */ @GetMapping(value = "/chat-json", produces = MediaType.APPLICATION_NDJSON_VALUE) public Flux<Map<String, Object>> streamChatJson(@RequestParam String message) { logger.info("收到JSON流式聊天请求:{}", message); // 创建完成响应 Map<String, Object> doneResponse = new HashMap<>(); doneResponse.put("type", "done"); doneResponse.put("content", ""); doneResponse.put("timestamp", System.currentTimeMillis()); // 创建错误响应 Map<String, Object> errorResponse = new HashMap<>(); errorResponse.put("type", "error"); errorResponse.put("content", "流式响应出现错误"); errorResponse.put("timestamp", System.currentTimeMillis()); return smartGeneratorService.streamChat(message) .map(chunk -> { Map<String, Object> response = new HashMap<>(); response.put("type", "chunk"); response.put("content", chunk); response.put("timestamp", System.currentTimeMillis()); return response; }) .concatWith(Flux.just(doneResponse)) .doOnSubscribe(subscription -> logger.info("开始JSON流式响应")) .doOnComplete(() -> logger.info("JSON流式响应完成")) .doOnError(error -> logger.error("JSON流式响应出错", error)) .onErrorReturn(errorResponse); } /** * 模拟打字机效果的流式响应 * * @param message 用户消息 * @return 带延迟的流式响应 */ @GetMapping(value = "/typewriter", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> typewriterChat(@RequestParam String message) { logger.info("收到打字机效果聊天请求:{}", message); return smartGeneratorService.streamChat(message) .delayElements(Duration.ofMillis(50)) // 添加50ms延迟模拟打字机效果 .map(chunk -> "data: " + chunk + "\n\n") .concatWith(Flux.just("data: [DONE]\n\n")) .doOnSubscribe(subscription -> logger.info("开始打字机效果流式响应")) .doOnComplete(() -> logger.info("打字机效果流式响应完成")) .doOnError(error -> logger.error("打字机效果流式响应出错", error)) .onErrorReturn("data: [ERROR] 流式响应出现错误\n\n"); } /** * 流式响应健康检查 * * @return 测试流式响应 */ @GetMapping(value = "/health", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> streamHealth() { return Flux.interval(Duration.ofSeconds(1)) .take(5) .map(i -> "data: 流式服务正常运行 - " + (i + 1) + "/5\n\n") .concatWith(Flux.just("data: [DONE] 健康检查完成\n\n")) .doOnSubscribe(subscription -> logger.info("开始流式健康检查")) .doOnComplete(() -> logger.info("流式健康检查完成")); } /** * 测试用的简单流式聊天(修复版本) * * @param message 用户消息 * @return 流式响应 */ @GetMapping(value = "/chat-fixed", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> streamChatFixed(@RequestParam String message) { logger.info("收到修复版流式聊天请求:{}", message); return smartGeneratorService.streamChat(message) .filter(chunk -> chunk != null && !chunk.trim().isEmpty()) .doOnNext(chunk -> logger.debug("修复版数据块: '{}'", chunk)) .map(chunk -> chunk.trim()) .filter(chunk -> !chunk.isEmpty()) .concatWith(Flux.just("[DONE]")) .doOnSubscribe(subscription -> logger.info("开始修复版流式响应")) .doOnComplete(() -> logger.info("修复版流式响应完成")) .doOnError(error -> logger.error("修复版流式响应出错", error)) .onErrorReturn("[ERROR] 修复版流式响应出现错误"); } /** * 获取流式API使用说明 * * @return 使用说明 */ @GetMapping("/info") public Map<String, Object> getStreamInfo() { Map<String, Object> info = new HashMap<>(); info.put("description", "Spring AI DeepSeek 流式响应服务"); info.put("endpoints", new String[]{ "GET /api/stream/chat?message=你好 - 基础流式聊天", "GET /api/stream/chat-fixed?message=你好 - 修复版流式聊天", "GET /api/stream/chat-json?message=你好 - JSON格式流式聊天", "GET /api/stream/typewriter?message=你好 - 打字机效果流式聊天", "GET /api/stream/health - 流式服务健康检查" }); info.put("usage", "使用curl测试: curl -N 'http://localhost:8080/api/stream/chat-fixed?message=你好'"); info.put("browser", "浏览器访问: http://localhost:8080/api/stream/chat-fixed?message=你好"); info.put("contentType", "text/event-stream"); return info; } }

更多推荐


所有评论(0)