SpringAI提示词模板实战:从概念到构建动态AI应用

发布时间:2026/8/9 8:23:41
SpringAI提示词模板实战:从概念到构建动态AI应用 你好我是专注于分享Java与AI应用实战的开发者。在构建基于大语言模型LLM的应用时我们常常需要向模型发送结构化的指令。如果每次请求都手动拼接字符串不仅代码冗长、难以维护更无法实现指令的动态化与复用。这正是提示词模板Prompt Template要解决的核心痛点。本文将深入解析SpringAI框架中的提示词模板从核心概念到项目实战手把手带你掌握如何高效、优雅地构建AI应用的“对话蓝图”。无论你是刚开始接触SpringAI还是已经用它写过简单Demo本文都将帮助你系统性地理解提示词模板的运作机制、多种用法以及工程最佳实践让你能轻松应对从简单问答到复杂Agent工作流的各种场景。1. 提示词模板AI应用的指令引擎1.1 什么是提示词模板简单来说提示词模板是一个预定义的文本结构其中包含固定部分和可变部分占位符。它允许开发者将复杂的提示逻辑抽象成可配置、可复用的组件。举个例子原始硬编码String prompt “请将以下英文翻译成中文” userInput;使用模板定义一个模板“请将以下{input_language}翻译成{output_language}{text}”。使用时只需传入input_language“英文”output_language“中文”textuserInput这三个变量即可动态生成最终提示。在SpringAI中提示词模板是Prompt对象的核心组成部分。一个Prompt通常包含一个或多个Message消息而Message的内容就可以通过模板来生成。1.2 为什么需要它关注点分离将业务逻辑要做什么与具体的提示文本构造怎么做解耦。提高可维护性当需要调整提示词时只需修改模板定义而无需在业务代码中四处搜索和替换。支持动态化轻松实现根据用户输入、上下文或系统状态生成不同的提示。促进复用通用的提示模式如总结、翻译、代码审查可以封装成模板在整个项目中共享。便于测试可以独立测试模板生成的结果是否符合预期。SpringAI的模板设计借鉴了LangChain等框架的思想提供了强大且灵活的字符串插值能力是构建复杂AI工作流的基石。2. 环境准备与项目搭建在开始编码前我们需要一个可运行的SpringAI项目环境。2.1 基础环境要求JDK: 17 或更高版本SpringAI 推荐构建工具: Maven 3.6 或 Gradle 7.xIDE: IntelliJ IDEA, VS Code 或 EclipseLLM API 密钥: 你需要一个可用的AI模型服务API密钥例如 OpenAI GPT、Azure OpenAI、Ollama本地或阿里云百炼/通义千问等。2.2 创建Spring Boot项目使用 Spring Initializr 快速生成项目依赖选择Spring Web(用于构建Web应用示例)Spring AI(核心依赖)如果你使用Maven生成项目的pom.xml中需要包含Spring AI的BOM物料清单和具体的模型启动器依赖。注意Spring AI版本迭代较快请以官方文档为准。以下是一个基于OpenAI的Maven配置示例?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.2.0/version !-- 使用与Spring AI兼容的版本 -- relativePath/ /parent groupIdcom.example/groupId artifactIdspring-ai-demo/artifactId version0.0.1-SNAPSHOT/version namespring-ai-demo/name descriptionDemo project for Spring AI/description properties java.version17/java.version spring-ai.version0.8.1/spring-ai.version !-- 请检查最新版本 -- /properties dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version${spring-ai.version}/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Spring AI OpenAI 启动器 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-openai-spring-boot-starter/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId /plugin /plugins /build /project2.3 配置API密钥在application.yml或application.properties中配置你的模型连接信息。以OpenAI为例# application.yml spring: ai: openai: api-key: ${OPENAI_API_KEY:your-api-key-here} # 建议使用环境变量 chat: options: model: gpt-3.5-turbo # 或 gpt-4 temperature: 0.7重要永远不要将API密钥硬编码在代码中或提交到版本控制系统。使用环境变量或安全的配置管理服务。3. 核心PromptTemplate 类详解SpringAI提供了org.springframework.ai.prompt.PromptTemplate类注意在早期版本中它可能在org.springframework.ai.core包下请根据版本调整导入。这是操作提示词模板的主要入口。3.1 基本用法字符串模板最简单的模板就是包含{variable}格式占位符的字符串。import org.springframework.ai.prompt.PromptTemplate; import org.springframework.ai.prompt.Prompt; // 1. 定义一个模板字符串 String templateText “你好请为我写一首关于{theme}的{poem_type}诗。”; // 2. 创建 PromptTemplate 对象 PromptTemplate promptTemplate new PromptTemplate(templateText); // 3. 使用 Map 提供变量值创建最终的 Prompt 对象 MapString, Object variables new HashMap(); variables.put(“theme”, “春天”); variables.put(“poem_type”, “五言绝句”); Prompt prompt promptTemplate.create(variables); // 4. 现在可以将这个prompt发送给ChatClient // String response chatClient.call(prompt.getContents()); System.out.println(prompt.getContents()); // 输出你好请为我写一首关于春天的五言绝句诗。3.2 模板语法进阶SpringAI的模板语法支持一些基础表达式增强了灵活性。默认值可以为变量设置默认值当Map中未提供该变量时使用。String template “推荐一些{category科技}领域的入门书籍。”; PromptTemplate pt new PromptTemplate(template); Prompt p1 pt.create(Map.of()); // 使用默认值“科技” Prompt p2 pt.create(Map.of(“category”, “历史”)); // 使用“历史”调用方法有限支持某些版本支持在模板中调用变量的方法。但这依赖于底层表达式引擎如Spring Expression Language - SpEL的支持并非所有场景都稳定需谨慎使用。// 假设 variable 是一个有 getName() 方法的对象 // String template “用户{user.name} 你好”; // 更通用的做法是在Java代码中处理好再传入。最佳实践保持模板简单。复杂的逻辑处理尽量在Java代码中完成然后将结果作为变量传入模板。这使模板更易于理解和维护。3.3 在Message中使用模板在实际应用中我们通常构建包含系统指令、用户消息、历史记录等在内的复杂对话。Prompt由多个Message组成每个Message都可以使用模板。SpringAI定义了常见的消息角色SystemMessage系统指令设定AI的行为角色和约束。UserMessage用户输入。AssistantMessageAI助手的回复。import org.springframework.ai.prompt.SystemMessage; import org.springframework.ai.prompt.UserMessage; import org.springframework.ai.prompt.Prompt; // 系统提示词模板 String systemTemplate “你是一位专业的{role}。请用{style}的风格回答问题。”; PromptTemplate systemPromptTemplate new PromptTemplate(systemTemplate); SystemMessage systemMessage new SystemMessage(systemPromptTemplate.create( Map.of(“role”, “软件架构师”, “style”, “简洁清晰”) ).getContents()); // 用户消息模板 String userTemplate “请为{project_type}项目设计一个高层架构需要考虑{requirement}。”; PromptTemplate userPromptTemplate new PromptTemplate(userTemplate); UserMessage userMessage new UserMessage(userPromptTemplate.create( Map.of(“project_type”, “高并发电商平台”, “requirement”, “微服务、缓存和数据库分库分表”) ).getContents()); // 构建完整的Prompt Prompt chatPrompt new Prompt(List.of(systemMessage, userMessage)); // 发送请求 // ChatResponse response chatClient.call(chatPrompt);这种方式使得系统指令和用户查询都能动态化非常适合构建需要根据场景切换角色和任务的AI应用。4. 完整实战案例构建一个动态翻译服务让我们通过一个完整的REST API服务将上述知识串联起来。这个服务能接受源语言、目标语言和文本动态生成翻译提示并调用AI模型。4.1 项目结构src/main/java/com/example/ai/ ├── AIDemoApplication.java ├── controller/ │ └── TranslationController.java ├── service/ │ └── TranslationService.java └── dto/ └── TranslationRequest.java4.2 创建请求DTO// file: src/main/java/com/example/ai/dto/TranslationRequest.java package com.example.ai.dto; public class TranslationRequest { private String sourceLang; private String targetLang; private String text; // 构造函数、Getter和Setter省略请务必加上 public TranslationRequest() {} public TranslationRequest(String sourceLang, String targetLang, String text) { this.sourceLang sourceLang; this.targetLang targetLang; this.text text; } // ... getters and setters }4.3 实现服务层服务层封装了提示词模板的创建和AI调用逻辑。// file: src/main/java/com/example/ai/service/TranslationService.java package com.example.ai.service; import org.springframework.ai.chat.ChatClient; import org.springframework.ai.chat.ChatResponse; import org.springframework.ai.prompt.Prompt; import org.springframework.ai.prompt.PromptTemplate; import org.springframework.ai.prompt.SystemMessage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Map; Service public class TranslationService { private final ChatClient chatClient; // 系统提示词模板定义翻译器的角色和行为 private static final String SYSTEM_TEMPLATE “”” 你是一位专业的语言翻译专家。 你的任务是将用户提供的文本从 {source_lang} 精准地翻译成 {target_lang}。 翻译要求 1. 保持原文含义不变。 2. 译文符合{target_lang}的语言习惯流畅自然。 3. 如果是技术术语请使用公认的标准译法。 4. 只输出翻译后的结果不要添加任何解释、说明或额外内容。 “””; // 用户消息模板用于组装待翻译文本 private static final String USER_TEMPLATE “待翻译文本{text}”; Autowired public TranslationService(ChatClient chatClient) { this.chatClient chatClient; } public String translate(String sourceLang, String targetLang, String text) { // 1. 创建系统消息模板并渲染 PromptTemplate systemPromptTemplate new PromptTemplate(SYSTEM_TEMPLATE); String systemMessageContent systemPromptTemplate.create( Map.of(“source_lang”, sourceLang, “target_lang”, targetLang) ).getContents(); SystemMessage systemMessage new SystemMessage(systemMessageContent); // 2. 创建用户消息模板并渲染 PromptTemplate userPromptTemplate new PromptTemplate(USER_TEMPLATE); String userMessageContent userPromptTemplate.create(Map.of(“text”, text)).getContents(); org.springframework.ai.prompt.UserMessage userMessage new org.springframework.ai.prompt.UserMessage(userMessageContent); // 3. 构建完整Prompt Prompt prompt new Prompt(List.of(systemMessage, userMessage)); // 4. 调用AI模型并返回结果 ChatResponse response chatClient.call(prompt); return response.getGeneration().getContent(); } }4.4 创建控制器// file: src/main/java/com/example/ai/controller/TranslationController.java package com.example.ai.controller; import com.example.ai.dto.TranslationRequest; import com.example.ai.service.TranslationService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; RestController RequestMapping(“/api/translate”) public class TranslationController { private final TranslationService translationService; Autowired public TranslationController(TranslationService translationService) { this.translationService translationService; } PostMapping public String doTranslate(RequestBody TranslationRequest request) { return translationService.translate( request.getSourceLang(), request.getTargetLang(), request.getText() ); } // 提供一个简单的GET接口用于测试 GetMapping(“/test”) public String testTranslate() { // 示例英文翻译成中文 return translationService.translate(“英语”, “中文”, “Hello, Spring AI! This is a prompt template demo.”); } }4.5 运行与验证启动Spring Boot应用 (AIDemoApplication)。使用curl、Postman 或浏览器测试。测试GET接口访问http://localhost:8080/api/translate/test预期返回“你好Spring AI这是一个提示词模板演示。”测试POST接口curl -X POST http://localhost:8080/api/translate \ -H “Content-Type: application/json” \ -d ‘{“sourceLang”: “法语”, “targetLang”: “中文”, “text”: “Bonjour le monde”}’预期返回“你好世界”。这个案例展示了如何将业务参数语言对、文本通过提示词模板动态注入到AI指令中构建出一个灵活可配置的翻译服务。你可以轻松扩展它比如增加“翻译风格正式/口语化”等参数。5. 高级应用与模式5.1 模板的复用与集中管理在大型项目中硬编码的模板字符串散落在各个Service中会难以管理。建议采用以下策略配置文件管理将模板字符串放在application.yml或独立的属性文件中。# application.yml spring: ai: prompts: translation-system: | 你是一位专业的语言翻译专家... translation-user: “待翻译文本{text}” code-review-system: | 你是一位资深代码审查员...然后在代码中通过Value注解注入。模板工厂或注册表创建一个PromptTemplateRegistry类统一注册和获取各种模板。Component public class PromptTemplateRegistry { private final MapString, PromptTemplate templateMap new ConcurrentHashMap(); PostConstruct public void init() { templateMap.put(“translation.system”, new PromptTemplate(systemTemplateString)); templateMap.put(“translation.user”, new PromptTemplate(userTemplateString)); // ... 加载其他模板 } public PromptTemplate getTemplate(String name) { return templateMap.get(name); } }5.2 构建复杂工作流Agent雏形提示词模板是构建AI Agent智能体工作流的关键。一个简单的Agent可能包含多个步骤每个步骤都有自己的模板。例如一个“代码生成与审查”Agent的工作流需求分析步骤使用模板A让AI理解用户需求并拆解。代码生成步骤使用模板B让AI根据拆解的需求生成代码。代码审查步骤使用模板C让AI审查生成的代码提出改进意见。// 伪代码示例 public class SimpleCodeAgent { private ChatClient chatClient; private PromptTemplate analysisTemplate; // “请分析需求{requirement}并输出关键功能点。” private PromptTemplate generationTemplate; // “根据以下功能点生成{language}代码{functions}” private PromptTemplate reviewTemplate; // “审查以下代码{code}指出潜在问题。” public String execute(String requirement, String language) { // 步骤1分析 String functions chatClient.call(analysisTemplate.create(Map.of(“requirement”, requirement))).getContent(); // 步骤2生成 String code chatClient.call(generationTemplate.create(Map.of(“language”, language, “functions”, functions))).getContent(); // 步骤3审查 String review chatClient.call(reviewTemplate.create(Map.of(“code”, code))).getContent(); return “生成的代码\n” code “\n\n审查意见\n” review; } }这就是“vibe coding 搭建工作流”的一个简单体现。通过串联不同的提示词模板引导AI完成一系列任务。5.3 与Spring AI ChatClient 深度集成在更简单的场景下Spring AI 的ChatClient可以直接接受Prompt对象。我们的实战案例已经展示了这一点。ChatClient会自动处理与后台AI服务OpenAI, Azure, Ollama等的通信、解析响应和异常处理让我们能更专注于提示工程本身。6. 常见问题与排查思路在使用SpringAI提示词模板时你可能会遇到以下问题问题现象可能原因排查与解决思路抛出IllegalArgumentException提示变量未找到模板字符串中的占位符变量名与传入Map中的key不匹配。1. 检查模板中的变量名如{name}。2. 检查传入Map的key是否为“name”大小写敏感。3. 使用调试器打印模板字符串和变量Map。AI回复不符合预期似乎忽略了系统指令1. 系统消息未被正确构建或加入Prompt。2. 使用的模型不完全遵循系统指令某些模型或配置下。3. 用户消息覆盖了系统指令。1. 确保SystemMessage被正确创建并添加到Prompt的消息列表首位。2. 检查最终生成的Prompt内容确认系统指令是否存在。3. 尝试调整系统指令的措辞使其更明确、强硬。模板渲染后出现乱码或格式错误模板字符串中包含特殊字符如换行符、引号在Java字符串或YAML中转义不正确。1. 对于多行模板使用Java Text Block语法“”” … “””。2. 在YAML中使用 调用chatClient.call()超时或报错1. 网络问题或API密钥错误。2. 模型名称配置错误。3. 生成的Prompt过长超出模型上下文限制。1. 检查网络连接和API密钥配置。2. 确认application.yml中配置的模型名称是有效的。3. 估算Prompt的token数量对于长文本考虑分块处理。使用{variable.method()}语法报错当前版本的SpringAI模板引擎可能不支持复杂的SpEL表达式。推荐做法避免在模板中进行复杂计算。在Java代码中处理好数据将结果作为简单变量传入模板。7. 最佳实践与工程建议职责分离将提示词模板视为“视图”将业务逻辑和数据准备视为“控制器”。不要在模板中编写复杂逻辑。版本化模板当对模板进行重大修改时考虑引入版本标识如prompt_v1prompt_v2便于A/B测试和回滚。外部化配置将重要的、可能频繁调整的模板放在配置文件或数据库中实现热更新无需重新部署应用。测试模板渲染为关键的PromptTemplate创建单元测试验证给定输入变量时渲染出的Prompt是否符合预期。这能有效防止因模板修改导致的运行时错误。关注Token消耗模板中的每一个字符包括占位符和固定文本都会计入Token消耗。优化模板去除冗余词语在清晰的前提下力求简洁。安全与伦理永远不要将未经处理的用户输入直接拼接进模板尽管模板变量本身有一定隔离。警惕提示词注入攻击避免模板被用户输入恶意篡改从而让AI执行危险操作。对用户输入进行必要的清洗和校验。为生产环境做好准备在生产中使用时务必配置合理的超时、重试、熔断机制可通过Spring Cloud CircuitBreaker等并监控AI调用的延迟、成功率和费用。掌握SpringAI的提示词模板就如同掌握了与大型语言模型高效沟通的“编程语言”。它让你从繁琐的字符串拼接中解放出来能够以结构化和可维护的方式构建复杂的AI交互逻辑。从简单的文本替换到驱动多步Agent工作流提示词模板都是不可或缺的核心组件。建议你从本文的翻译服务案例出发尝试改造你现有的项目或者创建一个新的小应用例如一个根据商品类别和风格生成营销文案的服务。一个接收Bug描述自动生成测试用例的服务。一个结合多个模板的会议纪要总结Agent。实践过程中你会更深刻地体会到模板在组织AI指令、分离关注点方面的强大威力。