SpringBoot 集成 LangChain4j OpenAI
·
SpringBoot 集成 LangChain4j OpenAI
1 依赖
<?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 配置
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
# 基础镜像
FROM eclipse-temurin:25-jre-alpine
# 设置工作目录
WORKDIR /app
# 复制应用
COPY ./target/*.jar app.jar
# 暴露端口
EXPOSE 8080
# 启动命令
ENTRYPOINT ["java", "-XX:+UseContainerSupport", "-jar", "app.jar"]
3 代码
1 AiConf.java
package com.xu.conf;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.moderation.ModerationModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import dev.langchain4j.model.openai.OpenAiImageModel;
import dev.langchain4j.model.openai.OpenAiModerationModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
import dev.langchain4j.store.memory.chat.InMemoryChatMemoryStore;
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;
/**
* 聊天模型记忆
*
* @return ChatMemoryStore
*/
public ChatMemoryStore chatMemory() {
return new InMemoryChatMemoryStore();
}
/**
* 流式聊天模型
*
* @return StreamingChatModel
*/
@Bean
public StreamingChatModel streamingChatModel() {
return OpenAiStreamingChatModel.builder()
.baseUrl(baseUrl)
.apiKey(apiKey)
.modelName(modelName)
.logRequests(logRequests)
.logResponses(logResponses)
.build();
}
/**
* 图片模型
*
* @return OpenAiImageModel
*/
@Bean
@Primary
public OpenAiImageModel openAiImageModel() {
return OpenAiImageModel.builder()
.baseUrl(baseUrl)
.apiKey(apiKey)
.modelName(modelName)
.logRequests(logRequests)
.logResponses(logResponses)
.build();
}
/**
* 可以将文本转换为Embedding
*
* @return OpenAiEmbeddingModel
*/
@Bean
public OpenAiEmbeddingModel openAiEmbeddingModel() {
return OpenAiEmbeddingModel.builder()
.baseUrl(baseUrl)
.apiKey(apiKey)
.modelName(modelName)
.logRequests(logRequests)
.logResponses(logResponses)
.build();
}
/**
* 检查文本是否包含有害内容
*
* @return OpenAiModerationModel
*/
@Bean
public OpenAiModerationModel openAiModerationModel() {
return OpenAiModerationModel.builder()
.baseUrl(baseUrl)
.apiKey(apiKey)
.modelName(modelName)
.logRequests(logRequests)
.logResponses(logResponses)
.build();
}
}
2 TextController.java
package com.xu.controller;
import dev.langchain4j.data.message.TextContent;
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
@AllArgsConstructor
@RequestMapping("/openai/text")
public class TextController {
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 chatModel.chat(request).aiMessage();
}
/**
* 聊天
*
* @param message 问题
* @return 结果
*/
@PostMapping("/chat3")
public Object chat3(@RequestParam(value = "message", defaultValue = "Hello") String message) {
var user = UserMessage.from(
TextContent.from(message)
);
var request = ChatRequest.builder().messages(user).build();
return openAiChatModel.chat(request).aiMessage();
}
/**
* 聊天
*
* @param message 问题
* @return 结果
*/
@PostMapping("/chat4")
public Object chat4(@RequestParam(value = "message", defaultValue = "Hello") String message) {
streamingChatModel.chat(message, new StreamingChatResponseHandler() {
@Override
public void onPartialResponse(String partialResponse) {
log.info("开始: {}", 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
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
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 OpenAiAssistant.java
@AiService 是 LangChain4j 框架中最核心的注解之一,用于快速将 Java 接口自动转换为 AI 增强的服务类,无需手动实现接口逻辑 —— 框架会根据注解配置和方法定义,自动对接大模型(LLM)、Embedding、工具调用等能力,极大简化 AI 应用开发。
一、核心作用
- 接口驱动开发:开发者只需定义业务接口(如问答、翻译、摘要),无需编写实现类,@AiService 自动生成代理实现。
- 大模型无缝集成:通过注解参数直接绑定 LLM(如 GPT-4、Claude)、配置模型参数(温度、最大令牌数)。
- 能力自动增强:支持自动集成工具调用、上下文管理、Embedding 关联、输出格式化等 LangChain4j 核心特性。
- 减少模板代码:替代手动创建 ChatModel、PromptTemplate、ResponseParser 等重复工作。
二、基础使用流程
5. 依赖前提
确保已引入 LangChain4j 核心依赖和对应大模型依赖(如 OpenAI)。
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
</dependency>
- 核心用法:定义接口 + 标注 @AiService
package com.xu.assistant;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.spring.AiService;
import dev.langchain4j.service.spring.AiServiceWiringMode;
/**
* @author hyacinth
*/
@AiService(wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "openAiChatModel", chatMemory = "chatMemory")
public interface OpenAiAssistant {
/**
* 聊天
*
* @param userMessage 问题
* @return 结果
*/
@SystemMessage("You are a polite assistant")
String chat(String userMessage);
}
6 Application.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 结果
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: 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)

更多推荐
所有评论(0)