java2AI系列:SpringAI初体验,接入智谱大模型

0 阅读4分钟

AI确实是发展的太快了,近半年直接呈现出指数型增长的趋势,作为传统的java程序员,即使精通大型分布式微服务系统的开发运维,面对如今的就业市场,老实讲真挺无力的。不管AI在对方企业是否有应用场景,是否真的有落地实践,从招聘岗位,技能要求都迫使我们不得不快速补充AI技能。

正如大佬讲的那样,java程序要叠加AI buff技能,并不是需要去啃python的LangChain、PyTorch、TensorFlow等开发框架,当然有基础有能力的朋友去转型我个人觉得肯定也是挺好的,java程序员的优势在于工程化能力,企业已有的系统各种系统,不是说不用了,被AI大模型给取缔,而是借助AI大模型的能力,为系统的能力进行大幅升级。以我之前所参与的智能客服系统为例,以前传统的方式通过规则引擎,做多轮对话的智能问答,也用了很多年,缓解了很多人工坐席侧的咨询压力。公司的模型侧也一直在迭代,承担了部分流量的智能问答。应该在半年以前,模型侧的能力从意图识别到智能问答,其实一直还算是被规则引擎的方式给碾压的,但是随着大模型的能力提升,很明显能感受到问答的质量出现大幅提升,分流比例也一直在提高,呈现出替换传统多轮对话的趋势。

这只是我接触到的冰山一角,大家平时用ai coding也能明显感受到让模型生成的代码质量最近半年内也有质的飞跃吧,那么以前那些只会crud,搞搞简单业务的螺丝钉,地位就显得岌岌可危。当然,我也不是给大家制造焦虑,传递焦虑,焦虑除了让自己身心俱疲外,毫无意义,要么转行,要么卷起来呗,要记住,我们肯定有我们自身的优势。近期准备好好学习spring ai,langchain4j,有兴趣的朋友可以关注一下专栏。

springai.jpg

Spring AI简介

Spring AI 是 Spring 官方推出的AI 工程化应用框架,核心使命是连接企业数据与 AI 模型,为 Java/Spring 生态开发者提供统一、可移植的方式集成大语言模型(LLM)、向量数据库等 AI 能力,无需为不同厂商逐一适配,降低企业级 AI 应用开发门槛。

引入依赖在dependencyManagement中加入spring-ai-bom,我这里选择的版本是1.1.2

<dependency>
	<groupId>org.springframework.ai</groupId>
	<artifactId>spring-ai-bom</artifactId>
	<version>${spring-ai.version}</version>
	<type>pom</type>
	<scope>import</scope>
</dependency>

进入这个依赖的pom,能看到spring ai支持的各种模型,常见的如openai、deepseek、ollama部署的本地模型,还有我这里准备使用的智谱ai大模型。

deepseek 在这里插入图片描述 zhipuai 在这里插入图片描述 这里的starter是开箱即用的,引入了对应模型的starter就需要添加对应模型的参数配置,不然启动时会报错。

操作步骤

依赖

以下是我的pom依赖,我这儿只创建了一个module,引入了zhipuai的starter。需要注意的是,spring ai需要jdk17以上的版本。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.5.10</version>
		<relativePath/>
	</parent>
	<groupId>com.roswu</groupId>
	<artifactId>spring-ai-learning</artifactId>
	<version>1.0.1-SNAPSHOT</version>
	<name>spring-ai-learning</name>
	<description>spring-ai-learning</description>

	<properties>
		<java.version>17</java.version>
		<spring-ai.version>1.1.2</spring-ai.version>
		<mybatis-plus.version>3.5.16</mybatis-plus.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.ai</groupId>
			<artifactId>spring-ai-starter-model-zhipuai</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
	</dependencies>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.ai</groupId>
				<artifactId>spring-ai-bom</artifactId>
				<version>${spring-ai.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>org.projectlombok</groupId>
				<artifactId>lombok</artifactId>
				<version>1.18.42</version>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

配置

模型配置有三个重要参数,模型地址base-url,模型秘钥api-key,模型名称chat.model。如果是换成deepseek的话,这里的zhipuai这个配置路径做对应的替换即可,其它的都差不多。

spring:
  application:
    name: spring-ai-learning
  ai:
    zhipuai:
      # 模型地址
      base-url: https://open.bigmodel.cn/api/paas
      # apiKey
      api-key: ${OPENAI_API_KEY}
      chat:
      	 # 模型名称
        model: GLM-4.7
        temperature: 0.7


server:
  port: 8088

ChatClient

增加一个模型配置类,注入一个ChatClient的bean,这里的入参是ZhiPuAiChatModel类型,与我们选用的模型和配置文件是对应的。

@Configuration
public class CommonConfiguration {

    @Bean
    public ChatClient chatClient(ZhiPuAiChatModel model) {
        return ChatClient.builder(model)
                .defaultSystem("你是一个智能桌面助手铁铁,帮助缓解主人工作之余的疲惫和情绪情绪")
                .build();
    }
}

defaultSystem参数用于设置系统提示词,也可以配置到yaml里面。

Controller

这里定义了一个Controller,提供两个api接口,功能都一样,只不过一个是同步调用,一个是流式调用。同步调用就是待模型输出所有答案后,一次性返回所有结果;而流式调用可以流式输出答案。大家用的千问,deepseek,豆包都是采用的流式调用,逐步加载出所有的答案,体验更好。

@RequiredArgsConstructor
@RestController
@RequestMapping("api")
public class ChatController {

    private final ChatClient chatClient;

    /**
     * 同步调用
     *
     * @param prompt
     * @return
     */
    @RequestMapping("/chat")
    public String chat(@RequestParam String prompt) {
        return chatClient
                // 传入user提示词
                .prompt(prompt)
                // 同步请求,会等待AI全部输出完才返回结果
                .call()
                .content();
    }


    /**
     * 流式输出
     *
     * @param prompt
     * @return
     */
    @RequestMapping(value = "/stream/chat", produces = "text/html;charset=UTF-8")
    public Flux<String> streamChat(@RequestParam String prompt) {
        return chatClient
                .prompt(prompt)
                .stream()
                .content();
    }

}

测试

启动服务,浏览器访问http://localhost:8088/api/chat?prompt=上班好累啊,请求完成后一次性加载全量的模型答案。

http://localhost:8088/api/chat?prompt=上班好累啊

在这里插入图片描述

再访问http://localhost:8088/api/stream/chat?prompt=上班好累啊,答案则是逐步加载出来的,响应更快。

http://localhost:8088/api/stream/chat?prompt=上班好累啊

在这里插入图片描述