AI 对话完善【人工智能】

AI 对话【人工智能】

  • 前言
  • 版权
  • 开源
  • 推荐
  • AI 对话
    • v0版本:基础
    • v1版本:对话
      • 数据表
      • tag.js
      • TagController
    • v2版本:回复中
      • textarea.js
      • ChatController
    • v3版本:流式输出
      • chatLast.js
      • ChatController
    • v4版本:多轮对话
      • QianfanUtil
      • ChatController
    • v5:其他修改
      • 前端样式:跳转到最后一个消息
      • 前端样式:Message保留空白符
      • 前端样式:最新回复保留空白符
  • 最后

前言

2024-4-7 15:04:07

以下内容源自《【人工智能】》
仅供学习交流使用

版权

禁止其他平台发布时删除以下此话
本文首次发布于CSDN平台
作者是CSDN@日星月云
博客主页是https://jsss-1.blog.csdn.net
禁止其他平台发布时删除以上此话

开源

日星月云 / AI对话完善版

jsss-1/aichat

推荐

百度智能云+SpringBoot=AI对话【人工智能】

对话Chat-千帆大模型平台

AI 对话

以下版本除了最简单的AI对话,还完善了一下功能。

以下是部分代码,完整代码请移步GIT。

v0版本:基础

聊天

v1版本:对话

新建新对话

可以置顶(取消置顶)、删除、修改对应的对话

在这里插入图片描述

数据表

create table tag
(
    id       int auto_increment
        primary key,
    user_id  int           not null,
    tag_name varchar(16)   not null,
    top      int default 0 null
);

create table conversation
(
    id           int auto_increment
        primary key,
    tag_id       int         null,
    user_message text        null,
    bot_message  text        null,
    create_time  varchar(32) null,
    username     varchar(16) null
);

tag.js

$(document).ready(function () {

    tagList();

    $("#editBlock").hide();

    $(".add-button").on("click", function() {
        addTag();
    });



});

function tagSearch(data) {
    var data=$("#search-input").val();
         
    if(!data){
        //没有数据搜索全部
        tagList();
        return false;
    }

    $.ajax({
        type: "GET",
        url: SERVER_PATH + "/tag/search",
        data: {
            data: data
        },
        xhrFields: {withCredentials: true},
        success: function (result) {
            if (result.status) {
                alertBox(result.data.message);
                return false;
            }
            set_tags(result.data);
        }
    });
}

function addTag() {
    $.ajax({
        type: "POST",
        url: SERVER_PATH + "/tag/addTag",
        xhrFields: {withCredentials: true},
        success: function (result) {
            if (result.status) {
                alertBox(result.data.message);
                return false;
            }
            tagList();
        }
    });
}


function tagList() {
    $.ajax({
        type: "GET",
        url: SERVER_PATH + "/tag/tagList",
        xhrFields: {withCredentials: true},
        success: function (result) {
            if (result.status) {
                alertBox(result.data.message);
                return false;
            }
            set_tags(result.data);
        }
    });
}

function set_tags(tags) {
    if (!tags) {
        return false;
    }

    $(".tag-list").empty();

    $.each(tags, function (i, tag) {
        var btnClass = tag.top === 0 ? "top-btn" : "notop-btn";
        var topClass = tag.top === 0 ? "ptTag" : "topTag";

        var tagDiv = `
            <div class="tag">
                <img class="tag-btn ${topClass}"></img>
                <span class="show-btn" data-id="${tag.id}">${tag.tagName}</span>
                <div class="button-group">
                    <img class="icon-btn ${btnClass}" data-id="${tag.id}"></img>
                    <img class="icon-btn modify-btn" data-id="${tag.id}" data-name="${tag.tagName}"></img>
                    <img class="icon-btn delete-btn" data-id="${tag.id}"></img>
                </div>
            </div>`;
        
        $(".tag-list").append(tagDiv);
    });
    


    $(".show-btn").on("click", function() {
        var tagId = $(this).data('id');
        window.location.href="aichat.html?tagId="+tagId;
    });

    $(".notop-btn").on("click", function() {
        var tagId = $(this).data('id');
        var newTop=0;
        topTag(tagId,newTop);
    });

    $(".top-btn").on("click", function() {
        var tagId = $(this).data('id');
        var newTop=top=1;
        topTag(tagId,newTop);
    });

    $(".modify-btn").on("click", function() {
        var tagId = $(this).data('id');
        var tagName = $(this).data('name'); // 获取标签名称
    
        // 将标签名称填充到输入框中
        $("#newName").val(tagName);
    
        // 显示编辑界面块
        $("#editBlock").show();
    
        // 保存按钮点击事件
        $("#saveBtn").off("click").on("click", function() {
            var newName = $("#newName").val();

            if(!newName){
                alertBox("请输入新名字");
                return false;
            }

            modify(tagId,newName);

            // 关闭编辑界面块
            $("#editBlock").hide();
        });

        $("#cancelBtn").on("click", function() {
            $("#editBlock").hide();
        });
    });

    $(".delete-btn").on("click", function() {
        var tagId = $(this).data('id');
       
        // 弹出确认删除的提示框
        var confirmDelete = confirm("确定要删除这个标签吗?");
    
        // 如果用户点击确定删除,则执行删除操作
        if (confirmDelete) {
            deleteTag(tagId);
        } 

    });

}

function topTag(tagId,newTop){

    $.ajax({
        type: "POST",
        url: SERVER_PATH + "/tag/top",
        data: {
            tagId: tagId,
            top: newTop
        },
        xhrFields: {withCredentials: true},
        success: function (result) {
            if (result.status) {
                alertBox(result.data.message);
                return false;
            }
            tagList();
        }
    });
}

function modify(tagId,newName){

    $.ajax({
        type: "POST",
        url: SERVER_PATH + "/tag/modify",
        data: {
            tagId: tagId,
            tagName: newName
        },
        xhrFields: {withCredentials: true},
        success: function (result) {
            if (result.status) {
                alertBox(result.data.message);
                return false;
            }
            tagList();
        }
    });
}

function deleteTag(tagId){

    $.ajax({
        type: "GET",
        url: SERVER_PATH + "/tag/delete",
        data: {
            tagId: tagId
        },
        xhrFields: {withCredentials: true},
        success: function (result) {
            if (result.status) {
                alertBox(result.data.message);
                return false;
            }
            tagList();
        }
    });
}



TagController

package com.jsss.qianfan.controller;

import com.jsss.common.BusinessException;
import com.jsss.common.ErrorCode;
import com.jsss.common.ResponseModel;
import com.jsss.entity.User;
import com.jsss.qianfan.entity.Tag;
import com.jsss.qianfan.service.TagService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("tag")
@CrossOrigin(origins = "${jsss.web.path}", allowedHeaders = "*", allowCredentials = "true")
public class TagController implements ErrorCode {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    TagService tagService;


    @GetMapping("/tagList")
    public ResponseModel getTags(String token) {

        User user = null;
        if (StringUtils.isNotEmpty(token)) {
            user = (User) redisTemplate.opsForValue().get(token);
        }

        if (user == null) {
            throw new BusinessException(USER_NOT_LOGIN, "用户未登录");
        }

        List<Tag> tags = tagService.searchByUserId(user.getUserId());

        return new ResponseModel(tags);


    }


    @PostMapping("/addTag")
    public ResponseModel addTag(String token) {
        User user = null;
        if (StringUtils.isNotEmpty(token)) {
            user = (User) redisTemplate.opsForValue().get(token);
        }

        if (user == null) {
            throw new BusinessException(USER_NOT_LOGIN, "用户未登录");
        }

        String tagName = "新对话";

        Tag tag = new Tag(null, user.getUserId(), tagName, 0);
        tagService.addTag(tag);

        return new ResponseModel("添加成功");
    }

    @PostMapping("/modify")
    public ResponseModel modifyTag(Integer tagId, String tagName) {
        if (StringUtils.isEmpty(tagName)){
            throw new BusinessException(PARAMETER_ERROR, "缺失新的tag名");
        }
        tagService.updateTagName(tagId, tagName);
        return new ResponseModel("修改成功");
    }

    @PostMapping("/top")
    public ResponseModel topTag(Integer tagId, Integer top) {
        tagService.updateTagTop(tagId, top);
        String res = top == 1 ? "置顶成功" : "取消置顶成功";
        return new ResponseModel(res);
    }

    @GetMapping("/delete")
    public ResponseModel deleteTag(Integer tagId) {
        tagService.deleteTag(tagId);
        return new ResponseModel("删除成功");
    }

    @GetMapping("/search")
    public ResponseModel searchTag(String token, String data) {


        User user = null;
        if (StringUtils.isNotEmpty(token)) {
            user = (User) redisTemplate.opsForValue().get(token);
        }

        if (user == null) {
            throw new BusinessException(USER_NOT_LOGIN, "用户未登录");
        }


        List<Tag> tags = tagService.searchTag(user.getUserId(),data);

        return new ResponseModel(tags);

    }


}

v2版本:回复中

用户发送问题之后,显示回复中,得到回复后显示。

前端发送请求之后,先会得到“回复中”;
之后,去轮询获取最新回复。

后端接受请求之后,先存入到数据库中一个未回复请求。
然后异步得到回复之后,再去更新数据库。

在这里插入图片描述

textarea.js

var textarea = document.getElementById("messageInput");

var isSendingMessage = false; // 添加一个变量用于标识是否正在发送消息

textarea.addEventListener("keydown", function(event) {
    if (event.key === "Enter" && !event.shiftKey) {
        event.preventDefault();


        if (isSendingMessage) {
            // 如果正在发送消息,则在文本框中添加换行符
            textarea.value += "\n";
        } else{
            var message = textarea.value.trim();
            textarea.value = "";
    
            if(!message){
                alertBox("输入内容不能为空!");
                return false;
            }
    
    
            var tagId=$.getUrlParam("tagId");;
    
            if(!tagId){
                alertBox("没有对应的参数");
                return false;
            }

            isSendingMessage = true; // 设置为true表示正在发送消息
    
            $.ajax({
                type: "POST",
                url: SERVER_PATH+"/chat/chat",
                data:{
                    "tagId": tagId,
                    "content":message
                },
                xhrFields: {withCredentials: true},
                success:function(result){
                    isSendingMessage = false; // 发送完成后设置为false
                    if (result.status) {
                        alertBox(result.data.message);
                        return false;
                    }

                    //请求成功之后
                    list(tagId);
                    
                    getChat(result.data.id);
                   
                }
            });
      
        }

        
    }
});

textarea.addEventListener("keydown", function(event) {
    if (event.key === "Enter" && event.shiftKey) {
        // 在 Shift+Enter 情况下允许换行
        textarea.value += "\n";
        event.preventDefault();
    }
});

function getChat(chatId){
    var tagId=$.getUrlParam("tagId");;
    
    $.ajax({
        type: "GET",
        url: SERVER_PATH+"/chat/getChat",
        data:{
            "id": chatId,
        },
        xhrFields: {withCredentials: true},
        success:function(result){
            isSendingMessage = false; // 发送完成后设置为false
            if (result.status) {
                alertBox(result.data.message);
                return false;
            }

            if (result.data.botMessage == "回复中...") {
                // 继续轮询,100ms 一次
                setTimeout(function() {
                    getChat(chatId);
                }, 100);
            } else {
                // 获取到最终回复
                // 处理回复逻辑
                list(tagId);
            }
           
        }
    });
}


ChatController

    @PostMapping("/chat")
    public ResponseModel chat(Integer tagId,String content){
        if (tagId==null){
            throw new BusinessException(PARAMETER_ERROR,"没有指定响应的tag");
        }

        if (StringUtils.isEmpty(content)){
            throw new BusinessException(PARAMETER_ERROR,"输入内容不能为空");
        }

        Tag tag = tagService.searchById(tagId);
        if (tag==null){
            throw new BusinessException(NOT_FIND,"没有找到对应的对话");
        }

        String username=userService.selectUserById(tag.getUserId()).getUsername();


        Conversation conversation = new Conversation(null, tagId,username, content, "回复中...", format(new Date()));
        chatService.addChat(conversation);


        // 异步处理AI回复
        CompletableFuture.runAsync(() -> {
            Integer id=conversation.getId();

            String res = null;
            try {
                res = qianfanUtil.addMessage(content);
            } catch (Exception e) {
                res = "回复失败";
            }
            Conversation aiConversation = new Conversation();
            aiConversation.setId(id);
            aiConversation.setBotMessage(res);
            chatService.updateChat(aiConversation);
        });

        return new ResponseModel(conversation);

    }

v3版本:流式输出

流式输出,终止生成。

前端实现,让消息一个字符一个字符显示

在这里插入图片描述

chatLast.js

var lastId;
var interval;

$(document).ready(function () {
    
    $("#stopButton").on("click", function() {
        var latestReply = $(".latest-reply");
        var latestReplyText = latestReply.text();
        clearInterval(interval); // 停止字符流输出
        $("#stopButton").hide();
        updateStop(lastId,latestReplyText);
    });

    

});

function listLastReply(tagId) {
    $.ajax({
        type: "GET",
        url: SERVER_PATH + "/chat/list",
        data: {
            tagId: tagId
        },
        xhrFields: {withCredentials: true},
        success: function (result) {
            if (result.status) {
                alertBox(result.data.message);
                return false;
            }
            set_conversations_last(result.data);
        }
    });
}

function set_conversations_last(conversations) {
    if (!conversations) {
        return false;
    }

    $(".conversation-list").empty();

    var len=conversations.length;

    $.each(conversations, function (i, conversation) {
        var questionDiv = '<div class="question-container">' +
            '<table class="question">' +
            '<td>' +
            '<span>' + conversation.createTime + '</span>' +
            '<div class="user-message">' + conversation.userMessage + '</div>' +
            '</td>' +
            '<td type="text">' + conversation.username + '</td>' +
            '</table>' +
            '</div>';

        var answerDiv = '<div class="answer-container">' +
            '<table class="answer">' +
            '<td type="text">AI</td>' +
            '<td>' +
            '<span>' + conversation.createTime + '</span>' +
            '<div class="bot-message">' + conversation.botMessage + '</div>' +
            '</td>' +
            '</table>' +
            '</div>';

        if(i!=len-1){
            $(".conversation-list").append(questionDiv);
            $(".conversation-list").append(answerDiv);
        }

    });

    // 获取最新对话的回复
    var lastConversation = conversations[len - 1];
    lastId=lastConversation.id;

    var questionDiv = 
        '<div class="question-container">' +
            '<table class="question">' +
                '<td>' +
                    '<span>' + lastConversation.createTime + '</span>' +
                    '<div class="user-message">' + lastConversation.userMessage + '</div>' +
                '</td>' +
                '<td type="text">' + lastConversation.username + '</td>' +
            '</table>' +
        '</div>';

    $(".conversation-list").append(questionDiv);


    var answerDiv = 
    '<div class="answer-container">' +
        '<table class="answer">' +
            '<td type="text">AI</td>' +
            '<td>' +
                '<span>' + lastConversation.createTime + '</span>' +
                '<div class="bot-message latest-reply">' + lastConversation.botMessage + '</div>' +
            '</td>' +
        '</table>' +
    '</div>';

    $(".conversation-list").append(answerDiv);


    // 逐字显示最新回复
    var latestReply = $(".latest-reply");
    var latestReplyText = latestReply.text();
    latestReply.empty();
    var index = 0;
    interval = setInterval(function() {
        if (index < latestReplyText.length) {
            $("#stopButton").show();
            latestReply.append(latestReplyText.charAt(index));
            index++;
        } else {
            clearInterval(interval);
            $("#stopButton").hide();
        }
    }, 10); // 逐字显示的速度,您可以根据需要调整

    
    
}

function updateStop(tagId,message){
    $.ajax({
        type: "POST",
        url: SERVER_PATH + "/chat/updateStop",
        data: {
            id: tagId,
            botMessage: message
        },
        xhrFields: {withCredentials: true},
        success: function (result) {
            if (result.status) {
                alertBox(result.data.message);
                return false;
            }
            
        }
    });
}

ChatController

    @PostMapping("/updateStop")
    public ResponseModel updateStop(Integer id,String botMessage){
        Conversation conversation=new Conversation();
        conversation.setId(id);
        conversation.setBotMessage(botMessage);
        chatService.updateChat(conversation);
        return new ResponseModel();
    }

v4版本:多轮对话

实现上下文有关的对话

多次调用qianfan.addMessage().addMessage()

在这里插入图片描述

QianfanUtil

    public String addMessagePlus(List<Message> messages, String content) {

        ChatResponse response = qianfan.chatCompletion()
                .messages(messages)
                .addMessage("user", content)
                .temperature(0.7)
                .execute();


        return response.getResult();

    }

ChatController



    @PostMapping("/chat")
    public ResponseModel chat(Integer tagId, String content) {
        if (tagId == null) {
            throw new BusinessException(PARAMETER_ERROR, "没有指定响应的tag");
        }

        if (StringUtils.isEmpty(content)) {
            throw new BusinessException(PARAMETER_ERROR, "输入内容不能为空");
        }

        Tag tag = tagService.searchById(tagId);
        if (tag == null) {
            throw new BusinessException(NOT_FIND, "没有找到对应的对话");
        }

        String username = userService.selectUserById(tag.getUserId()).getUsername();


        Conversation conversation = new Conversation(null, tagId, username, content, "回复中...", format(new Date()));
        chatService.addChat(conversation);


        // 异步处理AI回复
        CompletableFuture.runAsync(() -> {
            Integer id = conversation.getId();

            String res = null;
            try {
//                res = qianfanUtil.addMessage(content);
                res = qianfanUtil.addMessagePlus(getMessages(tagId), content);
            } catch (Exception e) {
                res = "回复失败";
            }
            Conversation aiConversation = new Conversation();
            aiConversation.setId(id);
            aiConversation.setBotMessage(res);
            chatService.updateChat(aiConversation);
        });

        return new ResponseModel(conversation);

    }

    public List<Message> getMessages(Integer tagId) {
        List<Message> messages = new ArrayList<>();
        List<Conversation> conversations = chatService.searchByTagId(tagId);
        int size = conversations.size() - 1;//最新的不需要
        for (int i = 0; i < size; i++) {
            Conversation conversation = conversations.get(i);
            Message userMessage = new Message();
            userMessage.setRole("user");
            userMessage.setContent(conversation.getUserMessage());
            messages.add(userMessage);
            Message botMessage = new Message();
            botMessage.setRole("assistant");
            botMessage.setContent(conversation.getBotMessage());
            messages.add(botMessage);

        }

        return messages;
    }

v5:其他修改

在这里插入图片描述

前端样式:跳转到最后一个消息

在aichat.html中

		<script>
			function scrollToLastMessage() {
				// 找到消息容器
				var messageContainer = document.querySelector(".message-container");
				
				// 找到消息容器中最后一个子元素
				var lastMessage = messageContainer.lastElementChild;
				
				// 将最后一个消息元素滚动到可见区域
				lastMessage.scrollIntoView({ behavior: 'auto', block: 'end' });
			}

			function onLoad() {
				setTimeout(scrollToLastMessage, 100); // 添加100毫秒的延迟
			}

			window.addEventListener('load', onLoad);
			
		</script>

前端样式:Message保留空白符

savePre(conversation.userMessage)
savePre(conversation.botMessage)
function savePre(content){
    return content.replace(/\n/g, "<br>").replace(/ /g, "<span>&nbsp;</span>");
}

前端样式:最新回复保留空白符

   var botMessageWithBrAndSpace = lastConversation.botMessage.replace(/\n/g, "\\n");

    var answerDiv = 
    '<div class="answer-container">' +
        '<table class="answer">' +
            '<td type="text">AI</td>' +
            '<td>' +
                '<span>' + lastConversation.createTime + '</span>' +
                '<div class="bot-message latest-reply">' + botMessageWithBrAndSpace + '</div>' +
            '</td>' +
        '</table>' +
    '</div>';

    $(".conversation-list").append(answerDiv);

  
    // 逐字显示最新回复
    var latestReply = $(".latest-reply");
    var latestReplyText = botMessageWithBrAndSpace;

    latestReply.empty();
    var index = 0;
    interval = setInterval(function() {
        if (index < latestReplyText.length) {
            $("#stopButton").show();
            if (latestReplyText.charAt(index) === "\\") {
                if (latestReplyText.charAt(index + 1) === "n") {
                    latestReply.append("<br>");
                    index++; // 跳过"n"
                } else {
                    latestReply.append(latestReplyText.charAt(index));
                }
            } else if(latestReplyText.charAt(index)===' '){
                latestReply.append("&nbsp;");

            }else {
                latestReply.append(latestReplyText.charAt(index));
            }
            index++;
        
        } else {
            clearInterval(interval);
            $("#stopButton").hide();
        }
    }, 25); // 逐字显示的速度,您可以根据需要调整

    
    
}

最后

2024-4-10 17:02:49

迎着日光月光星光,直面风霜雨霜雪霜。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/534123.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

1、Qt UI控件 -- qucsdk

前言&#xff1a;Qt编写的自定义控件插件的sdk集合&#xff0c;包括了各个操作系统的动态库文件以及控件的头文件和sdk使用demo。类似于Wpf中的LivChart2控件库&#xff0c;都是一些编译好的控件&#xff0c;可以直接集成到项目中。该控件是飞扬青云大神多年前开发的&#xff0…

从零开始:构建、打包并上传个人前端组件库至私有npm仓库的完整指南

文章目录 一、写组件1、注册全局组件方法2、组件13、组件2 二、测试三、发布1、配置package.json2、生成库包3、配置发布信息4、发布 四、使用1、安装2、使用 五、维护1、维护和更新2、注意事项 一、写组件 确定组件库的需求和功能&#xff1a;在开始构建组件库之前&#xff0c…

三相整流桥器件选型计算方法-电压与电流计算公式

三相整流桥的选型主要涉及到两个关键参数&#xff1a;电压和电流。以下是电压与电流的计算公式及选型方法&#xff1a; 电压计算&#xff1a; 输入交流电压有效值&#xff08;Vrms&#xff09;是选择整流桥的重要参考。整流桥的额定电压&#xff08;Vrrm&#xff09;应至少为输…

echarts tooltip提示框显示不全

一、背景&#xff1a; 写在前面&#xff1a; 自行封装。一个可由多个柱形图叠加而成的图表&#xff0c;命名为someHoverLine(可自定义)。 下面罗列了移动端和web端的封装组件代码&#xff1b; 展示了vue2、uniapp、vue3的不同封装和使用案列。 二、问题描述&#xff1a; 三、解…

数组常用方法

for循环 使用计数器变量来迭代数组元素 var arr [1,2,3,4,5]for(var i0;i<arr.length;i){console.log(array[i]) }上面的i就是计数器变量&#xff0c;初始值为0&#xff0c;每次循环后加1&#xff0c;直到i等于数组长度为止。在循环体内&#xff0c;可以通过数组索引arr[…

C 强制类型转换

强制类型转换是把变量从一种类型转换为另一种数据类型。例如&#xff0c;如果您想存储一个 long 类型的值到一个简单的整型中&#xff0c;您需要把 long 类型强制转换为 int 类型。您可以使用强制类型转换运算符来把值显式地从一种类型转换为另一种类型&#xff0c;如下所示&am…

攻防演练 | redis艰难写shell进入内网

背景 某地市级攻防演练 要求 拿到指定单位的靶标系统&#xff08;必须是web后台管理权限数据库服务器&#xff09; 正式开始 redis未授权 首先通过信息收集获取到了一些IP&#xff0c;且发现一个IP中存在redis未授权。 此时兴冲冲的去尝试写入定时任务反弹shell&#xff…

淘宝评论数据API接口:洞察消费者声音的关键工具

淘宝评论数据API接口&#xff1a;洞察消费者声音的关键工具 请求示例&#xff0c;API接口接入Anzexi58 随着电子商务的蓬勃发展&#xff0c;消费者对于商品的评价和反馈成为了购物决策中不可或缺的一部分。淘宝作为中国最大的电商平台之一&#xff0c;汇聚了海量的商品和评论数…

【SpringBoot】-- mapstruct进行类型转换时Converter实现类不能自动生成代码问题解决

问题描述 我的问题如下&#xff1a; 应该在红色区域生成对应的转换细节&#xff0c;但是这里只返回了一个空对象 问题解决 加入lombok-mapstruct-binding依赖,也要注意依赖引用顺序问题 <dependency><groupId>org.projectlombok</groupId><artifactId&…

photomaker:customizing realistic human photos via stacked id embedding

PhotoMaker: 高效个性化定制人像照片文生图 - 知乎今天分享我们团队最新的工作PhotoMaker的技术细节。该工作开源5天Githubstar数已过6千次&#xff0c;已列入Github官方Trending榜第一位&#xff0c;PaperswithCode热度榜第一位&#xff0c;HuggingFace Spaces趋势榜第一位。项…

小阳同学刷题日记-54. 螺旋矩阵

题目&#xff1a;给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 思路&#xff1a; 初始化四个边界指针&#xff1a;top, bottom, left, right 分别表示当前螺旋遍历的上边界、下边界、左边界和右边界。不断遍历矩阵直…

Windows虚拟主机上多个域名访问同一个网站

近日老板提出了想要多个域名访问同一个网站的想法。这边了解后&#xff0c;由于我们公司使用的是Hostease的Windows虚拟主机产品&#xff0c;因此咨询了Hostease的技术支持&#xff0c;寻求帮助了解到可以实现Windows主机上多个域名访问同一个网站&#xff0c;是需要进入Window…

win10如何移除此电脑下的“网络”

1.按住winr,然后输入regedit打开注册表&#xff0c;在导航栏输入&#xff0c;定位到ShellFolder文件夹 HKEY_CLASSES_ROOT\CLSID\{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}\ShellFolder2.更改权限&#xff0c;在ShellFolder文件夹上右键选择权限->高级->更改->输入Adm…

antd vue table控件的使用(三)

今天就讲讲Ant Design Vue下的控件----table表格&#xff08;分页、编辑和删除功能&#xff09; 结合项目中的需求&#xff0c;看看如何配置,让table即可以展示列表&#xff0c;又可以直接编辑数据。需求&#xff1a; &#xff08;1&#xff09;展示即将检查的数据列表&#…

通过WebShell登录SQL Server主机并使用SSRS报表服务

背景信息 RDS SQL Server提供了WebShell功能&#xff0c;允许用户通过Web界面登录到RDS SQL Server实例的操作系统中&#xff0c;并在该操作系统中执行命令、上传下载文件等操作。WebShell功能方便用户对RDS SQL Server实例的管理和维护&#xff0c;特别是在无法使用SSH客户端的…

FlashAttention V1 学习笔记

Flash Attention 是一种新型的注意力机制&#xff0c;旨在解决传统 Transformer 模型在处理长序列数据时面临的计算和内存效率问题。它通过一系列创新的技术优化&#xff0c;显著提高了注意力机制的计算速度和内存使用效率&#xff0c;同时保持了精确的结果&#xff0c;不依赖于…

超好用的iframe的postMessage穿参

前言 ❝ 跨域&#xff0c;简单来说是指不同域之间相互请求资源&#xff0c;例如AJAX请求&#xff0c;浏览器根据同源策略对响应结果进行拦截&#xff0c;这是浏览器对JavaScript实施的安全限制。所谓同源是指相同的域名、协议和端口&#xff0c;只要其中一项不同就为跨域 ❞ 背…

C++11异常:到底是怎么个异常

目录​​​​​​​ 一、C/C如何处理错误 1.1C语言传统的处理错误的方式 1.2C异常概念 二、异常的使用 2.1异常的抛出和捕获 2.2try/catch的使用 2.3异常安全 2.4异常的重新抛出 2.5异常的规范 三、服务器开发中异常体系的模拟 一、C/C如何处理错误 1.1C语言传统的处…

SEO关键词布局时如何查找用户爱搜索的关键词?

在关键词布局中&#xff0c;确定完核心词后&#xff0c;就要考虑在网站关键词扩展时&#xff0c;找到用户爱搜索的词&#xff0c;只有在网站页面关键词布局时&#xff0c;布局用户爱搜索的词&#xff0c;才能够使用户在搜索时网站的页面能够有机会出现在用户的搜索结果页&#…