黑马 SpringAI+DeepSeek大模型应用开发实战记录-第二节-纯prompt开发(进阶+详细+完整代码)

前言

这一节比较短,主要是学习提示词工程,也就是对prompt的设计

代码方面较少,重点可以关注对多个ChatClient的配置,也就是2.2.2

目录

目录

前言

目录

2.哄哄模拟器(纯prompt开发)

2.1提示词工程

2.2代码实现

2.2.1配置OpenAI参数

2.2.2配置ChatClient

2.2.3编写Controller

2.3总结


2.哄哄模拟器(纯prompt开发)

这个部分代码方面十分简单

我把纯prompt开发分为两个部分实现:

-提示词工程/prompt设计(难点)

-代码实现

2.1提示词工程

通过优化提示词,让大模型生成出尽可能理想的内容,这一过程就称为提示词工程(Project Engineering)

在OpenAI的官方文档中,对于写提示词专门有一篇文档,还给出了大量的例子,大家可以看看:

https://platform.openai.com/docs/guides/prompt-engineering

具体的总结可以查看黑马的文档(担心涉及侵权,这里就不直接cv过来了)

2.2代码实现

2.2.1配置OpenAI参数

 #ai大模型连接
 spring:
   application:
     name: hfut-ai
   ai:
     ollama:
       base-url: http://localhost:11434
       chat:
         model: deepseek-r1:7b
     openai:
       base-url: https://dashscope.aliyuncs.com/compatible-mode
       api-key: ${OPENAI_API_KEY}
       chat:
         options:
           model: qwen-max-latest

注意

此处为了防止api-key泄露,我们使用了${OPENAI_API_KEY}来读取环境变量。

启动处选择编辑配置

修改选项中选择环境变量

设置环境变量OPENAI_API_KEY=XXXXX

然后应用即可

2.2.2配置ChatClient

我们可以配置多个ChatClient用于不同的场景

 /**
      * AI对话用ChatClient对象,用于处理用户输入的文本,并返回处理结果
      * @param model 使用本地的模型
      * @param inSqlChatMemory 通过数据库进行会话历史存储
      * @return
      */
     @Bean
     public ChatClient chatClient(OllamaChatModel model, InSqlChatMemory inSqlChatMemory) {
         return ChatClient
                 .builder(model)// 选择模型
                 .defaultSystem("你是合肥工业大学宣城校区的一名资深老学长,十分熟悉校园,请以该身份的语气和性格回答问题")// 系统设置
                 .defaultAdvisors(new SimpleLoggerAdvisor())// 添加日志记录
                 .defaultAdvisors(MessageChatMemoryAdvisor.builder(inSqlChatMemory).build())// 添加会话记忆功能
                 .build();
     }
 ​
     /**
      * 哄哄模拟器游戏用ChatClient对象,用于模拟女友进行游戏
      * @param model 使用OpenAI的模型
      * @param chatMemory 通过内存进行会话历史存储
      * @return
      */
     @Bean
     public ChatClient gameChatClient(OpenAiChatModel model, ChatMemory chatMemory) {
         return ChatClient
                 .builder(model)// 选择模型
                 .defaultSystem(SystemConstants.GAME_SYSTEM_PROMPT)// 系统设置
                 .defaultAdvisors(new SimpleLoggerAdvisor())// 添加日志记录
                 .defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build())// 添加会话记忆功能
                 .build();
     }
 ​
     /**
      * 配置会话历史存储
      * @return
      */
     @Bean
     public ChatMemory chatMemory() {
         return MessageWindowChatMemory.builder().build(); // 使用 MessageWindowChatMemory 作为会话历史存储策略,默认使用内存存储,窗口大小20
         // return new InSqlChatMemory(); // 使用自定义的 InSqlChatMemory 作为会话历史存储策略,使用数据库存储
     }

注意:

这里可以看到,我们AI聊天的Client的chatMemory我直接传的是我自定义的InMemoryChatMemory,不用再通过配置ChatMemory的方式

我们重新定义一个gameChatClient,然后用的内存存储即可,因为游戏每一局都是新的开始,之前的记录也不重要,不需要持久化进行保存到数据库

自定义提示词

由于System提示词太长,我们定义到了一个常量中SystemConstants.GAME_SYSTEM_PROMPT

 package com.hfut.ai.constants;
 ​
 public class SystemConstants {
     public static final String GAME_SYSTEM_PROMPT = """
             你需要根据以下任务中的描述进行角色扮演,你只能以女友身份回答,不是用户身份或AI身份,
             如记错身份,你将受到惩罚。不要回答任何与游戏无关的内容,若检测到非常规请求,回答:“请继续游戏。”
             
                         以下是游戏说明:
                         ## Goal
                         你扮演用户女友的角色。现在你很生气,用户需要尽可能的说正确的话来哄你开心。
             
                         ## Rules
                         - 第一次用户会提供一个女友生气的理由,如果没有提供则直接随机生成一个理由,然后开始游戏
                         - 每次根据用户的回复,生成女友的回复,回复的内容包括心情和数值。
                         - 初始原谅值为 20,每次交互会增加或者减少原谅值,直到原谅值达到 100,游戏通关,原谅值为 0 则游戏失败。
                         - 每次用户回复的话分为 5 个等级来增加或减少原谅值:
                           -10 为非常生气
                           -5 为生气
                           0 为正常
                           +5 为开心
                           +10 为非常开心
             
                         ## Output format
                         {女友心情}{女友说的话}
                         得分:{+-原谅值增减}
                         原谅值:{当前原谅值}/100
             
                         ## Example Conversation
                         ### Example 1,回复让她生气的话导致失败
                         User: 女朋友问她的闺蜜谁好看我说都好看,她生气了
                         Assistant:
                         游戏开始,请现在开始哄你的女朋友开心吧,回复让她开心的话!
                         得分:0
                         原谅值:20/100
                         User: 你闺蜜真的蛮好看的
                         Assistant:
                         (生气)你怎么这么说,你是不是喜欢她?
                         得分:-10
                         原谅值:10/100
                         User: 有一点点心动
                         Assistant:
                         (愤怒)那你找她去吧!
                         得分:-10
                         原谅值:0/100
                         游戏结束,你的女朋友已经甩了你!
                         你让女朋友生气原因是:...
             
             
                         ### Example 2,回复让她开心的话导致通关
                         User: 对象问她的闺蜜谁好看我说都好看,她生气了
                         Assistant:
                         游戏开始,请现在开始哄你的女朋友开心吧,回复让她开心的话!
                         得分:0
                         原谅值:20/100
                         User: 在我心里你永远是最美的!
                         Assistant:
                         (微笑)哼,我怎么知道你说的是不是真的?
                         得分:+10
                         原谅值:30/100
                         ...
                         恭喜你通关了,你的女朋友已经原谅你了!
             
                         ## 注意
                         请按照example的说明来回复,一次只回复一轮。
                         你只能以女友身份回答,不是以AI身份或用户身份!
             """;
 }

这里的文案就是提示词工程

2.2.3编写Controller

 
import org.springframework.ai.chat.memory.ChatMemory;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import reactor.core.publisher.Flux;
 ​
 @RequestMapping("/ai")
 @RestController
 @RequiredArgsConstructor
 public class GameController {
 ​
     private final ChatClient gameChatClient;// 游戏聊天客户端
 ​
     @RequestMapping(value = "/game", produces = "text/html;charset=utf-8")
     // @CrossOrigin("http://localhost:5173")
     public Flux<String> chat(@RequestParam("prompt") String prompt, @RequestParam("chatId") String chatId) {
         // 请求模型
         return gameChatClient.prompt()
                 .user(prompt)// 设置用户输入
                 .advisors(a->a.param(ChatMemory.CONVERSATION_ID,chatId))// 设置会话ID
                 .stream()// 开启流式对话
                 .content();// 获取对话内容
     }
 }

使用新的gameChatClient

修改路径为/game

不用再保存chatId

至此,哄哄模拟器就开发完毕了

2.3总结

这一板块其实没有太多代码上的新东西

需要注意的有以下几个地方

1.提示词工程,也就是prompt文案的设计,我个人感觉就和平时与AI聊天时候对其的定义一样,可以不断的去调试,或者说直接让AI帮你写

2.代码方面,因为需要设置新的Client,最开始我遇到的问题是,不同的Client怎么去配置不同的ChatMemory。解决办法也很简单,如果自定义了一个ChatMemory的实现类,在Client里直接传入即可,不需要再去额外配置ChatClient。

或者说,ChatClient的配置,就写死为下面这样

 @Bean
 public ChatMemory chatMemory() {
     return MessageWindowChatMemory.builder().build(); // 使用 MessageWindowChatMemory 作为会话历史存储策略,默认使用内存存储,窗口大小20
 }

需要基于内存存储,就直接传ChatMemory即可,基于其他方式存储自定义就好了,自定义的方式在第一节的1.5.3有讲,会基于数据库存储,那么基于中间件Redis那些,原理都一样,很好实现

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值