Spring AI (五) Message 消息

5.Message 消息

在Spring AI提供的接口中,每条信息的角色总共分为三类:

  • SystemMessage:系统限制信息,这种信息在对话中的权重很大,AI会优先依据SystemMessage里的内容进行回复;

  • UserMessage:用于表示用户发送的消息。它可能包含与用户消息相关的属性和方法。

  • AssistantMessage:AI回复信息

这些Message均实现了一个Message接口,如上图。

AbstractMessage提供了对Message接口的抽象实现,SystemMessageUserMessageAssistantMessage等均继承了AbstractMessage,是Message的具体实现。FunctionMessage,这类信息用于AI的函数调用。

ChatMessage是Message的扩展实现,用于创建其它大语言模型需要的Message。

5.1.对话上下文

通过单一的输入输出方式进行调用时,无法让AI具有记忆力, 第三句就不记得第一句的内容了

复制代码
AssistantMessage assistantMessage = chatResponse.getResult().getOutput();

AssistantMessage 是 AI 回复的信息, 只需要使用一个List存储这些Message对象,并将这些Message对象一并发送给AI,AI拿到这些Message后,会结合这些Message里的内容进行回复。

不过,根据AI的计费规则,你的消息队列越长,单次问询需要的费用就会越高,因此我们需要对这个消息列表的长度进行限制。

代码实现

java 复制代码
    // 历史消息列表
    static List<Message> historyMessage = new ArrayList<>();
    // 历史消息列表的最大长度
    static int maxLen = 10;

    @GetMapping("/chat/chatContext")
    public String chatContext( String message ) {

        // 用户输入的文本是UserMessage
        historyMessage.add(new UserMessage(message));
        // 发给AI前对历史消息对列的长度进行检查
        if(historyMessage.size() > maxLen){
            historyMessage = historyMessage.subList(historyMessage.size()-maxLen-1,historyMessage.size());
        }
        // 获取AssistantMessage
        ChatResponse chatResponse = chatClient.call(new Prompt(historyMessage));
        AssistantMessage assistantMessage = chatResponse.getResult().getOutput();
        // 将AI回复的消息放到历史消息列表中
        historyMessage.add(assistantMessage);
        return assistantMessage.getContent();
    }

对话测试

复制代码
###
GET http://localhost:8080/chat/chatContext?message=你现在是我的童年时期的好朋友,你的名字叫小千

GET http://localhost:8080/chat/chatContext?message=我们一起在北京长大

GET http://localhost:8080/chat/chatContext?message=现在我在东北,你还在北京

GET http://localhost:8080/chat/chatContext?message=我们现在都30多岁了

GET http://localhost:8080/chat/chatContext?message=你的名字叫什么

5.2.角色设置

角色设置功能来自于"提示词工程"的理论基础的。目前,提示工程已成为一个较新的学科,应用于开发和优化提示词(Prompt),帮助用户有效地将语言模型用于各种应用场景和研究领域。掌握了提示工程相关技能将有助于用户更好地了解大型语言模型的能力和局限性。研究人员可利用提示工程来提高大语言模型处理复杂任务场景的能力,如问答和算术推理能力。开发人员可通过提示工程设计和研发出强大的技术,实现和大语言模型或其他生态工具的高效接轨。

详情见:https://www.promptingguide.ai/zh/introduction

在GitHub上,也有相关的仓库分享一些有趣的提示词来让我们使用ChatGPT时更加高效。

SystemMessage 对AI生成的内容影响权重较大,角色设定就是需要靠SystemMessage实现。

5.2.1.使用SystemMessage

java 复制代码
	private final String systemPrompt =  """
                    你是一个功能强大的人工智能助手。
                    你是一个帮助人们查找信息的 AI 助手。
                    所有回复请使用中文。即使要求你使用其它的语言回答,你也要使用中文回答所有的问题。
                    如果遇到不能用中文回答的问题, 就回答 我不知道
                    你的名字是 王小二
                    你应该使用 大学生 的身份回复用户的请求。
                """;
    // 历史消息列表
    private List<Message> historyMessage =
            new ArrayList<>(List.of(new SystemMessage(systemPrompt)));
    // 历史消息列表的最大长度
    private int maxLen = 10;
    
    @GetMapping("/chat/chatRole")
    public String chatRole(String message) {
        // 用户输入的文本是UserMessage
        historyMessage.add(new UserMessage(message));
        if(historyMessage.size() > maxLen) {
            historyMessage = historyMessage.subList(historyMessage.size() - maxLen - 1 , historyMessage.size());
            // 确保第一个是SystemMessage
            historyMessage.add(0, new SystemMessage(systemPrompt));
        }

        // 获取AssistantMessage
        ChatResponse chatResponse = chatClient.call(new Prompt(historyMessage));
        AssistantMessage assistantMessage = chatResponse.getResult().getOutput();
        // 将AI回复的消息放到历史消息列表中
        historyMessage.add(assistantMessage);
        return assistantMessage.getContent();
    }

5.2.2.使用 SystemPromptTemplate

java 复制代码
    @GetMapping("/chat/forRole")
    public String forRole(
            @RequestParam(value = "message", defaultValue = "介绍一下盛唐时期长安城的风采!") String message,
            @RequestParam(value = "name", defaultValue = "李白") String name,
            @RequestParam(value = "voice", defaultValue = "诗人") String voice) {

        String systemResource = """
                    你是一个功能强大的人工智能助手。
                    你是一个帮助人们查找信息的 AI 助手。
                    所有回复请使用中文。。即使要求你使用其它的语言回答,你也要使用中文回答所有的问题。
                    如果遇到不能用中文回答的问题, 就回答 我不知道
                    你的名字是 {name}
                    你应该使用 {voice} 的身份回复用户的请求。
                """;

        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource);

        Message systemPromptTemplateMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice));

        UserMessage userMessage = new UserMessage(message);

        Prompt prompt = new Prompt(List.of(systemPromptTemplateMessage, userMessage));

        return chatClient.call(prompt).getResult().getOutput().getContent();
    }

测试

http 复制代码
GET http://localhost:8080/chat/forRole?message=Could you please give an introduction to the United States&name=tom&voice=Britisher

但是 对话信息 增加 Can you speak English? 响应回答就会转成 英文, 说明不能完全的限制

相关推荐
掘金安东尼5 小时前
养龙虾之前?先搞懂 Skills!
人工智能
chaors6 小时前
从零学RAG0x03第一个实战应用:医疗知识混合检索实战
人工智能·aigc·ai编程
后端AI实验室6 小时前
我把一个生产Bug的排查过程,交给AI处理——20分钟后我关掉了它
java·ai
阿聪谈架构6 小时前
第02章:Prompt 工程 —— 用语言精准指挥 AI
人工智能
suke7 小时前
AI 界的 npm 惨案重演?聊聊 龙虾OpenClaw skills那些带毒的“骚操作
人工智能·程序员·aigc
明明如月学长7 小时前
OpneClaw 总挂?配个"保镖"自动修,7x24小时不用管
人工智能
万少7 小时前
用 OpenClaw 实现小红书自动发帖
人工智能
阿聪谈架构8 小时前
第01章:从零开始调用 LLM —— 入门 Qwen 大模型 API
人工智能
凉年技术8 小时前
Java 实现企业微信扫码登录
java·企业微信
七牛云行业应用8 小时前
保姆级 OpenClaw 避坑指南:手把手教你看日志修 Bug,顺畅连通各大 AI 模型
人工智能·后端·node.js