1. Spring AI提示词API概述
Spring AI 1.x系列中的提示词(Prompt)API是开发者与AI模型交互的核心桥梁。提示词作为引导AI生成特定输出的输入内容,其设计和措辞直接影响模型响应质量。在Spring框架生态中,这套API的设计理念与Spring MVC管理视图的方式有异曲同工之妙。
实际开发中,我们通常需要构建包含动态占位符的复杂文本,然后根据用户请求或程序中的其他代码替换这些占位符。这类似于包含某些表达式占位符的SQL语句。随着Spring AI的发展,它正在引入更高级别的AI模型交互抽象。
提示:Prompt类在Spring AI中的角色类似于JDK核心中的JDBC库,而ChatClient则类似于JdbcClient,构建在ChatModel之上并通过Advisor提供更高级的构造能力。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心接口与类解析
2.1 Prompt类结构
Prompt类作为一系列组织好的Message对象和请求ChatOptions的容器,其简化版定义如下:
java复制public class Prompt implements ModelRequest<List<Message>> {
private final List<Message> messages;
private ChatOptions chatOptions;
}
每个Message在提示词中体现特定的角色,其内容和意图各不相同。这些角色可以包含各种元素,从用户查询到AI生成的响应再到相关背景信息。这种安排使得与AI模型的交互变得复杂而详细,因为提示词由多个消息构建,每个消息都被分配了特定的对话角色。
2.2 Message接口体系
Message接口封装了Prompt文本内容、元数据属性集合和称为MessageType的分类:
java复制public interface Content {
String getContent();
Map<String, Object> getMetadata();
}
public interface Message extends Content {
MessageType getMessageType();
}
多模态消息类型还实现了MediaContent接口,提供Media内容对象集合:
java复制public interface MediaContent extends Content {
Collection<Media> getMedia();
}
2.3 消息角色类型
每个消息都被分配一个特定的角色,这些角色对消息进行分类,为AI模型阐明提示词每个部分的上下文和目的。这种结构化方法增强了与AI交流的细微差别和有效性,因为提示词的每个部分在交互中都扮演着独特和定义明确的角色。
主要角色包括:
- 系统角色(SYSTEM):指导AI的行为和响应风格
- 用户角色(USER):表示用户的输入
- 助手角色(ASSISTANT):表示AI生成的响应
- 工具角色(TOOL):专注于返回响应工具调用的额外信息
在Spring AI中表示为枚举:
java复制public enum MessageType {
USER("user"),
ASSISTANT("assistant"),
SYSTEM("system"),
TOOL("tool");
// ...
}
3. PromptTemplate深度解析
3.1 模板渲染机制
Spring AI中提示词模板化的关键组件是PromptTemplate类,它促进创建结构化提示词,然后发送给AI模型进行处理:
java复制public class PromptTemplate implements PromptTemplateActions, PromptTemplateMessageActions {
// 其他方法将在后面讨论
}
这个类使用TemplateRenderer API来渲染模板。默认情况下,Spring AI使用StTemplateRenderer实现,它基于Terence Parr开发的开源StringTemplate引擎。模板变量由{}语法标识,但您也可以配置分隔符以使用其他语法。
TemplateRenderer接口定义:
java复制public interface TemplateRenderer extends BiFunction<String, Map<String, Object>, String> {
@Override
String apply(String template, Map<String, Object> variables);
}
3.2 模板操作接口
PromptTemplate实现的接口支持提示词创建的不同方面:
- PromptTemplateStringActions:专注于创建和渲染提示词字符串
java复制public interface PromptTemplateStringActions {
String render();
String render(Map<String, Object> model);
}
- PromptTemplateMessageActions:专门通过生成和操作Message对象来创建提示词
java复制public interface PromptTemplateMessageActions {
Message createMessage();
Message createMessage(List<Media> mediaList);
Message createMessage(Map<String, Object> model);
}
- PromptTemplateActions:设计用于返回Prompt对象,可以传递给ChatModel以生成响应
java复制public interface PromptTemplateActions extends PromptTemplateStringActions {
Prompt create();
Prompt create(ChatOptions modelOptions);
Prompt create(Map<String, Object> model);
Prompt create(Map<String, Object> model, ChatOptions modelOptions);
}
3.3 实际应用示例
来自AI Workshop的简单示例:
java复制PromptTemplate promptTemplate = new PromptTemplate("告诉我一个关于{topic}的{adjective}笑话");
Prompt prompt = promptTemplate.create(Map.of("adjective", adjective, "topic", topic));
return chatModel.call(prompt).getResult();
更复杂的角色使用示例:
java复制String userText = """
告诉我关于黄金时代海盗时期的三位著名海盗以及他们的事迹。
为每个海盗至少写一句话。
""";
Message userMessage = new UserMessage(userText);
String systemText = """
你是一个帮助人们查找信息的AI助手。
你的名字是{name}
你应该用你的名字回应用户的请求,并且用{voice}的风格。
""";
SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemText);
Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice));
Prompt prompt = new Prompt(List.of(userMessage, systemMessage));
List<Generation> response = chatModel.call(prompt).getResults();
4. 高级用法与最佳实践
4.1 自定义模板渲染器
您可以通过实现TemplateRenderer接口并将其传递给PromptTemplate构建函数来使用自定义模板渲染器:
java复制PromptTemplate promptTemplate = PromptTemplate.builder()
.renderer(StTemplateRenderer.builder()
.startDelimiterToken('<')
.endDelimiterToken('>')
.build())
.template("告诉我5部由<composer>作曲的电影名称。")
.build();
String prompt = promptTemplate.render(Map.of("composer", "John Williams"));
4.2 使用资源而非原始字符串
Spring AI支持org.springframework.core.io.Resource抽象,因此您可以将提示词数据放在可直接在PromptTemplate中使用的文件中:
java复制@Value("classpath:/prompts/system-message.st")
private Resource systemResource;
SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource);
4.3 提示词工程技巧
创建有效提示词时,整合几个关键组件以确保清晰和有效性很重要:
- 指令:向AI提供清晰直接的指令
- 外部上下文:在必要时包含相关背景信息
- 用户输入:这是直接的部分 - 用户的直接请求或问题
- 输出指示器:指定AI响应所需的格式
专业建议:为AI提供预期问答格式的示例可能非常有益。这种做法帮助AI"理解"您的查询的结构和意图,从而产生更准确和相关的结果。
5. 性能优化与注意事项
5.1 令牌(Token)管理
在AI模型处理文本的方式中,令牌具有实际意义,特别是在计费和模型能力方面:
- 计费:AI模型服务通常基于令牌使用量计费
- 模型限制:不同的AI模型有不同的令牌限制
- 上下文窗口:模型的令牌限制决定了其"上下文窗口"
重要提示:当查询"哈姆雷特"时,不需要包含莎士比亚所有其他作品的令牌。只发送处理所需的最小有效信息集至关重要。
5.2 常见问题排查
- 模板渲染失败:检查分隔符是否匹配,确保所有变量都已提供值
- 角色分配错误:确保系统消息和用户消息使用正确的MessageType
- 令牌超限:监控提示词长度,特别是使用长上下文时
- 响应格式不符:在系统指令中明确指定所需的输出格式
5.3 调试技巧
- 在调用chatModel.call()之前,记录完整的Prompt对象
- 使用Token计算工具预估提示词成本
- 对于复杂提示,逐步构建并测试每个部分
- 利用Spring AI的可观测性功能监控AI交互
在实际项目中,我发现将常用提示模板存储在资源文件中,并通过@Value注入的方式管理,可以显著提高代码的可维护性。对于需要国际化的应用,可以结合Spring的MessageSource机制来实现多语言提示词。
