Java程序员学从0学AI(三)
一、前言
在上一篇文章中我们对Spring AI有了一个初步的认识,也通过编写DEMO体验了一下Spring AI,今天我们将继续学习Spring AI给我们提供的各种组件。
二、Advisors
Advisors翻译成中文的意思是顾问,Spring AI 顾问 API 提供了一种灵活且强大的方式,用于在 Spring 应用程序中拦截、修改和增强由AI驱动的交互。通过利用顾问 API,开发人员可以创建更复杂、可复用且易于维护的人工智能组件。可以把Advisorsl类比为Spring AOP,对代理对象做增强。Advisors结构如下
从图中可以看出,
(1)Advisor大体分为两类,一类是CallAroundAdvisor和StreamAroundAdvisor,从名字中就可以看出这两者的异同。
相同点:都是Around,类似于AOP中的环绕通知
不同点:前者是Call后者是Stream,也是就是说一个阻塞的一个是基于流式的。
(2)Chain:从这里我们可以看出Advisor是一个链式调用,也就是说我们可以创建多个Advisor然后构建成一个Advisorl链条,也就是责任链设计模式。
三、代码演示
1、单个Advisor
1、首先我们创建一个包名advisors,然后新建一个 MyCallAroundAdvisor 继承 BaseAdvisor,并重写相对应的方法,代码如下。这里我们先什么不做什么额外操作,只是简单的打印了一下请求参数和响应
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;public class MyCallAroundAdvisor implements BaseAdvisor {/*** 大模型执行前调用* @param chatClientRequest 大模型请求参数* @param advisorChain 大模型执行链* @return 拦截后的请求参数*/@Overridepublic ChatClientRequest before(ChatClientRequest chatClientRequest, AdvisorChain advisorChain) {System.out.println("before:chatClientRequest"+chatClientRequest.toString());return chatClientRequest;}/*** 大模型执行后调用* @param chatClientResponse 大模型响应参数* @param advisorChain 大模型执行链* @return 拦截后的响应参数*/@Overridepublic ChatClientResponse after(ChatClientResponse chatClientResponse, AdvisorChain advisorChain) {System.out.println("after:chatClientResponse"+chatClientResponse.toString());return chatClientResponse;}/*** 获取执行顺序* @return 执行顺序*/@Overridepublic int getOrder() {return 0;}
}
(2)编写测试代码
@RestController("/chat")
public class ChatController {private final ChatClient client;public ChatController(OllamaChatModel model) {client = ChatClient.builder(model).defaultAdvisors(new MyCallAroundAdvisor()).build();}@GetMapping("/chat")public String chat(String message) {return client.prompt("你是一个聊天机器人").user(message).call().content();}
}
(3)查看结果:可以看到我们已经在接口前后做了增强。
2、多个Advisors
package com.cmxy.spring_ai_demo.advisors;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;public class MySecondCallAroundAdvisor implements BaseAdvisor {/*** 大模型执行前调用* @param chatClientRequest 大模型请求参数* @param advisorChain 大模型执行链* @return 拦截后的请求参数*/@Overridepublic ChatClientRequest before(ChatClientRequest chatClientRequest, AdvisorChain advisorChain) {System.out.println("Second:chatClientRequest"+chatClientRequest.toString());return chatClientRequest;}/*** 大模型执行后调用* @param chatClientResponse 大模型响应参数* @param advisorChain 大模型执行链* @return 拦截后的响应参数*/@Overridepublic ChatClientResponse after(ChatClientResponse chatClientResponse, AdvisorChain advisorChain) {System.out.println("Second:chatClientResponse"+chatClientResponse.toString());return chatClientResponse;}/*** 获取执行顺序* @return 执行顺序*/@Overridepublic int getOrder() {return 1;}
}
再查看结果
可以看到执行的顺序为:
四、Advisor的应用场景
(1)既然是对请求前后做增强,那么Advisor第一个应用场景就是日志记录,我们可以通过Advisor来追踪整个请求。
(2)ChatMemory:聊天记忆,如果不借助外部工机具或者提示词,大模型是没有记忆功能的。例如你告诉大模型你叫什么名字,但是下次继续问大模型,大模型依旧不知道。这个是因为大模型的训练语料里并没包含相关信息,如果我们需要大模型有记忆就需要将聊天记录持久化(其实是以提示词的形式告知大模型),这里就可以用到Advisor,这个在后续的文章中也会说明
(3)RAG:很多时候我们希望大模型可以知道我们企业内部或者个人的信息,从而帮助我们做一些事情,正如上面说的大模型的训练语料里是不包含这些内容的。那怎么办呢?当然可以通过微调、提示词、或者RAG(后续会详细说),SpingAI通过Advisor可以让我们很简单的实现Rag功能。
五、结束语
今天的文章对Advisor做了简单的介绍,下一篇文章将继续Advisor,主要是针对聊天记忆和Rag进行实现,希望对你有所帮助。