提示词(Prompt)
一、Prompt是什么?
Prompt是引导AI模型生成特定输出的输入格式,Prompt的设计和措辞会显著影响模型的响应。
二、提示词的四大角色
- USER:用户原始提问输入。代表用户的输入他们向AI提出的问题、命令或陈述。
- ASSISTANT:Al返回的响应信息,定义为"助手角色"消息。用它可以确保上下文能够连贯的交互。
- SYSTEM:设定AI行为边界/角色/定位。指导AI的行为和响应方式,设置AI如何解释和回复输入的。
- TOOL:桥接外部服务,可以进行函数调用如,支付/数据查询等操作,类似调用第3方util工具类。
三、提示词模板
占位符(Prompt Template):通过占位符实现动态插入,只需要根据提前写好的模板,传入需要动态插入的参数,大模型就可以根据模板执行相关操作,无需进行额外操作。(例如,发送邮件,只需要在对话框输入邮件模板里占位符要传递的信息,大模型就可以自动执行填写,发送邮箱等操作。)
// 方式一:在模板代码里写死
// 方式二:可以从文件中读取模板
PromptTemplate promptTemplate = new PromptTemplate(
"讲一个关于{topic}的故事"
+"并以{output_format}格式输出,"
+ "字数在{wordCount}左右");
// PromptTempate -> Prompt
Prompt prompt = promptTemplate.create(Map.of(
"topic", topic,
"output_format",output_format,
"wordCount",wordCount));
return deepseekChatClient.prompt(prompt).stream().content();
格式化输出(Structured Output)
一、格式化输出是什么?
- 如果您想从LLM接收结构化输出,Structured Output可以协助将
ChatModel/ChatClient方法的返回类型从String更改为其他类型。 - LLM生成结构化输出的能力对于依赖可靠解析输出值的下游应用程序非常重要。开发人员希望快速将AI模型的结果转换为可以传递给其他应用程序函数和方法的数据类型,例如JSQN、XML或Java类。
- SpringAI结构化输出转换器有助于将LLM输出转换为结构化格式。
返回变成return deepseekChatClient.prompt(prompt).user().call().entity();
ChatMemory(连续对话保存和持久化)
"大模型的对话记忆"这一概念,根植于人工智能与自然语言处理领域,特别是针对具有深度学习能力的大型语言模型而言,它指的是模型在与用户进行交互式对话过程中,能够追踪、理解并利用先前对话上下文的能力。此机制使得大模型不仅能够响应即时的输入请求,还能基于之前的交流内容能够在对话中记住先前的对话内容,并根据这些信息进行后续的响应**。这种记忆机制使得模型能够在对话中持续跟踪和理解用户的意图和上下文,从而实现更自然和连贯的对话。**
Spring AI Alibaba中的聊天记忆提供了维护AI聊天应用程序的对话上下文和历史的机制。因大模型本身不存储数据,需将历史对话信息一次性提供给它以实现连续对话,不然服务一重启就什么都没了,所以必须持久化。因此需要考虑两个点:持久化媒介(用什么存储),消息对话窗口的记录上限
-
持久化媒介:可以根据需求考虑使用各种数据库来存储(Redis,MySQL,MongoDB等)
// 考虑到检索速度可以使用Redis,或者自行实现ChatMemory,这里以Redis为例
// 1. 导入pom依赖
//
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-memory-redis</artifactId>
</dependency>
//
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>// 2. 写yml配置
// SpringAIAlibaba Config
spring.ai.dashscope.api-key=${aliQwen-api}
// redis
configspring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.database=0
spring.data.redis.connect-timeout=3
spring.data.redis.timeout=2// 3. 核心代码
/*
1.实现SpringAI框架规定的ChatMemoryRepository接口
2.编码新建RedisMemoryConfig配置类
*/
@configuration
public class RedisMemoryConfig {
@Value("{spring.data.redis.host}") private String host; @Value("{spring.data.redis.port}")
private int port;@Bean public RedisChatMemoryRepository redisChatMemoryRepository() { retunn RedisChatMemoryRepository.builder() .host(host) .port(port) .build(); }}
/*
(消息窗口聊天记忆)MessageWindouChatMemory维护一个消息窗口,最多可达指定的最大大小。
当消息数超过最大值时,将删除较旧的消息,同时保留系统消息。默认窗口大小为20条消息。
/
MessageWindowChatMemory memory = MessageWindowChatMemory.builder()
.maxMessages(10)
.build();
/
顾问(Advisors) MessageChatMemoryAdvisor
一、MessageChatMemoryAdvisor 此顾问使用提供的实现来管理对话内存。
在每次交互中,它都会从内存中检索对话历史记录,并将其作为消息集合包含在提示中。ChatMemory
*/
ChatMemory chatMemory = MessageWindowChatMemory.builder().build();
ChatClient chatClient = ChatClient.builder(chatModel).defaultAdvisors(MessageChatMemoryAdvisor.builder(chatMemory).build()).build();
// 当执行对的调用时,内存将由自动管理。将根据指定的对话ID从内存中检索对话历史记录
String conversationId = "007";
chatClient.prompt()
.user("Do I have license to code?")
.advisors (a -> a.param(ChatMemory.CONVERSATION_ID, conversationId))
.call()
.content();// 完整编码
@Bean(name = "qwenChatClient")
public ChatClient qwenChatClient (@Qualifier("qwen") ChatModel qwen,
RedisChatMemoryRepository redisChatMemoryRepository) {
MessageWindowChatMemory windowChatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(redisChatMemoryRepository)
.maxMessages(10)
.build();
return ChatClient.builder(qwen)
.defaultOptions(ChatOptions.builder().model(QWEN MODEL).build())
.defaultAdvisors(MessageChatMemoryAdvisor.builder(windowChatMemory).build())
.build();
}@GetMapping("/chatmemory/chat")
public String chat(String msg, String userId) {
return qwenChatClient.prompt(msg)
.advisors(advisorSpec -> advisorSpec.param(CONVERSATION_ID, userId))
.call().content();
}
// 在对话框发送消息后即可在Redis看到存储的对话记录的KV
// 有默认的Key前缀spring_ai_alibaba_chat_memory 存储格式是用list
