相关依赖

我这边对接的是大模型是千问大模型,pom文件相关依赖,其中在 Maven 项目中引入 LangChain4j DashScope Spring Boot Starter 可以快速集成阿里云 DashScope 大模型能力到 Spring Boot 应用中,实现零样板代码的 AI 调用。

<?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>4.0.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ai.langchain</groupId>
    <artifactId>langchain4jTest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>langchain4jTest</name>
    <description>langchain4jTest</description>

    <properties>
        <java.version>21</java.version>
        <junit.platform.version>1.9.2</junit.platform.version>
        <junit.jupiter.version>5.9.2</junit.jupiter.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webmvc</artifactId>
        </dependency>
        <!-- Source: https://mvnrepository.com/artifact/dev.langchain4j/langchain4j-spring-boot-starter -->
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-spring-boot-starter</artifactId>
            <version>1.15.0-beta25</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <!-- 4.0.x 已经没有 vintage,可省略 exclusion -->
        </dependency>
        <!-- Source: https://mvnrepository.com/artifact/dev.langchain4j/langchain4j-community-dashscope-spring-boot-starter -->
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId>
            <version>1.15.0-beta25</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

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

    <build>
        <plugins>
            <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>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <executions>
                    <execution>
                        <id>default-compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <configuration>
                            <annotationProcessorPaths>
                                <path>
                                    <groupId>org.projectlombok</groupId>
                                    <artifactId>lombok</artifactId>
                                </path>
                            </annotationProcessorPaths>
                        </configuration>
                    </execution>
                    <execution>
                        <id>default-testCompile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>testCompile</goal>
                        </goals>
                        <configuration>
                            <annotationProcessorPaths>
                                <path>
                                    <groupId>org.projectlombok</groupId>
                                    <artifactId>lombok</artifactId>
                                </path>
                            </annotationProcessorPaths>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

YML配置

引入以来后在yml文件中配置你的apikey和模型名称:

关于如何获取apikey 在网上查查应该能找到,不行阿里官方也有说明

,spring:
  application:
    name: langchain4jTest
server:
  port: 10009
langchain4j:
  community:
    dashscope:
      chat-model:
        api-key: your-apikey
        model-name: qwen-max

在这里插入图片描述

基础版聊天功能

import com.ai.langchain.langchain4jtest.service.ChatService;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;


@Slf4j
@Service
public class ChatServiceImpl implements ChatService {

    @Resource
    private ChatModel qwenChatModel;


    @Override
    public String chat(String messageChat) {
        UserMessage userMessage = UserMessage.from(messageChat);
        ChatResponse response = qwenChatModel.chat(userMessage);
        AiMessage aiMessage = response.aiMessage();
        log.info("ai message:{}",aiMessage.toString());
        return aiMessage.text();
    }

}

支持图片,音频,视频,pdf传输

其次支持图片,音频,视频,pdf传输,注意如果需要图片支持需要选择多模态或者支持图片,音频,视频,pdf处理的模型,记得在yml变更一下模型,qwen-max是文本处理模型是不支持图片处理的,具体看官网那些模型支持你所需的文件处理:

import com.ai.langchain.langchain4jtest.service.ChatService;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;


@Slf4j
@Service
public class ChatServiceImpl implements ChatService {

    @Resource
    private ChatModel qwenChatModel;


    @Override
    public String chatUserMessage(UserMessage userMessage) {
        ChatResponse response = qwenChatModel.chat(userMessage);
        AiMessage aiMessage = response.aiMessage();
        log.info("ai message:{}",aiMessage.toString());
        return aiMessage.text();
    }
}


// 单元测试方法
@Test
public void chatImageHandel() {
    // 需要使用多模态的模型,在yml中进行配置
    // 还可以处理其他文件,相关的对象有:
    // AudioContent VideoContent PdfFileContent TextContent ImageContent
    // 音频,视频,pdf,文本,图片
    UserMessage userMessage = new UserMessage(
            TextContent.from("这张图片的内容是什么"),
            ImageContent.from("https://tse4.mm.bing.net/th/id/OIP.bl-kQplMxE9HV27SrrmekAHaLn?r=0&rs=1&pid=ImgDetMain&o=7&rm=3")
    );
    String responseMessage = chatService.chatUserMessage(userMessage);
    System.out.println(responseMessage);
}

包含提示词版本的

多余的部分我就拷贝了,和之前ChatServiceImpl类的内容一样,这相比之前多一个SystemMessage对象,用于处理大模型的预设,也就是提示词

private String SYSTEM_MESSAGE= """
        你是AI面试助手**小光**,专注面试题库检索、答案整理与分类工作。
        1. 接收用户面试相关提问,精准检索对应面试题目、标准答案与解题思路
        2. 按**技术方向、难度等级、题型类别**规整划分内容
        3. 排版清晰简洁,题目与答案分区展示,冗余信息剔除
        4. 主动区分基础题、进阶题、实操题、问答论述题,按需归类输出
        5. 严格围绕面试考点作答,不偏离求职面试场景
        """;


@Override
public String chatPrompt(String message) {
    SystemMessage systemMessage = new SystemMessage(SYSTEM_MESSAGE);
    UserMessage userMessage = UserMessage.from(message);
    ChatResponse response = qwenChatModel.chat(systemMessage,userMessage);
    AiMessage aiMessage = response.aiMessage();
    log.info("ai message:{}",aiMessage.toString());
    return aiMessage.text();
}

通过AiService简化代码

首先创建一个接口,这个接口不需要任何的实现,其实现是通过Spring的动态代理生成的:

Prompt.txt@SystemMessageimport dev.langchain4j.service.SystemMessage;

import java.util.List;

/**
 * @author JR
 * @version 1.0
 * @description:
 * @date 2026年05月25日 17:35
 */
public interface AiHelperService {

    @SystemMessage(fromResource = "Prompt.txt")
    String chat(String userMessage);
}

我们只需要做这样的配置就可以了:

import com.ai.langchain.langchain4jtest.service.AiHelperService;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.service.AiServices;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author JR
 * @version 1.0
 * @description:
 * @date 2026年05月25日 17:39
 */
@Configuration
public class AiServiceConfig {

    @Resource
    private ChatModel qwenChatModel;

    /**
     * 没有会话记忆的aiService创建
     */
    @Bean
    public AiHelperService aiHelperService() {
        return AiServices.create(AiHelperService.class,qwenChatModel);
    }
}

然后用单元测试直接调用,注意这里用是aiHelperService而不是之前的chatService:

// 单元测试
@Resource
private AiHelperService aiHelperService;

@Test
public void chatPromptAiService() {
    // 需要使用多模态的模型,在yml中进行配置
    // 还可以处理其他文件,相关的对象有:
    // AudioContent VideoContent PdfFileContent TextContent ImageContent
    // 音频,视频,pdf,文本,图片
    String responseMessage = aiHelperService.chat("你是谁?你的功能是什么?");
    System.out.println(responseMessage);
}

并且这里通过在AiHelperService的chat的方法中使用@SystemMessage注解配置了提示词文件,该注解会自动读取resource文件路径下的指定文件,例如这里的:Prompt.txt

在这里插入图片描述


会话记忆

在langchain4j里有一个MessageWindowChatMemory对象,该对象主要用于操作会话相关记忆,最多保存多少条

import com.ai.langchain.langchain4jtest.service.AiHelperService;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.service.AiServices;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author JR
 * @version 1.0
 * @description:
 * @date 2026年05月25日 17:39
 */
@Configuration
public class AiServiceConfig {

    @Resource
    private ChatModel qwenChatModel;


    /**
     * 有会话记忆的aiService创建
     */
    @Bean
    public AiHelperService aiHelperService() {
        ChatMemory messageWindowChatMemory = MessageWindowChatMemory.withMaxMessages(10);
        return AiServices.builder(AiHelperService.class)
                .chatModel(qwenChatModel)
                .chatMemory(messageWindowChatMemory)
                .build();
    }
}

// 单元测试
    @Test
    public void chatPromptMemoryAiService() {
        String responseMessage = aiHelperService.chat("现在是那年哪月那日,星期几");
        System.out.println("AI第一次回答:"+responseMessage);
        responseMessage = aiHelperService.chat("我刚刚问了你什么问题,你怎么回答的");
        System.out.println("AI第二次回答:"+responseMessage);
    }

Json scheam格式要求返回

格式化返回有三种方式:

  1. 提示词要求ai按照指定格式返回(有一定几率不按照要求处理)
  2. 提示词加Json mode
  3. 最精准:Json scheam

首先用record创建一个Report对象:

record Report(String name, List<String> suggetionList){}

然后创建一个方法,返回Report对象:

@SystemMessage(fromResource = "Prompt.txt")
Report chatReport(String userMessage);

最终效果如下:

public interface AiHelperService {

    @SystemMessage(fromResource = "Prompt.txt")
    Report chatReport(String userMessage);

    record Report(String name, List<String> suggetionList){}
}

单元测试:

/**
 * 以Json scheam的方式返回数据
 */
@Test
public void chatJsonScheam() {
    AiHelperService.Report report = aiHelperService.chatReport("给我几条学习建议,规划一些学习目标");
    System.out.println(report);
    System.out.println(report.suggetionList().size());
}

最后你会发现report和suggetionList被填充了数据

会话隔离

只需要在AiService配置中新增一行代码

/**
 * 会话隔离
 * @return
 */
@Bean
public AiHelperService aiHelperService() {
    ChatMemory messageWindowChatMemory = MessageWindowChatMemory.withMaxMessages(10);
    return AiServices.builder(AiHelperService.class)
            .chatModel(qwenChatModel)
            .chatMemory(messageWindowChatMemory)
            // 会话隔离
            .chatMemoryProvider(memoryId -> messageWindowChatMemory)
            .contentRetriever(contentRetriever)
            .build();
}

RAG相关配置

import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
import dev.langchain4j.data.document.splitter.DocumentByParagraphSplitter;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

/**
 * @author JR
 * @version 1.0
 * @description:
 * @date 2026年05月25日 18:45
 */
@Configuration
public class AiRagConfig {

    @Resource
    private EmbeddingModel qwenEmbeddingModel;

    // EmbeddingStore 的作用是什么?
    @Resource
    private EmbeddingStore<TextSegment> embeddingStore;

    /**
     * 内容检索器的配置
     * @return
     */
    @Bean
    public ContentRetriever contentRetriever() {
        // ---- RAG ----
        // 1. 加载文档
        List<Document> documents = FileSystemDocumentLoader.loadDocuments("src/main/resources/docs");
        // 2. 文档切割:每个文档按照段落进行分割,最大 1000 个字符,每次最多重叠 200 个字符
        DocumentByParagraphSplitter documentByParagraphSplitter =
                new DocumentByParagraphSplitter( 1000, 200);
        // 3. 自定义文档加载器,把文档转换成向量并保存到向量数据库中
        EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
                .documentSplitter(documentByParagraphSplitter)
                // 为了提高文档的质量,为每个切割后的文档碎片 TextSegment 添加文档名称作为元信息
                .textSegmentTransformer(textSegment -> TextSegment.from(
                        textSegment.metadata().getString("file_name") + "\n" + textSegment.text(),
                        textSegment.metadata()))
                // 使用的向量模型
                .embeddingModel(qwenEmbeddingModel)
                .embeddingStore(embeddingStore)
                .build();

        // 加载文档
        ingestor.ingest(documents);

        // 4. 自定义内容加载器
        return EmbeddingStoreContentRetriever.builder()
                .embeddingStore(embeddingStore)
                .embeddingModel(qwenEmbeddingModel)
                .maxResults(5) // 最多 5 条结果
                .minScore(0.75) // 过滤掉分数小于 0.75 的结果
                .build();
    }
}

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐