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

Spring Boot 集成国内AI,包含文心一言、通义千问和讯飞星火平台实战教程

Spring Boot 集成国内AI,包含文心一言、通义千问和讯飞星火平台实战教程

  • 一、项目结构
  • 二、添加Maven依赖
  • 三、配置API密钥 (application.yml)
  • 四、配置类
    • 1. AI配置类 (AiProperties.java)
    • 2. 启用配置类 (AiConfig.java)
  • 五、服务层实现
    • 1. 文心一言服务 (WenxinService.java)
    • 2. 通义千问服务 (QianwenService.java)
    • 3. 讯飞星火服务 (XinghuoService.java)
  • 六、统一控制器 (AiController.java)
  • 七、安全增强配置
    • 1. 添加API密钥保护(自定义Filter)
    • 2. 添加Rate Limiting(使用Resilience4j)
  • 八、应用入口 (AiIntegrationApplication.java)
  • 九、测试示例
  • 十、最佳实践建议

Spring Boot集成国内主流AI平台的详细实现方案,包含文心一言、通义千问和讯飞星火的对接代码,助力快速构建智能应用。

一、项目结构

ai-integration-demo/
├── src/main/java
│   ├── com/example/ai
│   │   ├── config                # 配置类
│   │   ├── controller            # API控制器
│   │   ├── service               # 服务层
│   │   │   ├── impl              # 服务实现
│   │   ├── dto                   # 数据传输对象
├── resources
│   ├── application.yml           # 配置文件

二、添加Maven依赖

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- HTTP客户端 --><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.11.0</version></dependency><!-- JSON处理 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><!-- 配置处理 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency>
</dependencies>

三、配置API密钥 (application.yml)

ai:wenxin:api-key: YOUR_WENXIN_API_KEYsecret-key: YOUR_WENXIN_SECRET_KEYapi-url: https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completionsqianwen:api-key: YOUR_QIANWEN_API_KEYapi-url: https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generationxinghuo:api-key: YOUR_XINGHUO_API_KEYsecret: YOUR_XINGHUO_SECRETappid: YOUR_XINGHUO_APPIDapi-url: https://spark-api.xf-yun.com/v3.5/chat

四、配置类

1. AI配置类 (AiProperties.java)

@ConfigurationProperties(prefix = "ai")
@Data
public class AiProperties {private Wenxin wenxin;private Qianwen qianwen;private Xinghuo xinghuo;@Datapublic static class Wenxin {private String apiKey;private String secretKey;private String apiUrl;}@Datapublic static class Qianwen {private String apiKey;private String apiUrl;}@Datapublic static class Xinghuo {private String apiKey;private String secret;private String appid;private String apiUrl;}
}

2. 启用配置类 (AiConfig.java)

@Configuration
@EnableConfigurationProperties(AiProperties.class)
public class AiConfig {@Beanpublic OkHttpClient okHttpClient() {return new OkHttpClient();}
}

五、服务层实现

1. 文心一言服务 (WenxinService.java)

@Service
@RequiredArgsConstructor
public class WenxinService {private final AiProperties aiProperties;private final OkHttpClient okHttpClient;// 获取AccessTokenprivate String getAccessToken() {String url = "https://aip.baidubce.com/oauth/2.0/token?"+ "grant_type=client_credentials"+ "&client_id=" + aiProperties.getWenxin().getApiKey()+ "&client_secret=" + aiProperties.getWenxin().getSecretKey();Request request = new Request.Builder().url(url).get().build();try (Response response = okHttpClient.newCall(request).execute()) {String responseBody = response.body().string();ObjectMapper objectMapper = new ObjectMapper();JsonNode rootNode = objectMapper.readTree(responseBody);return rootNode.get("access_token").asText();} catch (Exception e) {throw new RuntimeException("获取文心一言Token失败", e);}}public String chatCompletion(String prompt) {String accessToken = getAccessToken();String url = aiProperties.getWenxin().getApiUrl() + "?access_token=" + accessToken;JSONObject body = new JSONObject();body.put("messages", new JSONArray().put(new JSONObject().put("role", "user").put("content", prompt)));Request request = new Request.Builder().url(url).post(RequestBody.create(body.toString(), MediaType.get("application/json"))).build();try (Response response = okHttpClient.newCall(request).execute()) {if (!response.isSuccessful()) {throw new RuntimeException("文心一言API请求失败: " + response);}String responseBody = response.body().string();JSONObject jsonResponse = new JSONObject(responseBody);return jsonResponse.getJSONObject("result").getString("content");} catch (Exception e) {throw new RuntimeException("调用文心一言API出错", e);}}
}

2. 通义千问服务 (QianwenService.java)

@Service
@RequiredArgsConstructor
public class QianwenService {private final AiProperties aiProperties;private final OkHttpClient okHttpClient;public String generateText(String prompt) {JSONObject body = new JSONObject();body.put("model", "qwen-turbo");JSONObject input = new JSONObject();input.put("prompt", prompt);body.put("input", input);JSONObject parameters = new JSONObject();parameters.put("temperature", 0.85);parameters.put("top_p", 0.8);parameters.put("max_tokens", 1500);body.put("parameters", parameters);Request request = new Request.Builder().url(aiProperties.getQianwen().getApiUrl()).header("Authorization", "Bearer " + aiProperties.getQianwen().getApiKey()).post(RequestBody.create(body.toString(), MediaType.get("application/json"))).build();try (Response response = okHttpClient.newCall(request).execute()) {if (!response.isSuccessful()) {throw new RuntimeException("通义千问API请求失败: " + response);}String responseBody = response.body().string();JSONObject jsonResponse = new JSONObject(responseBody);return jsonResponse.getJSONObject("output").getString("text");} catch (Exception e) {throw new RuntimeException("调用通义千问API出错", e);}}
}

3. 讯飞星火服务 (XinghuoService.java)

@Service
@RequiredArgsConstructor
public class XinghuoService {private final AiProperties aiProperties;private final OkHttpClient okHttpClient;public String chat(String prompt) {try {// 构造鉴权URLString authUrl = generateAuthUrl();// 构造请求体JSONObject body = new JSONObject();JSONObject header = new JSONObject();header.put("app_id", aiProperties.getXinghuo().getAppid());JSONObject parameter = new JSONObject();JSONObject chat = new JSONObject();chat.put("domain", "generalv3.5");chat.put("temperature", 0.5);chat.put("max_tokens", 4096);parameter.put("chat", chat);JSONObject payload = new JSONObject();JSONObject message = new JSONObject();JSONArray text = new JSONArray();text.put(new JSONObject().put("role", "user").put("content", prompt));message.put("text", text);payload.put("message", message);body.put("header", header);body.put("parameter", parameter);body.put("payload", payload);// 发送请求Request request = new Request.Builder().url(authUrl).post(RequestBody.create(body.toString(), MediaType.get("application/json"))).build();try (Response response = okHttpClient.newCall(request).execute()) {if (!response.isSuccessful()) {throw new RuntimeException("讯飞星火API请求失败: " + response);}String responseBody = response.body().string();JSONObject jsonResponse = new JSONObject(responseBody);return extractContent(jsonResponse);}} catch (Exception e) {throw new RuntimeException("调用讯飞星火API出错", e);}}// 生成带鉴权信息的URLprivate String generateAuthUrl() throws ParseException, InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException {String apiUrl = aiProperties.getXinghuo().getApiUrl();String host = new URL(apiUrl).getHost();String path = new URL(apiUrl).getPath();// 创建日期对象SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);sdf.setTimeZone(TimeZone.getTimeZone("GMT"));String date = sdf.format(new Date());// 构造签名String signatureOrigin = "host: " + host + "\n";signatureOrigin += "date: " + date + "\n";signatureOrigin += "POST " + path + " HTTP/1.1";Mac mac = Mac.getInstance("hmacsha256");SecretKeySpec secretKeySpec = new SecretKeySpec(aiProperties.getXinghuo().getSecret().getBytes("UTF-8"), "hmacsha256");mac.init(secretKeySpec);byte[] signatureSha = mac.doFinal(signatureOrigin.getBytes("UTF-8"));String signature = Base64.getEncoder().encodeToString(signatureSha);// 构造授权头String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"",aiProperties.getXinghuo().getApiKey(), "hmac-sha256", "host date request-line", signature);return apiUrl + "?authorization=" + Base64.getEncoder().encodeToString(authorization.getBytes("UTF-8"))+ "&date=" + URLEncoder.encode(date, "UTF-8")+ "&host=" + URLEncoder.encode(host, "UTF-8");}// 提取响应内容private String extractContent(JSONObject response) {JSONObject payload = response.getJSONObject("payload");JSONObject message = payload.getJSONObject("message");JSONArray text = message.getJSONArray("text");StringBuilder result = new StringBuilder();for (int i = 0; i < text.length(); i++) {JSONObject textObj = text.getJSONObject(i);if (textObj.has("content")) {result.append(textObj.getString("content"));}}return result.toString();}
}

六、统一控制器 (AiController.java)

@RestController
@RequestMapping("/api/ai")
@RequiredArgsConstructor
public class AiController {private final WenxinService wenxinService;private final QianwenService qianwenService;private final XinghuoService xinghuoService;@PostMapping("/wenxin")public ResponseEntity<String> wenxinChat(@RequestBody @Valid AiRequest request) {return ResponseEntity.ok(wenxinService.chatCompletion(request.getPrompt()));}@PostMapping("/qianwen")public ResponseEntity<String> qianwenGenerate(@RequestBody @Valid AiRequest request) {return ResponseEntity.ok(qianwenService.generateText(request.getPrompt()));}@PostMapping("/xinghuo")public ResponseEntity<String> xinghuoChat(@RequestBody @Valid AiRequest request) {return ResponseEntity.ok(xinghuoService.chat(request.getPrompt()));}@Datastatic class AiRequest {@NotBlank(message = "提示语不能为空")private String prompt;}
}

七、安全增强配置

1. 添加API密钥保护(自定义Filter)

@Component
@RequiredArgsConstructor
public class ApiKeyFilter extends OncePerRequestFilter {private final AiProperties aiProperties;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {String clientId = request.getHeader("X-API-CLIENT-ID");String clientSecret = request.getHeader("X-API-CLIENT-SECRET");// 验证客户端凭证if (!isValidCredentials(clientId, clientSecret)) {response.sendError(HttpStatus.UNAUTHORIZED.value(), "无效的API凭证");return;}filterChain.doFilter(request, response);}private boolean isValidCredentials(String clientId, String clientSecret) {// 这里应该是从数据库或配置中读取验证信息// 简化示例:使用配置中的文心API密钥做演示return clientId != null && clientSecret != null && clientId.equals("demo-app") && clientSecret.equals(aiProperties.getWenxin().getApiKey());}
}

2. 添加Rate Limiting(使用Resilience4j)

@Configuration
public class RateLimiterConfig {@Beanpublic RateLimiter wenxinRateLimiter() {return RateLimiter.of("wenxin-limiter", RateLimiterConfig.custom().limitRefreshPeriod(Duration.ofSeconds(10)).limitForPeriod(5).timeoutDuration(Duration.ofSeconds(5)).build());}
}// 在控制器中使用
@RestController
@RequestMapping("/api/ai")
public class AiController {private final RateLimiter wenxinRateLimiter;@PostMapping("/wenxin")@RateLimiter(name = "wenxin-limiter")public ResponseEntity<String> wenxinChat(@RequestBody AiRequest request) {// ...}
}

八、应用入口 (AiIntegrationApplication.java)

@SpringBootApplication
public class AiIntegrationApplication {public static void main(String[] args) {SpringApplication.run(AiIntegrationApplication.class, args);}
}

九、测试示例

使用cURL测试:

# 通义千问测试
curl -X POST http://localhost:8080/api/ai/qianwen \-H "Content-Type: application/json" \-d '{"prompt": "用100字介绍Spring Boot"}'# 文心一言测试
curl -X POST http://localhost:8080/api/ai/wenxin \-H "Content-Type: application/json" \-d '{"prompt": "用Java写一个快速排序算法"}'# 讯飞星火测试
curl -X POST http://localhost:8080/api/ai/xinghuo \-H "Content-Type: application/json" \-d '{"prompt": "如何做好电商运营"}'

十、最佳实践建议

  1. 异步处理:使用@Async注解异步调用AI接口,避免阻塞
  2. 缓存结果:对常见问题的结果进行缓存,减少API调用
  3. 错误重试:实现指数退避重试机制处理临时错误
  4. 流量控制:针对不同AI平台设置不同的QPS限制
  5. 统一接口:创建统一的AI门面服务,提供平台无关的调用
@Service
public class AiFacadeService {private enum AiProvider { WENXIN, QIANWEN, XINGHUO }private final WenxinService wenxinService;private final QianwenService qianwenService;private final XinghuoService xinghuoService;public String unifiedChat(String prompt) {// 简单轮询策略AiProvider[] providers = AiProvider.values();AiProvider provider = providers[(int)(System.currentTimeMillis() % providers.length)];switch (provider) {case WENXIN: return wenxinService.chatCompletion(prompt);case QIANWEN: return qianwenService.generateText(prompt);case XINGHUO: return xinghuoService.chat(prompt);default: throw new IllegalStateException("未知的AI提供商");}}
}

本项目提供了完整的企业级Spring Boot集成国内主流AI平台的实现方案,可根据实际需求进行扩展和优化。

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

相关文章:

  • 域名+nginx反向代理实现案例
  • Python学习笔记:错误和异常处理
  • 影像组学5:Radiomics Score的计算
  • 深度学习驱动的验证码识别实战:从原理到高并发工业部署
  • YOLOV11改进之多尺度扩张残差模块(MS-DRM)
  • [特殊字符][特殊字符] Harmony OS Next玩转多层级手势事件:当组件遇上“套娃”,触摸该怎么分家?
  • 北斗导航 | 基于matlab的卫星导航单点定位算法
  • Linux文件权限详解:从入门到精通
  • 每日Prompt:Steve Winter风格插画
  • 2.3 ASPICE的架构与设计
  • 服务器上安装配置vsftpd
  • Java流处理中的常见错误与最佳实践
  • 第八十篇 大数据开发基石:深入解析栈结构及其生活化应用(附全流程图解)
  • Cloud Events:事件驱动架构的未来标准化
  • 访问者模式:解耦数据结构与操作的优雅之道
  • 前端性能优化:打造极致用户体验
  • 洛谷:B3799 [NICA #1] 序列
  • 单片机,主循环和中断资源访问冲突的案例
  • P1197 [JSOI2008] 星球大战
  • AI 应用开发(一):TRAE 下自定义 MCP Server
  • 【压缩中断数目--二级中断查找】
  • PostgreSQL的扩展adminpack
  • 机器翻译指标:BLEU
  • 基于边缘计算的丝杆状态实时监测系统设计?
  • 【通用定时器TIM2 TIM3 TIM4 TIM5】
  • Codeforces Round 1023 (Div. 2) C. Maximum Subarray Sum
  • 2025秋招后端突围:JVM核心面试题与高频考点深度解析
  • 电脑在使用过程中频繁死机怎么办
  • Java并发编程实战 Day 21:分布式并发控制
  • 华为云Flexus+DeepSeek征文 | 基于Dify构建个人在线旅游助手