Skip to content

链式组件 Advisors

作用

img.png

AdvisorSpringAI 中极其重要的一个组件,构建了整个 SpringAI 的执行流程。

简单原理如上图所示:多个 Advisor 组成链表结构,在调用大模型前按照优先级从高到低依次执行前置逻辑,之后执行大模型调用,最后在大模型调用之后按照优先级从低到高依次执行后置逻辑。

如果熟悉 DubboFilter 链式结构,Advisor 的作用就相当于 Filter 的作用。不过 SpringAI 做的更彻底,将对大模型的调用也包装为一个 advisor,该 advisor 的优先级最低。

原理分析

java
@RequestMapping("/10000")
public String execute10000() {
    return chatClient.prompt()
            .advisors(new SimpleLoggerAdvisor())
            .user("tell me a joke")
            .call()
            .content();
}

步骤如下:

  1. 启动时创建 DefaultChatClient 实例,其间接包含属性 List<Advisor> advisors
  2. advisors(new SimpleLoggerAdvisor()):新建一个 SimpleLoggerAdvisor 实例,添加到 1 中的 advisors 列表里
  3. call():仅看同步调用,新建一个 ChatModelCallAdvisor,添加到 1 中的 advisors 列表里(ChatModelCallAdvisor 就是真正调用模型的地方);新建一个 DefaultAroundAdvisorChain 实例,将 advisors 列表设置为其的一个属性,并且对该列表中的 Advisor 实例按照 getOrder() 进行排序。order 越小,优先级越高,越先执行。
  4. content():调用 DefaultAroundAdvisorChainnextCall() 方法,依次执行 advisors 列表的链式调用

说明:

  1. Advisor 的 order 属性值越小,优先级越高,越先执行;自定义的 Advisor 需要格外注意该值的定义
  2. ChatModelCallAdvisor 的优先级最低,order=Integer.MAX_VALUE
  3. 官方建议在启动构建 ChatClient Bean时,使用 defaultAdvisors() 方法注册 Advisor

自定义一个 Advisor

java
import org.springframework.ai.chat.client.ChatClientRequest;
import org.springframework.ai.chat.client.ChatClientResponse;
import org.springframework.ai.chat.client.advisor.api.CallAdvisor;
import org.springframework.ai.chat.client.advisor.api.CallAdvisorChain;

public class MyCustomAdvisor2 implements CallAdvisor {
    @Override
    public ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain) {
        /*
         * 前置逻辑
         */
        System.out.println("MyCustomAdvisor2: start");
        /*
         * 传递上下文参数
         */
        chatClientRequest.context().put("customAdvisor", "MyCustomAdvisor2");
        /*
         * 链式调用,最后到 LLM 调用
         */
        ChatClientResponse chatClientResponse = callAdvisorChain.nextCall(chatClientRequest);
        /*
         * 后置逻辑
         */
        System.out.println("MyCustomAdvisor2: end");
        return chatClientResponse;
    }

    @Override
    public String getName() {
        return this.getClass().getSimpleName();
    }

    @Override
    public int getOrder() {
        return -2;
    }
}

以上仅展示了同步调用的方式,流式调用需要实现 StreamAdvisor,可以参考 org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor 进行实现。

文章的最后,如果您觉得本文对您有用,请打赏一杯咖啡!感谢!