文章目录
什么是 Spring Cloud Alibaba AI
原始的Spring AI并没有国内相关大模型的接入,对国内开发者不太友好。
总的来说,Spring Cloud Alibaba AI 目前基于Spring AI 0.8.1版本 API 完成通义系列大模型的接入。
在当前最新版本中,Spring Cloud Alibaba AI 主要完成了几种常见生成式模型的适配,包括对话、文生图、文生语音等,开发者可以使用 Spring Cloud Alibaba AI 开发基于通义的聊天、图片或语音生成 AI 应用,框架还提供 OutParser、Prompt Template、Stuff 等实用能力。
动手体验 Spring Cloud Alibaba AI
使用Ai的jdk最低版本17,使用老版本的需要重新下载jdk。
https://www.oracle.com/cn/java/technologies/downloads/#java17
jdk17的Windows版本链接已提供,只需要下载解压即可以使用。
1.创建maven项目 导入以下依赖
<dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-ai</artifactId></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2023.0.1.0</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
因为 Spring AI 还没有正式发布到 maven 仓库,所以需要添加仓库配置项
<!-- 因为 Spring AI 还没有正式发布到 maven 仓库,所以需要添加此配置项 目前 maven 仓库为假的。
issue:https://github.com/spring-projects/spring-ai/issues/537
--><repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository><repository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><releases><enabled>false</enabled></releases></repository></repositories>
2.在Resource包中创建application.yml文件,并配置api-key
在正式开始体验之前,需要申请到模型的 api-key。申请地址:https://help.aliyun.com/zh/dashscope/developer-reference/activate-dashscope-and-create-an-api-key
申请完只有30天的免费试用。
spring:cloud:ai:tongyi:# api-key setting:api-key: sk-xxxxxxxxxxxxxxxxxxx
3.创建Controller和service开始使用
聊天对话、图片生成、语音生成体验
Controller代码
@RestController@CrossOrigin@RequestMapping("/ai")publicclassTongYiController{@ResourceprivateTongYiService tongYiService;/**
* 聊天对话体验
* @param msg
* @return
*/@GetMapping("/getMsg")publicStringgetMessage(@RequestParam(value ="msg",defaultValue ="讲一个笑话")String msg){return tongYiService.completion(msg);}/**
* 体验生成图片
* @param msg
* @return
*/@GetMapping("/getImage")publicResponseEntity<byte[]>getImage(@RequestParam(value ="msg",defaultValue ="动漫女主图片")String msg){ResponseEntity<byte[]> responseEntity = tongYiService.genImg(msg);return responseEntity;}/**
* 流式客户端形式
* @param message
* @return
*/@GetMapping("/stream")publicMap<String,String>streamCompletion(@RequestParam(value ="message", defaultValue ="请告诉我西红柿炖牛腩怎么做?")String message){return tongYiService.streamCompletion(message);}/**
* 生成语音
* @param prompt
* @return
*/@GetMapping("/audio")publicStringgenAudio(@RequestParam(value ="prompt",
defaultValue ="你好,Spring Cloud Alibaba AI 框架!")String prompt){return tongYiService.genAudio(prompt);}}
service代码
publicinterfaceTongYiService{/**
* 基本问答
*/Stringcompletion(String message);/**
* 文生图
*/ResponseEntity<byte[]>genImg(String imgPrompt);/**
* 语音合成
*/StringgenAudio(String text);/**
* 流式回答
* @param message
* @return
*/Map<String,String>streamCompletion(String message);}
service实现类代码(只能使用的构造器注入)推荐使用client封装一个工具类,而不是写在service里面。
@ServicepublicclassTongYiSimpleServiceImplimplementsTongYiService{/**
* 自动注入ChatClient、imageClient、StreamingChatClient,屏蔽模型调用细节
*/privatefinalChatClient chatClient;privatefinalImageClient imageClient;privatefinalStreamingChatClient streamingChatClient;@AutowiredpublicTongYiSimpleServiceImpl(ChatClient chatClient,StreamingChatClient streamingChatClient,ImageClient imageClient){this.chatClient = chatClient;this.imageClient = imageClient;this.streamingChatClient = streamingChatClient;}/**
* 具体实现:
*/@OverridepublicStringcompletion(String message){Prompt prompt =newPrompt(newUserMessage(message));return chatClient.call(prompt).getResult().getOutput().getContent();}@OverridepublicResponseEntity<byte[]>genImg(String imgPrompt){ImagePrompt imagePrompt =newImagePrompt(imgPrompt);ImageResponse response = imageClient.call(imagePrompt);//处理生成的图片base64码String b64Json = response.getResult().getOutput().getB64Json();//将b64转换成图片返回给前端byte[] decode =Base64.getDecoder().decode(b64Json);HttpHeaders httpHeaders =newHttpHeaders();
httpHeaders.setContentType(MediaType.IMAGE_PNG);returnnewResponseEntity<>(decode,httpHeaders,HttpStatus.OK);}@OverridepublicMap<String,String>streamCompletion(String message){StringBuilder fullContent =newStringBuilder();
streamingChatClient.stream(newPrompt(message)).flatMap(chatResponse ->Flux.fromIterable(chatResponse.getResults())).map(content -> content.getOutput().getContent()).doOnNext(fullContent::append).last().map(lastContent ->Map.of(message, fullContent.toString())).block();returnMap.of(message, fullContent.toString());}@OverridepublicStringgenAudio(String text){var resWAV = speechClient.call(text);returnsave(resWAV,SpeechSynthesisAudioFormat.WAV.getValue());}/**
* 将语音保存到本地的方法
*
* @param audio
* @param type
* @return
*/privateStringsave(ByteBuffer audio,String type){String currentPath =System.getProperty("user.dir");LocalDateTime now =LocalDateTime.now();DateTimeFormatter formatter =DateTimeFormatter.ofPattern("MM-dd-HH-mm-ss");String fileName = currentPath +File.separator + now.format(formatter)+"."+ type;File file =newFile(fileName);try(FileOutputStream fos =newFileOutputStream(file)){
fos.write(audio.array());}catch(Exception e){thrownewRuntimeException(e);}return fileName;}}
启动项目,浏览器输入地址测试
1.localhost:8080/ai/getMsg聊天对话测试
localhost:8080/ai/stream采用流式客户端方式测试(对话形式)
2.getImage (1024×1024)生成图片测试
- localhost:8080/ai/audio生成语音测试,返回路径(默认项目路径)
封装工具类
有了之前的实现,我们封装工具类就很方便
@ComponentpublicclassCloudAiUtil{privatefinalChatClient chatClient;//图片客户端privatefinalImageClient imageClient;//语言客户端privatefinalSpeechClient speechClient;// stream 流式客户端privatefinalStreamingChatClient streamingChatClient;@AutowiredpublicCloudAiUtil(ChatClient chatClient,StreamingChatClient streamingChatClient,ImageClient imageClient,SpeechClient speechClient){this.chatClient = chatClient;this.imageClient = imageClient;this.streamingChatClient = streamingChatClient;this.speechClient = speechClient;}publicStringcompletion(String message){Prompt prompt =newPrompt(newUserMessage(message));return chatClient.call(prompt).getResult().getOutput().getContent();}publicResponseEntity<byte[]>genImg(String imgPrompt){ImagePrompt imagePrompt =newImagePrompt(imgPrompt);ImageResponse response = imageClient.call(imagePrompt);//处理生成的图片base64码String b64Json = response.getResult().getOutput().getB64Json();//将b64转换成图片返回给前端byte[] decode =Base64.getDecoder().decode(b64Json);HttpHeaders httpHeaders =newHttpHeaders();
httpHeaders.setContentType(MediaType.IMAGE_PNG);returnnewResponseEntity<>(decode, httpHeaders,HttpStatus.OK);}publicMap<String,String>streamCompletion(String message){StringBuilder fullContent =newStringBuilder();
streamingChatClient.stream(newPrompt(message)).flatMap(chatResponse ->Flux.fromIterable(chatResponse.getResults())).map(content -> content.getOutput().getContent()).doOnNext(fullContent::append).last().map(lastContent ->Map.of(message, fullContent.toString())).block();returnMap.of(message, fullContent.toString());}publicStringgenAudio(String text){var resWAV = speechClient.call(text);returnsave(resWAV,SpeechSynthesisAudioFormat.WAV.getValue());}privateStringsave(ByteBuffer audio,String type){String currentPath =System.getProperty("user.dir");LocalDateTime now =LocalDateTime.now();DateTimeFormatter formatter =DateTimeFormatter.ofPattern("MM-dd-HH-mm-ss");String fileName = currentPath +File.separator + now.format(formatter)+"."+ type;File file =newFile(fileName);try(FileOutputStream fos =newFileOutputStream(file)){
fos.write(audio.array());}catch(Exception e){thrownewRuntimeException(e);}return fileName;}}
这样我们service代码就很简介,同时这个工具类可以在任意service使用
@ServicepublicclassTongYiSimpleServiceImplimplementsTongYiService{@ResourceprivateCloudAiUtil cloudAiUtil;@OverridepublicStringcompletion(String message){return cloudAiUtil.completion(message);}}
版权归原作者 码农OvO 所有, 如有侵权,请联系我们删除。