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 应用开发。

一、核心作用

  1. 接口驱动开发:开发者只需定义业务接口(如问答、翻译、摘要),无需编写实现类,@AiService 自动生成代理实现。
  2. 大模型无缝集成:通过注解参数直接绑定 LLM(如 GPT-4、Claude)、配置模型参数(温度、最大令牌数)。
  3. 能力自动增强:支持自动集成工具调用、上下文管理、Embedding 关联、输出格式化等 LangChain4j 核心特性。
  4. 减少模板代码:替代手动创建 ChatModel、PromptTemplate、ResponseParser 等重复工作。

二、基础使用流程
5. 依赖前提
确保已引入 LangChain4j 核心依赖和对应大模型依赖(如 OpenAI)。

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-spring-boot-starter</artifactId>
</dependency>
  1. 核心用法:定义接口 + 标注 @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)

在这里插入图片描述

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐