当前位置: 首页 > ops >正文

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进行实现,希望对你有所帮助。

未完待续

http://www.xdnf.cn/news/8647.html

相关文章:

  • 实验7 HTTP协议分析与测量
  • LangGraph实现多智能体的方法
  • AI大模型核心基础:向量与张量原理及实践应用指南
  • Level1.7列表
  • 内存越界(Memory Out-of-Bounds)详解
  • 数字图像处理:基于 hough 变换的图像边缘提取
  • vector中reserve导致的析构函数问题
  • MySQL主从同步原理
  • 大模型推理 memory bandwidth bound (4) - Speculative Decoding
  • 【Bluedroid】蓝牙HID Host virtual_unplug全流程源码解析
  • 【笔记】关于synchronized关键字的底层原理之我流理解(未完)
  • TReport组件指南总结
  • C++ 继承详解:基础篇(含代码示例)
  • 【算法】:动态规划--背包问题
  • Linux常用下载资源命令
  • OpenLayers 加载导航与基本操作控件
  • AD9268、AD9643调试过程中遇到的问题
  • Linux的读写屏障
  • Mysql 通过案例快速学习常见操作
  • 索引下探(Index Condition Pushdown,简称ICP)
  • 大模型介绍
  • 动态规划dp
  • Java中==和equals()的终极对比
  • SpikingYOLOX
  • GATT 服务的核心函数bt_gatt_discover的介绍
  • Day 34
  • Docker 镜像标签(Tag)规范与要求
  • 历史数据分析——宁波港
  • 防火墙流量管理-带宽管理
  • OpenLayers 加载图层探查控件