9. LangChain4j + 整合 Spring Boot

9. LangChain4j + 整合 Spring Boot

文章目录

  • [9. LangChain4j + 整合 Spring Boot](#9. LangChain4j + 整合 Spring Boot)
    • [LangChain4j + 整合 Spring Boot 实操](#LangChain4j + 整合 Spring Boot 实操)
  • 最后:

LangChain4j 整合 SpringBoot 官方文档:https://docs.langchain4j.dev/tutorials/spring-boot-integration/

浅谈---下: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);
    }
}

最后:

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

相关推荐
拾年2753 分钟前
从 Prompt 到 Context 再到 Harness:AI 工程化的三年三级跳
人工智能
玉宇夕落6 分钟前
别再死磕 Prompt 了!上下文工程 (Context Engineering) 的简单学习
后端
小九九的爸爸8 分钟前
前端想要入门Agent开发,要具备哪些Python基础?
python·agent·ai编程
AlbertZein9 分钟前
别只盯着最强模型了,Agent 场景更该看这类 Flash 档模型
aigc·openai·ai编程
用户30904636139417 分钟前
Claude 不会直接执行你的函数,它只会生成一段结构化的工具调用请求。真正执行函数、访问数据库、请求外部 API 的动作,必须由你的后端完成。
人工智能
不加辣椒18 分钟前
第14章 Prompt 编排与优化技术
人工智能
Bolt21 分钟前
读懂 Claude Code `/loop` 与编码 Agent 的循环革命
人工智能·程序员·agent
用户2080468045621 分钟前
文本分块策略与最佳实践实战指南
人工智能
ZzT22 分钟前
公司用 AI 筛简历,他写了个 AI 帮你挑公司
面试·aigc·ai编程
用户342323237631728 分钟前
定时器与 PWM 输出详解
后端