ToB企服应用市场:ToB评测及商务社交产业平台

标题: SpringAI调用OpenAI Demo [打印本页]

作者: 诗林    时间: 2024-6-20 22:43
标题: SpringAI调用OpenAI Demo
Spring AI



在maven的setting.xml
   <mirror>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <mirrorOf>spring-milestones</mirrorOf>
            <url>https://repo.spring.io/milestone</url>
        </mirror>
  这里以调用GPT4o为例



厥后为了测试JDK8是否可用  将版本调整成了2.7.2   结果不能使用


因国内无法直接访问  按了个nginx代理


  1. server {
  2.                  #HTTPS的默认访问端口443。
  3.                  #如果未在此处配置HTTPS的默认访问端口,可能会造成Nginx无法启动。
  4.                  listen 443 ssl;
  5.                  
  6.                  #填写证书绑定的域名
  7.                  server_name xxxx xxxxxx;
  8.          
  9.                  #填写证书文件绝对路径
  10.                  ssl_certificate /etc/letsencrypt/live/xxx.com/fullchain.pem;
  11.                  #填写证书私钥文件绝对路径
  12.                  ssl_certificate_key /etc/letsencrypt/live/xxxx.com/privkey.pem;
  13.          
  14.                  ssl_session_cache shared:SSL:1m;
  15.                  ssl_session_timeout 5m;
  16.                  
  17.                  #自定义设置使用的TLS协议的类型以及加密套件(以下为配置示例,请您自行评估是否需要配置)
  18.                  #TLS协议版本越高,HTTPS通信的安全性越高,但是相较于低版本TLS协议,高版本TLS协议对浏览器的兼容性较差。
  19.                  ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  20.                  #ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
  21.                  #表示优先使用服务端加密套件。默认开启
  22.                  ssl_prefer_server_ciphers on;
  23.                  location /v1/{
  24.             chunked_transfer_encoding off;
  25.             proxy_cache off;
  26.             proxy_buffering off;
  27.             proxy_redirect off;
  28.             proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  29.             proxy_ssl_server_name on;
  30.             proxy_http_version 1.1;
  31.             proxy_set_header Host api.openai.com;
  32.                         proxy_set_header X-Real-IP $server_addr;
  33.                         proxy_set_header X-Forwarded-For $server_addr;
  34.                         proxy_set_header X-Real-Port $server_port;
  35.             proxy_set_header Connection '';
  36.                         proxy_pass https://api.openai.com/;
  37.         }
复制代码




配置ChatClient另外种方式




特定的对话风格或角色,通常发起详细定义你盼望模子如何回应,然后在你的应用中相应地构建提示   其实就是对话之前






你也可以为每一个接口设置单独的预定义角色  比方



以流的方式返回


这个在postMan中不好提现

可以直接在浏览器

可以看到它是以流的方式返回的,但是乱码

 





除了使用nginx转发   还可以用本地代理   只要在应用启动前配置好就行




关于ChatClient和ChatModel
ChatClient:较为通用 
ChatModel:设置模子独有功能


模子选择





下面使用ChatModel演示调用
可以参数中指定, 也可以application.properties中指定



流式



演示文生图功能








文生语音

下面做法是有题目的,由于你保存到resources目次下的话   项目是打包之后运行的  因此你第一次运行保存之后是读不到的  要读只能重新启动,这里只是演示  就先如许了



重启应用


关于语音转文本







关于多模态(意思就是你可以要发文本,要发图片,要发语音)



意思只能用GPT4或4o模子才气用多模态







以上的代码
  1. package com.example.springai.controller;
  2. import org.springframework.ai.chat.client.ChatClient;
  3. import org.springframework.ai.chat.messages.Media;
  4. import org.springframework.ai.chat.messages.UserMessage;
  5. import org.springframework.ai.chat.model.ChatResponse;
  6. import org.springframework.ai.chat.prompt.Prompt;
  7. import org.springframework.ai.image.ImagePrompt;
  8. import org.springframework.ai.image.ImageResponse;
  9. import org.springframework.ai.openai.*;
  10. import org.springframework.ai.openai.api.OpenAiApi;
  11. import org.springframework.ai.openai.api.OpenAiAudioApi;
  12. import org.springframework.ai.openai.audio.speech.SpeechPrompt;
  13. import org.springframework.ai.openai.audio.speech.SpeechResponse;
  14. import org.springframework.ai.openai.audio.transcription.AudioTranscriptionPrompt;
  15. import org.springframework.ai.openai.audio.transcription.AudioTranscriptionResponse;
  16. import org.springframework.beans.factory.annotation.Autowired;
  17. import org.springframework.core.io.ClassPathResource;
  18. import org.springframework.http.HttpStatus;
  19. import org.springframework.http.ResponseEntity;
  20. import org.springframework.util.MimeTypeUtils;
  21. import org.springframework.web.bind.annotation.GetMapping;
  22. import org.springframework.web.bind.annotation.RestController;
  23. import reactor.core.publisher.Flux;
  24. import java.io.IOException;
  25. import java.nio.file.Files;
  26. import java.nio.file.Path;
  27. import java.nio.file.Paths;
  28. import java.util.List;
  29. /**
  30. * @author hrui
  31. * @date 2024/6/8 2:19
  32. */
  33. @RestController
  34. public class HelloGPT {
  35.     @Autowired
  36.     private ChatClient chatClient;
  37. //    public HelloGPT(ChatClient.Builder chatClientBuilder) {
  38. //        this.chatClient=chatClientBuilder.build();
  39. //    }
  40.     @GetMapping("/helloai")
  41.     public Object generate(String userInput) {
  42.         System.out.println("userInput:"+userInput);
  43.         return chatClient.prompt()//提示词
  44.                 .user(userInput)//用户输入
  45.                 //.system("You are a helpful assistant.")
  46.                 .call()//调用
  47.                 .content();//返回文本
  48.     }
  49.     @GetMapping(value = "/helloai2",produces = "text/html;charset=UTF-8")
  50.     public Flux<String> generate2(String userInput) {
  51.         Flux<String> output = chatClient.prompt()
  52.                 .user(userInput)
  53.                 .stream()
  54.                 .content();
  55.         return output;
  56.     }
  57.     @Autowired
  58.     private OpenAiChatModel chatModel;//ChatModel可以自动装配  不需要@Bean
  59.     @GetMapping("/helloai3")
  60.     public Object generate3(String userInput) {
  61. //        ChatResponse response = chatModel.call(
  62. //                new Prompt(
  63. //                        "Generate the names of 5 famous pirates.",//这个其实好比用户消息
  64. //                        OpenAiChatOptions.builder()
  65. //                                .withModel("gpt-4-32k")
  66. //                                .withTemperature(0.8F)
  67. //                                .build()
  68. //                ));
  69.         ChatResponse response = chatModel.call(
  70.                 new Prompt(
  71.                         userInput,//底层封装成new UserMessage(userInput)
  72.                         OpenAiChatOptions.builder()
  73.                                 .withModel("gpt-4-turbo")
  74.                                 .withTemperature(0.8F)
  75.                                 .build()
  76.                 ));
  77.         return response.getResult().getOutput().getContent();
  78.     }
  79.     @GetMapping("/helloai4")
  80.     public Flux<ChatResponse> generate4(String userInput) {
  81.         System.out.println("userInput:"+userInput);
  82.         Flux<ChatResponse> stream = chatModel.stream(
  83.                 new Prompt(
  84.                         userInput//底层封装成new UserMessage(userInput)
  85.                 ));
  86.         return stream;
  87.     }
  88.     @Autowired
  89.     private OpenAiImageModel openAiImageModel;
  90.     @GetMapping("/helloai6")
  91.     public Object generate6(String userInput) {
  92.         ImageResponse response = openAiImageModel.call(
  93.                 new ImagePrompt(userInput,
  94.                         OpenAiImageOptions.builder()
  95.                                 //设置图片清晰度
  96.                                 .withQuality("hd")
  97.                                 .withModel("dall-e-3")//默认就是这个
  98.                                 .withN(1)//生成几张图片
  99.                                 //默认高度和宽度
  100.                                 .withHeight(1024)
  101.                                 .withWidth(1024).build())
  102.         );
  103.         return response.getResult().getOutput().getUrl();
  104.     }
  105. //    @Autowired
  106. //    private OpenAiAudioTranscriptionModel openAiAudioTranscriptionModel;
  107.     @Autowired
  108.     private OpenAiAudioSpeechModel openAiAudioSpeechModel;
  109.     @GetMapping("/helloai7")
  110.     public Object generate7(String userInput) {
  111.         OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder()
  112.                 //用的模型
  113.                 .withModel(OpenAiAudioApi.TtsModel.TTS_1.value)
  114.                 //设置人声
  115.                 .withVoice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY)
  116.                 .withResponseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
  117.                 .withSpeed(1.0f)//合成语音的速度 0.0最慢  1.0最快
  118.                 .build();
  119.         SpeechPrompt speechPrompt = new SpeechPrompt(userInput, speechOptions);
  120.         SpeechResponse response = openAiAudioSpeechModel.call(speechPrompt);
  121.         byte[] output = response.getResult().getOutput();
  122.         try {
  123.             // 指定文件名,这里以当前时间戳命名以避免重名
  124.             String filename = "audio_" + System.currentTimeMillis() + ".mp3";
  125.             // 指定保存路径
  126.             Path path = Paths.get("src/main/resources/static/" + filename);
  127.             // 写入文件
  128.             Files.write(path, output);
  129.             // 获取可访问的URL,假设你的服务运行在 localhost:8080
  130.             String fileUrl = "http://localhost:8082/" + filename;
  131.             return ResponseEntity.ok(fileUrl);
  132.         } catch (Exception e) {
  133.             e.printStackTrace();
  134.             return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error saving file");
  135.         }
  136.     }
  137.     @Autowired
  138.     private OpenAiAudioTranscriptionModel openAiTranscriptionModel;
  139.     @GetMapping("/helloai8")
  140.     public Object generate8() {
  141.         //语音翻译的可选配置
  142.         var transcriptionOptions = OpenAiAudioTranscriptionOptions.builder()
  143.                 .withResponseFormat(OpenAiAudioApi.TranscriptResponseFormat.TEXT)
  144.                 //温度  0f不需要创造力,语音是什么,翻译什么
  145.                 .withTemperature(0f)
  146.                 .build();
  147.         var audioFile=new ClassPathResource("hello.m4a");
  148.         //var audioFile = new FileSystemResource("/path/to/your/resource/speech/jfk.flac");
  149.         AudioTranscriptionPrompt transcriptionRequest = new AudioTranscriptionPrompt(audioFile, transcriptionOptions);
  150.         AudioTranscriptionResponse response = openAiTranscriptionModel.call(transcriptionRequest);
  151.         return response.getResult().getOutput();
  152.     }
  153.     @GetMapping("/helloai9")
  154.     public Object generate9() throws IOException {
  155.         //图片二进制流
  156.         byte[] imageData=new ClassPathResource("1717865484569.png").getContentAsByteArray();
  157.         //用户信息
  158.         var userMessage=new UserMessage("这是什么", List.of(new Media(MimeTypeUtils.IMAGE_PNG,imageData)));
  159.         OpenAiChatOptions build = OpenAiChatOptions.builder()
  160.                 .withModel(OpenAiApi.ChatModel.GPT_4_O.getValue()).build();
  161.         ChatResponse response=chatModel.call(new Prompt(userMessage,build));
  162.         return response.getResult().getOutput().getContent();
  163.     }
  164. }
复制代码




关于Function call    应对大模子无法获取实时信息的毛病
比如说,我现在问  本日杭州火车东站的客流量是多少,如许GPT肯定无法回答
那么需要怎么办呢   我们可以调用第三方接口得到信息 再告知GPT  然后GPT回答题目



大概表明
比方 我问   杭州有多少生齿
这类题目,GPT是无法回答的,当然现在GPT会查阅相关资料回答,假设
这句话里有  location和count两个关键        
Function Call的作用是    当问GPT一个类似题目之后,GPT用Function Call往返调我们的应用并携带关键信息 location和count信息,我们的应用去查数据库也好,去调用第三方接口也好,再告诉GPT   那么GPT就可以回答这个题目了

当GPT携带参数过来的时间会调用Function.apply(){}这个方法,那么我们在这个方法里写我们自己的逻辑  可以查数据库,可以调用第三方接口

创建一个实现Function接口的类


如果报错








全部代码
  1. package com.example.springai.controller;
  2. import org.springframework.ai.chat.model.ChatResponse;
  3. import org.springframework.ai.chat.prompt.Prompt;
  4. import org.springframework.ai.openai.OpenAiChatModel;
  5. import org.springframework.ai.openai.OpenAiChatOptions;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.web.bind.annotation.GetMapping;
  8. import org.springframework.web.bind.annotation.RequestParam;
  9. import org.springframework.web.bind.annotation.RestController;
  10. /**
  11. * @author hrui
  12. * @date 2024/6/9 1:16
  13. */
  14. @RestController
  15. public class FunctionCallController {
  16.     @Autowired
  17.     private OpenAiChatModel chatModel;
  18.     @GetMapping("/functionCall")
  19.     public Object functionCall(@RequestParam(value = "message",defaultValue = "杭州有多少个名字叫韩妹妹的人") String message) {
  20.         OpenAiChatOptions aiChatOptions=OpenAiChatOptions.builder()
  21.                 //设置实现了Function接口的beanName
  22.         .withFunction("locationCount")
  23.         .withModel("gpt-3.5-turbo")
  24.         .build();
  25.         ChatResponse response=chatModel.call(new Prompt(message,aiChatOptions));
  26.         //Flux<ChatResponse> stream = chatModel.stream(new Prompt(message, aiChatOptions));
  27.         return response.getResult().getOutput().getContent();
  28.     }
  29. }
复制代码

  1. package com.example.springai.controller;
  2. import org.springframework.ai.chat.client.ChatClient;
  3. import org.springframework.ai.chat.messages.Media;
  4. import org.springframework.ai.chat.messages.UserMessage;
  5. import org.springframework.ai.chat.model.ChatResponse;
  6. import org.springframework.ai.chat.prompt.Prompt;
  7. import org.springframework.ai.image.ImagePrompt;
  8. import org.springframework.ai.image.ImageResponse;
  9. import org.springframework.ai.openai.*;
  10. import org.springframework.ai.openai.api.OpenAiApi;
  11. import org.springframework.ai.openai.api.OpenAiAudioApi;
  12. import org.springframework.ai.openai.audio.speech.SpeechPrompt;
  13. import org.springframework.ai.openai.audio.speech.SpeechResponse;
  14. import org.springframework.ai.openai.audio.transcription.AudioTranscriptionPrompt;
  15. import org.springframework.ai.openai.audio.transcription.AudioTranscriptionResponse;
  16. import org.springframework.beans.factory.annotation.Autowired;
  17. import org.springframework.core.io.ClassPathResource;
  18. import org.springframework.http.HttpStatus;
  19. import org.springframework.http.ResponseEntity;
  20. import org.springframework.util.MimeTypeUtils;
  21. import org.springframework.web.bind.annotation.GetMapping;
  22. import org.springframework.web.bind.annotation.RestController;
  23. import reactor.core.publisher.Flux;
  24. import java.io.IOException;
  25. import java.nio.file.Files;
  26. import java.nio.file.Path;
  27. import java.nio.file.Paths;
  28. import java.util.List;
  29. /**
  30. * @author hrui
  31. * @date 2024/6/8 2:19
  32. */
  33. @RestController
  34. public class HelloGPT {
  35.     @Autowired
  36.     private ChatClient chatClient;
  37. //    public HelloGPT(ChatClient.Builder chatClientBuilder) {
  38. //        this.chatClient=chatClientBuilder.build();
  39. //    }
  40.     @GetMapping("/helloai")
  41.     public Object generate(String userInput) {
  42.         System.out.println("userInput:"+userInput);
  43.         return chatClient.prompt()//提示词
  44.                 .user(userInput)//用户输入
  45.                 //.system("You are a helpful assistant.")
  46.                 .call()//调用
  47.                 .content();//返回文本
  48.     }
  49.     @GetMapping(value = "/helloai2",produces = "text/html;charset=UTF-8")
  50.     public Flux<String> generate2(String userInput) {
  51.         Flux<String> output = chatClient.prompt()
  52.                 .user(userInput)
  53.                 .stream()
  54.                 .content();
  55.         return output;
  56.     }
  57.     @Autowired
  58.     private OpenAiChatModel chatModel;//ChatModel可以自动装配  不需要@Bean
  59.     @GetMapping("/helloai3")
  60.     public Object generate3(String userInput) {
  61. //        ChatResponse response = chatModel.call(
  62. //                new Prompt(
  63. //                        "Generate the names of 5 famous pirates.",//这个其实好比用户消息
  64. //                        OpenAiChatOptions.builder()
  65. //                                .withModel("gpt-4-32k")
  66. //                                .withTemperature(0.8F)
  67. //                                .build()
  68. //                ));
  69.         ChatResponse response = chatModel.call(
  70.                 new Prompt(
  71.                         userInput,//底层封装成new UserMessage(userInput)
  72.                         OpenAiChatOptions.builder()
  73.                                 .withModel("gpt-4-turbo")
  74.                                 .withTemperature(0.8F)
  75.                                 .build()
  76.                 ));
  77.         return response.getResult().getOutput().getContent();
  78.     }
  79.     @GetMapping("/helloai4")
  80.     public Flux<ChatResponse> generate4(String userInput) {
  81.         System.out.println("userInput:"+userInput);
  82.         Flux<ChatResponse> stream = chatModel.stream(
  83.                 new Prompt(
  84.                         userInput//底层封装成new UserMessage(userInput)
  85.                 ));
  86.         return stream;
  87.     }
  88.     @Autowired
  89.     private OpenAiImageModel openAiImageModel;
  90.     @GetMapping("/helloai6")
  91.     public Object generate6(String userInput) {
  92.         ImageResponse response = openAiImageModel.call(
  93.                 new ImagePrompt(userInput,
  94.                         OpenAiImageOptions.builder()
  95.                                 //设置图片清晰度
  96.                                 .withQuality("hd")
  97.                                 .withModel("dall-e-3")//默认就是这个
  98.                                 .withN(1)//生成几张图片
  99.                                 //默认高度和宽度
  100.                                 .withHeight(1024)
  101.                                 .withWidth(1024).build())
  102.         );
  103.         return response.getResult().getOutput().getUrl();
  104.     }
  105. //    @Autowired
  106. //    private OpenAiAudioTranscriptionModel openAiAudioTranscriptionModel;
  107.     @Autowired
  108.     private OpenAiAudioSpeechModel openAiAudioSpeechModel;
  109.     @GetMapping("/helloai7")
  110.     public Object generate7(String userInput) {
  111.         OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder()
  112.                 //用的模型
  113.                 .withModel(OpenAiAudioApi.TtsModel.TTS_1.value)
  114.                 //设置人声
  115.                 .withVoice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY)
  116.                 .withResponseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
  117.                 .withSpeed(1.0f)//合成语音的速度 0.0最慢  1.0最快
  118.                 .build();
  119.         SpeechPrompt speechPrompt = new SpeechPrompt(userInput, speechOptions);
  120.         SpeechResponse response = openAiAudioSpeechModel.call(speechPrompt);
  121.         byte[] output = response.getResult().getOutput();
  122.         try {
  123.             // 指定文件名,这里以当前时间戳命名以避免重名
  124.             String filename = "audio_" + System.currentTimeMillis() + ".mp3";
  125.             // 指定保存路径
  126.             Path path = Paths.get("src/main/resources/static/" + filename);
  127.             // 写入文件
  128.             Files.write(path, output);
  129.             // 获取可访问的URL,假设你的服务运行在 localhost:8080
  130.             String fileUrl = "http://localhost:8082/" + filename;
  131.             return ResponseEntity.ok(fileUrl);
  132.         } catch (Exception e) {
  133.             e.printStackTrace();
  134.             return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error saving file");
  135.         }
  136.     }
  137.     @Autowired
  138.     private OpenAiAudioTranscriptionModel openAiTranscriptionModel;
  139.     @GetMapping("/helloai8")
  140.     public Object generate8() {
  141.         //语音翻译的可选配置
  142.         var transcriptionOptions = OpenAiAudioTranscriptionOptions.builder()
  143.                 .withResponseFormat(OpenAiAudioApi.TranscriptResponseFormat.TEXT)
  144.                 //温度  0f不需要创造力,语音是什么,翻译什么
  145.                 .withTemperature(0f)
  146.                 .build();
  147.         var audioFile=new ClassPathResource("hello.m4a");
  148.         //var audioFile = new FileSystemResource("/path/to/your/resource/speech/jfk.flac");
  149.         AudioTranscriptionPrompt transcriptionRequest = new AudioTranscriptionPrompt(audioFile, transcriptionOptions);
  150.         AudioTranscriptionResponse response = openAiTranscriptionModel.call(transcriptionRequest);
  151.         return response.getResult().getOutput();
  152.     }
  153.     @GetMapping("/helloai9")
  154.     public Object generate9() throws IOException {
  155.         //图片二进制流
  156.         byte[] imageData=new ClassPathResource("1717865484569.png").getContentAsByteArray();
  157.         //用户信息
  158.         var userMessage=new UserMessage("这是什么", List.of(new Media(MimeTypeUtils.IMAGE_PNG,imageData)));
  159.         OpenAiChatOptions build = OpenAiChatOptions.builder()
  160.                 .withModel(OpenAiApi.ChatModel.GPT_4_O.getValue()).build();
  161.         ChatResponse response=chatModel.call(new Prompt(userMessage,build));
  162.         return response.getResult().getOutput().getContent();
  163.     }
  164. }
复制代码


  1. package com.example.springai.function;
  2. import org.springframework.context.annotation.Description;
  3. import org.springframework.stereotype.Component;
  4. import org.springframework.util.StringUtils;
  5. import java.util.function.Function;
  6. /**
  7. * @author hrui
  8. * @date 2024/6/9 1:46
  9. */
  10. @Component("locationCount")
  11. @Description("某个地方有多少个名字某某的人")
  12. public class LocationCount implements Function<LocationCount.Request, LocationCount.Response> {
  13.     @Override//接收GPT提取后的信息(自动调用该方法)
  14.     public Response apply(Request request) {
  15.         //好的(聪明的模型)当location和name确实时候根本不会来调用该方法
  16.         if(!StringUtils.hasLength(request.location)||!StringUtils.hasLength(request.name)){
  17.             return new Response("参数缺失,无需Function-Call,正常响应就可以");
  18.         }
  19.         //如果有值 调用数据库或者第三方接口
  20.         return new Response("只有唯一强调唯一1个");
  21.     }
  22.     //密封类(好比有了@Data作用) 接收GPT信息
  23.     public record Request(String name, String location) {}
  24.     //密封类,最终响应GPT信息
  25.     public record Response(String message) {}
  26. }
复制代码
  1. package com.example.springai;
  2. import org.springframework.ai.chat.client.ChatClient;
  3. import org.springframework.ai.chat.model.ChatModel;
  4. import org.springframework.boot.SpringApplication;
  5. import org.springframework.boot.autoconfigure.SpringBootApplication;
  6. import org.springframework.context.annotation.Bean;
  7. @SpringBootApplication
  8. public class SpringaiApplication {
  9.     @Bean
  10.     public ChatClient chatClient(ChatClient.Builder chatClientBuilder){
  11.         return chatClientBuilder.defaultSystem("你现在不是ChatGPT,也不是人工智能AI,现在开始你是一个正常人类,你的名字叫hrui")
  12.                 .build();
  13.     }
  14.     public static void main(String[] args) {
  15.         //System.setProperty("proxyType","4");
  16.         System.setProperty("proxyHost","127.0.0.1");
  17.         System.setProperty("proxyPort","7897");
  18.         //System.setProperty("proxySet","true");
  19.         SpringApplication.run(SpringaiApplication.class, args);
  20.     }
  21. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4