Springboot——整合LangChain4j实现交互

文章目录

前言

虽然Spring 生态园中,推出了Spring AI。但用起来总感觉不是那么好用。LangChain4j 本身就对许多大模型做了封装,支持普通输出流式输出操作。

本篇博客重点说明如何将LangChain4j整合到Springboot 的项目应用中。

环境准备

  • jdk 17
  • maven 3.6.3
  • springboot 3.4.0
  • langchain4j 1.0.0-beta1

依赖引入

核心依赖以及版本限定。

xml 复制代码
<properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <langchain4j.version>1.0.0-beta1</langchain4j.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- langchain4j 核心依赖 -->
    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j</artifactId>
        <version>${langchain4j.version}</version>
    </dependency>

    <!-- langchain4j -->
    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId>
    </dependency>

    <!-- 流式输出 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</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>
        <version>1.18.24</version> <!-- 使用最新版本 -->
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.14.1</version> <!-- 使用最新的稳定版本 -->
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.14.1</version> <!-- 使用与 log4j-api 相同的版本 -->
    </dependency>

    <!-- ArrayListMultimap -->
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>33.3.1-jre</version>
        <scope>compile</scope>
    </dependency>

</dependencies>

<!-- 版本限制 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-community-bom</artifactId>
            <version>${langchain4j.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

常规输出与流式输出

配置大模型key和使用模型信息

langchain4j-community-dashscope-spring-boot-starter这个依赖中,存在一个他定义好的bean实例 dev.langchain4j.community.dashscope.spring.AutoConfig

当存在langchain4j.community.dashscope.chat-model.api-key的配置点时,会自动构建QwenChatModel的实例对象。

简单输出

按照bean的配置要求,本次使用大模型为qwen-max,对应key为阿里百炼key

复制代码
langchain4j.community.dashscope.chat-model.api-key=${ALI_AI_KEY}
langchain4j.community.dashscope.chat-model.model-name=qwen-max

构建简单测试接口

java 复制代码
import dev.langchain4j.community.model.dashscope.QwenChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * 普通对话模式
 */
@RestController
@RequestMapping("/ai")
public class ChatController {

    @Autowired
    private QwenChatModel qwenChatModel;

    @GetMapping("/chat")
    public String chat(@RequestParam(defaultValue = "你是谁?") String message) {
        return qwenChatModel.chat(message);
    }
}

访问与结果

http://localhost:8080/ai/chat

流式输出

使用流式输出,需要引入spring-boot-starter-webflux依赖。且大模型需要更换为支持流式输出的,如qwq-32b

配置文件

复制代码
langchain4j.community.dashscope.streaming-chat-model.api-key=${ALI_AI_KEY}
langchain4j.community.dashscope.streaming-chat-model.model-name=qwq-32b

编写流式输出接口

java 复制代码
import dev.langchain4j.community.model.dashscope.QwenStreamingChatModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

/**
 * 流式输出
 */
@RestController
@RequestMapping("/ai/stream")
public class ChatStreamController {

    @Autowired
    private QwenStreamingChatModel qwenStreamingChatModel;

    // MediaType.TEXT_EVENT_STREAM_VALUE
    // produces = "text/event-stream;charset=UTF-8"
    @RequestMapping(value = "/chat",produces = "text/stream;charset=UTF-8")
    public Flux<String> chat(@RequestParam(defaultValue = "你是谁?") String message) {
        return Flux.create(emitter-> {
            qwenStreamingChatModel.chat(message, new StreamingChatResponseHandler() {

                /**
                 * 每次流式响应的文本
                 *  大模型根据每个token响应
                 * @param partialResponse The partial response (usually a single token), which is a part of the complete response.
                 */
                @Override
                public void onPartialResponse(String partialResponse) {
                    System.out.println("onPartialResponse---"+partialResponse);
                    // 逐次返回不分响应
                    emitter.next(partialResponse);
                }

                /**
                 * 响应结束的文本
                 *
                 * @param completeResponse The complete response generated by the model.
                 *                         For textual responses, it contains all tokens from {@link #onPartialResponse} concatenated.
                 */
                @Override
                public void onCompleteResponse(ChatResponse completeResponse) {
                    System.out.println("onCompleteResponse---"+completeResponse);
                    // 完成整个响应流
                    emitter.complete();
                }

                /**
                 * 出现报错的文本
                 *
                 * @param error The error that occurred
                 */
                @Override
                public void onError(Throwable error) {
                    System.out.println("onError---"+error);
                    emitter.error(error);
                }
            });
        });
    }
}

效果展示

http://localhost:8080/ai/stream/chat

相关推荐
你知道烟火吗26 分钟前
谈谈对反射的理解?
java·开发语言·spring boot·后端
it自1 小时前
Redisson在Spring Boot项目中的集成与实战
java·spring boot·redis·后端·缓存
我命由我123452 小时前
Spring Boot 项目问题:Web server failed to start. Port 5566 was already in use.
java·前端·jvm·spring boot·后端·spring·java-ee
热河暖男5 小时前
Spring Boot AI 极速入门:解锁智能应用开发
java·人工智能·spring boot·ai编程
苦学编程的谢5 小时前
SpringBoot统一功能处理
java·spring boot·后端
旋风菠萝16 小时前
JVM易混淆名称
java·jvm·数据库·spring boot·redis·面试
weisian15117 小时前
Java WEB技术-序列化和反序列化认识(SpringBoot的Jackson序列化行为?如何打破序列化过程的驼峰规则?如何解决学序列化循环引用问题?)
java·spring boot
橘子编程17 小时前
SpringMVC核心原理与实战指南
java·spring boot·spring·tomcat·mybatis
慌糖20 小时前
Spring Boot音乐服务器项目-查询喜欢的音乐模块
服务器·spring boot·mybatis
尚学教辅学习资料1 天前
SpringBoot3.x入门到精通系列:1.2 开发环境搭建
spring boot·gradle·maven·intellij idea·jdk17·开发环境