1.前言

在使用SpringAI构建智能应用时,如何精准地控制大模型的行为、输入输出格式以及上下文理解能力,是开发者面临的核心挑战。本文将深入探讨SpringAI框架中的消息类型机制、提示词模板的高级用法以及如何实现结构化数据输出。通过掌握这些技术,开发者可以构建更加可控、专业且符合业务需求的AI应用。

1.消息类型深度解析

在SpringAI框架的交互模型中,Message接口是构建对话的基础。最常用的两种实现类是UserMessageSystemMessage。理解它们的区别对于精准控制AI模型的行为至关重要。

1.1.核心差异对比
维度 UserMessage SystemMessage
角色定义 代表终端用户 代表系统或开发者
主要用途 承载用户的查询、指令或对话内容 设定AI的角色、行为准则、输出规范及对话背景
内容性质 具体的业务数据、自然语言提问 元信息,如“你是一个资深的Java开发专家”或“请用JSON格式输出”
处理优先级 在系统设定的约束框架内被处理 高优先级。模型会优先遵循SystemMessage的指令,以此作为生成回复的基础约束
典型场景 日常问答、任务触发、信息检索 人设设定(Persona)、领域知识限定、风格微调、安全护栏设置
1.2.代码实现与逻辑

在代码层面,SpringAI提供了清晰的API来创建这两种消息。以下示例展示了如何分别构建并发送用户消息和系统消息:

    public String userMessage(String message) {
        Message promptMessage = new UserMessage(message);
        return openAiChatClient.prompt(new Prompt(promptMessage)).call().content();
    }

    public String systemMessage(String message) {
        Message promptMessage = new SystemMessage(message);
        return openAiChatClient.prompt(new Prompt(promptMessage)).call().content();
    }
1.3.请求日志分析

为了更直观地理解两者的区别,我们可以观察发送至大模型API的底层请求日志。

UserMessage请求日志示例:
通常日志中会显示"user",其后紧跟具体的用户输入文本。这表示模型将其视为对话中的用户轮次。

SystemMessage请求日志示例:
日志中会明确标记"system"。模型在处理后续的用户消息时,会先读取该字段中的指令,以此调整生成的概率分布,确保回复符合系统设定的要求。
在这里插入图片描述
在这里插入图片描述

2.提示词模板与资源外部化

在企业级应用开发中,将提示词硬编码在Java代码中是一种反模式。这不仅降低了代码的可维护性,也使得非技术人员(如产品经理)难以调整提示词策略。SpringAI支持类似于Mustache或SpringExpressionLanguage(SpEL)的模板机制,允许我们将提示词定义在外部文件中。

2.1.资源文件准备

首先,在项目的resources目录下创建提示词模板文件和参考文档。

文档路径:src/main/resources/docs/document.md
此文件用于存放作为上下文的参考知识,例如产品手册或技术规范。

模板路径:src/main/resources/prompts/prompt.st

使用以下格式来回答问题。
如果你不知道答案,就说不知道,不要尝试自己编一个答案。

{context}

问题: {question}

有效的答案:
2.2.代码实现:动态填充与文档注入

下面的PromptService类演示了如何加载资源、动态填充模板,并根据业务逻辑决定是否注入外部文档上下文。

public class PromptService {
    @Value("classpath:/docs/document.md")
    private Resource promptDocResource;

    @Value("classpath:/prompts/prompt.st")
    private Resource promptQuestResource;
    
    public String completion(String message, boolean stuffit) {
        PromptTemplate promptTemplate = new PromptTemplate(promptQuestResource);

        Map<String, Object> map = new HashMap<>();
        map.put("question", message);

        // 是否填充 prompt 上下文,以增强大模型回答。
        if (stuffit) {
            map.put("context", promptDocResource);
        } else {
            map.put("context", "");
        }
        return openAiChatClient
                .prompt(promptTemplate.create(map))
                .call().content();
    }
}
2.3.使用说明

通过调用completion方法并设置stuffit参数为true,开发者可以轻松实现基于特定知识库的问答。这种方式有效解决了大模型知识滞后和幻觉问题。

3.结构化输出解析

LLM默认输出的是非结构化文本。但在后端开发中,我们通常需要将提取到的信息直接映射为Java对象(POJO)以便于业务处理。SpringAI提供了便捷的.entity()方法,支持将模型输出自动反序列化为指定类型的对象。

3.1.输出基本类型:布尔值判断

以下示例展示了如何判断用户输入是否包含投诉意图。这种方法常用于客服系统的工单自动分类或情绪预警。

    public Boolean isComplaint(String message) {
        Boolean content = openAiChatClient.prompt()
                .system("""
                        请判断用户信息是否表达了投诉意图?
                        只能用 true 或 false 回答,不要输出多余内容
                        """)
                .user(message)
                .call()
                .entity(Boolean.class);
        return content;
    }
3.2.输出复杂对象:信息提取

在处理表单自动填充或订单处理等场景时,从自然语言中提取结构化信息(如地址)非常有用。

首先定义一个标准的POJO类,字段命名应清晰且符合业务语义。

@Data
public class Address {
    private String name;
    private String phone;
    private String province;
    private String city;
    private String district;
    private String detail;
}

利用SpringAI的实体提取功能,将非结构化的地址字符串转换为Address对象。

    public Address getAddress(String message) {
        Address content = openAiChatClient.prompt()
                .system("""
                        请从内容中提取收货信息
                        """)
                .user(message)
                .call()
                .entity(Address.class);
        return content;
    }

编写单元测试验证提取的准确性。

    @Test
    void getAddress() {
        Address address = structureService.getAddress("收货人:张三,电话188xxxxxxxx,地址:湖南省长沙市xx区xx栋xx单元xx号");
        log.info("address:{}", address);
    }

通过结构化输出,我们无需编写复杂的正则表达式或解析规则,即可利用LLM强大的语义理解能力,将杂乱的文本转化为标准化的业务数据,极大降低了开发成本并提高了系统的灵活性。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐