Spring AI:提示词工程 - Prompt 角色分类(系统角色与用户角色)

Spring AI 之前的文章列表

Spring AI:对接DeepSeek实战
Spring AI:对接官方 DeepSeek-R1 模型 ------ 实现推理效果
Spring AI:ChatClient实现对话效果
Spring AI:使用 Advisor 组件 - 打印请求大模型出入参日志
Spring AI:ChatMemory 实现聊天记忆功能
Spring AI:本地安装 Ollama 并运行 Qwen3 模型
Spring AI:提示词工程

Prompt 角色分类

Prompt(提示词)

目前,我们知道通过 ChatModel 的 call() 方法 ,或则 steam() 方法,调用 AI 大模型,该方法入参接收一个 Prompt 实例,并返回 ChatResponse 响应。

Prompt 类可以看做一个容器,用于组织一系列 Message 消息对象和可选的 ChatOptions 请求配置。

以下是 Prompt 类的源码简化版(省略了构造器和工具方法):

java 复制代码
public class Prompt implements ModelRequest<List<Message>> {
    private final List<Message> messages; // 消息列表
    private ChatOptions chatOptions;      // 聊天配置选项
}

每个 Message 消息,在提示词中扮演不同的角色,其作用各不相同,涵盖用户消息、AI 生成的响应等等。这种结构支持与 AI 模型进行复杂精细的交互,因为提示词由多条消息构建而成,每条消息在对话中被赋予特定功能。

Message(消息)

查看 Message 消息接口源码,它封装了提示词的文本内容、元数据属性集合以及分类标识 MessageType。

接口定义如下:

java 复制代码
// 内容接口
public interface Content {
    String getContent();                 // 获取文本内容
    Map<String, Object> getMetadata();   // 获取元数据
}

// 消息接口
public interface Message extends Content {
    MessageType getMessageType();        // 获取消息类型,如用户消息、系统消息、AI 回复等
}

另外,对于多模态消息类型 (指模型支持多种类型的数据输入或输出,如文本,图片等等),Spring AI 额外定义了 MediaContent 接口,提供媒体内容对象列表:

java 复制代码
public interface MediaContent extends Content {
    Collection<Media> getMedia();        // 支持图像/音频/视频等多媒体内容
}

Message 接口的多种实现,对应着 AI 模型可处理的不同类别的消息。

角色分类 (Roles)

每条消息都被赋予一个特定的角色 (role)。这些角色用于对消息进行分类,向 AI 大模型阐明在提示词中,每个部分的上下文和目的。这种结构化的方法增强了与 AI 沟通的细微差别和有效性,因为提示词中的每个部分,在交互中都扮演着独特且定义明确的角色。

主要角色包括:

  • 系统角色 (System Role): 指导 AI 的行为和响应风格,设定 AI 如何解释和回复输入的参数或规则,比如让 AI 大模型扮演一个客服。类似于在开始对话之前,向 AI 大模型提供指令。

  • 用户角色 (User Role): 即用户的输入------ 如向 AI 提出的问题、发出的命令或陈述。这个角色是基础性的,因为它构成了 AI 响应的依据。

  • 助手角色 (Assistant Role):

    即 AI 大模型对用户输入的响应。

    它不仅仅是一个回答,对于维持对话的流畅性至关重要。通过跟踪 AI 之前的响应(即其 '助手角色' 消息),系统确保聊天是连贯的。

  • 工具/函数角色 (Tool/Function Role): 调用外部服务,比如获取天气数据、查询数据库等等。这里仅做了解,后面会单独学习这块。

在 Spring AI 中,以上角色通过 MessageType 枚举类型来表示,源码如下:

java 复制代码
public enum MessageType {

    USER("user"), // 用户消息
    ASSISTANT("assistant"), // 助手消息
    SYSTEM("system"), // 系统消息
    TOOL("tool"); // 工具/函数消息
}

ChatClient 指定系统角色消息

接下来,我们在代码中,实际感受一下,如何对消息设定角色。其实,在之前的文章中,就体验过,在初始化 ChatClient 对象时,为其指定一个系统角色,如下:

除了上面这种以 "全局" 的方式,设置系统角色外,也可以在接口中,动态、更灵活的指定系统角色消息,如下图所示:

java 复制代码
@RestController
@RequestMapping("/v2/ai")
public class ChatClientController {

    @Resource
    private ChatClient chatClient;

    // 省略...

    /**
     * 流式对话
     * @param message
     * @return
     */
    @GetMapping(value = "/generateStream", produces = "text/html;charset=utf-8")
    public Flux<String> generateStream(@RequestParam(value = "message", defaultValue = "你是谁?") String message,
                                       @RequestParam(value = "chatId") String chatId
    ) {

        // 流式输出
        return chatClient.prompt()
                .system("请你扮演一个智能客服")
                .user(message) // 提示词
                .advisors(a -> a.param(ChatMemory.CONVERSATION_ID, chatId))
                .stream()
                .content();

    }

}

ChatModel 指定系统角色、用户角色消息

那么,如果是通过 ChatModel 这种方式来调用 AI 大模型,要如何指定 "系统角色" 的消息呢?也很简单,代码如下:

java 复制代码
@RestController
@RequestMapping("/v6/ai")
public class PController {

    @Resource
    private DeepSeekChatModel chatModel;

	// 省略...

    /**
     * 流式对话
     * @param message
     * @return
     */
    @GetMapping(value = "/generateStream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<AIResponse> generateStream(@RequestParam(value = "message", defaultValue = "你是谁?") String message) {
        // 系统角色消息
        SystemMessage systemMessage = new SystemMessage("请你扮演一个智能客服");
        // 用户角色消息
        UserMessage userMessage = new UserMessage(message);
        // 构建提示词
        Prompt prompt = new Prompt(Arrays.asList(systemMessage, userMessage));

        // 流式输出
        return chatModel.stream(prompt)
                .mapNotNull(chatResponse -> {
                    Generation generation = chatResponse.getResult();
                    String text = generation.getOutput().getText();
                    return AIResponse.builder().v(text).build();
                });

    }

}

解释一下上面的代码:

  • new SystemMessag() : 设置一个系统角色的消息,如指定 AI 大模型扮演一个客服;
  • new UserMessage() : 初始化一个用户角色消息,设置用户提出的问题;
  • Prompt 作为一个容器,将这些消息包装一下,扔给 AI 大模型;
相关推荐
Where-9 分钟前
深度学习中的过拟合问题及解决方式
人工智能·深度学习
wen__xvn15 分钟前
目标检测的局限
人工智能·目标检测·计算机视觉
力学与人工智能25 分钟前
博士答辩PPT分享 | 高雷诺数湍流场数据同化与湍流模型机器学习研究
人工智能·机器学习·ppt分享·高雷诺数·流场数据同化·湍流模型
调参札记37 分钟前
医学研究中的因果推断:重视态度与实践流程的结构性落差
人工智能
木卫四科技40 分钟前
Chonkie 技术深度学习
人工智能·python·rag
梁下轻语的秋缘43 分钟前
ESP32-WROOM-32E存储全解析:RAM/Flash/SD卡读写与速度对比
java·后端·spring
努力毕业的小土博^_^1 小时前
【地学应用】溜砂坡scree slope / talus slope的定义、机制、分布、危害、与滑坡区别、研究方向与代表论文
人工智能·深度学习·遥感·地质灾害·地学应用
JeffDingAI1 小时前
【Datawhale学习笔记】基于Gensim的词向量实战
人工智能·笔记·学习
Ryan老房1 小时前
自动驾驶数据标注-L4-L5级别的数据挑战
人工智能·目标检测·目标跟踪·自动驾驶
weixin_398187751 小时前
YOLOv8结合SCI低光照图像增强算法实现夜晚目标检测
人工智能·yolo