1、什么是提示词
英文单词:prompt,中文:提示词,就是用户(或开发者)给AI的指令或问题,用来引导AI生成回复。好的提示词能帮助AI更准确地理解用户的需求。
1.1、核心原则(PROMPT框架)
- P - 明确目标 (Purpose)
- 明确你想要的结果类型(分析、创作、解释等)
- R - 提供角色 (Role)
- 给AI分配一个专业角色
- O - 输出格式 (Output Format)
- 指定想要的格式(JSON、表格、代码等)
- M - 详细描述 (Minutiae)
- 包含细节、约束条件和上下文
- P - 参数要求 (Parameters)
- 字数、语言、风格等具体要求
- T - 测试迭代 (Test & Iterate)
- 不断优化提示词
1.2、实用技巧
- 使用分隔符:用```、—、###等分隔不同部分
- 温度参数:创造性任务用高temperature(0.8-1.0),准确性任务用低temperature(0.2-0.5)
- 分步骤:复杂任务分解成子任务
- 限制长度:用"用一句话…"、"简要总结…"控制输出
- 指定视角:“从技术专家角度…”、"以用户视角…"等
简而言之:写提示词时,尽量描述清楚需求(或说约束条件),AI给的回复才会符合预期结果。不符合要求,根据回复的结果进行调整提示词,再进行提问。建议使用markdown格式。
1.3、提示词类型
在Spring AI中用MessageType枚举类,来定义提示词类型
publicenumMessageType{USER("user"),// 用户发送的消息(显示)ASSISTANT("assistant"),// AI助手的回复消息SYSTEM("system"),// 系统指令或初始提示(隐式)TOOL("tool");// 工具调用相关的消息(用于Function Calling).....}区分消息(即提示词)类型的目的
- 角色管理:AI模型需要知道每条消息是谁产生的,
- 上下文维护:维护正确的对话轮次和顺序
- 系统指令:
SYSTEM消息,通常用于设置AI的行为模式 - 工具集成:
TOOL类型用于AI调用外部工具的交互
使用说明:
开发人员主要创建:USER、SYSTEM、TOOL消息;AI模型主要创建:ASSISTANT消息,只有在特定场景(如历史记录、测试)下,开发人员才需要手动创建ASSISTANT消息。
接下来,是代码实战部分,还是在ollama的项目基础上写demo。
2、Spring AI ChatClient + 模板化实现
提示词可以无参数模板,一段文本说明;也可以动态参数模板,还可以是模板文件热重载的方式。
无参数模板,即固定文本一般用于SYSTEM消息,作用是初始提示信息。
动态参数模板,比如不同登录用户,给出的不同问候语,或者不同角色使用不同提示词内容,可用于SYSTEM和USER消息,对于USER消息一般是要拼接上用户输入的消息,不然每次的提问都是相同内容了。
模板文件热重载,可以是无参数,也可以是带参数。使用模板文件的方式,主要是为了方便调整提示词内容。
由于设置提示词是使用ChatClient,因为如果不清楚的,请移步我的另一篇文章《Spring AI ChatClient:让你的AI应用轻松适配各大模型》。
以下示例代码,为方便查看返回消息,都是使用文本生成测试,返回值是Flux类型。提示词都是以markdown格式。
2.1、无参数模板
提示词示例:
# 角色设定 你是Spring Boot专家小助手 # 回答要求1.分步骤说明2.给出最小配置示例3.提示常见坑点4.提供验证方法 # 格式要求-使用emoji区分步骤-配置代码单独显示-关键配置项加粗创建测试类:PromptController,写接口调用API进行测试,方便实时修改提示信息与接口交互测试,在接口加了一个msg参数接收用户输入的信息。
@RestController@RequestMapping(value="/ai/prompt")@Slf4jpublicclassPromptController{@AutowiredprivateOllamaChatModelollamaChatModel;/** * 测试系统提示词 * @param msg 用户提示信息 * @return */@RequestMapping(value="/system/flux",produces=MediaType.APPLICATION_JSON_VALUE+"; charset=UTF-8")publicFlux<String>systemPromptTest(@RequestParam(value="msg",defaultValue="你好")Stringmsg){ChatClientchatClient=ChatClient.builder(ollamaChatModel).defaultSystem(""+"# 角色设定\n"+"你是Spring Boot专家小助手\n"+"\n"+"# 回答要求\n"+"1. 分步骤说明\n"+"2. 给出最小配置示例\n"+"3. 提示常见坑点\n"+"4. 提供验证方法\n"+"\n"+"# 格式要求\n"+"- 使用emoji区分步骤\n"+"- 配置代码单独显示\n"+"- 关键配置项加粗").build();returnchatClient.prompt().user(msg).stream().content();}}启动项目,访问接口,测试结果如下:
2.2、动态参数模板
为了更好测试模板效果,用ChatClient的user()来实现。
提示词示例还是无参数版本,再添加参数。
# 角色设定 你是Spring Boot专家小助手 # 回答要求1.分步骤说明2.给出最小配置示例3.提示常见坑点4.提供验证方法 # 格式要求-使用emoji区分步骤-配置代码单独显示-关键配置项加粗 # 上下文信息 回答用户的问题:{question}姓名:{name}在测试类:PromptController,添加userPromptTest(),示例代码如下:
@RequestMapping(value="/user/flux",produces=MediaType.APPLICATION_JSON_VALUE+"; charset=UTF-8")publicFlux<String>userPromptTest(@RequestParam(value="msg",defaultValue="你好")Stringmsg){ChatClientchatClient=ChatClient.builder(ollamaChatModel).build();returnchatClient.prompt().user(u->u.text(""+"# 角色设定\n"+"你是Spring Boot专家小助手\n"+"\n"+"# 回答要求\n"+"1. 分步骤说明\n"+"2. 给出最小配置示例\n"+"3. 提示常见坑点\n"+"4. 提供验证方法\n"+"\n"+"# 格式要求\n"+"- 使用emoji区分步骤\n"+"- 配置代码单独显示\n"+"- 关键配置项加粗\n"+"\n"+"# 上下文信息\n"+"回答用户的问题: {question}\n"+"姓名:{name}").param("question",msg).param("name","大象")).stream().content();}测试结果如下:
2.3、模板文件热重载
模板文件支持参数,条件,条件模板跟参数是类似的,只是语法需要注释而已。使用时,可以找一个模板做一下调整即可,跟写代码一样,比较好理解。
**热重载说明:**指的项目启动后,在目录target/classes下的文件。调试时需要特别注意一下,我在测试过程中,一时没注意直接修改resources目录的文件。
2.3.1. 目录结构
src/main/resources/prompts/├── spring-assistant.st// Spring Boot专家小助手带参数的提示词├── conditional-assistant.st// 条件示例的提示词2.3.2、代码实现
步骤一:先实现模板文件热重载HotReloadTemplateService,提供模板加载、渲染模板,定时扫描更新等方法,如果无参数直接使用模板加载方法即可。
@Service@Slf4jpublicclassHotReloadTemplateService{privatefinalMap<String,TemplateCache>templateCache=newConcurrentHashMap<>();privatefinalMap<String,Long>fileLastModified=newConcurrentHashMap<>();/** * 带版本检查的模板加载 */publicStringloadWithVersionCheck(StringtemplateName){StringfilePath="prompts/"+templateName+".st";.....// 文章篇幅关系暂时不列出详细代码,详细代码获取方式详见文末}/** * 渲染模板 */publicStringrenderTemplate(StringtemplateName,Map<String,Object>params){StringtemplateContent=loadWithVersionCheck(templateName);PromptTemplatetemplate=newPromptTemplate(templateContent);returntemplate.render(params);}/** * 定时扫描更新 */@Scheduled(fixedDelay=60000)// 每60秒检查一次publicvoidscanForUpdates(){log.info("开始扫描模板更新...");.....// 文章篇幅关系暂时不列出详细代码,详细代码获取方式详见文末}@Data@AllArgsConstructorprivatestaticclassTemplateCache{privateStringcontent;privatelonglastModified;}privateStringgetDefaultTemplate(){return"你是一个有帮助的AI助手。";}}步骤二:由于有定时扫描更新功能,使用的是spring框架自带的定时功能。因此,需要在启动类上方要添加声明@EnableScheduling,才会生效。如下图:
步骤三:写调用方测试代码。
@RequestMapping(value="/template/flux",produces=MediaType.APPLICATION_JSON_VALUE+"; charset=UTF-8")publicFlux<String>templatePromptTest(@RequestParam(value="msg",defaultValue="你好")Stringmsg){ChatClientchatClient=ChatClient.builder(ollamaChatModel).build();// 构造参数Map<String,Object>userParams=newHashMap<>();userParams.put("name","大象");userParams.put("question",msg);// 获取模板文件内容,并替换动态参数StringuserPromptText=hotReloadTemplateService.renderTemplate("spring-assistant",userParams);returnchatClient.prompt().user(userPromptText).stream().content();}代码调试跟踪的模板内容,符合预期,如下图:
测试结果如下:
至此,Spring AI ChatClient + 模板化实现的内容就结束啦!感兴趣的同学赶快动手起来吧。
3、我的公众号&资料获取
敬请关注我的公众号:大象只为你,持续更新技术知识…
如需Spring AI与Ollama实现 Demo,代码有更新,请后台回复:【ollama】。