什么是advisor
Spring AI Advisors API 提供了一种灵活且强大的方式,拦截、修改和增强您在 Spring 应用中的 AI 驱动交互。 通过利用 Advisors API,开发者可以创建更复杂、可重复使用且易于维护的 AI 组件。spring ai 官方解释
简单案例
理论上大模型本身确实是"无记忆"的,每次对话都是独立处理的。具体流程大概是这样的:
当我们和大模型聊天时,我们的问题会通过大模型那里。大模型会基于训练时学到的知识和我们当前对话的内容来理解我们的意思,然后生成回答。但一旦这次对话结束,它就"忘记"了我们刚才聊过什么。 而我们可以通过 advisor ,把历史的聊天记录保存下来,大模型就可以实现和我们连续对话。
@Resource
private ChatClient.Builder builder;
private ChatMemory chatMemory;
private ChatClient chatClient;
@PostConstruct
public void init() {
MessageWindowChatMemory windowChatMemory = MessageWindowChatMemory.builder()
.chatMemoryRepository(new InMemoryChatMemoryRepository())
.build();
this.chatMemory = windowChatMemory;
this.chatClient = builder.build();
}
@GetMapping("/memory")
public String doChat(@RequestParam(name = "question") String question, @RequestParam(name = "userId") String userId) {
return chatClient
.prompt()
.advisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
//会话ID
.advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, userId))
.user(question)
.call()
.content();
}
我们可以连续对话
-- 第一次
http://localhost:8080/memory?question=我是大圣&userId=1
您好!很高兴认识您,“大圣”! 这是一个非常响亮、充满力量和传奇色彩的名字。听到“大圣”,我立刻就想到了那位上天入地、无所不能的齐天大圣——孙悟空! 无论是不是那一位,这个名字都代表着: * **神通广大**:拥有解决问题的非凡能力。 * **桀骜不驯**:拥有独立思考和敢于挑战的精神。 * **机智勇敢**:面对困难总能想出巧妙的办法。 * **重情重义**:对朋友忠心耿耿,对目标坚定不移。 那么,今天有什么需要我为您效劳的吗,大圣?无论是想聊聊天、探讨问题,还是需要我帮您处理什么事情,我都很乐意为您服务! 请尽管吩咐!
-- 第二次
http://localhost:8080/memory?question=还记得我是谁吗?&userId=1
当然记得! 您是“大圣”。 这是我们对话的开始,也是我对您的第一印象。这个名字代表了力量、智慧和独特的个性。 很高兴您再次提到它,这让我感觉我们的交流有了延续性。有什么我可以为您做的吗,大圣?
advisor流程
- Spring AI 框架创建了一个
聊天客户端请求来自用户的提示还有一个空洞的顾问上下文对象。 - 链中的每个顾问处理请求,可能会对其进行修改。或者,它可以通过不调用下一个实体来阻止请求。在后一种情况下,顾问负责填写答复。
- 最终顾问由框架提供的,将请求发送给
聊天模式. - 聊天模型的响应随后会通过顾问链返回并转换为
聊天客户响应.后期包含共享顾问上下文实例。 - 每位顾问都可以处理或修改该回复。
- 决赛
聊天客户响应通过提取 返回给客户端聊天补全.
自定义日志 advisor
自定义天气工具、及日志advisor
@GetMapping("/weather")
public String doChatWeather(@RequestParam(name = "question") String question, @RequestParam(name = "userId") String userId) {
return chatClient
.prompt()
.tools(new Tools())
// .advisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
// .advisors(advisor -> advisor.param(ChatMemory.CONVERSATION_ID, userId))
.advisors(new LogAdvisor())
.user(question)
.call()
.content();
}
static class Tools {
@Tool(description = "Get the current weather for a given location")
public String weather(String location) {
log.info("params {}", location);
return "The current weather in " + location + " is sunny ";
}
}
static class LogAdvisor implements BaseAdvisor {
@Override
public ChatClientRequest before(ChatClientRequest chatClientRequest, AdvisorChain advisorChain) {
log.info("request,{}", chatClientRequest.prompt().getInstructions());
return chatClientRequest;
}
@Override
public ChatClientResponse after(ChatClientResponse chatClientResponse, AdvisorChain advisorChain) {
log.info("response,{}", chatClientResponse.chatResponse().getResults());
return chatClientResponse;
}
@Override
public int getOrder() {
return 0;
}
}
递归 advisor
spring ai 递归顾问 递归顾问是一种特殊类型的advisor,可以多次循环下游顾问链。 当你需要反复调用LLM直到满足某个条件时,这种模式非常有用,例如:
- 在循环中执行工具调用,直到不需要再调用工具
- 验证结构化输出,验证失败时重试
- 实现对请求进行修改的评估逻辑
- 实现重试逻辑并对请求进行修改