【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型)

这篇具有很好参考价值的文章主要介绍了【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 🎉🎉欢迎光临🎉🎉

🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀

🌟特别推荐给大家我的最新专栏《Spring 狂野之旅:底层原理高级进阶》 🚀

本专栏纯属为爱发电永久免费!!!

这是苏泽的个人主页可以看到我其他的内容哦👇👇

努力的苏泽http://suzee.blog.csdn.net/

大家好这里还是苏泽,关于我的Spring狂野之旅已经出了5期,基本都是从Spring的底层源码去读它,不仅能学会使用方法又能理解其工作机制以及原理,我认为这是非常美妙的一件事,这几期反响都还行,

于是这一章专门出一期运用前面所讲过的知识  自己从0开始搭建一个后台程序  能够对接市面上绝大多数的ai对话api(不同公司的具体的鉴权方法你们找官网文档copy就行了)

那么正片开始

目录

大家好这里还是苏泽,关于我的Spring狂野之旅已经出了5期,基本都是从Spring的底层源码去读它,不仅能学会使用方法又能理解其工作机制以及原理,我认为这是非常美妙的一件事,这几期反响都还行,

于是这一章专门出一期运用前面所讲过的知识  自己从0开始搭建一个后台程序  能够对接市面上绝大多数的ai对话api(不同公司的具体的鉴权方法你们找官网文档copy就行了)

从零开始 搭建一个Spring boot程序

确保你已经安装了Java开发工具(JDK)。你可以在命令行中输入java -version来验证是否已安装Java,并确保版本符合Spring Boot的要求。​编辑安装的部分我就不演示了默认大家已经装好配置好环境

创建一个新的Spring Boot项目。你可以使用​编辑新建一个Springboot项目​编辑

手动添加的依赖:

统一封装一下返回结果

开干:

1.构建好机器人需要的常量:

下面的部分就是存放对应模型的url和Serverid以及秘钥 这些是根据你们要选定的模型去改的

存历史记录 以及查询历史记录的方法:

下面是获取ai对话的回答内容的部分 (这里是有线程优化的处理的)

这段代码实现了一个基于Spring和WebSocket的异步问答系统。主要的逻辑如下:

在并发场景下,这样优化的优势在于:

这一段代码是可以应用在其他使用WebSocket连接ai的业务上的

是基于WebSocket的与远程服务进行问答的功能。主要的逻辑如下:

最后 就是鉴权方法 这个内容 作为api的调用者  我们是不需要理解的(并不影响使用),当然如果对网络协议以及加密感兴趣的伙伴可以细看 我就直接放上来了,因为每家公司的鉴权方法都不一样,而且文档中会直接给出鉴权方法 直接复制到代码里面就可以的

实现效果 

如果朋友对定向提示词工程有兴趣的话可以专门出一期这个模块的博客

提示词工程主要的优势在于以下:


从零开始 搭建一个Spring boot程序

  1. 确保你已经安装了Java开发工具(JDK)。你可以在命令行中输入java -version来验证是否已安装Java,并确保版本符合Spring Boot的要求。


    【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型),java Spring后端项目实战 所遇问题及解决方案,《Spring 狂野之旅:底层原理高级进阶》 🚀,spring boot,后端,java,ai
    安装的部分我就不演示了默认大家已经装好配置好环境
     

  2. 创建一个新的Spring Boot项目。你可以使用
    【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型),java Spring后端项目实战 所遇问题及解决方案,《Spring 狂野之旅:底层原理高级进阶》 🚀,spring boot,后端,java,ai

    新建一个Springboot项目
    【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型),java Spring后端项目实战 所遇问题及解决方案,《Spring 狂野之旅:底层原理高级进阶》 🚀,spring boot,后端,java,ai

我这里选了Springboot版本2.6.13  这个倒是不会有太大问题根据自己项目来就行 

【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型),java Spring后端项目实战 所遇问题及解决方案,《Spring 狂野之旅:底层原理高级进阶》 🚀,spring boot,后端,java,ai

旁边这些依赖自己有需要的就加 我这边不用这里的东西就不选了 

【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型),java Spring后端项目实战 所遇问题及解决方案,《Spring 狂野之旅:底层原理高级进阶》 🚀,spring boot,后端,java,ai

然后出来  他就帮我们建立好了 这些依赖跟框架了 可以在pom文件里看到

【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型),java Spring后端项目实战 所遇问题及解决方案,《Spring 狂野之旅:底层原理高级进阶》 🚀,spring boot,后端,java,ai

手动添加的依赖:

在Maven里输入:

<!-- Hutool -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-json</artifactId>
    <version>5.7.10</version>
</dependency>

<!-- Alibaba FastJSON -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.78</version>
</dependency>

<!-- Google Gson -->
<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.9</version>
</dependency>

<!-- OkHttp -->
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.9.1</version>
</dependency>

<!-- Spring Data Redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <version>2.5.4</version>
</dependency>

<!-- Spring Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.5.4</version>
</dependency>

然后我们新建一个class文件
在里面加入导包:
 

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;

配置了那么多。终于可以开始项目了...

统一封装一下返回结果

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
/*/**
 *@author suze
 *@date 2023-10-25
 *@time 15:19
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
    private Boolean success;
    private String errorMsg;
    private Object data;
    private Long total;

    public static Result ok(){
        return new Result(true, null, null, null);
    }
    public static Result ok(Object data){
        return new Result(true, null, data, null);
    }
    public static Result ok(List<?> data, Long total){
        return new Result(true, null, data, total);
    }
    public static Result fail(String errorMsg){
        return new Result(false, errorMsg, null, null);
    }
//    public static Result fail(int  errorCode, String errorMsg){
//        return new Result(false, errorMsg, null, null);
//    }
}

然后用到的地方就导入Result的包即可

import TopOne.dto.Result;

 

开干:

为了方便演示我把Controller和Server放在一个文件里 大家根据自己需要去调整

1.构建好机器人需要的常量:

public static final Gson gson = new Gson();

    // 个性化参数
    private String userId;
    private Boolean wsCloseFlag;

    private static Boolean totalFlag=true; // 控制提示用户是否输入

    public  List<RoleContent> historyList=new ArrayList<>(); // 这个是临时的 每次用完在线程中要注销他


    //写一个结构专门来存机器的回答
    public static class BotText{
        String content=" ";
    }
    public static BotText botText=new BotText();


    //告诉控制器输出完没有
    public static Boolean outputFlag=true;
    private String botContent = "";

    //返回的json结果拆解
    class JsonParse {
        Header header;
        Payload payload;
    }

    class Header {
        int code;
        int status;
        String sid;
    }

    class Payload {
        Choices choices;
    }

    class Choices {
        List<Text> text;
    }

    class Text {
        String role;
        String content;
    }
    class RoleContent{

        String role;
        String content;

        public String getRole() {
            return role;
        }

        public void setRole(String role) {
            this.role = role;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }
    }

下面的部分就是存放对应模型的url和Serverid以及秘钥 这些是根据你们要选定的模型去改的

public static final String hostUrl = "";
    public static final String appid = "";
    public static final String apiSecret = "";
    public static final String apiKey = "";

存历史记录 以及查询历史记录的方法:

我这里做的缓存是2h  用的是Redis,一开始构建项目的时候可以用一个简单的Map来代替Redis  自行替换掉Redis部分代码即可

// 将对话历史存储到 Redis
    public void saveHistory(String  history,String id) {
        // 设置有效期为 2 小时
        stringRedisTemplate.opsForValue().set("id:" + id + ":history", history, 2, TimeUnit.HOURS);
    }
    @RequestMapping("/SaveHistory")
    public Result SaveHistory(@RequestParam("userId") String id, @RequestBody String history)  {
        saveHistory(history,id);
        return Result.ok("保存历史记录成功有效时间:2h");
    }
    // 从 Redis 中获取对话历史
    public List<RoleContent> getHistory(String userId) {
        String historyStr = stringRedisTemplate.opsForValue().get("id:" + userId + ":history");
        if (historyStr==null){
            return null;
        }
        return JSONUtil.toList(JSONUtil.parseArray(historyStr), RoleContent.class);
    }
    //用于获取历史聊天记录
    @RequestMapping("/history")
    public Result history(@RequestParam("userId") String id)  {

        String history = stringRedisTemplate.opsForValue().get("id:" + id + ":history");
        if (history == null) {
            return Result.fail("没有找到历史记录");
        }

        JSONArray jsonObject = JSON.parseArray(history);
//        String jsonString = JSON.toJSONString(jsonObject);
        return Result.ok(jsonObject);
    }

下面是获取ai对话的回答内容的部分 (这里是有线程优化的处理的)

public static String totalAnswer=""; // 大模型的答案汇总

    // 可以写原始问题
    public static  String NewQuestion = "";
    public WordUtils wordUtils=new WordUtils();
    //线程池
    public ThreadPoolExecutor pool = new ThreadPoolExecutor(13, 13, 1,
            TimeUnit.MINUTES, new ArrayBlockingQueue<>(6),
            Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
    @RequestMapping("/get")
    public DeferredResult<Result> get(@RequestParam("question") String question, @RequestParam("id") String id) {
        //创建了一个DeferredResult<Result>对象,并将其返回给前端。在异步任务执行完毕后,
        // 通过调用deferredResult.setResult(result)方法将结果设置到DeferredResult对象中,从而实现异步返回结果给前端。
        DeferredResult<Result> deferredResult = new DeferredResult<>();
        CompletableFuture.supplyAsync(() -> {
            try {
                callable callable = new callable(question, id);
                String answer = callable.call();
                Result result = Result.ok(answer);
                
                return result;
            } catch (Exception e) {
                Result result = Result.fail(e.getMessage());
                return result;
            }
        }, pool).whenComplete((result, throwable) -> {
            if (throwable != null) {
                result = Result.fail(throwable.getMessage());
                deferredResult.setResult(result);

            } else {
                deferredResult.setResult(result);

            }
        });
        return deferredResult;
    }
    public class callable implements Callable<String>{
        private  String  id;
        private String question;
        public callable(String question,String id) {
            //这里处理一下userId的长度 因为讯飞那边限制了
            if (id.length() >= 30) {
                id= id.substring(0, 30);
            }
            this.question = question;
            this.id=id;
        }
        @Override
        public String call() throws Exception {
            String answer =main(question,id);
            //System.out.println(answer);
            answer = JSONUtil.toJsonStr(answer);
            System.out.println("call");
            botText.content="";//清空
            //缓存历史对话  时效两小时
            //String historyStr = JSONUtil.toJsonStr();
            //stringRedisTemplate.opsForValue().set("id:"+id+":history", historyStr,2,TimeUnit.HOURS);
            return answer;
        }
    }
    // 主函数
    public String main(String newQuestion,String userid) throws Exception {
        // 个性化参数入口,如果是并发使用,可以在这里模拟
        System.out.println(totalFlag);
        if(totalFlag){
            totalFlag=false;
            NewQuestion=newQuestion;
            // 构建鉴权url
            String authUrl = getAuthUrl(hostUrl, apiKey, apiSecret);
            OkHttpClient client = new OkHttpClient.Builder().build();
            String url = authUrl.toString().replace("http://", "ws://").replace("https://", "wss://");
         
            Request request = new Request.Builder().url(url).build();
            totalAnswer="";
//                    WebSocket webSocket = client.newWebSocket(request, new BigModelNew(i + "",false));
            //这里创建了大模型的新对象  实际上那些发送请求获取答案的操作都是在这个线程中做的

            BigModelNew bigModelNew = null;
            if (getHistory(userid)!=null){
                bigModelNew=new BigModelNew(userid, false,getHistory(userid),stringRedisTemplate);
            }
            else {
                bigModelNew=new BigModelNew(userid, false,historyList,stringRedisTemplate);
            }
            // 等待 WebSocket 的 run() 方法执行完毕
            int maxWaitTime = 10000; // 最大等待时间,单位:毫秒
            int currentWaitTime = 0; // 当前已等待的时间,单位:毫秒
            int waitInterval = 1000;// 每次等待的时间间隔,单位:毫秒
            WebSocket webSocket = client.newWebSocket(request, bigModelNew);
            System.out.println(maxWaitTime);
            while (currentWaitTime < maxWaitTime) {
                if (bigModelNew.getBotContent().equals("")) {
                    // run() 方法还未执行完毕,可以进行一些其他操作或等待一段时间
                    Thread.sleep(waitInterval);
                    System.out.println("正在执行线程"+Thread.currentThread().getName()+"...等待时间还剩:"+(maxWaitTime-currentWaitTime));
                    currentWaitTime += waitInterval;
                } else {
                    // run() 方法已执行完毕,获取 bot.content 值并进行后续操作
                    //System.out.println("run执行完毕");
                    return bigModelNew.getBotContent();
                    //System.out.println(botText.content);
                    // ...
                }
            }
        }
        totalFlag=true;
        return "网络开了点小差 试试重新发送你的消息吧";
    }
    // 构造函数
    public BigModelNew(@Value("${userId}") String userId
            ,@Value("${wsCloseFlag}") Boolean wsCloseFlag
            ,@Value("${HistoryList}")List<RoleContent> HistoryList
            ,@Value("${stringRedisTemplate}") StringRedisTemplate stringRedisTemplate) {
        this.userId = userId;
        this.wsCloseFlag = wsCloseFlag;
        this.historyList=HistoryList;
        this.stringRedisTemplate = stringRedisTemplate;
    }

这段代码实现了一个基于Spring和WebSocket的异步问答系统。主要的逻辑如下:

  1. get()方法中,接收前端传递的问题和id参数,并创建一个DeferredResult<Result>对象,用于异步返回结果给前端。

  2. 通过CompletableFuture.supplyAsync()方法创建一个异步任务,该任务会在一个线程池中执行。

  3. 异步任务的具体逻辑在callable类的call()方法中实现。在该方法中,调用main()方法进行问题回答,并将结果转换为JSON格式。

  4. 异步任务执行完毕后,通过deferredResult.setResult(result)方法将结果设置到DeferredResult对象中,实现异步返回结果给前端。

  5. main()方法中,判断是否是并发场景下的第一个请求。如果是第一个请求,则创建一个WebSocket连接,并等待run()方法执行完毕。

  6. run()方法中,通过WebSocket与远程服务进行通信,获取问题的回答。

  7. 在并发场景下,如果有多个请求同时到达,只有第一个请求会创建WebSocket连接,后续的请求会等待第一个请求的回答结果,并共享同一个totalAnswer

在并发场景下,这样优化的优势在于:

  1. 使用线程池和异步任务可以提高并发处理能力,减少请求的等待时间。通过异步任务,可以将耗时的操作(如远程服务调用)放在后台线程中执行,而不会阻塞主线程。

  2. 使用DeferredResult对象可以实现异步返回结果给前端。每个请求都会得到一个独立的DeferredResult对象,通过设置结果到该对象中,可以实现异步返回给前端。

  3. 在并发场景下,只有第一个请求会创建WebSocket连接,后续的请求会等待第一个请求的回答结果。这样可以减少对远程服务的重复请求,节省资源和提高性能。

然后我们把外面的调用的功能构建好了 接下来就是WebSocket内部当中 重写的具体方法 下面是重写部分的方法:
 

//一个很关键的函数 用于得到botContent
    public String getBotContent() {
        return botContent;
    }


    public boolean canAddHistory(){  // 由于历史记录最大上线1.2W左右,需要判断是能能加入历史

        int history_length=0;
        for(RoleContent temp:historyList){
            history_length=history_length+temp.content.length();
        }
        if(history_length>12000){
            historyList=new ArrayList<>();
            return false;
        }else{
            return true;
        }

    }

    // 线程来发送音频与参数
    class MyThread extends Thread {
        private WebSocket webSocket;
        private  String newAnswer;
        public MyThread(WebSocket webSocket) {
            this.webSocket = webSocket;
        }

        public void run() {
            try {
                JSONObject requestJson=new JSONObject();
                JSONObject header=new JSONObject();  // header参数
                header.put("app_id",appid);
                header.put("uid",userId);//这里放userId
                JSONObject parameter=new JSONObject(); // parameter参数
                JSONObject chat=new JSONObject();
                chat.put("domain","generalv3");
                chat.put("temperature",0.6);
                chat.put("max_tokens",8192);
                parameter.put("chat",chat);
                JSONObject payload=new JSONObject(); // payload参数
                JSONObject message=new JSONObject();
                JSONArray text=new JSONArray();
                // 历史问题获取
                if(historyList.size()>0){
                    for(RoleContent tempRoleContent:historyList){
                        text.add(JSON.toJSON(tempRoleContent));
                    }
                }
                // 最新问题
                RoleContent roleContent=new RoleContent();
                roleContent.role="user";
                roleContent.content=NewQuestion;
                text.add(JSON.toJSON(roleContent));
//                System.err.println("text:");
                historyList.add(roleContent);
//                historyList.forEach(System.out::println);
                //saveHistory(historyList);//在这里就把历史记录存到Redis了 就可以清空该线程的历史记录List了
                //historyList.clear();
                message.put("text",text);
                payload.put("message",message);
                requestJson.put("header",header);
                requestJson.put("parameter",parameter);
                requestJson.put("payload",payload);
//                  System.err.println(requestJson); // 可以打印看每次的传参明细
                webSocket.send(requestJson.toString());
                // 等待服务端返回完毕后关闭
                while (true) {
                    // System.err.println(wsCloseFlag + "---");
                    Thread.sleep(200);
                    if (wsCloseFlag) {
                        break;
                    }
                }
                webSocket.close(1000, "");
//                System.out.println("answer"+botText.content);
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                botContent=botText.content;
            }
        }
    }

    @Override
    public void onOpen(WebSocket webSocket, Response response) {
        super.onOpen(webSocket, response);
        //System.out.print("AI:");
        MyThread myThread = new MyThread(webSocket);
        myThread.start();
    }

    @Override
    public void onMessage(WebSocket webSocket, String text) {
        // System.out.println(userId + "用来区分那个用户的结果" + text);
        JsonParse myJsonParse = gson.fromJson(text, JsonParse.class);
        //System.out.println("AI:" + gson.toJson(myJsonParse.payload));
        if (myJsonParse.header.code != 0) {
            System.out.println("发生错误,错误码为:" + myJsonParse.header.code);
            System.out.println("本次请求的sid为:" + myJsonParse.header.sid);
            webSocket.close(1000, "");
        }
        List<Text> textList = myJsonParse.payload.choices.text;

        for (Text temp : textList) {
            //System.out.println("这里存了机器的话"+temp.content);
            botText.content=botText.content+temp.content;//这里存机器的话
            totalAnswer=totalAnswer+temp.content;
        }
        //System.out.println("answeraaaa:"+botText.content);//这里能够打印 但是打印很多次说明他调用了很多次
//        botText.content=totalAnswer;
        if (myJsonParse.header.status == 2) {
            // 可以关闭连接,释放资源
//            System.out.println();
//            System.out.println("*************************************************************************************");
            if(canAddHistory()){
                RoleContent roleContent=new RoleContent();
                roleContent.setRole("assistant");
                roleContent.setContent(totalAnswer);
                historyList.add(roleContent);
                //System.out.println("OnMessage:"+historyList.toString());
                //String jsonString = JSON.toJSONString(historyList, SerializerFeature.PrettyFormat);
                //history.text=jsonString;//这里已经把历史记录给保存了
                //在这里答案已经输出完了,就应该outputFinished = true;
//                output=botText.content;
//                myHistory=history.text;
                outputFlag=true;
                System.out.println("AI:answer"+botText.content);
            }else{
                RoleContent roleContent=new RoleContent();
                roleContent.setRole("assistant");
                roleContent.setContent(totalAnswer);
                historyList.add(roleContent);
            }
            //saveHistory(historyList);//在这里就把历史记录存到Redis了 就可以清空该线程的历史记录List了
            historyList.clear();
            wsCloseFlag = true;//只有等消息传过来了  才能够结束
            totalFlag=true;
        }

    }

    @Override
    public void onFailure(WebSocket webSocket, Throwable t, Response response) {
        super.onFailure(webSocket, t, response);
        if (null != response) {
            int code = response.code();
                System.out.println("onFailure code:" + code);
            try {
                System.out.println("onFailure body:" + response.body().string());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            if (101 != code) {
                System.out.println("connection failed");
                System.exit(0);
            }
        }
    }

这一段代码是可以应用在其他使用WebSocket连接ai的业务上的

是基于WebSocket的与远程服务进行问答的功能。主要的逻辑如下:

  1. MyThread类是一个继承自Thread的线程类,用于发送问答请求和接收回答。在run()方法中,首先构建请求的JSON对象,包括头部参数、参数和载荷参数。然后通过WebSocket发送该JSON对象。接着,在一个循环中等待服务端返回结果,并将返回的结果拼接到botText.contenttotalAnswer中。最后,关闭WebSocket连接,并将botText.content赋值给botContent

  2. onOpen()方法在WebSocket连接建立时被调用。在该方法中,创建一个MyThread对象并启动线程。

  3. onMessage()方法在接收到WebSocket消息时被调用。该方法首先解析收到的消息,并判断是否存在错误。如果没有错误,则将回答文本拼接到botText.contenttotalAnswer中,并根据返回的状态码进行相应的处理。如果状态码为2,表示回答已经完整返回,此时可以关闭连接并进行一些后续处理,如将回答文本添加到历史记录中。

  4. onFailure()方法在WebSocket连接失败时被调用。在该方法中,可以根据失败的原因进行相应的处理。

最后 就是鉴权方法 这个内容 作为api的调用者  我们是不需要理解的(并不影响使用),当然如果对网络协议以及加密感兴趣的伙伴可以细看 我就直接放上来了,因为每家公司的鉴权方法都不一样,而且文档中会直接给出鉴权方法 直接复制到代码里面就可以的

// 鉴权方法
    public static String getAuthUrl(String hostUrl, String apiKey, String apiSecret) throws Exception {
        URL url = new URL(hostUrl);
        // 时间
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());
        // 拼接
        String preStr = "host: " + url.getHost() + "\n" +
                "date: " + date + "\n" +
                "GET " + url.getPath() + " HTTP/1.1";
//        System.err.println(preStr);
        // SHA256加密
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "hmacsha256");
        mac.init(spec);
        byte[] hexDigits = mac.doFinal(preStr.getBytes(StandardCharsets.UTF_8));

        // Base64加密
        String sha = Base64.getEncoder().encodeToString(hexDigits);
//        System.err.println(sha);
        // 拼接
        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);
        // 拼接地址
        HttpUrl httpUrl = Objects.requireNonNull(HttpUrl.parse("https://" + url.getHost() + url.getPath())).newBuilder().//
                addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(StandardCharsets.UTF_8))).//
                addQueryParameter("date", date).//
                addQueryParameter("host", url.getHost()).//
                build();

//        System.err.println(httpUrl.toString());
        return httpUrl.toString();
    }

实现效果 

跟一个搞小程序的朋友借了个模板 套了一下前端 目前在小程序端实现了

响应的内容:

【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型),java Spring后端项目实战 所遇问题及解决方案,《Spring 狂野之旅:底层原理高级进阶》 🚀,spring boot,后端,java,ai

这是获取聊天记录的响应:

【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型),java Spring后端项目实战 所遇问题及解决方案,《Spring 狂野之旅:底层原理高级进阶》 🚀,spring boot,后端,java,ai

具体的业务我还做了提示词工程,让ai具备一点定向场景的倾向了,就像如下

具体的业务截图回应效果

【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型),java Spring后端项目实战 所遇问题及解决方案,《Spring 狂野之旅:底层原理高级进阶》 🚀,spring boot,后端,java,ai

如果朋友对定向提示词工程有兴趣的话可以专门出一期这个模块的博客

提示词工程主要的优势在于以下:

  1. 提高问答准确性:通过给用户提供定向场景的提示词,可以引导用户在特定领域或场景下提问。这样做可以减少模糊或不相关的问题,从而提高问答的准确性。提示词可以限制用户的问题范围,使得AI能够更好地理解用户的意图并给出相关的回答。

  2. 加速问题解决:定向场景的提示词工程可以帮助用户快速定位到他们感兴趣的领域或问题类型,并提供相关的问题模板或关键词。这样可以节省用户在描述问题上的时间和精力,使得问题能够更快地得到解答,提高问题解决的效率。

  3. 提升用户体验:通过为用户提供定向场景的提示词,可以使用户感到更加舒适和自信。用户知道他们在与AI进行交互时所处的场景,并且可以根据提示词的指引进行提问。这种引导性的交互方式可以减少用户的迷茫和犹豫,提升用户与AI的交互体验。

  4. 简化系统配置:定向场景的提示词工程可以帮助系统管理员或开发人员更好地配置和管理问答系统。通过定义和组织不同的场景和相关的提示词,可以使系统的配置更加直观和可控。管理员可以根据实际需求进行提示词的调整和更新,以适应不同的应用场景。

有兴趣的小伙伴可以先关注一下我  下一期出的话我会发粉丝通告哦文章来源地址https://www.toymoban.com/news/detail-826757.html

到了这里,关于【Spring boot实战】Springboot+对话ai模型整体框架+高并发线程机制处理优化+提示词工程效果展示(按照框架自己修改可对接市面上百分之99的模型)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Boot Testing: 使用springboot-test提供的测试框架来实现自动化测试

    作者:禅与计算机程序设计艺术 软件测试是在开发过程中不可缺少的一环。单元测试、集成测试、功能测试等都是为了保证系统的质量而进行的测试活动。单元测试主要验证各个模块(类、方法)在各种情况下是否正常工作;集成测试则是将不同模块组合起来看是否可以正常

    2024年02月07日
    浏览(21)
  • SpringBoot + Vue前后端分离项目实战 || 三:Spring Boot后端与Vue前端连接

    系列文章: SpringBoot + Vue前后端分离项目实战 || 一:Vue前端设计 SpringBoot + Vue前后端分离项目实战 || 二:Spring Boot后端与数据库连接 SpringBoot + Vue前后端分离项目实战 || 三:Spring Boot后端与Vue前端连接 SpringBoot + Vue前后端分离项目实战 || 四:用户管理功能实现 SpringBoot + Vue前后

    2024年02月12日
    浏览(32)
  • SpringBoot + Vue前后端分离项目实战 || 二:Spring Boot后端与数据库连接

    系列文章: SpringBoot + Vue前后端分离项目实战 || 一:Vue前端设计 SpringBoot + Vue前后端分离项目实战 || 二:Spring Boot后端与数据库连接 SpringBoot + Vue前后端分离项目实战 || 三:Spring Boot后端与Vue前端连接 SpringBoot + Vue前后端分离项目实战 || 四:用户管理功能实现 SpringBoot + Vue前后

    2024年02月11日
    浏览(35)
  • 【AI项目实战】某语言模型-stable diffusion-vits-cqhttp 实现能对话能语音能绘画的Q群机器人

    好久没写文章了,终于想起来我有个博客账号系列。。 项目已开源在github上。 文章已滤敏,一切涉及语言模型名字的内容都以某语言模型代替 提示:AI绘画部分建议6G显存以上。 用于接收群友消息,并回复消息。 基于这种对话式的语言模型,可以对用户的聊天进行响应。

    2024年02月10日
    浏览(20)
  • 【AI实战】大语言模型(LLM)有多强?还需要做传统NLP任务吗(分词、词性标注、NER、情感分类、知识图谱、多伦对话管理等)

    大语言模型(LLM)是指使用大量文本数据训练的深度学习模型,可以生成自然语言文本或理解语言文本的含义。大语言模型可以处理多种自然语言任务,如文本分类、问答、对话等,是通向人工智能的一条重要途径。来自百度百科 发展历史 2020年9月,OpenAI授权微软使用GPT-3模

    2024年02月10日
    浏览(15)
  • Springboot实战之spring-boot-starter-data-elasticsearch搭建ES搜索接口

    本教程是本人亲自实战的,然后运行起来的全部步骤。 环境 Elasticsearch 7.15.2 Kibana 7.15.2 springboot 2.6.4 以及对应的spring-boot-starter-web和spring-boot-starter-data-elasticsearch fastjson 1.2.97 安装好Elasticsearch7.15.2以及对应的Kibana。 去Springboot Start 新建项目 使用 devtools 创建 number_of_shards 数据分

    2023年04月08日
    浏览(21)
  • 【AI实战】大模型 LLM 部署推理框架的 vLLM 应用

    vLLM is a fast and easy-to-use library for LLM inference and serving. vLLM 速度很快: State-of-the-art serving throughput Efficient management of attention key and value memory with PagedAttention Continuous batching of incoming requests Optimized CUDA kernels vLLM灵活且易于使用: Seamless integration with popular HuggingFace models High-throughput

    2024年02月04日
    浏览(16)
  • SpringBoot 插件 spring-boot-maven-plugin 原理,以及SpringBoo工程部署的 jar 包瘦身实战

    我们直接使用 maven package (maven自带的package打包功能),打包Jar包的时候,不会将该项目所依赖的Jar包一起打进去,在使用 java -jar 命令启动项目时会报错,项目无法正常启动。这个时候,我们就可以考虑引用 spring-boot-maven-plugin 插件来为项目打Jar包。 maven项目的pom.xml中,添

    2024年02月06日
    浏览(15)
  • Spring AI 来了,打造Java生态大模型应用开发新框架!

    尽管 Python 长期主导 AI 大模型应用开发领域,但 Java 并未熄火!Spring AI 来了,正式告别实验期,迈向广泛应用新阶段!这意味着 Spring 生态体系的广大开发者,迎来 AI 大模型应用开发的新里程。 Spring AI 是一个 AI 工程师的应用框架,它提供了一个友好的 API 和开发 AI 应用的抽

    2024年04月12日
    浏览(23)
  • 定时任务特辑 | Quartz、xxl-job、elastic-job、Cron四个定时任务框架对比,和Spring Boot集成实战

    专栏集锦,大佬们可以收藏以备不时之需: Spring Cloud 专栏: Python 专栏: Redis 专栏: TensorFlow 专栏: Logback 专栏: 量子计算: 量子计算 | 解密著名量子算法Shor算法和Grover算法 AI机器学习实战: AI机器学习实战 | 使用 Python 和 scikit-learn 库进行情感分析 AI机器学习 | 基于lib

    2024年02月05日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包