当前位置: 首页 > news >正文

【Spring Boot 】Spring Boot + OpenAI API 万能集成模板,实现快速集成AI

Spring Boot + OpenAI API 万能集成模板

  • 一、核心架构设计
  • 二、万能模板实现
    • 2.1 基础配置类
    • 2.2 通用请求模板
  • 三、常用功能封装
    • 3.1 聊天对话接口
    • 3.2 图像生成接口
    • 3.3 文本嵌入接口
  • 四、高级功能扩展
    • 4.1 带上下文的连续对话
    • 4.2 函数调用能力
  • 五、安全与优化
    • 5.1 敏感信息过滤
    • 5.2 缓存优化
    • 5.3 限流策略
  • 六、完整控制器示例
  • 七、错误处理与日志
    • 7.1 全局异常处理
    • 7.2 审计日志
  • 八、部署配置
    • 8.1 application.yml
    • 8.2 Dockerfile
  • 九、使用示例
    • 9.1 聊天请求
    • 9.2 图像生成
    • 9.3 连续对话
  • 十、最佳实践建议

一、核心架构设计

Spring Boot应用
OpenAI API
聊天对话
图像生成
文本嵌入
代码生成
缓存层
限流控制
日志审计
异常处理

二、万能模板实现

2.1 基础配置类

@Configuration
public class OpenAIConfig {@Value("${openai.api.key}")private String apiKey;@Value("${openai.api.url}")private String apiUrl = "https://api.openai.com/v1";@Beanpublic WebClient openaiWebClient() {return WebClient.builder().baseUrl(apiUrl).defaultHeader("Authorization", "Bearer " + apiKey).defaultHeader("Content-Type", "application/json").build();}@Beanpublic ObjectMapper objectMapper() {return new ObjectMapper().registerModule(new JavaTimeModule()).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);}
}

2.2 通用请求模板

@Service
public class OpenAIService {private final WebClient webClient;private final ObjectMapper objectMapper;private final RateLimiter rateLimiter = RateLimiter.create(3); // 每秒3次调用public OpenAIService(WebClient webClient, ObjectMapper objectMapper) {this.webClient = webClient;this.objectMapper = objectMapper;}public <T> Mono<T> sendRequest(String endpoint, Object request, Class<T> responseType) {return Mono.fromCallable(() -> objectMapper.writeValueAsString(request)).flatMap(requestBody -> {if (!rateLimiter.tryAcquire()) {return Mono.error(new RateLimitExceededException("OpenAI API rate limit exceeded"));}return webClient.post().uri(endpoint).bodyValue(requestBody).retrieve().onStatus(HttpStatus::is4xxClientError, response -> handleClientError(response, endpoint)).onStatus(HttpStatus::is5xxServerError, response -> handleServerError(response, endpoint)).bodyToMono(String.class).flatMap(responseBody -> parseResponse(responseBody, responseType));}).retryWhen(Retry.backoff(3, Duration.ofSeconds(1)).doOnError(e -> log.error("OpenAI API call failed", e)).doOnSuccess(response -> log.info("API call to {} succeeded", endpoint));}private <T> Mono<T> parseResponse(String responseBody, Class<T> responseType) {try {return Mono.just(objectMapper.readValue(responseBody, responseType));} catch (JsonProcessingException e) {return Mono.error(new OpenAIException("Failed to parse response", e));}}private Mono<? extends Throwable> handleClientError(ClientResponse response, String endpoint) {return response.bodyToMono(String.class).flatMap(errorBody -> {log.error("Client error for {}: {}", endpoint, errorBody);return Mono.error(new OpenAIException("Client error: " + errorBody));});}private Mono<? extends Throwable> handleServerError(ClientResponse response, String endpoint) {return Mono.error(new OpenAIException("Server error for endpoint: " + endpoint));}
}

三、常用功能封装

3.1 聊天对话接口

public class ChatService {private final OpenAIService openAIService;public ChatService(OpenAIService openAIService) {this.openAIService = openAIService;}public Mono<String> chatCompletion(String prompt, String model) {ChatRequest request = new ChatRequest(model,List.of(new Message("user", prompt)),0.7, // temperature1000 // max tokens);return openAIService.sendRequest("/chat/completions", request, ChatResponse.class).map(ChatResponse::getContent);}@Data@AllArgsConstructorprivate static class ChatRequest {private String model;private List<Message> messages;private double temperature;private int max_tokens;}@Dataprivate static class Message {private final String role;private final String content;}@Dataprivate static class ChatResponse {private List<Choice> choices;public String getContent() {return choices.get(0).getMessage().getContent();}@Dataprivate static class Choice {private Message message;}}
}

3.2 图像生成接口

public class ImageService {private final OpenAIService openAIService;public ImageService(OpenAIService openAIService) {this.openAIService = openAIService;}public Mono<List<String>> generateImage(String prompt, int n, String size) {ImageRequest request = new ImageRequest(prompt, n, size);return openAIService.sendRequest("/images/generations", request, ImageResponse.class).map(ImageResponse::getImageUrls);}@Data@AllArgsConstructorprivate static class ImageRequest {private String prompt;private int n;private String size;}@Dataprivate static class ImageResponse {private List<ImageData> data;public List<String> getImageUrls() {return data.stream().map(ImageData::getUrl).collect(Collectors.toList());}@Dataprivate static class ImageData {private String url;}}
}

3.3 文本嵌入接口

public class EmbeddingService {private final OpenAIService openAIService;public EmbeddingService(OpenAIService openAIService) {this.openAIService = openAIService;}public Mono<List<Double>> getEmbedding(String text, String model) {EmbeddingRequest request = new EmbeddingRequest(model, text);return openAIService.sendRequest("/embeddings", request, EmbeddingResponse.class).map(EmbeddingResponse::getEmbedding);}@Data@AllArgsConstructorprivate static class EmbeddingRequest {private String model;private String input;}@Dataprivate static class EmbeddingResponse {private List<EmbeddingData> data;public List<Double> getEmbedding() {return data.get(0).getEmbedding();}@Dataprivate static class EmbeddingData {private List<Double> embedding;}}
}

四、高级功能扩展

4.1 带上下文的连续对话

public class ConversationService {private final OpenAIService openAIService;private final Map<String, List<Message>> conversationHistory = new ConcurrentHashMap<>();public ConversationService(OpenAIService openAIService) {this.openAIService = openAIService;}public Mono<String> continueConversation(String sessionId, String userMessage) {List<Message> history = conversationHistory.computeIfAbsent(sessionId, k -> new ArrayList<>());history.add(new Message("user", userMessage));// 限制历史记录长度if (history.size() > 10) {history = history.subList(history.size() - 10, history.size());conversationHistory.put(sessionId, history);}ChatRequest request = new ChatRequest("gpt-4",history,0.7,1000);return openAIService.sendRequest("/chat/completions", request, ChatResponse.class).map(response -> {String assistantResponse = response.getContent();history.add(new Message("assistant", assistantResponse));return assistantResponse;});}
}

4.2 函数调用能力

public class FunctionCallService {private final OpenAIService openAIService;public FunctionCallService(OpenAIService openAIService) {this.openAIService = openAIService;}public Mono<FunctionCallResult> callFunction(String prompt, List<FunctionSpec> functions) {FunctionCallRequest request = new FunctionCallRequest("gpt-4",List.of(new Message("user", prompt)),functions,0.7);return openAIService.sendRequest("/chat/completions", request, FunctionCallResponse.class).map(response -> {FunctionCall functionCall = response.getChoices().get(0).getMessage().getFunction_call();return new FunctionCallResult(functionCall.getName(),parseArguments(functionCall.getArguments()));});}private Map<String, Object> parseArguments(String argumentsJson) {try {return objectMapper.readValue(argumentsJson, new TypeReference<Map<String, Object>>() {});} catch (JsonProcessingException e) {throw new OpenAIException("Failed to parse function arguments", e);}}@Data@AllArgsConstructorprivate static class FunctionCallRequest {private String model;private List<Message> messages;private List<FunctionSpec> functions;private double temperature;}@Dataprivate static class FunctionCallResponse {private List<Choice> choices;@Dataprivate static class Choice {private Message message;}@Dataprivate static class Message {private FunctionCall function_call;}@Dataprivate static class FunctionCall {private String name;private String arguments;}}@Data@AllArgsConstructorpublic static class FunctionSpec {private String name;private String description;private Map<String, Object> parameters;}@Data@AllArgsConstructorpublic static class FunctionCallResult {private String functionName;private Map<String, Object> arguments;}
}

五、安全与优化

5.1 敏感信息过滤

public class ContentFilter {private static final List<String> SENSITIVE_WORDS = List.of("password", "secret", "api_key");private static final Pattern CREDIT_CARD_PATTERN = Pattern.compile("\\b(?:\\d[ -]*?){13,16}\\b");public String filterSensitiveInfo(String text) {// 过滤敏感词for (String word : SENSITIVE_WORDS) {text = text.replaceAll("(?i)" + word, "***");}// 过滤信用卡号Matcher matcher = CREDIT_CARD_PATTERN.matcher(text);return matcher.replaceAll("[CARD_FILTERED]");}
}

5.2 缓存优化

@Configuration
@EnableCaching
public class CacheConfig {@Beanpublic CacheManager cacheManager() {return new ConcurrentMapCacheManager("openaiResponses");}
}@Service
public class CachedOpenAIService {private final OpenAIService openAIService;private final CacheManager cacheManager;private final ContentFilter contentFilter;public CachedOpenAIService(OpenAIService openAIService, CacheManager cacheManager, ContentFilter contentFilter) {this.openAIService = openAIService;this.cacheManager = cacheManager;this.contentFilter = contentFilter;}@Cacheable(value = "openaiResponses", key = "#prompt.hashCode()")public Mono<String> getCachedResponse(String prompt, String model) {String filteredPrompt = contentFilter.filterSensitiveInfo(prompt);return openAIService.chatCompletion(filteredPrompt, model);}
}

5.3 限流策略

@Bean
public RateLimiterRegistry rateLimiterRegistry() {return RateLimiterRegistry.of(RateLimiterConfig.custom().limitForPeriod(100) // 每分钟100次.limitRefreshPeriod(Duration.ofMinutes(1)).timeoutDuration(Duration.ofSeconds(5)).build());
}@Aspect
@Component
public class RateLimiterAspect {private final RateLimiter rateLimiter;public RateLimiterAspect(RateLimiterRegistry registry) {this.rateLimiter = registry.rateLimiter("openaiApi");}@Around("@annotation(com.example.annotation.RateLimited)")public Object rateLimit(ProceedingJoinPoint joinPoint) throws Throwable {if (rateLimiter.acquirePermission()) {return joinPoint.proceed();} else {throw new RateLimitExceededException("API rate limit exceeded");}}
}

六、完整控制器示例

@RestController
@RequestMapping("/api/openai")
public class OpenAIController {private final ChatService chatService;private final ImageService imageService;private final ConversationService conversationService;public OpenAIController(ChatService chatService, ImageService imageService, ConversationService conversationService) {this.chatService = chatService;this.imageService = imageService;this.conversationService = conversationService;}@PostMapping("/chat")public Mono<ResponseEntity<String>> chat(@RequestBody ChatRequest request) {return chatService.chatCompletion(request.getPrompt(), request.getModel()).map(response -> ResponseEntity.ok(response));}@PostMapping("/image")public Mono<ResponseEntity<List<String>>> generateImage(@RequestBody ImageRequest request) {return imageService.generateImage(request.getPrompt(), request.getN(), request.getSize()).map(ResponseEntity::ok);}@PostMapping("/conversation/{sessionId}")public Mono<ResponseEntity<String>> continueConversation(@PathVariable String sessionId,@RequestBody UserMessage request) {return conversationService.continueConversation(sessionId, request.getMessage()).map(ResponseEntity::ok);}@Dataprivate static class ChatRequest {private String prompt;private String model = "gpt-4";}@Dataprivate static class ImageRequest {private String prompt;private int n = 1;private String size = "1024x1024";}@Dataprivate static class UserMessage {private String message;}
}

七、错误处理与日志

7.1 全局异常处理

@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(OpenAIException.class)public ResponseEntity<ErrorResponse> handleOpenAIException(OpenAIException ex) {return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorResponse("OPENAI_ERROR", ex.getMessage()));}@ExceptionHandler(RateLimitExceededException.class)public ResponseEntity<ErrorResponse> handleRateLimitException(RateLimitExceededException ex) {return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).body(new ErrorResponse("RATE_LIMIT_EXCEEDED", ex.getMessage()));}@ExceptionHandler(Exception.class)public ResponseEntity<ErrorResponse> handleGeneralException(Exception ex) {return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ErrorResponse("INTERNAL_ERROR", "An unexpected error occurred"));}@Data@AllArgsConstructorprivate static class ErrorResponse {private String code;private String message;}
}

7.2 审计日志

@Aspect
@Component
public class APIAuditAspect {@Autowiredprivate AuditLogRepository auditLogRepository;@AfterReturning(pointcut = "execution(* com.example.controller.OpenAIController.*(..))", returning = "result")public void logSuccess(JoinPoint joinPoint, Object result) {Object[] args = joinPoint.getArgs();String methodName = joinPoint.getSignature().getName();AuditLog log = new AuditLog();log.setMethod(methodName);log.setRequest(serializeRequest(args));log.setResponse(serializeResponse(result));log.setStatus("SUCCESS");log.setTimestamp(LocalDateTime.now());auditLogRepository.save(log);}@AfterThrowing(pointcut = "execution(* com.example.controller.OpenAIController.*(..))", throwing = "ex")public void logError(JoinPoint joinPoint, Throwable ex) {Object[] args = joinPoint.getArgs();String methodName = joinPoint.getSignature().getName();AuditLog log = new AuditLog();log.setMethod(methodName);log.setRequest(serializeRequest(args));log.setResponse(ex.getMessage());log.setStatus("ERROR");log.setTimestamp(LocalDateTime.now());auditLogRepository.save(log);}private String serializeRequest(Object[] args) {try {return new ObjectMapper().writeValueAsString(args);} catch (JsonProcessingException e) {return "Serialization error";}}private String serializeResponse(Object response) {try {return new ObjectMapper().writeValueAsString(response);} catch (JsonProcessingException e) {return "Serialization error";}}
}

八、部署配置

8.1 application.yml

openai:api:key: ${OPENAI_API_KEY}url: https://api.openai.com/v1timeout: 30sspring:cache:type: caffeineredis:host: localhostport: 6379logging:level:root: INFOcom.example: DEBUG

8.2 Dockerfile

FROM eclipse-temurin:17-jdk-alpine
VOLUME /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

九、使用示例

9.1 聊天请求

curl -X POST http://localhost:8080/api/openai/chat \-H "Content-Type: application/json" \-d '{"prompt": "解释量子计算的基本原理","model": "gpt-4"}'

9.2 图像生成

curl -X POST http://localhost:8080/api/openai/image \-H "Content-Type: application/json" \-d '{"prompt": "未来城市景观,赛博朋克风格","n": 2,"size": "1024x1024"}'

9.3 连续对话

curl -X POST http://localhost:8080/api/openai/conversation/session123 \-H "Content-Type: application/json" \-d '{"message": "上一个问题中提到的量子比特是什么?"}'

十、最佳实践建议

  1. 密钥管理:
    • 使用环境变量或密钥管理服务存储API密钥
    • 避免在代码库中硬编码敏感信息
  2. 成本控制:
    • 设置API使用配额
    • 监控OpenAI API使用情况
    • 使用缓存减少重复请求
  3. 性能优化:
    • 设置合理的超时时间
    • 使用异步非阻塞调用
    • 批量处理请求
  4. 安全合规:
    • 实现内容过滤机制
    • 遵守OpenAI使用政策
    • 记录审计日志
  5. 错误处理:
    • 实现重试机制
    • 优雅降级处理
    • 监控API错误率

通过此万能模板,可快速集成OpenAI各种API功能,同时确保系统的稳定性、安全性和可扩展性。

http://www.xdnf.cn/news/1241245.html

相关文章:

  • sqli-labs通关笔记-第30关GET字符注入(WAF绕过 双引号闭合 手工注入+脚本注入两种方法)
  • AI Agents漏洞百出,恶意提示等安全缺陷令人担忧
  • 高防服务器租用的作用都有哪些?
  • 随笔之 ClickHouse 列式分析数据库安装注意事项及基准测试
  • 【BUUCTF系列】[SUCTF 2019]EasySQL1
  • 【论文简读】LongSplat
  • Claude Code深度操作指南:从零到专家的AI编程助手实战
  • MAC-Spring Cloud + Spring Boot + RocketMQ集成
  • 链表问题解决分析框架
  • SP20D120CTU:1200 V/20 A SiC肖特基二极管的TO-263封装升级版,数据工程师必看!
  • 政府财政行业云原生转型之路
  • Maya 2024安装指南及安装包下载
  • 车载通信架构 ---车内通信的汽车网络安全
  • Linux中netstat详细使用指南
  • 【Linux】System V - 基于建造者模式的信号量
  • DP-v2.1-mem-clean学习(3.6.8.2-3.6.8.3)
  • Linux文件权限管理与ACL配置指南
  • wpf Image 转 90 度
  • 9.感知机、神经网络
  • 国产化Word处理控件Spire.Doc教程:Python提取Word文档中的文本、图片、表格等
  • Excel商业智能分析报表 【销售管理分析仪】
  • 百度翻译详解:包括PaddleNLP、百度AI开放平台、接口逆向(包括完整代码)
  • Android工程命令行打包并自动生成签名Apk
  • Go语言高并发价格监控系统设计
  • 向量空间模型
  • 从exec到Shell:深度解析Linux进程等待,程序替换与自主Shell实现
  • 抛出自定义异常
  • Android UI 组件系列(九):ListView 性能优化与 ViewHolder 模式实战
  • 复现论文《A Fiber Bragg Grating Sensor System for Train Axle Counting》
  • 多级表头的导出