SpringBoot 集成 LangChain4j OpenAI

SpringBoot 集成 LangChain4j OpenAI

  • [1 依赖](#1 依赖)
  • [2 配置](#2 配置)
  • [3 代码](#3 代码)
    • [1 AiConf.java](#1 AiConf.java)
    • [2 ChatController.java](#2 ChatController.java)
    • [3 ImageController.java](#3 ImageController.java)
    • [4 AudioController.java](#4 AudioController.java)
    • [5 Application.java](#5 Application.java)
  • [4 结果](#4 结果)

1 依赖

xml 复制代码
<?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.7</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<groupId>com.xu</groupId>
	<artifactId>langchain-openai</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>langchain-openai</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>25</java.version>
        <maven.compiler.source>25</maven.compiler.source>
        <maven.compiler.target>25</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
	</properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>dev.langchain4j</groupId>
                <artifactId>langchain4j-bom</artifactId>
                <version>1.8.0</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>dev.langchain4j</groupId>
                <artifactId>langchain4j-community-bom</artifactId>
                <version>1.8.0-beta15</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

	<dependencies>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
        </dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<annotationProcessorPaths>
						<path>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</path>
					</annotationProcessorPaths>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<releases>
				<enabled>false</enabled>
			</releases>
		</repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/snapshot</url>
			<releases>
				<enabled>false</enabled>
			</releases>
		</pluginRepository>
	</pluginRepositories>

</project>

2 配置

yml 复制代码
server:
  port: 8080
  context-path: /

spring:
  application:
    name: langchain-openai
  servlet:
    multipart:
      max-file-size: 50MB
      max-request-size: 50MB

langchain4j:
  open-ai:
    chat-model:
      api-key: demo
      model-name: gpt-4o-mini
      temperature: 0.7
      base-url: http://*********
      log-requests: true
      log-responses: true

logging:
  level:
    dev.langchain4j: debug

3 代码

1 AiConf.java

java 复制代码
package com.xu.conf;

import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiImageModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * @author hyacinth
 */
@Configuration
public class AiConf {

    @Value("${langchain4j.open-ai.chat-model.api-key}")
    private String apiKey;

    @Value("${langchain4j.open-ai.chat-model.model-name}")
    private String modelName;

    @Value("${langchain4j.open-ai.chat-model.base-url}")
    private String baseUrl;

    @Value("${langchain4j.open-ai.chat-model.log-requests}")
    private boolean logRequests;

    @Value("${langchain4j.open-ai.chat-model.log-responses}")
    private boolean logResponses;

    @Bean
    @Primary
    public OpenAiImageModel openAiImageModel() {
        return OpenAiImageModel.builder()
                .baseUrl(baseUrl)
                .apiKey(apiKey)
                .modelName(modelName)
                .logRequests(true)
                .logResponses(true)
                .build();
    }

    @Bean
    public StreamingChatModel streamingChatModel(){
        return OpenAiStreamingChatModel.builder()
                .baseUrl(baseUrl)
                .apiKey(apiKey)
                .modelName(modelName)
                .logRequests(logRequests)
                .logResponses(logResponses)
                .build();
    }

}

2 ChatController.java

java 复制代码
package com.xu.controller;

import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.chat.request.ChatRequest;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;
import dev.langchain4j.model.openai.OpenAiChatModel;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * 普通聊天
 *
 * @author hyacinth
 */
@Slf4j
@RestController
@RequestMapping("/openai/text")
@AllArgsConstructor
public class ChatController {

    private final ChatModel chatModel;

    private final StreamingChatModel streamingChatModel;

    private final OpenAiChatModel openAiChatModel;

    /**
     * 聊天
     *
     * @param message 问题
     * @return 结果
     */
    @PostMapping("/chat1")
    public Object chat1(@RequestParam(value = "message", defaultValue = "Hello") String message) {
        return chatModel.chat(message);
    }

    /**
     * 聊天
     *
     * @param message 问题
     * @return 结果
     */
    @PostMapping("/chat2")
    public Object chat2(@RequestParam(value = "message", defaultValue = "Hello") String message) {
        var user = UserMessage.from(message);
        var request = ChatRequest.builder().messages(user).build();
        return openAiChatModel.chat(request).aiMessage();
    }

    /**
     * 聊天
     *
     * @param message 问题
     * @return 结果
     */
    @PostMapping("/chat3")
    public Object chat3(@RequestParam(value = "message", defaultValue = "Hello") String message) {
        streamingChatModel.chat(message, new StreamingChatResponseHandler() {
            @Override
            public void onPartialResponse(String partialResponse) {
                log.info("开始: {}", partialResponse);
                IO.println("开始: " + partialResponse);
            }

            @Override
            public void onCompleteResponse(ChatResponse completeResponse) {
                log.info("结束: {}", completeResponse);
            }

            @Override
            public void onError(Throwable error) {
                log.error("异常: {}", error.getMessage());
            }
        });
        return 1;
    }

}

3 ImageController.java

java 复制代码
package com.xu.controller;

import dev.langchain4j.data.message.ImageContent;
import dev.langchain4j.data.message.TextContent;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.request.ChatRequest;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiImageModel;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.Base64;

/**
 * 图片处理
 *
 * @author hyacinth
 */
@RestController
@RequestMapping("/openai/images")
@AllArgsConstructor
public class ImageController {

    private final OpenAiImageModel openAiImageModel;

    private final OpenAiChatModel openAiChatModel;

    /**
     * 生成图片
     *
     * @param message 描述
     * @return 结果
     */
    @PostMapping("/gen1")
    public Object gen1(@RequestParam(value = "message", defaultValue = "生成一个唐老鸭图片") String message) {
        var response = openAiImageModel.generate(message);
        return response.content().base64Data();
    }

    /**
     * 图片识别
     *
     * @param message 描述
     * @param file    图片
     * @return 结果
     * @throws Exception 异常
     */
    @PostMapping("/read")
    public Object read(@RequestParam("message") String message, @RequestParam("file") MultipartFile file) throws Exception {
        var user = UserMessage.from(
                TextContent.from(message),
                ImageContent.from(Base64.getEncoder().encodeToString(file.getBytes()), file.getContentType(), ImageContent.DetailLevel.AUTO)
        );
        var request = ChatRequest.builder().messages(user).build();
        return openAiChatModel.chat(request).aiMessage();
    }

}

4 AudioController.java

java 复制代码
package com.xu.controller;

import dev.langchain4j.data.message.AudioContent;
import dev.langchain4j.data.message.TextContent;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.request.ChatRequest;
import dev.langchain4j.model.openai.OpenAiChatModel;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.Base64;

/**
 * 语音处理
 *
 * @author hyacinth
 */
@RestController
@RequestMapping("/openai/audio")
@AllArgsConstructor
public class AudioController {

    private final OpenAiChatModel openAiChatModel;

    /**
     * 语音转文字
     *
     * @param message 描述
     * @param file    予以文件
     * @return 结果
     * @throws Exception 异常
     */
    @PostMapping("/asr1")
    public Object asr1(@RequestParam("message") String message, @RequestParam("file") MultipartFile file) throws Exception {
        var user = UserMessage.from(
                TextContent.from(message),
                AudioContent.from(Base64.getEncoder().encodeToString(file.getBytes()), file.getContentType())
        );
        var request = ChatRequest.builder().messages(user).build();
        return openAiChatModel.chat(request).aiMessage();
    }

}

5 Application.java

java 复制代码
package com.xu;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author hyacinth
 */
@SpringBootApplication
public class Application {

    static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

4 结果

java 复制代码
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v3.5.7)

2025-10-30T15:55:21.321+08:00  INFO 29536 --- [langchain-openai] [  restartedMain] com.xu.Application                       : Starting Application using Java 25 with PID 29536 (D:\SourceCode\JavaLearn\langchain-openai\target\classes started by hyacinth in D:\SourceCode\JavaLearn\langchain-openai)
2025-10-30T15:55:21.324+08:00  INFO 29536 --- [langchain-openai] [  restartedMain] com.xu.Application                       : No active profile set, falling back to 1 default profile: "default"
2025-10-30T15:55:21.365+08:00  INFO 29536 --- [langchain-openai] [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2025-10-30T15:55:21.365+08:00  INFO 29536 --- [langchain-openai] [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2025-10-30T15:55:22.155+08:00  INFO 29536 --- [langchain-openai] [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
2025-10-30T15:55:22.168+08:00  INFO 29536 --- [langchain-openai] [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2025-10-30T15:55:22.169+08:00  INFO 29536 --- [langchain-openai] [  restartedMain] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.48]
2025-10-30T15:55:22.203+08:00  INFO 29536 --- [langchain-openai] [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2025-10-30T15:55:22.203+08:00  INFO 29536 --- [langchain-openai] [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 838 ms
2025-10-30T15:55:22.678+08:00  INFO 29536 --- [langchain-openai] [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2025-10-30T15:55:22.694+08:00  INFO 29536 --- [langchain-openai] [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path '/'
2025-10-30T15:55:22.699+08:00  INFO 29536 --- [langchain-openai] [  restartedMain] com.xu.Application                       : Started Application in 1.772 seconds (process running for 2.246)
相关推荐
安当加密6 小时前
基于ASP身份认证网关实现Web系统免代码改造的单点登录方案
java·开发语言·前端
CV搬运专家7 小时前
Rust 控制流深度解析:安全保证与迭代器哲学
java·开发语言
寒月霜华7 小时前
JavaWeb后端-JDBC、MyBatis
spring boot·junit·mybatis
无敌少年小旋风7 小时前
05-面试解析 Agent 理论 + 实践(Spring AI Alibaba)
人工智能·spring·面试
张泽腾667 小时前
<FreeRTOS>
java·开发语言
低音钢琴7 小时前
【SpringBoot从初学者到专家的成长25】认识SpringBoot中的Spring Expression Language (SpEL)
spring boot·后端·spring·spel
BeingACoder7 小时前
【项目实践】公寓租赁项目(九):SpringBoot与Redis整合的快速入门使用
java·spring boot·redis
Javatutouhouduan7 小时前
我用ChatGPT,给RabbitMQ加了个连接池
java·spring·rabbitmq·消息中间件·后端开发·java程序员·java八股文
Zhangzy@9 小时前
仓颉的空安全基石:Option类型的设计与实践
java·开发语言·安全