解析 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 应用" 的关键一步。

相关推荐
兮动人9 小时前
Spring中@Configuration注解的proxyBeanMethods属性详解
java·后端·spring
Jing_jing_X10 小时前
Spring 自动注入是怎么实现的?从 @Component 到 @Autowired 的完整流程
java·后端·spring
李昊哲小课11 小时前
spring 中 HttpStatus 与 ResponseEntity
spring boot·后端·spring·http·spring cloud·restful
后端小张13 小时前
【JAVA 进阶】SpringBoot集成Sa-Token权限校验框架深度解析
java·spring boot·spring·架构·sa-token·springboot·权限框架
DokiDoki之父14 小时前
SpringMVC—请求映射路径 & get请求与Post请求发送请求参数 & 5种类型参数传递 & json数据传递参数 & 日期型参数的传递 & 响应
spring
weixin_4196583114 小时前
Spring的三级缓存和SpringMVC的流程
java·spring·缓存
吹晚风吧1 天前
spring是如何解决循环依赖的(二级缓存不行吗)?
java·spring·循环依赖·三级缓存
九丶弟1 天前
SpringBoot的cache使用说明
java·spring boot·spring·cache
信仰_2739932431 天前
Mybatis-Spring重要组件介绍
java·spring·mybatis