SpringAI整合AI大模型(1)
1.SpringAI简介
引言
随着人工智能(AI)技术的快速发展,越来越多的传统软件开发框架开始尝试与 AI 技术结合,以提升开发效率、优化系统性能并提供更智能的功能。作为 Java 生态中最流行的开发框架之一,Spring Framework 在企业级应用开发中占据重要地位。而 SpringAI 是一个假设性但极具前瞻性的概念,它代表了 Spring 框架与人工智能技术深度融合的可能性。本文将探讨 SpringAI 的潜在定义、应用场景以及未来发展方向。
什么是 SpringAI?
SpringAI 并不是一个当前存在的具体项目或工具,而是对 Spring Framework 在未来可能集成人工智能技术的一种设想。可以将其理解为一种扩展或增强版的 Spring Framework,旨在通过引入 AI 技术,使开发者能够更高效地构建智能化应用程序。
核心理念
自动化与智能化:利用机器学习和深度学习算法,自动完成代码生成、测试用例创建、性能调优等任务。
动态适应性:通过实时分析运行时数据,调整应用程序的行为以适应不同的负载条件或用户需求。
增强开发者体验:通过自然语言处理(NLP)技术,让开发者可以通过语音或文本指令与开发工具交互。
2.Spring AI 使用 (采用springAi alibaba,因为原生的springAi 对国内大模型并不友好)
2.1 pom.xml
添加Maven存储库: 在项目的pom.xml中添加spring-ai-alibaba-starter。
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>1.0.0-M5.1</version>
</dependency>
2.2 应用场景
生成式AI:
借助 Spring AI 的生成式AI能力,开发者可以通过简明的API调用,实现高质量的文本生成、多语言翻译、智能摘要提取等功能。这些功能基于先进的自然语言处理(NLP)技术,能够显著提升应用的内容生成能力和用户体验。
矢量数据库:
在需要对大规模文本数据进行语义搜索和相似性匹配时,Spring AI 提供了高效的矢量数据库支持。通过集成最新的向量检索技术,开发者可以轻松实现高精度的语义搜索功能,大幅提升数据查询的效率与相关性。
AI绘画:
针对将文本描述转化为视觉内容的需求,Spring AI 提供了强大的AI绘画功能。该功能基于生成对抗网络(GAN)和其他前沿图像生成技术,能够无缝集成到各类应用场景中,如创意设计、虚拟场景构建等,为用户提供从文本到图像的智能化转换能力。
通过以上核心功能,Spring AI 不仅简化了AI技术的应用开发流程,还为企业和开发者提供了高效、灵活的智能化解决方案。
3.Spring Cloud Alibaba AI 实践
3.1 版本选择
注意:因为 Spring AI Alibaba 基于 Spring Boot 3.x 开发,因此本地 JDK 版本要求为 17 及以上。
我选择了 JDK 17 作为运行环境,Spring Boot 3.4.3 框架。
3.2 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.an</groupId>
<artifactId>aiApiClient</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>aiApiClient</name>
<description>aiApiClient</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>1.0.0-M5.1</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.12.261</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.8.31</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>5.8.31</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.5</version>
</dependency>
<!-- druid 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>1.2.20</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- <plugin>-->
<!-- <groupId>org.apache.maven.plugins</groupId>-->
<!-- <artifactId>maven-compiler-plugin</artifactId>-->
<!-- <configuration>-->
<!-- <annotationProcessorPaths>-->
<!-- <path>-->
<!-- <groupId>org.projectlombok</groupId>-->
<!-- <artifactId>lombok</artifactId>-->
<!-- </path>-->
<!-- </annotationProcessorPaths>-->
<!-- </configuration>-->
<!-- </plugin>-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.2 配置文件
此处很多配置属于自定义配置如果只想实现简单的聊天功能,配置一下端口号就好
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
username: ${MYSQL_USER:root}
password: ${MYSQL_PWD:root}
url: jdbc:mysql://${MYSQL_HOST:localhost}:${MYSQL_PORT:3306}/${MYSQL_DB:ai}?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false
ai:
nacos:
prompt:
template:
enabled: false
application:
name: aiApiClient
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
server:
port: 8080
ai:
chat:
scene: 我想咨询你一些医学上的问题,你需要初步判断我的症状,以及给出开药建议以及生活方式建议,以及推荐一些医生治疗
topP: 0.8
model: qwen-vl-max-latest
enableSearch: true
multiModel: true
file:
bucketName: ai # 默认存储桶名称
local: # 本地文件配置信息
enable: true # 是否开启
basePath: D:/local/files # 默认路径
domain: http://localhost:${server.port}
logging:
level:
com: DEBUG
阿里云申请api-key:获取api-key
说明
仅主账号拥有查看全部API-KEY的权限。主账号可以获取所有子账号的API Key,子账号仅能获取自己的API Key。
请不要将API Key以任何方式公开,避免因未经授权的使用造成安全风险或资金损失。
API Key是您的重要资产,请务必妥善保管。如果您单击操作列的删除将已有API Key删除,您将无法继续通过该Key访问百炼大模型提供的各项服务,如果您之前在某些应用程序或服务中集成了这个API Key,那么这些应用将会因为认证失败而无法正常工作。
3.3 设置 AI_DASHSCOPE_API_KEY 环境变量
AI_DASHSCOPE_API_KEY=阿里云上获取的apiKey
3.4 对接文本模型
@RestController
@RequestMapping("/api/v1")
public class AlController {
private final ChatClient dashScopeChatClient;
public AlController(ChatClient dashScopeChatClient) {
this.dashScopeChatClient = dashScopeChatClient;
}
/**
* 纯文本聊天接口
* @param query 文本
* @return ai回复内容
*/
@GetMapping("/simple/chat")
public String simpleChat(String query) {
return dashScopeChatClient.prompt(query).call().content();
}
}
3.5 文本加图片输入
@RestController
@RequestMapping("/api/v1")
public class AlController {
private final ChatClient dashScopeChatClient;
public AlController(ChatClient dashScopeChatClient) {
this.dashScopeChatClient = dashScopeChatClient;
}
/**
* 纯文本聊天接口
* @param query 文本
* @return ai回复内容
*/
@GetMapping("/simple/chat")
public String simpleChat(String query) {
return dashScopeChatClient.prompt(query).call().content();
}
/**
* 图片+文本接口
* @param prompt 文本
* @param imageFile 文件
* @param response 响应体
* @return ai回复内容
*/
@PostMapping("/imageRecognition")
public String imageRecognition(
@RequestParam(value = "prompt") String prompt,
@RequestPart(value = "image",required = false) MultipartFile imageFile,
HttpServletResponse response) throws IOException {
if (Objects.isNull(imageFile)) {
return dashScopeChatClient
.prompt(prompt)
.advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, DEFAULT_CHAT_MEMORY_CONVERSATION_ID)
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
.call().content();
}
UserMessage message = buildAlMsg(prompt, imageFile, response);
return dashScopeChatClient.prompt(
new Prompt(message)
).advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, DEFAULT_CHAT_MEMORY_CONVERSATION_ID)
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10)).call().content();
}
/**
* 图片+文本接口
* @param prompt 文本
* @param url 图片资源url
* @return ai回复内容
*/
@PostMapping("/recognition")
public String recognition(
@RequestParam(value = "prompt") String prompt,
@RequestParam(value = "url",required = false) String url) throws IOException {
if (StrUtil.isBlank(url)) {
return dashScopeChatClient
.prompt(prompt)
.advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, DEFAULT_CHAT_MEMORY_CONVERSATION_ID)
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10))
.call().content();
}
Resource resource = convertUrlToResource(url);
// 创建 MimeType 对象
MimeType mimeType = MimeTypeUtils.parseMimeType(Objects.requireNonNull(APPLICATION_OCTET_STREAM));
List<Media> mediaList = List.of(new Media(mimeType, resource));
UserMessage message = new UserMessage(prompt, mediaList);
message.getMetadata().put(DashScopeChatModel.MESSAGE_FORMAT, MessageFormat.IMAGE);
return dashScopeChatClient.prompt(
new Prompt(message)
).advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, DEFAULT_CHAT_MEMORY_CONVERSATION_ID)
.param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10)).call().content();
}
public static Resource convertUrlToResource(String urlString) throws MalformedURLException {
URL url = new URL(urlString);
return new UrlResource(url);
}