【SpringAIAlibaba新手村系列】(5)Prompt 提示词基础与多种消息类型

第五章 Prompt 提示词基础与多种消息类型

版本标注

  • Spring AI: 1.1.2
  • Spring AI Alibaba: 1.1.2.0

章节定位

  • Prompt 仍然是基础,但在 1.1.2.x 中,Prompt 往往会与 Tool Calling、MCP、RAG、结构化输出、Agent System Prompt、Routing Prompt 一起协同工作。

s01 > s02 > s03 > s04 > [ s05 ] s06 > s07 > s08 > s09 > s10 > s11 > s12 > s13 > s14 > s15 > s16 > s17 > s18

"同一句话, 放在不同消息角色里, 效果可能完全不同" -- Prompt 的本质不是提问, 而是精确表达任务。


一、Prompt 的核心概念

1.1 什么是 Prompt?

Prompt(提示词) 是我们与 AI 沟通的唯一方式,你可以把它理解成:

"给 AI 写的 prompt 就是给 AI 下达的指令或提出的问题"

就像和人沟通一样,你说的越清楚,对方理解得越准确。Prompt 写得好不好,直接决定了 AI 输出的质量。

1.2 Prompt 的组成要素

一个完整的 Prompt 通常由两部分组成:

复制代码
┌────────────────────────────────────────────────────┐
│                    Prompt 的组成                    │
├────────────────────────────────────────────────────┤
│                                                    │
│  【系统消息 System Message】                        │
│  ─────────────────────────                         │
│  你是一个法律助手,只回答法律相关问题               │
│  其他问题回复"抱歉,我只能回答法律问题"             │
│                                                    │
│  【用户消息 User Message】                          │
│  ──────────────────                                │
│  什么是知识产权法?                                │
│                                                    │
└────────────────────────────────────────────────────┘

1.3 Spring AI 中的消息类型

在 Spring AI 中,消息被抽象为几个类:

消息类型 说明 典型用途
SystemMessage 系统提示词,设定 AI 角色和行为 "你是一个Java专家"
UserMessage 用户消息,实际的问题 "什么是反射?"
AssistantMessage AI 的回复消息 记录对话历史
ToolResponseMessage 工具调用返回的结果 天气查询结果

二、多种模型支持

2.1 多模型配置

本章的项目展示了如何在同一个应用中支持多个不同的 AI 模型:

复制代码
// 项目中配置了两种模型
@Resource(name = "deepseek")       // DeepSeek 开源模型
private ChatModel deepseekChatModel;

@Resource(name = "qwen")           // 阿里云通义千问
private ChatModel qwenChatModel;

// 对应的两个 ChatClient
@Resource(name = "deepseekChatClient")
private ChatClient deepseekChatClient;

@Resource(name = "qwenChatClient")
private ChatClient qwenChatClient;

2.2 模型选择策略

不同模型有不同的特点:

模型 特点 适用场景
DeepSeek 开源免费,中文能力强 成本敏感场景
Qwen (通义千问) 阿里云服务稳定,中文优化好 生产环境首选

三、项目代码详解

3.1 控制器代码

复制代码
package com.atguigu.study.controller;

import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.ToolResponseMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.util.List;

/**
 * Prompt 提示词控制器
 * 展示各种 Prompt 的使用方式
 */
@RestController
public class PromptController
{
    // 注入 DeepSeek 模型和 ChatClient
    @Resource(name = "deepseek")
    private ChatModel deepseekChatModel;
    
    @Resource(name = "qwen")
    private ChatModel qwenChatModel;

    @Resource(name = "deepseekChatClient")
    private ChatClient deepseekChatClient;
    
    @Resource(name = "qwenChatClient")
    private ChatClient qwenChatClient;

    /**
     * 方式一:使用 ChatClient 的简洁 API(推荐)
     * 
     * .system() 方法设置系统提示词
     * .user() 方法设置用户消息
     * .stream() 开启流式输出
     *
     * 接口:http://localhost:8005/prompt/chat?question=火锅介绍下
     */
    @GetMapping("/prompt/chat")
    public Flux<String> chat(String question)
    {
        return deepseekChatClient.prompt()
            // system() 设置系统消息:AI的角色设定
            .system("你是一个法律助手,只回答法律问题,"
                   + "其它问题回复,我只能回答法律相关问题,其它无可奉告")
            // user() 设置用户消息
            .user(question)
            // stream() 流式输出
            .stream()
            .content();
    }

    /**
     * 方式二:使用底层 Message 对象(更底层灵活)
     * 
     * 创建 SystemMessage 和 UserMessage 对象
     * 组合成 Prompt 进行调用
     * 
     * 接口:http://localhost:8005/prompt/chat2?question=葫芦娃
     */
    @GetMapping("/prompt/chat2")
    public Flux<ChatResponse> chat2(String question)
    {
        // 1. 系统消息:设定AI为"讲故事助手"
        SystemMessage systemMessage = new SystemMessage(
            "你是一个讲故事的助手,每个故事控制在300字以内"
        );

        // 2. 用户消息:用户的问题
        UserMessage userMessage = new UserMessage(question);

        // 3. 组合成 Prompt
        //    Prompt 是 Message 的容器,可以包含多个消息
        Prompt prompt = new Prompt(userMessage, systemMessage);

        // 4. 调用并返回流式响应
        return deepseekChatModel.stream(prompt);
    }

    /**
     * 方式三:提取响应中的文本
     * 
     * 获取 ChatResponse 对象后,需要手动提取内容
     * 
     * 接口:http://localhost:8005/prompt/chat3?question=葫芦娃
     */
    @GetMapping("/prompt/chat3")
    public Flux<String> chat3(String question)
    {
        SystemMessage systemMessage = new SystemMessage(
            "你是一个讲故事的助手,每个故事控制在600字以内且以HTML格式返回"
        );

        UserMessage userMessage = new UserMessage(question);
        Prompt prompt = new Prompt(userMessage, systemMessage);

        // 使用 map 转换响应,提取文本内容
        // getResults().get(0) 获取第一个结果块
        // getOutput().getText() 获取生成的文本
        return deepseekChatModel.stream(prompt)
            .map(response -> response.getResults().get(0).getOutput().getText());
    }

    /**
     * 方式四:获取 AssistantMessage 对象
     * 
     * 如果需要获取 AI 回复的完整对象(包含元数据)
     * 可以获取 AssistantMessage
     * 
     * 接口:http://localhost:8005/prompt/chat4?question=葫芦娃
     */
    @GetMapping("/prompt/chat4")
    public String chat4(String question)
    {
        // 通过 ChatClient 获取完整响应
        AssistantMessage assistantMessage = deepseekChatClient.prompt()
                .user(question)
                .call()
                .chatResponse()            // 获取 ChatResponse 对象
                .getResult()               // 获取结果
                .getOutput();              // 获取输出消息

        // 通过 getText() 获取文本内容
        return assistantMessage.getText();
    }

    /**
     * 方式五:模拟工具调用场景(ToolResponseMessage)
     * 
     * 这个示例展示了 ToolResponseMessage 的使用场景
     * 实际使用会在 ToolCalling 章节详细讲解
     * 
     * 接口:http://localhost:8005/prompt/chat5?city=北京
     */
    @GetMapping("/prompt/chat5")
    public String chat5(String city)
    {
        // 1. 用户问题:询问城市天气
        String answer = deepseekChatClient.prompt()
                .user(city + "未来3天天气情况如何?")
                .call()
                .chatResponse()
                .getResult()
                .getOutput()
                .getText();

        // 2. 模拟工具返回结果(实际是外部工具调用的返回值)
        ToolResponseMessage toolResponseMessage = new ToolResponseMessage(
                List.of(
                    // ToolResponse 参数:toolCallId, toolName, content
                    new ToolResponseMessage.ToolResponse("1", "获得天气", city)
                )
        );

        // 3. 组合结果
        //    在实际应用中,会把工具返回的信息再发送给 AI,让它结合信息回答
        String toolResponse = toolResponseMessage.getText();
        String result = answer + toolResponse;

        return result;
    }
}

四、系统消息的最佳实践

4.1 系统消息的作用

系统消息(SystemMessage)就像是给 AI 设置的"人格"和"工作规则":

复制代码
// ❌ 模糊的系统消息(AI 可能自由发挥)
.system("你是一个助手")

// ✅ 明确的系统消息(AI 知道该怎么做)
.system("""
    你是一个专业的Java技术博主。
    1. 回答问题时优先使用代码示例
    2. 解释概念时要用通俗易懂的语言
    3. 每次回答控制在500字以内
    4. 使用Markdown格式输出代码块
    """)

4.2 优秀的系统消息包含要素

要素 说明 示例
角色设定 AI 是什么身份 "你是一个法律顾问"
能力边界 能回答什么,不能回答什么 "只回答法律相关问题"
输出格式 要求如何返回结果 "用HTML格式返回"
字数控制 要求输出多长 "控制在300字以内"
风格要求 语气、措辞要求 "用通俗易懂的语言"

五、本章小结

5.1 核心概念回顾

概念 说明
Prompt 提示词,发送给 AI 的完整指令
SystemMessage 系统消息,设定 AI 的角色和行为
UserMessage 用户消息,用户实际提出的问题
AssistantMessage AI 回复的消息对象
ToolResponseMessage 工具调用返回的结果消息

5.2 使用建议

  1. 简单场景 :使用 ChatClient.prompt().system().user().call() 链式 API
  2. 需要精细控制 :创建 SystemMessage + UserMessage 组装 Prompt
  3. 多模型切换 :通过 @Qualifier 区分不同的 ChatModel

本章重点

  1. 理解 Prompt 的组成:系统消息 + 用户消息
  2. 掌握多种创建和使用 Prompt 的方式
  3. 学会在系统中切换使用不同模型

下章剧透(s06):

了解了 Prompt 的基本使用后,下一章我们将学习 PromptTemplate(提示词模板)------如何用占位符实现可复用的提示词。


📝 编辑者 :Flittly

📅 更新时间 :2026年3月

🔗 相关资源:【SpringAIAlibaba新手村系列】(5)Prompt 提示词基础与多种消息类型

相关推荐
wdfk_prog3 小时前
嵌入式面试真题第 10 题:高优化等级下共享状态可见性、内存模型与系统级同步设计
java·linux·开发语言·面试·职场和发展·架构·c
卓怡学长3 小时前
w255基于springboot仓库管理系统
java·数据库·spring boot·spring·intellij-idea
x-cmd5 小时前
Mac 涨价后,本地 AI 还能千元入门吗?
linux·人工智能·macos·ai·agent·amd·本地ai入门
Sirius Wu5 小时前
OpenClaw Skill:Matplotlib 可视化技能 + 沙箱双层隔离完整详解
服务器·网络·人工智能·安全·ai·架构·aigc
这个DBA有点耶6 小时前
SQL调优进阶:从“优化一条SQL”到“优化一个系统”的思维升级
java·大数据·数据库·sql·程序人生·dba·改行学it
csdn2015_6 小时前
springboot读取配置的方法
java·spring boot·spring
AOwhisky7 小时前
下一代容器来了?Docker 宣布原生支持 WebAssembly
java·运维·docker·容器·rust·wasm
chouchuang8 小时前
day-030-综合练习-笔记管理器
开发语言·笔记·python
云云只是个程序马喽9 小时前
海外短剧平台搭建方案:私有化源码系统选型|云微短剧系统技术架构拆解
java·php
龙智DevSecOps解决方案10 小时前
Atlassian团队协作套件技术评估:Jira、Confluence、Loom 与 Rovo Agent 的协同架构分析
ai·atlassian·jira·企业协作