Spring AI 教程

Spring AI 核心组件 Advisor

Spring AI 的 Advisor 为拦截、修改和增强 Spring AI 应用中的 AI 交互提供了灵活且强大的解决方案。借助 Advisor,开发者能够构建更为复杂、具备高复用性且易于维护的 AI 组件。

Advisor 的核心功能在于对聊天交互流程进行拦截与增强,其设计理念类似于 AOP(面向切面编程)中的切面机制,可在消息发送至 AI 模型前及接收模型响应后,添加额外的处理逻辑。

Advisor 的核心优势包括:

  • 封装可复用的生成式 AI 模式

  • 转换与大语言模型(LLM)交互的数据

  • 实现跨模型与用例的可移植性

简单示例

下面通过一个简单示例,介绍如何通过 ChatClient API 配置现有 Advisor,代码如下:

(1)创建名为 VectorStoreConfig 的配置类,创建 VectorStore Bean,并且通过 VectorStore 的 add() 方法,内嵌一个关于“张三介绍”的文档片段,用于后续的 RAG 增强。

package com.hxstrive.springai.springai_openai.advisor1.config;

import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;

/**
 * 向量存储配置
 * @author hxstrive.com
 */
@Configuration
public class VectorStoreConfig {

    @Bean
    public VectorStore vectorStore(EmbeddingModel embeddingModel) {
        SimpleVectorStore simpleVectorStore = SimpleVectorStore.builder(embeddingModel).build();

        // 向向量存储中添加文档
        simpleVectorStore.add(new ArrayList<>(){{
            // 张三介绍
            add(new Document("张三,男,汉族,1996 年 7 月 26 日出生,现年 30 岁,毕业于四川大学计算机工程系。" +
                             "凭借扎实的专业教育背景,他在技术领域展现出强劲实力。\n" +
                             "张三尤其擅长算法设计与优化,能以高效逻辑解决复杂问题;在编程语言方面,对 C/C++ 运用娴熟,凭借该语言的高性能优势," +
                             "完成众多高质量项目。同时,他在游戏开发领域造诣颇深,从游戏逻辑搭建到画面渲染优化,都能出色完成。" +
                             "此外,他对 AI 有着深入研究,善于将 AI 技术融入游戏开发,为游戏增添智能化体验,是兼具多元技能与创新思维的复合型技术人才。"));
        }});

        return simpleVectorStore;
    }

}

注意:SimpleVectorStore 是 Spring AI 框架中提供的一个基础向量存储实现,用于存储和检索文本的向量表示(嵌入向量)。它作为向量数据库的简化替代方案,特别适合于开发环境、测试场景或小型应用,帮助开发者快速实现检索增强生成(RAG)功能。

(2)创建名为“AIController”的控制器,提供 /ai/simple 接口,实现简单的聊天,根据用户提供信息进行回答,并且通过 defaultAdvisors() 方法添加多个默认现有的 Advisor 实现。如下:

package com.hxstrive.springai.springai_openai.advisor1.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;

@RestController
public class AIController {

    @Autowired
    private ChatModel chatModel;

    @Autowired
    private ChatMemory chatMemory;

    @Autowired
    private VectorStore vectorStore;


    @GetMapping("/ai/simple")
    public String completion(@RequestParam("userText") String userText) {
        //OpenAiChatModel [defaultOptions=OpenAiChatOptions: {"streamUsage":false,"model":"gpt-3.5-turbo","temperature":0.7}]
        System.out.println(chatModel);
        //org.springframework.ai.chat.memory.MessageWindowChatMemory@3ba4a2a1
        System.out.println(chatMemory);
        //org.springframework.ai.vectorstore.SimpleVectorStore@15bab664
        System.out.println(vectorStore);

        // 构建 RAG advisor 时需要完成 vectorStore 初始化
        ChatClient chatClient = ChatClient.builder(chatModel)
        .defaultAdvisors(
            // 聊天记忆处理器 - 维护会话上下文
            MessageChatMemoryAdvisor.builder(chatMemory).build(),
            // RAG 处理器 - 检索增强生成,从向量数据库中检索答案
            QuestionAnswerAdvisor.builder(vectorStore).build()
        )
        .build();

        String conversationId = UUID.randomUUID().toString(); // 使用 UUID 生成唯一会话ID
        return chatClient.prompt()
        // 运行时设置会话ID参数
        .advisors(advisor -> {
            advisor.param(ChatMemory.CONVERSATION_ID, conversationId);
            System.out.println(advisor.getClass().getSimpleName() + " - " + conversationId);
        })
        .user(userText)
        .call()
        .content();
    }

}

上面代码中 QuestionAnswerAdvisor.builder(vectorStore).build() 会从我们自定义的 VectorStore(见 VectorStoreConfig 配置) 中检索文档。

运行示例,输出效果如下图:

image1.png

上图中,输出的信息确实是我们添加的内嵌文档。

注意:建议在构建时使用构建器(builder)的 defaultAdvisors() 方法注册 Advisor。

  

核心组件

API 包括用于非流式场景的 CallAdvisor 和 CallAdvisorChain,以及用于流式场景的 StreamAdvisor 和 StreamAdvisorChain。它还包括提示请求的 ChatClientRequest 和代表聊天完成响应的 ChatClientResponse。如下图:

image2.png

image3.png

上图中:

  • CallAdvisor:Spring AI 1.0.0 中用于拦截同步调用的增强处理器接口,替代旧版的 CallAroundAdvisor,允许在 LLM 调用前后添加自定义逻辑,如参数校验、日志记录或结果转换。

  • CallAdvisorChain:管理多个 CallAdvisor 的执行链,确保拦截器按顺序执行,实现责任链模式,可在链中动态添加或删除拦截逻辑。

  • StreamAdvisor:处理流式响应的增强处理器接口,替代旧版的 StreamAroundAdvisor,支持对 Flux 流中的每个元素进行实时处理,适用于需要逐块处理生成内容的场景。

  • StreamAdvisorChain:管理多个 StreamAdvisor 的执行链,确保流式响应在生成过程中依次经过各个拦截器,实现复杂的流式处理逻辑。

  • ChatClientRequest:封装发送给 LLM 的聊天请求,包含消息列表、模型配置(如温度、最大令牌数)及其他自定义参数,支持构建符合不同供应商规范的请求结构。

  • ChatClientResponse:封装 LLM 返回的聊天响应,包含生成的消息、使用的令牌统计、元数据等信息,提供统一接口访问不同供应商的响应内容。

 

Spring AI 框架构建的 Advisor Chain 支持按 getOrder() 值排序依次调用多个 Advisor — 数值越小优先级越高。链末自动加入的最终顾问会将请求发送至大语言模型(LLM)。

以下流程图展示了 Advisor 链与聊天模型的交互过程:

advisors-flow.jpg

流程图说明:

(1)Spring AI 框架将用户的 Prompt 封装为 AdvisedRequest 对象,并创建空的 AdvisorContext 上下文。

(2) 链中每个 Advisor 依次处理请求并可进行修改,也可选择阻断请求(不调用下一实体)。若选择阻断,该 Advisor 需负责填充响应内容。

(3)框架提供的最终 Advisor 将请求发送至聊天模型。

(4) 聊天模型的响应会逆向传回 Advisor 链,被转换为包含共享 AdvisorContext 实例的 AdvisedResponse 对象。

(5) 每个 Advisor 均可处理或修改该响应。

(6)通过提取 ChatCompletion 内容,最终生成的 AdvisedResponse 将返回给客户端。

  

Advisor 顺序

链中 Advisor 的执行顺序由 getOrder() 方法决定。因为,Advisor 继承了 Ordered 接口,源码如下:

public interface Advisor extends Ordered {
    int DEFAULT_CHAT_MEMORY_PRECEDENCE_ORDER = -2147482648;

    String getName();
}

下面是 Ordered 接口的定义:

package org.springframework.core;

public interface Ordered {
    // 最高优先级的常量值
    int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
    // 最低优先级的常量值
    int LOWEST_PRECEDENCE = Integer.MAX_VALUE;

    // 获取此对象的顺序值
    int getOrder();
}

关于排序的一些要点:

  • getOrder() 方法返回值越小,Advisor 优先级越高,越优先执行。返回值越大,优先级越低。如果多个 Advisor 的 getOrder() 方法返回值相同,其执行顺序无法保证。

  • Advisor 链采用栈式结构运作,链首 Advisor 最先处理请求,也是最后处理响应的环节。

  • 控制执行顺序:

    • 将 order 值设为接近 Ordered.HIGHEST_PRECEDENCE 可确保 Advisor 优先执行(请求处理时最先触发,响应处理时最后触发)。

    • 将 order 值设为接近 Ordered.LOWEST_PRECEDENCE 可确保 Advisor 最后执行(请求处理时最后触发,响应处理时最先触发)。

注意:执行顺序与数值看似矛盾的现象源于 Advisor 链的栈式特性,优先级最高(order 值最小)的 Advisor 会被置于栈顶。 随着栈展开,它将最先处理请求。而在栈回退时,它将最后处理响应。

如果需要在 Advisor 链中输入输出两端都优先处理的使用场景,应为每侧使用独立的 Advisor,通过配置不同的 order 值实现。最后,利用 advisor context 在它们之间共享状态。

  

相关 API 预览

核心接口 Advisor 位于 org.springframework.ai.chat.client.advisor.api 包中,如下图:

image4.png

如果开发要自定义 Advisor,需关注以下关键接口:

public interface Advisor extends Ordered {
    /**
     * 获取当前Advisor的唯一名称
     * 该名称用于标识和区分不同的Advisor实现
     * @return 标识当前Advisor的字符串名称
     */
    String getName();
}

同步式与响应式 Advisor 的两个子接口分别为:

public interface CallAdvisor extends Advisor {
    /**
     * 拦截并处理LLM的同步调用请求
     * 实现该方法可对请求进行预处理或对响应进行后处理
     * 
     * @param chatClientRequest 封装了发送给LLM的完整请求信息
     *        包含用户消息、系统提示、模型配置参数(如temperature、maxTokens)等
     *        可通过该对象读取或修改请求内容
     *        
     * @param callAdvisorChain 调用链对象,用于将请求传递给下一个Advisor或最终处理者
     *        通过调用chain.adviseCall()方法继续执行后续处理流程
     *        若中断调用链,则需手动构建并返回ChatClientResponse
     * 
     * @return 返回处理后的响应对象
     *         可能是原始响应的增强版本,或完全自定义的响应内容
     *         包含生成的回复消息、使用的token数量、元数据等信息
     */
    ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain);
}

以及:

public interface StreamAdvisor extends Advisor {
    /**
     * 拦截并处理LLM的流式调用请求
     * 实现该方法可对请求进行预处理或对流式响应进行实时转换
     * 
     * @param chatClientRequest 封装了发送给LLM的完整请求信息
     *        包含用户消息、系统提示、模型配置参数(如temperature、maxTokens)等
     *        可通过该对象读取或修改请求内容
     *        
     * @param streamAdvisorChain 流式调用链对象,用于将请求传递给下一个Advisor或最终处理者
     *        通过调用chain.adviseStream()方法继续执行后续处理流程
     *        返回的Flux流包含一系列ChatClientResponse对象,每个代表部分生成内容
     * 
     * @return 返回一个响应式Flux流,包含处理后的流式响应数据
     *         流中的每个元素代表LLM生成的部分内容
     *         可对原始流进行转换、过滤、增强等操作
     */    
    Flux<ChatClientResponse> adviseStream(ChatClientRequest chatClientRequest, StreamAdvisorChain streamAdvisorChain);
}

要在 Advisor 实现中将请求传递到下一个 Advisor(如果存在下一个 Advisor),需使用 CallAdvisorChain 与 StreamAdvisorChain 接口:

public interface CallAdvisorChain extends AdvisorChain {
    /**
     * 触发执行链中的下一个CallAdvisor或最终调用LLM服务
     * 每个CallAdvisor可以选择继续调用此方法将请求传递给下一环
     * 或直接返回响应,终止执行链的后续处理
     *
     * @param chatClientRequest 封装了发送给LLM的完整请求信息
     *        包含用户消息、系统提示、模型配置参数(如temperature、maxTokens)等
     *        可被各Advisor读取或修改
     *
     * @return 返回处理后的响应对象
     *         可能经过多个Advisor的增强或转换
     *         包含LLM生成的内容及处理过程中添加的元数据
     */
    ChatClientResponse nextCall(ChatClientRequest chatClientRequest);

    /**
     * 获取当前执行链中注册的所有CallAdvisor列表
     * 列表顺序决定了Advisor的执行顺序
     *
     * @return 包含所有注册的CallAdvisor的不可变列表
     *         列表顺序基于Ordered接口的getOrder()方法或 @Order 注解
     */
    List<CallAdvisor> getCallAdvisors();
}

以及:

public interface StreamAdvisorChain extends AdvisorChain {
    /**
     * 触发执行链中的下一个StreamAdvisor或最终调用LLM服务
     * 每个StreamAdvisor可以选择继续调用此方法将请求传递给下一环
     * 或直接返回自定义的Flux流,终止原始执行链的后续处理
     *
     * @param chatClientRequest 封装了发送给LLM的完整请求信息
     *        包含用户消息、系统提示、模型配置参数(如temperature、maxTokens)等
     *        可被各Advisor读取或修改
     *
     * @return 返回一个响应式Flux流,包含处理后的流式响应数据
     *         流中的每个元素代表LLM生成的部分内容
     *         可能经过多个Advisor的实时转换或增强
     */
    Flux<ChatClientResponse> nextStream(ChatClientRequest chatClientRequest);

    /**
     * 获取当前执行链中注册的所有StreamAdvisor列表
     * 列表顺序决定了Advisor的执行顺序
     *
     * @return 包含所有注册的StreamAdvisor的不可变列表
     *         列表顺序基于Ordered接口的getOrder()方法或@Order注解
     */
    List<StreamAdvisor> getStreamAdvisors();
}

  

自定义实现 Advisor

创建自定义 Advisor 需实现 CallAdvisor 或 StreamAdvisor(或两者)接口。核心实现方法是:

  • 非流式用 adviseCall()

  • 流式用 adviseStream()

简单示例

通过具体示例演示如何实现观察型(日志 Advisor)与增强型(重读 Re2)Advisor。

日志 Advisor

我们可以实现一个简单的日志 Advisor,在调用链中下一 Advisor 前后,分别记录 ChatClientRequest ChatClientResponse。该实现仅观察请求与响应而不修改,同时支持非流式与流式场景。代码如下:

package com.hxstrive.springai.springai_openai.advisor2.my_advisor;

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;
import org.springframework.ai.chat.client.advisor.api.StreamAdvisor;
import org.springframework.ai.chat.client.advisor.api.StreamAdvisorChain;
import reactor.core.publisher.Flux;

/**
 * 自定义 Advisor
 * @author hxstrive.com
 */
public class MyLoggerAdvisor implements CallAdvisor, StreamAdvisor {

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

    @Override
    public int getOrder() { 
        return 0;
    }

    @Override
    public ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain) {
        // 打印请求信息
        System.out.println("\n\nBEFORE: " + chatClientRequest);
        
        ChatClientResponse chatClientResponse = callAdvisorChain.nextCall(chatClientRequest);
        
        // 打印响应信息
        System.out.println("\n\nAFTER: " + chatClientResponse);
        
        return chatClientResponse;
    }

    @Override
    public Flux<ChatClientResponse> adviseStream(ChatClientRequest chatClientRequest, StreamAdvisorChain streamAdvisorChain) {
        System.out.println("BEFORE: {}" + chatClientRequest);
        Flux<ChatClientResponse> chatClientResponses = streamAdvisorChain.nextStream(chatClientRequest);
        System.out.println("AFTER: {}" + chatClientResponses);
        return chatClientResponses;
    }

}

创建名为“AIController”的控制器,在“/ai/simple”接口中添加自定义 MyLoggerAdvisor 实现,如下:

package com.hxstrive.springai.springai_openai.advisor2.controller;

import com.hxstrive.springai.springai_openai.advisor2.my_advisor.MyLoggerAdvisor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AIController {

    @Autowired
    private ChatModel chatModel;

    @Autowired
    private ChatMemory chatMemory;

    // 见章节最顶端的 VectorStoreConfig 配置文件
    @Autowired
    private VectorStore vectorStore;


    @GetMapping("/ai/simple")
    public String completion(@RequestParam("userText") String userText) {
        // 构建 RAG advisor 时需要完成 vectorStore 初始化
        ChatClient chatClient = ChatClient.builder(chatModel)
                .defaultAdvisors(
                        // 聊天记忆处理器 - 维护会话上下文
                        MessageChatMemoryAdvisor.builder(chatMemory).build(),
                        // RAG 处理器 - 检索增强生成,从向量数据库中检索答案
                        QuestionAnswerAdvisor.builder(vectorStore).build(),
                        // 自定义日志处理器 - 记录聊天对话【看这里】
                        new MyLoggerAdvisor()
                )
                .build();

        String conversationId = "sessionID-1990";
        return chatClient.prompt()
                // 运行时设置会话ID参数
                .advisors(advisor -> {
                    advisor.param(ChatMemory.CONVERSATION_ID, conversationId);
                })
                .user(userText)
                .call()
                .content();
    }

}

运行上述示例,效果如下图:

image.png

输出日志如下:

image.png

自定义 Advisor 注意事项:

  • 为 Advisor 提供一个唯一的名称。

  • 你可以通过设置 order 值来控制执行顺序,值越小优先级越高,值越大优先级越低。

  

重读(Re2)Advisor

近年来,大语言模型(LLMs)在各类推理任务上展现出惊人能力,但研究者发现这些模型在一次性阅读和推理时仍存在局限性。“Re-Reading Improves Reasoning in Large Language Models(重读可提高大型语言模型的推理能力)”这项研究提出了一种简单而有效的方法 —— 通过让模型“重读”问题文本来提升其推理表现。

研究发现,让大语言模型在生成回答前多次阅读输入问题可以显著提高其:

  • 逻辑推理的准确性

  • 数学解题的正确率

  • 复杂问题理解能力

  • 答案的连贯性和一致性

重读”具体实现通常采用以下两种策略:

  • 显式重读指令:在提示词中明确要求模型“请仔细阅读问题两遍后再回答”,例如:通过以下方式增强输入提示词来优化模型推理表现

{Input_Query}
Read the question again: {Input_Query}
  • 隐式重读架构:设计特殊的解码策略,让模型在生成答案前自动进行多轮文本处理。

简单应用:实现应用 Re2 技术的 Advisor 可按如下方式处理用户输入查询:

package com.hxstrive.springai.springai_openai.advisor3.my_advisor;

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;
import org.springframework.ai.chat.client.advisor.api.StreamAdvisor;
import org.springframework.ai.chat.client.advisor.api.StreamAdvisorChain;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.MessageType;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import reactor.core.publisher.Flux;
import java.util.ArrayList;
import java.util.List;

/**
 * Re2 技术实现
 * @author hxstrive.com
 */
public class ReReadingAdvisor implements CallAdvisor, StreamAdvisor {

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

    @Override
    public int getOrder() {
        return 0;
    }

    private ChatClientRequest before(ChatClientRequest chatClientRequest) {
        Prompt prompt = chatClientRequest.prompt();
        // 创建可修改的消息列表
        List<Message> modifiedMessages = new ArrayList<>(prompt.getUserMessages());

        // 修改用户输入(通常是最后一条消息)
        if (!modifiedMessages.isEmpty()) {
            Message lastMessage = modifiedMessages.get(modifiedMessages.size() - 1);
            if (lastMessage.getMessageType() == MessageType.USER) {
                String originalContent = lastMessage.getText();
                modifiedMessages.set(
                        modifiedMessages.size() - 1,
                        new UserMessage(String.format("""
                            %s
                            再读一遍问题: %s
                            """, originalContent, originalContent))
                );
            }
        }

        // 使用修改后的消息创建新请求
        System.out.println("\n\nReReadingAdvisor before: " + chatClientRequest);
        ChatClientRequest request = ChatClientRequest.builder()
                .prompt(Prompt.builder().chatOptions(prompt.getOptions()).messages(modifiedMessages).build())
                .build();
        System.out.println("\n\nReReadingAdvisor after: " + request);
        return request;
    }

    @Override
    public ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAdvisorChain callAdvisorChain) {
        return callAdvisorChain.nextCall(before(chatClientRequest));
    }

    @Override
    public Flux<ChatClientResponse> adviseStream(ChatClientRequest chatClientRequest, StreamAdvisorChain streamAdvisorChain) {
        return streamAdvisorChain.nextStream(before(chatClientRequest));
    }

}

创建名为“AIController”的控制器,在“/ai/simple”接口中添加自定义 ReReadingAdvisor 实现,如下:

package com.hxstrive.springai.springai_openai.advisor3.controller;

import com.hxstrive.springai.springai_openai.advisor3.my_advisor.ReReadingAdvisor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

@RestController
public class AIController {

    @Autowired
    private ChatModel chatModel;

    @Autowired
    private ChatMemory chatMemory;

    // 见最顶部的 VectorStoreConfig 配置文件
    @Autowired
    private VectorStore vectorStore;


    @GetMapping("/ai/simple")
    public String completion(@RequestParam("userText") String userText) {
        // 构建 RAG advisor 时需要完成 vectorStore 初始化
        ChatClient chatClient = ChatClient.builder(chatModel)
                .defaultAdvisors(
                        // 聊天记忆处理器 - 维护会话上下文
                        MessageChatMemoryAdvisor.builder(chatMemory).build(),
                        // RAG 处理器 - 检索增强生成,从向量数据库中检索答案
                        QuestionAnswerAdvisor.builder(vectorStore).build(),
                        // 自定义 Re2 处理器
                        new ReReadingAdvisor()
                )
                .build();

        String conversationId = "sessionID-1990";
        return chatClient.prompt()
                // 运行时设置会话ID参数
                .advisors(advisor -> {
                    advisor.param(ChatMemory.CONVERSATION_ID, conversationId);
                    System.out.println(advisor.getClass().getSimpleName() + " - " + conversationId);
                })
                .user(userText)
                .call()
                .content();
    }

}

运行上述示例,效果如下图:

image.png

输出日志如下:

image.png

关于更多内置 Advisor 的详细介绍,请阅读后续章节……

  

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号