当前位置: 首页 > wzjs >正文

广州做网站好的公司百度seo优化方案

广州做网站好的公司,百度seo优化方案,沈阳专业网站制作团队,淮安市广德育建设网站原文链接:SpringAI的Advisor:快速上手源码解读 教程说明 说明:本教程将采用2025年5月20日正式的GA版,给出如下内容 核心功能模块的快速上手教程核心功能模块的源码级解读Spring ai alibaba增强的快速上手教程 源码级解读 版…

原文链接:SpringAI的Advisor:快速上手+源码解读

教程说明

说明:本教程将采用2025年5月20日正式的GA版,给出如下内容

  1. 核心功能模块的快速上手教程
  2. 核心功能模块的源码级解读
  3. Spring ai alibaba增强的快速上手教程 + 源码级解读

版本:JDK21 + SpringBoot3.4.5 + SpringAI 1.0.0 + SpringAI Alibaba最新

将陆续完成如下章节教程

快速上手

实战代码可见:https://github.com/GTyingzi/spring-ai-tutorial 下的 advisor

pom 文件

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-autoconfigure-model-openai</artifactId><version>${spring-ai.version}</version></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-autoconfigure-model-chat-client</artifactId><version>${spring-ai.version}</version></dependency></dependencies>

application.yml

server:port: 8080spring:application:name: advisor-baseai:openai:api-key: ${DASHSCOPEAPIKEY}base-url: https://dashscope.aliyuncs.com/compatible-modechat:options:model: qwen-max

controller

MemoryMessageAdvisorController
package com.spring.ai.tutorial.advisor.controller;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemoryRepository;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;import static org.springframework.ai.chat.memory.ChatMemory.CONVERSATIONID;/*** @author yingzi* @date 2025/5/22 22:59*/
@RestController
@RequestMapping("/advisor/memory/message")
public class MemoryMessageAdvisorController {private final ChatClient chatClient;private final InMemoryChatMemoryRepository chatMemoryRepository = new InMemoryChatMemoryRepository();private final int MAXMESSAGES = 100;private final MessageWindowChatMemory messageWindowChatMemory = MessageWindowChatMemory.builder().chatMemoryRepository(chatMemoryRepository).maxMessages(MAXMESSAGES).build();public MemoryMessageAdvisorController(ChatClient.Builder builder) {this.chatClient = builder.defaultAdvisors(MessageChatMemoryAdvisor.builder(messageWindowChatMemory).build()).build();}@GetMapping("/call")public String call(@RequestParam(value = "query", defaultValue = "你好,我的外号是影子,请记住呀") String query,@RequestParam(value = "conversationid", defaultValue = "yingzi") String conversationId) {return chatClient.prompt(query).advisors(a -> a.param(CONVERSATIONID, conversationId)).call().content();}@GetMapping("/messages")public List<Message> messages(@RequestParam(value = "conversationid", defaultValue = "yingzi") String conversationId) {return messageWindowChatMemory.get(conversationId);}}
效果

以会话 Id=“yingzi”,先告知模型我的名字

再以同一个会话 Id=“yingzi”,模型能根据以往的消息记住了我的名字

获取历史消息记录,我们能得到历史消息记录

MemoryPromptAdvisorController
package com.spring.ai.tutorial.advisor.controller;import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.PromptChatMemoryAdvisor;
import org.springframework.ai.chat.memory.InMemoryChatMemoryRepository;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.List;import static org.springframework.ai.chat.memory.ChatMemory.CONVERSATIONID;/*** @author yingzi* @date 2025/5/23 17:29*/
@RestController
@RequestMapping("/advisor/memory/prompt")
public class MemoryPromptAdvisorController {private final ChatClient chatClient;private final InMemoryChatMemoryRepository chatMemoryRepository = new InMemoryChatMemoryRepository();private final int MAXMESSAGES = 100;private final MessageWindowChatMemory messageWindowChatMemory = MessageWindowChatMemory.builder().chatMemoryRepository(chatMemoryRepository).maxMessages(MAXMESSAGES).build();public MemoryPromptAdvisorController(ChatClient.Builder builder) {this.chatClient = builder.defaultAdvisors(PromptChatMemoryAdvisor.builder(messageWindowChatMemory).build()).build();}@GetMapping("/call")public String call(@RequestParam(value = "query", defaultValue = "你好,我的外号是影子,请记住呀") String query,@RequestParam(value = "conversationid", defaultValue = "yingzi") String conversationId) {return chatClient.prompt(query).advisors(a -> a.param(CONVERSATIONID, conversationId)).call().content();}@GetMapping("/messages")public List<Message> messages(@RequestParam(value = "conversationid", defaultValue = "yingzi") String conversationId) {return messageWindowChatMemory.get(conversationId);}
}
效果

以会话 Id=“yingzi”,先告知模型我的名字

再以同一个会话 Id=“yingzi”,模型能根据以往的消息记住了我的名字

获取历史消息记录,我们能得到历史消息记录

advisor 源码篇

[!TIP]
本源码取自:Spring AI 的 5 月 20 号发布的 1.0.0(GA 版)

  1. 基础只提供 BaseChatMemoryAdvisor
  2. rag 模块引入 RAG,源码可参照 Rag 源码篇

架构图

Advisor

advisor 基础信息配置

  • name:指定名字,确保唯一性
  • order:数值越小,执行越靠前
package org.springframework.ai.chat.client.advisor.api;import org.springframework.core.Ordered;public interface Advisor extends Ordered {int DEFAULTCHATMEMORYPRECEDENCEORDER = -2147482648;String getName();
}
package org.springframework.core;public interface Ordered {int HIGHESTPRECEDENCE = Integer.MINVALUE;int LOWESTPRECEDENCE = Integer.MAXVALUE;int getOrder();
}
CallAdvisor

call 调用,跟 AI 模型交互前、后的一些逻辑

package org.springframework.ai.chat.client.advisor.api;import org.springframework.ai.chat.client.ChatClientRequest;
import org.springframework.ai.chat.client.ChatClientResponse;public interface CallAdvisor extends Advisor {ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain);
}
StreamAdvisor

Stream 调用,跟 AI 模型交互前、后的一些逻

package org.springframework.ai.chat.client.advisor.api;import org.springframework.ai.chat.client.ChatClientRequest;
import org.springframework.ai.chat.client.ChatClientResponse;
import reactor.core.publisher.Flux;public interface StreamAdvisor extends Advisor {Flux<ChatClientResponse> adviseStream(ChatClientRequest chatClientRequest, StreamAdvisorChain streamAdvisorChain);
}
BaseAdvisor

类说明:继承 CallAdvisor、StreamAdvisor,提供统一扩展点,统计拦截机制实现与 AI 模型请求和响应后的统一交互逻辑。

字段说明

字段名称
类型
描述
DEFAULTSCHEDULER
Scheduler
定义默认调度器Schedulers.boundedElastic(),用于流式处理时的线程调度

方法说明

方法名称
描述
adviseCall
同步调用,拦截call调用AI模型的请求和响应。子类实现before、after方法
adviseStream
流式调用,拦截stream调用AI模型的请求和响应。子类实现before、after方法
before
AI模型请求前的逻辑,需要子类实现
after
AI模型响应后的逻辑,需要子类实现
package org.springframework.ai.chat.client.advisor.api;import java.util.Objects;
import org.springframework.ai.chat.client.ChatClientRequest;
import org.springframework.ai.chat.client.ChatClientResponse;
import org.springframework.ai.chat.client.advisor.AdvisorUtils;
import org.springframework.util.Assert;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;public interface BaseAdvisor extends CallAdvisor, StreamAdvisor {Scheduler DEFAULTSCHEDULER = Schedulers.boundedElastic();default ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain) {Assert.notNull(chatClientRequest, "chatClientRequest cannot be null");Assert.notNull(callAdvisorChain, "callAdvisorChain cannot be null");ChatClientRequest processedChatClientRequest = this.before(chatClientRequest, callAdvisorChain);ChatClientResponse chatClientResponse = callAdvisorChain.nextCall(processedChatClientRequest);return this.after(chatClientResponse, callAdvisorChain);}default Flux<ChatClientResponse> adviseStream(ChatClientRequest chatClientRequest, StreamAdvisorChain streamAdvisorChain) {Assert.notNull(chatClientRequest, "chatClientRequest cannot be null");Assert.notNull(streamAdvisorChain, "streamAdvisorChain cannot be null");Assert.notNull(this.getScheduler(), "scheduler cannot be null");Mono var10000 = Mono.just(chatClientRequest).publishOn(this.getScheduler()).map((request) -> this.before(request, streamAdvisorChain));Objects.requireNonNull(streamAdvisorChain);Flux<ChatClientResponse> chatClientResponseFlux = var10000.flatMapMany(streamAdvisorChain::nextStream);return chatClientResponseFlux.map((response) -> {if (AdvisorUtils.onFinishReason().test(response)) {response = this.after(response, streamAdvisorChain);}return response;}).onErrorResume((error) -> Flux.error(new IllegalStateException("Stream processing failed", error)));}default String getName() {return this.getClass().getSimpleName();}ChatClientRequest before(ChatClientRequest chatClientRequest, AdvisorChain advisorChain);ChatClientResponse after(ChatClientResponse chatClientResponse, AdvisorChain advisorChain);default Scheduler getScheduler() {return DEFAULTSCHEDULER;}
}

BaseChatMemoryAdvisor

类说明:从传入的上下文 Map 中提取会话 Id,若不存在则使用默认值

package org.springframework.ai.chat.client.advisor.api;import java.util.Map;
import org.springframework.util.Assert;public interface BaseChatMemoryAdvisor extends BaseAdvisor {default String getConversationId(Map<String, Object> context, String defaultConversationId) {Assert.notNull(context, "context cannot be null");Assert.noNullElements(context.keySet().toArray(), "context cannot contain null keys");Assert.hasText(defaultConversationId, "defaultConversationId cannot be null or empty");return context.containsKey("chatmemoryconversationid") ? context.get("chatmemoryconversationid").toString() : defaultConversationId;}
}
MessageChatMemoryAdvisor

类的说明:消息记忆存储的 Advisor 类

字段说明

字段名称
类型
描述
order
int
指定顺序
defaultConversationId
String
默认会话Id
chatMemory
ChatMemory
聊天记忆接口
scheduler
Scheduler
流式处理时的线程调度

方法说明

方法名称
描述
before
1. 从ChatMemory中取出历史消息
2. 当前消息加入ChatMemory
3. 整合当前消息+历史消息
after
将模型响应的消息加入ChatMemory
adviseStream
覆盖了BaseAdvisor默认实现逻辑
- 注:在将多个流式响应合并成一个完整响应对象后,在调用after,确保只保留完整的模型输出,避免部分信息写入memory导致混乱
package org.springframework.ai.chat.client.advisor;import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.springframework.ai.chat.client.ChatClientMessageAggregator;
import org.springframework.ai.chat.client.ChatClientRequest;
import org.springframework.ai.chat.client.ChatClientResponse;
import org.springframework.ai.chat.client.advisor.api.AdvisorChain;
import org.springframework.ai.chat.client.advisor.api.BaseAdvisor;
import org.springframework.ai.chat.client.advisor.api.BaseChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.api.StreamAdvisorChain;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.util.Assert;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;public final class MessageChatMemoryAdvisor implements BaseChatMemoryAdvisor {private final ChatMemory chatMemory;private final String defaultConversationId;private final int order;private final Scheduler scheduler;private MessageChatMemoryAdvisor(ChatMemory chatMemory, String defaultConversationId, int order, Scheduler scheduler) {Assert.notNull(chatMemory, "chatMemory cannot be null");Assert.hasText(defaultConversationId, "defaultConversationId cannot be null or empty");Assert.notNull(scheduler, "scheduler cannot be null");this.chatMemory = chatMemory;this.defaultConversationId = defaultConversationId;this.order = order;this.scheduler = scheduler;}public int getOrder() {return this.order;}public Scheduler getScheduler() {return this.scheduler;}public ChatClientRequest before(ChatClientRequest chatClientRequest, AdvisorChain advisorChain) {String conversationId = this.getConversationId(chatClientRequest.context(), this.defaultConversationId);List<Message> memoryMessages = this.chatMemory.get(conversationId);List<Message> processedMessages = new ArrayList(memoryMessages);processedMessages.addAll(chatClientRequest.prompt().getInstructions());ChatClientRequest processedChatClientRequest = chatClientRequest.mutate().prompt(chatClientRequest.prompt().mutate().messages(processedMessages).build()).build();UserMessage userMessage = processedChatClientRequest.prompt().getUserMessage();this.chatMemory.add(conversationId, userMessage);return processedChatClientRequest;}public ChatClientResponse after(ChatClientResponse chatClientResponse, AdvisorChain advisorChain) {List<Message> assistantMessages = new ArrayList();if (chatClientResponse.chatResponse() != null) {assistantMessages = chatClientResponse.chatResponse().getResults().stream().map((g) -> g.getOutput()).toList();}this.chatMemory.add(this.getConversationId(chatClientResponse.context(), this.defaultConversationId), assistantMessages);return chatClientResponse;}public Flux<ChatClientResponse> adviseStream(ChatClientRequest chatClientRequest, StreamAdvisorChain streamAdvisorChain) {Scheduler scheduler = this.getScheduler();Mono var10000 = Mono.just(chatClientRequest).publishOn(scheduler).map((request) -> this.before(request, streamAdvisorChain));Objects.requireNonNull(streamAdvisorChain);return var10000.flatMapMany(streamAdvisorChain::nextStream).transform((flux) -> (new ChatClientMessageAggregator()).aggregateChatClientResponse(flux, (response) -> this.after(response, streamAdvisorChain)));}public static Builder builder(ChatMemory chatMemory) {return new Builder(chatMemory);}public static final class Builder {private String conversationId = "default";private int order = -2147482648;private Scheduler scheduler;private ChatMemory chatMemory;private Builder(ChatMemory chatMemory) {this.scheduler = BaseAdvisor.DEFAULTSCHEDULER;this.chatMemory = chatMemory;}public Builder conversationId(String conversationId) {this.conversationId = conversationId;return this;}public Builder order(int order) {this.order = order;return this;}public Builder scheduler(Scheduler scheduler) {this.scheduler = scheduler;return this;}public MessageChatMemoryAdvisor build() {return new MessageChatMemoryAdvisor(this.chatMemory, this.conversationId, this.order, this.scheduler);}}
}
PromptChatMemoryAdvisor

类的说明:将聊天记忆嵌入到系统提示词的 Advisor 类

字段说明

字段名称
类型
描述
order
int
指定顺序
defaultConversationId
String
默认会话Id
chatMemory
ChatMemory
聊天记忆接口
scheduler
Scheduler
流式处理时的线程调度
systemPromptTemplate
PromptTemplate
当前使用的系统提示模板

方法说明

方法名称
描述
before
1. 从ChatMemory中取出历史消息
2. 当前消息加入ChatMemory
3. 将历史消息结合系统提示消息作为最新的系统提示
after
将模型响应的消息加入ChatMemory
adviseStream
覆盖了BaseAdvisor默认实现逻辑
- 注:在将多个流式响应合并成一个完整响应对象后,在调用after,确保只保留完整的模型输出,避免部分信息写入memory导致混乱
package org.springframework.ai.chat.client.advisor;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClientMessageAggregator;
import org.springframework.ai.chat.client.ChatClientRequest;
import org.springframework.ai.chat.client.ChatClientResponse;
import org.springframework.ai.chat.client.advisor.api.AdvisorChain;
import org.springframework.ai.chat.client.advisor.api.BaseAdvisor;
import org.springframework.ai.chat.client.advisor.api.BaseChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.api.StreamAdvisorChain;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.MessageType;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.util.Assert;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;public final class PromptChatMemoryAdvisor implements BaseChatMemoryAdvisor {private static final Logger logger = LoggerFactory.getLogger(PromptChatMemoryAdvisor.class);private static final PromptTemplate DEFAULTSYSTEMPROMPTTEMPLATE = new PromptTemplate("{instructions}\n\nUse the conversation memory from the MEMORY section to provide accurate answers.\n\n---------------------\nMEMORY:\n{memory}\n---------------------\n\n");private final PromptTemplate systemPromptTemplate;private final String defaultConversationId;private final int order;private final Scheduler scheduler;private final ChatMemory chatMemory;private PromptChatMemoryAdvisor(ChatMemory chatMemory, String defaultConversationId, int order, Scheduler scheduler, PromptTemplate systemPromptTemplate) {Assert.notNull(chatMemory, "chatMemory cannot be null");Assert.hasText(defaultConversationId, "defaultConversationId cannot be null or empty");Assert.notNull(scheduler, "scheduler cannot be null");Assert.notNull(systemPromptTemplate, "systemPromptTemplate cannot be null");this.chatMemory = chatMemory;this.defaultConversationId = defaultConversationId;this.order = order;this.scheduler = scheduler;this.systemPromptTemplate = systemPromptTemplate;}public static Builder builder(ChatMemory chatMemory) {return new Builder(chatMemory);}public int getOrder() {return this.order;}public Scheduler getScheduler() {return this.scheduler;}public ChatClientRequest before(ChatClientRequest chatClientRequest, AdvisorChain advisorChain) {String conversationId = this.getConversationId(chatClientRequest.context(), this.defaultConversationId);List<Message> memoryMessages = this.chatMemory.get(conversationId);logger.debug("[PromptChatMemoryAdvisor.before] Memory before processing for conversationId={}: {}", conversationId, memoryMessages);String memory = (String)memoryMessages.stream().filter((m) -> m.getMessageType() == MessageType.USER || m.getMessageType() == MessageType.ASSISTANT).map((m) -> {String var10000 = String.valueOf(m.getMessageType());return var10000 + ":" + m.getText();}).collect(Collectors.joining(System.lineSeparator()));SystemMessage systemMessage = chatClientRequest.prompt().getSystemMessage();String augmentedSystemText = this.systemPromptTemplate.render(Map.of("instructions", systemMessage.getText(), "memory", memory));ChatClientRequest processedChatClientRequest = chatClientRequest.mutate().prompt(chatClientRequest.prompt().augmentSystemMessage(augmentedSystemText)).build();UserMessage userMessage = processedChatClientRequest.prompt().getUserMessage();this.chatMemory.add(conversationId, userMessage);return processedChatClientRequest;}public ChatClientResponse after(ChatClientResponse chatClientResponse, AdvisorChain advisorChain) {List<Message> assistantMessages = new ArrayList();if (chatClientResponse.chatResponse() != null) {assistantMessages = chatClientResponse.chatResponse().getResults().stream().map((g) -> g.getOutput()).toList();} else if (chatClientResponse.chatResponse() != null && chatClientResponse.chatResponse().getResult() != null && chatClientResponse.chatResponse().getResult().getOutput() != null) {assistantMessages = List.of(chatClientResponse.chatResponse().getResult().getOutput());}if (!assistantMessages.isEmpty()) {this.chatMemory.add(this.getConversationId(chatClientResponse.context(), this.defaultConversationId), assistantMessages);logger.debug("[PromptChatMemoryAdvisor.after] Added ASSISTANT messages to memory for conversationId={}: {}", this.getConversationId(chatClientResponse.context(), this.defaultConversationId), assistantMessages);List<Message> memoryMessages = this.chatMemory.get(this.getConversationId(chatClientResponse.context(), this.defaultConversationId));logger.debug("[PromptChatMemoryAdvisor.after] Memory after ASSISTANT add for conversationId={}: {}", this.getConversationId(chatClientResponse.context(), this.defaultConversationId), memoryMessages);}return chatClientResponse;}public Flux<ChatClientResponse> adviseStream(ChatClientRequest chatClientRequest, StreamAdvisorChain streamAdvisorChain) {Scheduler scheduler = this.getScheduler();Mono var10000 = Mono.just(chatClientRequest).publishOn(scheduler).map((request) -> this.before(request, streamAdvisorChain));Objects.requireNonNull(streamAdvisorChain);return var10000.flatMapMany(streamAdvisorChain::nextStream).transform((flux) -> (new ChatClientMessageAggregator()).aggregateChatClientResponse(flux, (response) -> this.after(response, streamAdvisorChain)));}public static final class Builder {private PromptTemplate systemPromptTemplate;private String conversationId;private int order;private Scheduler scheduler;private ChatMemory chatMemory;private Builder(ChatMemory chatMemory) {this.systemPromptTemplate = PromptChatMemoryAdvisor.DEFAULTSYSTEMPROMPTTEMPLATE;this.conversationId = "default";this.order = -2147482648;this.scheduler = BaseAdvisor.DEFAULTSCHEDULER;this.chatMemory = chatMemory;}public Builder systemPromptTemplate(PromptTemplate systemPromptTemplate) {this.systemPromptTemplate = systemPromptTemplate;return this;}public Builder conversationId(String conversationId) {this.conversationId = conversationId;return this;}public Builder scheduler(Scheduler scheduler) {this.scheduler = scheduler;return this;}public Builder order(int order) {this.order = order;return this;}public PromptChatMemoryAdvisor build() {return new PromptChatMemoryAdvisor(this.chatMemory, this.conversationId, this.order, this.scheduler, this.systemPromptTemplate);}}
}

ChatMemory

类说明:管理会话聊天记忆的接口,提供了保存、获取、清除对话消息的基本功能

字段说明

字段名称
类型
描述
CONVERSATIONID
String
会话Id。当作键,方便提取对应的List

方法说明

方法名称
描述
add
添加消息到指定会话Id中
get
根据指定会话Id获取消息
clear
根据会话Id清除消息
package org.springframework.ai.chat.memory;import java.util.List;
import org.springframework.ai.chat.messages.Message;
import org.springframework.util.Assert;public interface ChatMemory {String DEFAULTCONVERSATIONID = "default";String CONVERSATIONID = "chatmemoryconversationid";default void add(String conversationId, Message message) {Assert.hasText(conversationId, "conversationId cannot be null or empty");Assert.notNull(message, "message cannot be null");this.add(conversationId, List.of(message));}void add(String conversationId, List<Message> messages);List<Message> get(String conversationId);void clear(String conversationId);
}
MessageWindowChatMemory

类说明:消息窗口类,提供了保存、获取、清除对话消息的基本功能

字段说明

字段名称
类型
描述
maxMessages
int
当前会话最多保留的消息数量
chatMemoryRepository
ChatMemoryRepository
存储后端,实现该接口可拓展内存、Mysql、Redis、ES等数据库存储消息

其他方法说明

方法名称
描述
process
用于控制消息数量,核心逻辑下
1. 新增 SystemMessage 时,清除之前的 SystemMessage
2. 若消息数超过限制,优先保留SystemMessage
package org.springframework.ai.chat.memory;import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.util.Assert;public final class MessageWindowChatMemory implements ChatMemory {private static final int DEFAULTMAXMESSAGES = 20;private final ChatMemoryRepository chatMemoryRepository;private final int maxMessages;private MessageWindowChatMemory(ChatMemoryRepository chatMemoryRepository, int maxMessages) {Assert.notNull(chatMemoryRepository, "chatMemoryRepository cannot be null");Assert.isTrue(maxMessages > 0, "maxMessages must be greater than 0");this.chatMemoryRepository = chatMemoryRepository;this.maxMessages = maxMessages;}public void add(String conversationId, List<Message> messages) {Assert.hasText(conversationId, "conversationId cannot be null or empty");Assert.notNull(messages, "messages cannot be null");Assert.noNullElements(messages, "messages cannot contain null elements");List<Message> memoryMessages = this.chatMemoryRepository.findByConversationId(conversationId);List<Message> processedMessages = this.process(memoryMessages, messages);this.chatMemoryRepository.saveAll(conversationId, processedMessages);}public List<Message> get(String conversationId) {Assert.hasText(conversationId, "conversationId cannot be null or empty");return this.chatMemoryRepository.findByConversationId(conversationId);}public void clear(String conversationId) {Assert.hasText(conversationId, "conversationId cannot be null or empty");this.chatMemoryRepository.deleteByConversationId(conversationId);}private List<Message> process(List<Message> memoryMessages, List<Message> newMessages) {List<Message> processedMessages = new ArrayList();Set<Message> memoryMessagesSet = new HashSet(memoryMessages);Stream var10000 = newMessages.stream();Objects.requireNonNull(SystemMessage.class);boolean hasNewSystemMessage = var10000.filter(SystemMessage.class::isInstance).anyMatch((messagex) -> !memoryMessagesSet.contains(messagex));var10000 = memoryMessages.stream().filter((messagex) -> !hasNewSystemMessage || !(messagex instanceof SystemMessage));Objects.requireNonNull(processedMessages);var10000.forEach(processedMessages::add);processedMessages.addAll(newMessages);if (processedMessages.size() <= this.maxMessages) {return processedMessages;} else {int messagesToRemove = processedMessages.size() - this.maxMessages;List<Message> trimmedMessages = new ArrayList();int removed = 0;for(Message message : processedMessages) {if (!(message instanceof SystemMessage) && removed < messagesToRemove) {++removed;} else {trimmedMessages.add(message);}}return trimmedMessages;}}public static Builder builder() {return new Builder();}public static final class Builder {private ChatMemoryRepository chatMemoryRepository;private int maxMessages = 20;private Builder() {}public Builder chatMemoryRepository(ChatMemoryRepository chatMemoryRepository) {this.chatMemoryRepository = chatMemoryRepository;return this;}public Builder maxMessages(int maxMessages) {this.maxMessages = maxMessages;return this;}public MessageWindowChatMemory build() {if (this.chatMemoryRepository == null) {this.chatMemoryRepository = new InMemoryChatMemoryRepository();}return new MessageWindowChatMemory(this.chatMemoryRepository, this.maxMessages);}}
}

ChatMemoryRepository

package org.springframework.ai.chat.memory;import java.util.List;
import org.springframework.ai.chat.messages.Message;public interface ChatMemoryRepository {List<String> findConversationIds();List<Message> findByConversationId(String conversationId);void saveAll(String conversationId, List<Message> messages);void deleteByConversationId(String conversationId);
}
InMemoryChatMemoryRepository

类说明:基于内存的实际存储数据,维护一个会话 Id 到消息列表的键值对

package org.springframework.ai.chat.memory;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.ai.chat.messages.Message;
import org.springframework.util.Assert;public final class InMemoryChatMemoryRepository implements ChatMemoryRepository {Map<String, List<Message>> chatMemoryStore = new ConcurrentHashMap();public List<String> findConversationIds() {return new ArrayList(this.chatMemoryStore.keySet());}public List<Message> findByConversationId(String conversationId) {Assert.hasText(conversationId, "conversationId cannot be null or empty");List<Message> messages = (List)this.chatMemoryStore.get(conversationId);return (List<Message>)(messages != null ? new ArrayList(messages) : List.of());}public void saveAll(String conversationId, List<Message> messages) {Assert.hasText(conversationId, "conversationId cannot be null or empty");Assert.notNull(messages, "messages cannot be null");Assert.noNullElements(messages, "messages cannot contain null elements");this.chatMemoryStore.put(conversationId, messages);}public void deleteByConversationId(String conversationId) {Assert.hasText(conversationId, "conversationId cannot be null or empty");this.chatMemoryStore.remove(conversationId);}
}

问题

MessageChatMemoryAdvisor 和 PromptChatMemoryAdvisor 的区别是什么?

PromptChatMemoryAdvisor

  1. 有些模型可能可能不支持 messag

    1. 如本地部署,LLaMA、BLOOM 等 text-in/text-out 模型
  2. 调试时,希望快速看到完整上下文

MessageChatMemoryAdvisor

  1. 需要精确控制消息类型(用户、系统、助手)
  2. 使用 OpenAI GPT-3.5/4 等 chat 模型

总结:MessageChatMemoryAdvisor 是面向结构化对话记忆的最佳实践,而 PromptChatMemoryAdvisor 是面向文本提示增强的经典方案

为什么需要覆盖 adviseStream 方法?

在将多个流式响应合并成一个完整响应对象后,在调用 after,确保只保留完整的模型输出,避免部分信息写入 memory 导致混乱

http://www.dtcms.com/wzjs/326178.html

相关文章:

  • 做民宿的网站有哪些郑州seo服务公司
  • 企业制作网站一般多少钱金城武重庆森林经典台词
  • 网站推广分销系统免费域名解析
  • 像天猫网站怎么做小说推广平台有哪些
  • shopex网站经常出错免费行情网站app大全
  • 电商 网站 设计武汉seo建站
  • 东营北京网站建设推广赚钱的平台
  • 购物网站建设机构重庆seo排
  • 湖南企业网站定制百度浏览器网址链接
  • 怎么查看网站有没有做推广一个新手怎么去运营淘宝店铺
  • 企业网站建设不足seo的范畴是什么
  • 网站安全监测预警平台建设成效营销页面设计
  • 百姓国货app下载宁波品牌网站推广优化公司
  • 电商运营需要掌握哪些知识seo的优化策略有哪些
  • 温州网站推广有哪些方法百度广告怎么投放
  • 网站客服系统有哪些厦门百度快照优化排名
  • 影视网站seo描述竞价推广专员
  • 澳门网站建设公司网站优化排名方法有哪些
  • 镇江百度优化成都网站seo性价比高
  • 网站设计的主要机构有哪些海外网站推广优化专员
  • 网站建设与管理教学大纲免费建站网站大全
  • 中国纪检监察网站首页申请网站怎么申请
  • 免费做电子目录的网站b站推广网站2023
  • 广州网站建设如何做三只松鼠网络营销策划书
  • 电子硬件工程师培训机构2020站群seo系统
  • 学设计的网站推荐推广软文范例
  • 常州建设工程电子审图网站营销软文范例
  • 网站建设九步走国内网站排名
  • 文案转行做网站编辑百度风云榜电视剧排行榜
  • 家具公司网站建设亚马逊查关键词排名工具