• spring整合openAI大模型之Spring AI


    「章节总览」
     
          【ollama部署本地大模型 https://blog.csdn.net/weixin_45404884/article/details/139747748】

    一、SpringAI简介

    1.什么是SpringAI

    Spring AI 是一个面向 AI 工程的应用框架,其目标是将 Spring 生态系统的可移植性和模块化设计等设计原则应用到 AI 领域,并推动将 POJO 作为应用的构建块应用于 AI 领域。
    简单地说,就是不再需要我们再去封装各种各样的类或者方法,直接用spring框架内置的方法,和大模型进行通信

    官网地址https://spring.io/projects/spring-ai

    2.SpringAI支持的大模型类型

    (1)聊天模型

    • OpenAI
    • Azure Open AI
    • Amazon Bedrock
    • Cohere’s Command
    • AI21 Labs’ Jurassic-2
    • Meta’s LLama 2
    • Amazon’s Titan
    • Google Vertex AI Palm
    • Google Gemini
    • HuggingFace - access thousands of models, including those from Meta such as Llama2
    • Ollama - run AI models on your local machine
    • MistralAI

    (2)文本到图像模型

    • OpenAI with DALL-E
    • StabilityAI

    (3)转录(音频到文本)模型

    • OpenAI

    (4)嵌入模型

    • OpenAI
    • Azure OpenAI
    • Ollama
    • ONNX
    • PostgresML
    • Bedrock Cohere
    • Bedrock Titan
    • Google VertexAI
    • Mistal AI

    (5)矢量数据库

    • Azure Vector Search
    • Chroma
    • Milvus
    • Neo4j
    • PostgreSQL/PGVector
    • PineCone
    • Redis
    • Weaviate
    • Qdrant

    3.SpringAI版本

    目前只出了一个版本1.0.0-M1
    请添加图片描述

    二、SpringAI框架使用,对接OpenAI

    1.环境信息

    • Maven: apache-maven-3.9.6
    • springBoot: 3.3.0
    • JAVA:JDK17

    2.初始化

    server url里面如果是阿里云的链接,给换掉,因为阿里云的构建springboot里面选不了AI模块
    jdk一定要选17
    请添加图片描述
    引入springweb和openAI两个依赖模块就可以
    请添加图片描述

    3.配置文件

    (1)application.yml

    这里面你要去百度上找,或者自己去买openai的api-key,贴在api-key后面就可以,
    base-url可以通过代理方式去调用,后面会讲到。

    spring:
      application:
        name: springAI
      ai:
        openai:
          api-key: 
          base-url: https://api.chatanywhere.tech  #国内中转访问
    

    (2)pom文件

    
    <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.0modelVersion>
        <parent>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-parentartifactId>
            <version>3.3.0version>
            <relativePath/> 
        parent>
        <groupId>com.kdxgroupId>
        <artifactId>springAIartifactId>
        <version>0.0.1-SNAPSHOTversion>
        <name>springAIname>
        <description>Demo project for Spring Bootdescription>
        <properties>
            <java.version>17java.version>
            <spring-ai.version>1.0.0-M1spring-ai.version>
        properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            dependency>
            <dependency>
                <groupId>org.springframework.aigroupId>
                <artifactId>spring-ai-openai-spring-boot-starterartifactId>
            dependency>
    
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-testartifactId>
                <scope>testscope>
            dependency>
        dependencies>
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.aigroupId>
                    <artifactId>spring-ai-bomartifactId>
                    <version>${spring-ai.version}version>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
            dependencies>
        dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.pluginsgroupId>
                    <artifactId>maven-compiler-pluginartifactId>
                    <version>3.8.1version>
                    <configuration>
                        <compilerVersion>17compilerVersion>
                        <source>16source>
                        <target>16target>
                        <encoding>UTF-8encoding>
                        
                        <parameters>trueparameters>
                        <skip>trueskip>
                    configuration>
                plugin>
            plugins>
    
    
        build>
        <repositories>
            <repository>
                <id>spring-milestonesid>
                <name>Spring Milestonesname>
                <url>https://repo.spring.io/milestoneurl>
                <snapshots>
                    <enabled>falseenabled>
                snapshots>
            repository>
        repositories>
    
    project>
    
    

    4.聊天代码测试

    新建Controller类,通过接口调用测试

    (1)聊天接口

        @Autowired
        private ChatClient chatClient;
    
    //交流
        @RequestMapping("/chat")
        public String generation(@RequestParam(value = "message", defaultValue = "讲个笑话") String message) {
    
            //prompt:提示词
            return this.chatClient.prompt()
                    //用户信息
                    .user(message)
                    //请求大模型
                    .call()
                    //返回文本
                    .content();
        }
    

    启动项目访问接口测试
    请添加图片描述

    (2)流式响应

    流式响应的意思就是,调用接口一次响应太多文字给浏览器需要等很久,使用流式响应真正的像GPT

        @Autowired
        private ChatClient chatClient;
    //流式响应
        @RequestMapping(value = "/stream", produces = "text/html;charset=UTF-8")
        public Flux<String> stream(@RequestParam(value = "message", defaultValue = "讲个笑话") String message) {
            Flux<String> output = chatClient.prompt()
                    .user(message)
                    //流式调用
                    .stream()
                    .content();
            return output;
        }
    

    启动项目访问接口测试
    请添加图片描述

    (3)chatModel api

    chatModel API比ChatClient 更灵活,但是底层还是用的ChatClient ,可以去参考一下chatModel的API,可以设置很多参数,因为下面设置的是gpt-4,api-key必须要和版本对应

        @Autowired(required = false)
        private ChatModel chatModel;
        //chatModel api
        @RequestMapping(value = "/ChatResponse", produces = "text/html;charset=UTF-8")
        public String ChatResponse(@RequestParam(value = "message") String message) {
            ChatResponse response = chatModel.call(new Prompt(
                    message,
                    OpenAiChatOptions.builder()
                            //选择gpt版本
                            .withModel("gpt-4-32k")
                            .withTemperature(0.4f)
                            .build()
            ));
            return response.getResult().getOutput().getContent();
        }
    

    (4)文字生成图片

    它也是只有特定的模型才能使用,需要对应的api-key

        @Autowired(required = false)
        private OpenAiImageModel openaiImageModel;
    	//文生图
        @RequestMapping(value = "/openaiImageModel", produces = "text/html;charset=UTF-8")
        public String openaiImageModel(@RequestParam(value = "message") String message) {
            ImageResponse response = openaiImageModel.call(
                    new ImagePrompt(message,
                            OpenAiImageOptions.builder()
                                    //图片质量
                                    .withQuality("hd")
                                    //生成几张
                                    .withN(1)
                                    //尺寸
                                    .withHeight(1024)
                                    .withWidth(1024).build())
    
            );
            return response.getResult().getOutput().getUrl();
        }
    

    (5)文字生成语音

    它也是只有特定的模型才能使用,需要对应的api-key

    	//文生语音
        @RequestMapping(value = "/writeByte", produces = "text/html;charset=UTF-8")
        public String writeByte(@RequestParam(value = "message") String message) {
            OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder()
                    .withModel(OpenAiAudioApi.TtsModel.TTS_1.value)
                    .withVoice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY)
                    .withResponseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
                    .withSpeed(1.0f)
                    .build();
    
            SpeechPrompt speechPrompt = new SpeechPrompt(message, speechOptions);
            SpeechResponse response = openAiAudioSpeechModel.call(speechPrompt);
    
            byte[] body = response.getResult().getOutput();
            try {
                writeByte(body,"D:\\Project");
            } catch (Exception e) {
                System.out.println(e);
            }
            return "ok";
        }
    
        public static void writeByte(byte[] audioBytes, String outputFilePath) throws IOException {
            FileOutputStream fileOutputStream = new FileOutputStream(outputFilePath + "111.mp3");
            fileOutputStream.write(audioBytes);
            fileOutputStream.close();
        }
    

    (6)预先定义角色

    意思就是在调用聊天模型的时候,预先给他设定好一个角色
    比如调用聊天接口,他是怎么知道他是java开发工程师的呢?就是通过预先定义角色
    请添加图片描述
    新建一个AIConfig 配置类,通过一段文字在springboot启动时,预先给他定义他的角色

    @Configuration
    public class AIConfig {
    
        //角色预设
        @Bean
        ChatClient chatClient(ChatClient.Builder builder) {
            return builder.defaultSystem("你现在不是chatGPT了,我希望你以一个java工程师的身份来和我对话,你是一个在卡迪熊公司工作的java开发工程师,你叫小鹏!")
                    .build();
        }
    }
    

    (7)functionCall功能

    目的是可以让其他的应用程序结合GPT使用,可以更精准的返回信息,下面的apply方法就可以调用别的程序,收集信息。

    • 在AIConfig的配置类中加入代码,这里的Description注解就是触发该Function方法的关键字
        @Bean
        @Description("有多少人")
        LocationNameFunction LocationNameFunction() {
            return new LocationNameFunction();
        }
    
    • 然后再新建一个LocationNameFunction类,通过关键字"有多少人"触发动作,执行类中apply方法
    package com.kdx.springai.functions;
    
    
    
    import java.util.Objects;
    import java.util.function.Function;
    
    
    public class LocationNameFunction implements Function<LocationNameFunction.Request, LocationNameFunction.Response> {
    
        @Override
        public Response apply(Request request) {
            if (Objects.isNull(request.location) || Objects.isNull(request.name)) {
                return new Response("缺少参数");
            }
    
            return new Response("有10个人");
        }
    
        //接收提取关键信息
    
        public record Request(
                String name,
                String location) {
            @Override
            public String name() {
                return name;
            }
    
            @Override
            public String location() {
                return location;
            }
        }
    
        //最终响应给gpt
        public record Response(String message) {
        }
    
    }
    
    
    • 定义接口
    	//functionCall
        @RequestMapping(value = "/functionCall", produces = "text/html;charset=UTF-8")
        public String functionCall(@RequestParam(value = "message") String message) {
            OpenAiChatOptions aiChatOptions = OpenAiChatOptions.builder()
                    //设置实现了function接口的bean名称
                    .withFunction("LocationNameFunction")
                    .withModel(OpenAiApi.ChatModel.GPT_3_5_TURBO)
                    .build();
            ChatResponse response = chatModel.call(new Prompt(message, aiChatOptions));
            return response.getResult().getOutput().getContent();
        }
    
    • 测试
      请添加图片描述

    (8)如何通过代理的方式访问接口

    现在是通过访问国内中转代理的方式,访问GPT的接口,但是怎么直接访问他的接口呢?
    可以通过在启动类中加入代理信息。

        public static void main(String[] args) {
            System.setProperty("proxyType", "4");   //类型
            System.setProperty("proxyPort", "7890");    //端口
            System.setProperty("proxyHost", "127.0.0.1");   //ip
            System.setProperty("proxySet", "true");
            SpringApplication.run(SpringAiApplication.class, args);
        }
    

    这个时候yaml文件的url就可以配置https://api.chatanywhere.cn,直接访问了

    ------------------------------------------------------需要源码,可以留言------------------------------------------------------
    源码地址:https://github.com/ximinsideyuezhang/springAI

  • 相关阅读:
    vue3中的isRef toRef toRefs readonly
    华为浏览器风险提示 - 解决方案
    ChatGPT OpenAI 行政HR会计财务办公自动化操作
    图论篇--代码随想录算法训练营第五十六天打卡| 108. 冗余连接,109. 冗余连接II
    Maven3.6.2安装详细教程
    Qt信号槽与多线程的关系
    生成式 AI 如何释放开发者的生产力?
    MCUXpresso IDE下高度灵活的FreeMarker链接文件模板机制
    JVM GC垃圾回收
    GFS分布式文件系统
  • 原文地址:https://blog.csdn.net/weixin_45404884/article/details/139743783