6. Advisor 对话拦截

文章目录

6. Advisor 对话拦截

Advisor对话拦截

Spring AI 利用面向切面的思想提供 Advisors API , 它提供了灵活而强大的方法来拦截、修改和增强 Spring 应用程序中的 AI 驱动交互。

Advisor 接口提供了CallAdvisor和组成CallAdvisorChain(适用于非流式场景),以及StreamAdvisor和 (StreamAdvisorChain适用于流式场景)。它还包括ChatClientRequest,用于表示未密封的 Prompt 请求,以及 ,ChatClientResponse用于表示聊天完成响应。

日志拦截:

由于整个对话过程是一个"黑盒", 不利于我们调试, 可以通过SimpleLoggerAdvisor拦截对话记录可以帮助观察我们发了什么信息给大模型便于调试。

  1. 设置defaultAdvisors
java 复制代码
@SpringBootTest
public class AdvisorTest {

    ChatClient chatClient;
    @BeforeEach
    public  void init(@Autowired
                      DeepSeekChatModel chatModel) {
        chatClient = ChatClient
                .builder(chatModel)
        // 在构造器当中设置拦截器,构造器当中设置的拦截器,是使用该构造器对话都会生效
                .defaultAdvisors(
                        new SimpleLoggerAdvisor()
                )
                .build();
    }
    @Test
    public void testChatOptions() {
        String content = chatClient.prompt()
                .user("Hello")
                .advisors() // 在其中的某个对话当中设置拦截器,对话中,只会在对话当中生效
                .call()
                .content();
        System.out.println(content);
    }

    ChatClient chatClient;
    @BeforeEach
    public  void init2(@Autowired
                      DeepSeekChatModel chatModel) {
        chatClient = ChatClient
                .builder(chatModel)
        // 在构造器当中设置拦截器,构造器当中设置的拦截器,是使用该构造器对话都会生效
                .defaultAdvisors(
                        new SimpleLoggerAdvisor(),
                    // 可以设置多个拦截器,除非敏感词就会报一个错误的,也可以定义
                    new SafeGuardAdvisor(List.of("过滤敏感词"))
                )
                .build();
    }
}
  1. 设置日志级别(注意:需要设置日志级别才会生效,拦截器才会生效)
properties 复制代码
logging.level.org.springframework.ai.chat.client.advisor=DEBUG

日志中就记录了

request: 请求的日志信息

response: 响应的信息

自定义拦截:

重读(Re2)

重读策略的核心在于让LLMs重新审视输入问题,这借鉴了人类解决问题的思维方式。通过这种方式,LLMs能够更深入地理解问题,发现复杂的模式,从而在各种推理任务中表现得更加强大。

简单的说,就是让大模型,重复多次,精读理解该内容

properties 复制代码
{Input_Query}
再次阅读问题:{Input_Query}

可以基于BaseAdvisor来实现自定义Advisor, 他实现了重复的代码 提供 模板方法让我们可以专注自己业务编写即可。

java 复制代码
/**
 */
// 实现 BaseAdvisor 接口,其中该 BaseAdvisor 已经是已经继承了CallAdvisor,StreamAdvisor 同时做了增强
public class ReReadingAdvisor implements BaseAdvisor {

	private static final String DEFAULT_USER_TEXT_ADVISE = """
      {re2_input_query}
      Read the question again: {re2_input_query}
      """;

    // 表示设置优先级别, 0 是最高的
	@Override
	public int getOrder() {
		return 0;
	}

	@Override
	public ChatClientRequest before(ChatClientRequest chatClientRequest, AdvisorChain advisorChain) {
		// 获得用户(用户上一秒)输入文本内容
		String inputQuery = chatClientRequest.prompt().getUserMessage().getText();

		// 定义重复输入模版
		String augmentedSystemText = PromptTemplate.builder().template(DEFAULT_USER_TEXT_ADVISE).build()
				.render(Map.of("re2_input_query", inputQuery));

		// 设置请求的提示词
		ChatClientRequest processedChatClientRequest =
				// 不保留
				ChatClientRequest.builder()
				.prompt(Prompt.builder().content(augmentedSystemText).build())
				.build();
		return processedChatClientRequest;
	}

	@Override
	public ChatClientResponse after(ChatClientResponse chatClientResponse, AdvisorChain advisorChain) {
		//我们不做任何处理
		return chatClientResponse;
	}
}

测试:

java 复制代码
@SpringBootTest
public class AdvisorTest {

    ChatClient chatClient;
    @BeforeEach
    public  void init(@Autowired
                      DeepSeekChatModel chatModel) {
        chatClient = ChatClient
                .builder(chatModel)
                .defaultAdvisors(
                        new SimpleLoggerAdvisor()
                )
                .build();
    }
    @Test
    public void testChatOptions() {
        String content = chatClient.prompt()
                .user("中国有多大?")
                .advisors(new ReReadingAdvisor())
                .call()
                .content();
        System.out.println(content);
    }
}
原理

记住!

Advisor只有结合ChatClient才能用! 是SpringAi上层提供的。 模型底层并没有这个东西

最后:

"在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。"

相关推荐
全栈弄潮儿4 小时前
《小项目实战 1:用 AI 从零搭一个 API 服务》
aigc·openai·ai编程
m4Rk_5 小时前
【论文阅读】Agent 记忆机制(83):Inside Out——用可演化 PersonaTree 构建 Agent 的核心长期记忆
论文阅读·人工智能·学习·开源·github
运行时异常5 小时前
【WMS 仓储系统集成 AI Agent 实战】第 8 讲(终篇):生产部署与并发安全——Semaphore 放进 Flux.defer 的坑,压测抓了一晚上
人工智能·安全
杨杨杨大侠5 小时前
Jev、Kev、Laya:决策模型怎么选,什么时候需要微调?
人工智能·python·agent
代码方舟5 小时前
零信任架构实战:基于天远人企关联构建自动化供应链金融网关
运维·人工智能·架构·自动化
EatFan5 小时前
Spring Boot 4 落地观察:从 yudao-cloud、matecloud、JPower 看国产脚手架的升级路线与迁移清单
java·spring boot·后端·spring cloud·微服务·后端开发·jdk 21
虹科网络安全6 小时前
“顶会”看安全(十八):超越越狱:揭示由能力边界模糊引发的 LLM 应用安全风险
人工智能·安全
Maiko Star6 小时前
* LangChain 提示词模板详解:ChatPromptTemplate 的使用与高级特性
java·人工智能·langchain
鬓戈6 小时前
Rust 语言与 AI 应用生态调研及学习路径
人工智能·学习·rust