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? 响应回答就会转成 英文, 说明不能完全的限制

相关推荐
中微极客12 小时前
解锁LLM开发全栈能力:Python + LangChain + RAG 工程实战指南
人工智能·python·langchain
CCC:CarCrazeCurator13 小时前
A100作为深度学习基础计算节点的原因
人工智能·深度学习
米小虾13 小时前
操作系统正在被AI重写:从谷歌到微软,为什么所有人都在押注"Agent OS"?
人工智能
ACP广源盛1392462567313 小时前
IX8024@ACP# 搭配此芯 AI 服务器 + 爱芯元智产品完整方案
大数据·运维·服务器·人工智能·分布式·嵌入式硬件
hhzz13 小时前
Barbershop:基于GAN和分割Mask的图像合成技术——从理论到实战全解析
图像处理·人工智能·python·深度学习·计算机视觉
qyr678914 小时前
全球新能源汽车电机驱动器市场深度调研报告
大数据·网络·人工智能·自动化·汽车
动物园猫14 小时前
校园异常行为目标检测数据集:5类别 | 目标检测
人工智能·目标检测·计算机视觉
ShallWeL14 小时前
NVIDIA Jetson 早期系列演进
人工智能·嵌入式硬件·边缘计算·智能硬件
IT_陈寒14 小时前
SpringBoot自动装配坑了我一天,原来问题出在这
前端·人工智能·后端
wuqingshun31415914 小时前
MYSQL的乐观锁和悲观锁是什么?
java