解析 Prompt 工程中的四大核心角色

在大语言模型(LLM)交互中,Prompt 工程的本质是通过明确角色分工实现 "人机协作" 的高效闭环。无论是简单问答还是复杂的工具调用场景,都离不开四大核心角色的协同:系统角色(System)用户角色(User)工具角色(Tool)响应处理角色(Response Handler)。这四大角色共同构成了 LLM 应用的交互骨架,决定了 AI 行为的边界、交互的流畅度和结果的可用性。

代码地址

一、系统角色(System):定义 AI 的 "行为准则"

系统角色是 LLM 的 "隐形指挥官",通过预设指令定义 AI 的身份、能力边界和输出规范。它决定了 AI"是什么样的存在",直接影响交互的专业性和可靠性。

核心职责

  • 明确 AI 的身份定位(如法律助手、翻译官)
  • 划定能力边界(如 "只回答法律问题")
  • 规范输出格式(如 "以 HTML 格式返回")
  • 设定交互风格(如 "简洁明了"、"详细严谨")

代码实现与解析

在 Spring AI 中,系统角色通过SystemMessageprompt().system()方法定义,是 Prompt 中优先级最高的指令。

java 复制代码
// 场景1:法律助手角色定义(链式API)
@GetMapping("/prompt/chat")
public Flux<String> chat(String question) {
    return deepseekChatClient.prompt()
            // 系统角色:明确身份和边界
            .system("你是一个法律助手,只回答法律相关问题。" +
                    "回答需基于中国现行法律条文,避免模糊表述。" +
                    "若问题超出法律范围,直接回复'该问题不属于法律范畴'")
            .user(question)  // 用户输入
            .stream()
            .content();
}
java 复制代码
// 场景3:格式约束的系统角色(手动构建Prompt)
@GetMapping("/prompt/chat3")
public Flux<String> chat3(String question) {
    // 系统角色:强制输出格式
    SystemMessage systemMessage = new SystemMessage(
        "你是内容排版助手,需将用户问题的答案以HTML格式返回。" +
        "要求:标题用<h3>,段落用<p>,重点用<strong>,列表用<ul><li>"
    );
    UserMessage userMessage = new UserMessage(question);
    Prompt prompt = new Prompt(userMessage, systemMessage);  // 组合系统指令与用户输入
    // ...
}

关键设计原则

  • 指令具体化:避免模糊表述(如不说 "回答专业",而说 "基于中国现行法律条文")
  • 边界清晰化:明确 "不能做什么"(如 "超出法律范围直接拒绝")
  • 格式标准化:对输出格式的约束要可执行(如明确 HTML 标签规则)

二、用户角色(User):交互的 "发起者与需求方"

用户角色是交互的源头,通过输入传递需求。它的核心价值是清晰、准确地表达意图,为 AI 提供足够的上下文信息。

核心职责

  • 传递原始需求(如 "解释《民法典》第 1043 条")
  • 提供必要上下文(如 "我是企业 HR,想了解劳动合同解除的条件")
  • 反馈交互结果(如 "请用更通俗的语言解释")

代码实现与解析

用户角色的输入通过UserMessageprompt().user()方法传递,在多轮对话中还需要携带历史上下文。

java 复制代码
// 单轮对话:简单用户输入
@GetMapping("/prompt/chat4")
public String chat4(String question) {
    // 用户角色输入直接通过user()方法传递
    AssistantMessage assistantMessage = deepseekChatClient.prompt()
            .user(question)  // 用户需求:question参数
            .call()
            .chatResponse()
            .getResult()
            .getOutput();
    return assistantMessage.getText();
}
java 复制代码
// 多轮对话:携带上下文的用户角色(伪代码)
public String multiTurnChat(String newQuestion, List<Message> history) {
    // 构建包含历史的Prompt:历史消息+新用户输入
    List<Message> messages = new ArrayList<>(history);
    messages.add(new UserMessage(newQuestion));  // 新的用户需求
    Prompt prompt = new Prompt(messages);
    
    return qwenChatModel.call(prompt)
            .getResult()
            .getOutput()
            .getText();
}

最佳实践

  • 上下文完整性:复杂问题需提供背景(如 "我公司员工连续旷工 3 天,能否解除合同?" 比 "如何解除合同" 更有效)
  • 需求明确化:避免歧义(如不说 "解释这个法律条文",而说 "解释《民法典》第 1043 条在婚姻纠纷中的应用")
  • 渐进式提问:复杂需求分步骤提出(先问 "什么是劳动合同",再问 "解除条件")

三、工具角色(Tool):AI 的 "能力扩展器"

工具角色是 LLM 突破自身知识局限的 "外挂",通过调用外部系统(如 API、数据库、计算器)获取实时信息或执行复杂操作,让 AI 从 "纯文本交互" 升级为 "实际问题解决者"。

核心职责

  • 提供实时数据(如天气查询、股票行情)
  • 执行计算逻辑(如财务计算、数据分析)
  • 操作外部系统(如发送邮件、查询数据库)
  • 将工具结果格式化回传给 AI

代码实现与解析

Spring AI 通过ToolResponseMessage封装工具调用结果,实现 "AI - 工具 - AI" 的闭环。

java 复制代码
@GetMapping("/prompt/chat5")
public String chat5(String city) {
    // 1. 第一步:AI判断是否需要调用工具(模拟场景)
    String initialAnswer = deepseekChatClient.prompt()
            .user(city + "未来3天天气情况如何?")  // 用户问天气(AI无实时数据)
            .call()
            .chatResponse()
            .getResult()
            .getOutput()
            .getText();
    // (实际场景中,AI会返回工具调用指令,如{"tool":"weatherApi","params":{"city":"北京"}})
    
    // 2. 第二步:调用工具获取数据(模拟天气API调用)
    String weatherData = mockWeatherApiCall(city);  // 工具角色:返回实时天气
    
    // 3. 第三步:工具结果封装为ToolResponseMessage回传给AI
    ToolResponseMessage toolResponse = new ToolResponseMessage(
        List.of(new ToolResponseMessage.ToolResponse(
            "weather_api_123",  // 工具调用ID(用于多工具区分)
            "获取天气数据",     // 工具描述
            weatherData         // 工具返回结果
        ))
    );
    
    // 4. 第四步:AI基于工具结果生成最终回答
    String finalAnswer = deepseekChatClient.prompt()
            .messages(
                new UserMessage(city + "未来3天天气情况如何?"),
                new AssistantMessage(initialAnswer),  // 历史:AI的初步响应
                toolResponse                          // 工具返回结果
            )
            .call()
            .chatResponse()
            .getResult()
            .getOutput()
            .getText();
    
    return finalAnswer;
}

// 模拟天气工具(工具角色的具体实现)
private String mockWeatherApiCall(String city) {
    return city + "未来3天天气:晴/25℃,多云/23℃,小雨/20℃";
}

工具调用流程

  1. 触发判断:AI 接收用户需求后,判断是否需要工具(基于自身知识局限性)
  2. 工具调用:应用程序解析 AI 的工具调用指令,调用对应外部系统
  3. 结果回传 :将工具返回的原始数据用ToolResponseMessage封装,作为新消息传入 Prompt
  4. 二次处理:AI 基于工具结果生成自然语言回答

四、响应处理角色(Response Handler):结果的 "最终塑造者"

响应处理角色负责将 AI 的原始输出转换为应用所需的形式,确保结果可用、易用。它是连接 AI 输出与用户体验的关键环节。

核心职责

  • 格式转换(如将纯文本转为 HTML、JSON)
  • 流式处理(实时返回长文本结果)
  • 结果过滤(去除敏感信息、修正格式错误)
  • 元数据处理(提取 token 统计、调用耗时等信息)

代码实现与解析

在 Spring AI 中,响应处理通过响应式操作(如mapfilter)或同步处理实现,适配不同的交互场景。

java 复制代码
// 场景2:获取完整元数据(响应处理:保留原始信息)
@GetMapping("/prompt/chat2")
public Flux<ChatResponse> chat2(String question) {
    SystemMessage systemMessage = new SystemMessage("你是一个讲故事的助手,擅长创作童话");
    UserMessage userMessage = new UserMessage(question);
    Prompt prompt = new Prompt(userMessage, systemMessage);
    
    // 响应处理:直接返回完整ChatResponse(包含元数据)
    return deepseekChatModel.stream(prompt);
    // ChatResponse包含:模型名称、token使用量、响应时间、完整消息等
}

// 场景3:格式转换(响应处理:提取并转换文本)
@GetMapping("/prompt/chat3")
public Flux<String> chat3(String question) {
    // ... 省略Prompt构建 ...
    
    // 响应处理:从ChatResponse中提取文本,并通过map转换
    return deepseekChatModel.stream(prompt)
            .map(response -> {
                String rawText = response.getResults().get(0).getOutput().getText();
                // 额外处理:去除可能的格式错误(如多余的HTML标签)
                return rawText.replaceAll("<[^>]*>", ""); 
            });
}

// 场景1:流式响应(响应处理:实时推送)
@GetMapping("/prompt/chat")
public Flux<String> chat(String question) {
    // ... 省略Prompt构建 ...
    
    // 响应处理:通过stream()实现流式返回,前端可逐段渲染
    return deepseekChatClient.prompt()
            .system(...)
            .user(question)
            .stream()  // 触发流式处理
            .content(); // 提取文本内容
}

响应处理策略

  • 实时性优先 :长文本场景用流式响应(Flux),避免用户等待
  • 结构化优先:需存储或二次处理的场景,转换为 JSON/XML 等格式
  • 透明性优先:调试或成本监控场景,保留完整元数据(token 数、模型信息)

四大角色的协同逻辑:从需求到结果的闭环

四大角色并非孤立存在,而是形成了完整的交互链路:

plaintext 复制代码
用户角色(提需求)→ 系统角色(定规则)→ AI(初处理)
→ [工具角色(补能力)→ AI(再处理)] → 响应处理角色(塑结果)→ 用户(获答案)
  • 系统角色贯穿全程,为 AI 提供 "行为指南"
  • 用户角色是起点,需求的质量决定交互效率
  • 工具角色是扩展,解决 AI"做不到" 的问题
  • 响应处理角色是终点,决定用户最终体验

例如在 "法律查询 + 案例检索" 场景中:

  1. 用户角色提出 "劳动合同解除的赔偿标准"(需求)
  2. 系统角色定义 "法律助手,需引用法条和案例"(规则)
  3. AI 初步回答法条内容,但发现需要最新案例(触发工具调用)
  4. 工具角色调用 "裁判文书网 API" 获取案例(扩展能力)
  5. 响应处理角色将法条 + 案例整合成 HTML 格式(结果塑造)
  6. 用户获得结构化的法律参考(最终体验)

总结:角色设计是 Prompt 工程的核心

四大角色的设计质量直接决定 LLM 应用的效果:系统角色定义 AI 的 "专业性",用户角色决定交互的 "准确性",工具角色扩展 AI 的 "能力边界",响应处理角色保障结果的 "可用性"。

在实际开发中,需根据业务场景灵活调整角色权重:

  • 客服场景:强化系统角色的 "服务语气" 和响应处理的 "实时性"
  • 数据分析场景:强化工具角色的 "计算能力" 和响应处理的 "结构化"
  • 创作场景:弱化系统角色的约束,强化用户角色的 "创意引导"

理解并掌握这四大角色的协同逻辑,是从 "简单调用 LLM" 到 "构建企业级 LLM 应用" 的关键一步。

相关推荐
pangtao20259 小时前
【瑞萨RA × Zephyr评测】看门狗
java·后端·spring
任子菲阳9 小时前
学Javaweb第四天——springboot入门
java·spring·mybatis
Coder_Boy_10 小时前
基于SpringAI的智能平台基座开发-(十一)
人工智能·spring·langchain·langchain4j
爱吃山竹的大肚肚11 小时前
优化SQL:如何使用 EXPLAIN
java·数据库·spring boot·sql·spring
向上的车轮11 小时前
Apache Camel 与 Spring Integration的区别是什么?
java·spring·apache
URBBRGROUN46711 小时前
Spring AI Alibaba入门
java·人工智能·spring
码界奇点12 小时前
基于Spring Boot和Vue.js的视频点播管理系统设计与实现
java·vue.js·spring boot·后端·spring·毕业设计·源代码管理
爱吃山竹的大肚肚12 小时前
MySQL 支持的各类索引
java·数据库·sql·mysql·spring·spring cloud
高老庄小呆子12 小时前
SpringBoot3.5.4 引入Knife4j的官方start包
spring
廋到被风吹走12 小时前
【Spring】Spring Boot详细介绍
java·spring boot·spring