9. LangChain4j + 整合 Spring Boot

9. LangChain4j + 整合 Spring Boot

@toc


LangChain4j 整合 SpringBoot 官方文档:docs.langchain4j.dev/tutorials/s...

浅谈---下:LangChain4j twolevels of abstraction

低阶 APi 和 高阶 API

Spring Boot整合底阶API所需POM:

xml 复制代码
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
    <version>1.2.0-beta8</version>
</dependency>
properties 复制代码
langchain4j.open-ai.chat-model.api-key=${OPENAI_API_KEY}
langchain4j.open-ai.chat-model.model-name=gpt-4o
langchain4j.open-ai.chat-model.log-requests=true
langchain4j.open-ai.chat-model.log-responses=true
...

Spring Boot整合高阶API所需POM:

截至目前,存在两种整合 Spring Boot 的方式:

LangChain4J 原生整合:

LangChain4J + Spring Boot 整合:

小总结:

LangChain4j + 整合 Spring Boot 实操

  1. 创建对应项目的 module 模块内容:
  2. 导入相关的 pom.xml 的依赖,这里我们采用流式输出的方式,导入 整合 Spring Boot ,`langchain4j-open-ai-spring-boot-starter,langchain4j-spring-boot-starter 这里我们不指定版本,而是通过继承的 pom.xml 当中获取。
xml 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--1 LangChain4j 整合boot底层支持-->
        <!--   https://docs.langchain4j.dev/tutorials/spring-boot-integration  -->
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
        </dependency>
        <!--2 LangChain4j 整合boot高阶支持-->
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-spring-boot-starter</artifactId>
        </dependency>
  1. 设置 applcation.yaml / properties 配置文件,其中指明我们的输出响应的编码格式,因为如果不指定的话,存在返回的中文,就是乱码了。
properties 复制代码
server.port=9008

spring.application.name=langchain4j-08boot-integration


# 设置响应的字符编码,避免流式返回输出乱码
server.servlet.encoding.charset=utf-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true

# https://docs.langchain4j.dev/tutorials/spring-boot-integration
#langchain4j.open-ai.chat-model.api-key=${aliQwen-api}
#langchain4j.open-ai.chat-model.model-name=qwen-plus
#langchain4j.open-ai.chat-model.base-url=https://dashscope.aliyuncs.com/compatible-mode/v1


# 大模型调用不可以明文配置,你如何解决该问题
# 1 yml:                ${aliQwen-api},从环境变量读取
# 2 config配置类:      System.getenv("aliQwen-api")从环境变量读取
  1. 编写大模型三件套(大模型 key,大模型 name,大模型 url) 三件套的大模型配置类。

这里我们测试操作两个大模型:DeepSeek,通义千问。

java 复制代码
import com.rainbowsea.langchain4jbootintegration.service.ChatAssistantQwen;
import com.rainbowsea.langchain4jbootintegration.service.ChatAssistantDeepSeek;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description: 知识出处 https://docs.langchain4j.dev/get-started
 */
@Configuration
public class LLMConfig {

    @Bean(name = "qwen")
    public ChatModel chatModelQwen() {
        return OpenAiChatModel.builder()
                .apiKey(System.getenv("aliQwen_api"))
                .modelName("qwen-plus")
                .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                .build();
    }

    /**
     * @Description: 知识出处,https://api-docs.deepseek.com/zh-cn/
     */
    @Bean(name = "deepseek")
    public ChatModel chatModelDeepSeek() {
        return
                OpenAiChatModel.builder()
                        .apiKey(System.getenv("deepseek_api"))
                        .modelName("deepseek-chat")
                        //.modelName("deepseek-reasoner")
                        .baseUrl("https://api.deepseek.com/v1")
                        .build();
    }

}

  1. 编写我们操作两个大模型的将接口类,同时通过在我们的配置类上 + 通过 @AiService 进行一个对接口的实现。

@AiService 注解的源码如下:

java 复制代码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package dev.langchain4j.service.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.stereotype.Service;

@Service
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AiService {
    AiServiceWiringMode wiringMode() default AiServiceWiringMode.AUTOMATIC;

    String chatModel() default "";

    String streamingChatModel() default "";

    String chatMemory() default "";

    String chatMemoryProvider() default "";

    String contentRetriever() default "";

    String retrievalAugmentor() default "";

    String moderationModel() default "";

    String[] tools() default {};
}
java 复制代码
package com.rainbowsea.langchain4jbootintegration.service;

import dev.langchain4j.service.spring.AiService;

import static dev.langchain4j.service.spring.AiServiceWiringMode.EXPLICIT;

/**
 */
@AiService(wiringMode = EXPLICIT, chatModel = "qwen")
public interface ChatAssistantQwen
{
    String chat(String prompt);
}
java 复制代码
import com.rainbowsea.langchain4jbootintegration.service.ChatAssistantQwen;
import com.rainbowsea.langchain4jbootintegration.service.ChatAssistantDeepSeek;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description: 知识出处 https://docs.langchain4j.dev/get-started
 */
@Configuration
public class LLMConfig {

    @Bean(name = "qwen")
    public ChatModel chatModelQwen() {
        return OpenAiChatModel.builder()
                .apiKey(System.getenv("aliQwen_api"))
                .modelName("qwen-plus")
                .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                .build();

    }

    // 你使用第2种类,高阶API    AiService
    @Bean(name = "qwenAssistant")
    public ChatAssistantQwen chatAssistantQwen(@Qualifier("qwen") ChatModel chatModelQwen) {
        return AiServices.create(ChatAssistantQwen.class, chatModelQwen);
    }
}

同理我们添加上 DeepSeek 操作的接口类,以及对应大模型的实现类

java 复制代码
package com.rainbowsea.langchain4jbootintegration.service;

import dev.langchain4j.service.spring.AiService;
import static dev.langchain4j.service.spring.AiServiceWiringMode.EXPLICIT;
/**
 */
@AiService(wiringMode = EXPLICIT, chatModel = "deepseek")
public interface ChatAssistantDeepSeek
{
    String chat(String prompt);
}
java 复制代码
package com.rainbowsea.langchain4jbootintegration.config;

import com.rainbowsea.langchain4jbootintegration.service.ChatAssistantQwen;
import com.rainbowsea.langchain4jbootintegration.service.ChatAssistantDeepSeek;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description: 知识出处 https://docs.langchain4j.dev/get-started
 */
@Configuration
public class LLMConfig {

    /**
     * @Description: 知识出处,https://api-docs.deepseek.com/zh-cn/
     */
    @Bean(name = "deepseek")
    public ChatModel chatModelDeepSeek() {
        return
                OpenAiChatModel.builder()
                        .apiKey(System.getenv("deepseek_api"))
                        .modelName("deepseek-chat")
                        //.modelName("deepseek-reasoner")
                        .baseUrl("https://api.deepseek.com/v1")
                        .build();
    }


    @Bean(name = "deepseekAssistant")
    public ChatAssistantDeepSeek chatAssistantDeepSeek(@Qualifier("deepseek") ChatModel chatModelDeepSeek) {
        return AiServices.create(ChatAssistantDeepSeek.class, chatModelDeepSeek);
    }
}

DeepSeek + 通义千问

java 复制代码
package com.rainbowsea.langchain4jbootintegration.config;

import com.rainbowsea.langchain4jbootintegration.service.ChatAssistantQwen;
import com.rainbowsea.langchain4jbootintegration.service.ChatAssistantDeepSeek;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description: 知识出处 https://docs.langchain4j.dev/get-started
 */
@Configuration
public class LLMConfig {

    @Bean(name = "qwen")
    public ChatModel chatModelQwen() {
        return OpenAiChatModel.builder()
                .apiKey(System.getenv("aliQwen_api"))
                .modelName("qwen-plus")
                .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                .build();

    }

    // 你使用第2种类,高阶API    AiService
    @Bean(name = "qwenAssistant")
    public ChatAssistantQwen chatAssistantQwen(@Qualifier("qwen") ChatModel chatModelQwen) {
        return AiServices.create(ChatAssistantQwen.class, chatModelQwen);
    }


    /**
     * @Description: 知识出处,https://api-docs.deepseek.com/zh-cn/
     */
    @Bean(name = "deepseek")
    public ChatModel chatModelDeepSeek() {
        return
                OpenAiChatModel.builder()
                        .apiKey(System.getenv("deepseek_api"))
                        .modelName("deepseek-chat")
                        //.modelName("deepseek-reasoner")
                        .baseUrl("https://api.deepseek.com/v1")
                        .build();
    }


    @Bean(name = "deepseekAssistant")
    public ChatAssistantDeepSeek chatAssistantDeepSeek(@Qualifier("deepseek") ChatModel chatModelDeepSeek) {
        return AiServices.create(ChatAssistantDeepSeek.class, chatModelDeepSeek);
    }
}
  1. 编写操作两大,大模型的 Controller 类,使用我们自己编写的接口类操作大模型。

操作访问通义千问。

java 复制代码
import com.rainbowsea.langchain4jbootintegration.service.ChatAssistantDeepSeek;
import com.rainbowsea.langchain4jbootintegration.service.ChatAssistantQwen;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description: https://docs.langchain4j.dev/tutorials/spring-boot-integration
 */
@RestController
@Slf4j
public class DeclarativeAIServiceController
{
    @Resource(name = "qwenAssistant")
    private ChatAssistantQwen chatAssistantQwen;


    // http://localhost:9008/chatapi/highapi
    @GetMapping(value = "/chatapi/highapi")
    public String highApi(@RequestParam(value = "prompt", defaultValue = "你是谁") String prompt)
    {
        return chatAssistantQwen.chat(prompt);
    }

}

操作访问 DeepSeek

java 复制代码
package com.rainbowsea.langchain4jbootintegration.controller;

import com.rainbowsea.langchain4jbootintegration.service.ChatAssistantDeepSeek;
import com.rainbowsea.langchain4jbootintegration.service.ChatAssistantQwen;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Description: https://docs.langchain4j.dev/tutorials/spring-boot-integration
 */
@RestController
@Slf4j
public class DeclarativeAIServiceController
{
   
    @Resource(name = "deepseekAssistant")
    private ChatAssistantDeepSeek chatAssistantDeepSeek;



    // http://localhost:9008/chatapi/highapi02
    @GetMapping(value = "/chatapi/highapi02")
    public String highApi02(@RequestParam(value = "prompt", defaultValue = "你是谁") String prompt)
    {
        return chatAssistantDeepSeek.chat(prompt);
    }
}

最后:

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

相关推荐
仙逆GPT44 分钟前
ChatGPT Pro 20X重新开放订阅:还是原来的Pro 20X吗?Codex重度用户先看这4个变化
chatgpt·ai编程·codex·chatgptplus·chatgptpro
9i编程1 小时前
17. 把 DDD 开源脚手架化为自己的:第四次联调(三)——一坨 MalformedInputException,最后查出来是 yml 里的中文注释
人工智能·openai·ai编程
Solara2 小时前
29 条回复永远没送到:翻完 108 条投递台账,我才发现「微信限流」是我取错的名字
人工智能·agent·ai编程
HelloWorld0012 小时前
告别 Toy Demo!基于 MCP 协议打造生产级 AI 自动化中台:架构演进、权限沙箱与实战踩坑
ai编程
小虎AI生活2 小时前
微信上线AI帮写,朋友圈文案不用自己憋了
aigc·ai编程
柒和远方2 小时前
LangSmith RAG 量化评估:从"感觉还行"到"数据说话"
langchain·llm·测试
Lambert2812 小时前
删不掉的 1.19.1:LangChain4j 发了个事故版本,升错的 Java 团队别乱降级
aigc·openai·ai编程
Yuhano2 小时前
W3. 实现Agent工具调用引擎
前端·aigc·ai编程
用户41716576618202 小时前
AI 写完的系统,挂在了 Redis 集群上
ai编程
染指11103 小时前
131.Agent-Agent设计模式-MAS多智能体系统(Multi-Agent-System)
人工智能·设计模式·langchain·agent·agents