随着人工智能技术的发展,越来越多的企业开始利用大模型提升自身产品的智能化水平。阿里巴巴的通义千问大模型作为国内领先的语言模型之一,为企业提供了强大的自然语言处理能力。本文将详细介绍如何在Spring Boot项目中集成通义千问大模型,并通过具体的代码示例展示其实现过程。
一、环境准备
1. 导入依赖
首先,在项目的pom.xml
文件中添加通义千问SDK的依赖:
<!-- https://mvnrepository.com/artifact/com.alibaba/dashscope-sdk-java -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dashscope-sdk-java</artifactId>
<version>the-latest-version</version>
</dependency>
请前往mvnrepository获取最新的版本号。
2. 配置文件
在application.yml
中添加必要的API密钥和提示词配置:
spring:
ai:
api-key: sk-58xxxxxxxxxxxxxxxxx
prompt: 注意,回答结果言简意赅
二、核心组件实现
1. 配置类
创建一个配置类QwenVl
来读取配置文件中的API密钥和提示词:
@Component
public class QwenVl implements InitializingBean {
@Value("${spring.ai.api-key}")
private String apiKey;
@Value("${spring.ai.prompt}")
private String prompt;
public static String QWENVL_API_KEY;
public static String PROMPT;
@Override
public void afterPropertiesSet() {
QWENVL_API_KEY = apiKey;
PROMPT = prompt;
}
}
2. 通用工具类
接下来,编写一个工具类QwenVlUtils
,用于封装与通义千问模型交互的所有功能:
/**
* 通义千问图文识别工具类
*
* @author zk
* @date 2024/8/13
*/
public class QwenVlUtils {
private static final String ERROR_MSG = "该%s文件类型暂不支持AI识别";
/**
* 识别单张图片,返回识别结果
*/
public static String identify(@NotNull String url) throws NoApiKeyException, UploadFileException {
if (url.startsWith("file")) {
return identifyByLocalFile(url);
}
MultiModalConversation conv = new MultiModalConversation();
MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
.content(Arrays.asList(Collections.singletonMap("image", url),
Collections.singletonMap("text", QwenVl.PROMPT))).build();
MultiModalConversationParam param = MultiModalConversationParam.builder()
.model(MultiModalConversation.Models.QWEN_VL_PLUS)
.apiKey(QwenVl.QWENVL_API_KEY)
.message(userMessage)
.build();
MultiModalConversationResult result = conv.call(param);
String msg = (String) result.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text");
System.err.println("qwen-AI-VL 回答结果 result:" + result);
return msg;
}
/**
* 识别本地单张图片,返回识别结果
*/
@SneakyThrows
public static String identifyByLocalFile(@NotNull String url) throws ApiException, NoApiKeyException, UploadFileException {
MultiModalConversation conv = new MultiModalConversation();
MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
.content(Arrays.asList(new HashMap<String, Object>() {{
put("image", url);
}},
new HashMap<String, Object>() {{
put("text", QwenVl.PROMPT);
}})).build();
MultiModalConversationParam param = MultiModalConversationParam.builder()
.model(MultiModalConversation.Models.QWEN_VL_PLUS)
.apiKey(QwenVl.QWENVL_API_KEY)
.message(userMessage)
.build();
Flowable<MultiModalConversationResult> result = conv.streamCall(param);
MultiModalConversationResult last = result.blockingLast();
String msg = (String) last.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text");
System.err.println("qwen-AI-VL 结果 result:" + msg);
// 识别完,删除文件
URL url1 = new URL(url);
String path = url1.getPath();
if (path.startsWith("/")) {
path = path.substring(1);
}
Path filePath = Paths.get(path);
Files.delete(filePath);
return msg;
}
}
其中,除了PROMPT提示词,读者也可以自定义要与模型交互的提问内容,而后和PROMPT拼接到一起即可。其中本地文件上传给模型识别,笔者是通过文件上传到本地,然后通过一些操作得到其需要的资源路径,如: file://D:/images/test.png,最后识别完成后,把这个上传的临时文件进行删除。当然,具体的操作可以随各自开发者的业务要求进行变化。
注意Windows系统下,本地上传需要传入的文件路径:file:///{文件的绝对路径}
示例:file:///home/images/test.png
而Linux或macOS系统下的传入的文件路径:file://{文件的绝对路径}
示例:file:///D:images/test.png。
3. 枚举类
定义一个枚举类QwenVLImageEnum
来存储所有支持的图片格式及其对应的MIME类型:
@Getter
public enum QwenVLImageEnum {
BMP("image/bmp", ".bmp"),
DIB("image/bmp", ".dib"), // 注意:DIB与BMP使用相同的MIME类型
ICNS("image/icns", ".icns"),
ICO("image/x-icon", ".ico"),
JPEG("image/jpeg", ".jfif", ".jpe", ".jpeg", ".jpg"),
JPEG2000("image/jp2", ".j2c", ".j2k", ".jp2", ".jpc", ".jpf", ".jpx"),
PNG("image/png", ".apng", ".png"),
SGI("image/sgi", ".bw", ".rgb", ".rgba", ".sgi"),
TIFF("image/tiff", ".tif", ".tiff"),
WEBP("image/webp", ".webp");
private final String mimeType;
private final String[] extensions;
QwenVLImageEnum(String mimeType, String... extensions) {
this.mimeType = mimeType;
this.extensions = extensions;
}
public static boolean checkExtension(String extension) {
for (QwenVLImageEnum format : values()) {
for (String ext : format.getExtensions()) {
if (ext.equalsIgnoreCase(extension)) {
return true;
}
}
}
return false;
}
}
对于输入的图片,图片文件大小不超过10MB。当然,笔者这里并没有做对图片大小的判断,后续开发者可以自己加上这一块的逻辑。
三、控制层接口
在Spring Boot应用中添加一个RESTful API接口,用于接收图片链接并调用QwenVlUtils
进行识别:
@RestController
@RequestMapping("/ai")
public class AiController {
/**
* 通过AI识别
*
* @param url 图片URL
*/
@GetMapping("/identify")
public ResponseEntity<String> identify(@RequestParam String url) {
try {
String res = QwenVlUtils.identify(url);
return ResponseEntity.ok(res);
} catch (Exception e) {
return ResponseEntity.badRequest().body("识别失败,上传的临时文件或已删除,请重新上传");
}
}
}
四、最后
通过上述步骤,我们不仅实现了Spring Boot项目与通义千问大模型的集成,还展示了如何通过简单的API接口调用来实现图片识别功能。这为开发者提供了快速接入AI技术的途径,同时也为企业的智能化转型提供了有力支持。未来,随着技术的不断进步,相信会有更多类似的工具和服务涌现出来,进一步推动AI技术在各行各业的应用与发展。