LangChain4j学习笔记(一):整合进SpringBoot

LangChain4j学习笔记(一):整合进SpringBoot

知识分子没文化
2026-01-08 / 0 评论 / 944 阅读 / 4,448 字数 / 正在检测是否收录...


目录

LangChain官网:LangChain4j,官方英文文档:Get Started | LangChain4j,API 文档:Overview (LangChain4j)

非官方中文文档:快速开始 | LangChain4j 中文文档

官方示例代码仓库:langchain4j/langchain4j-examples

LangChain4j版本:1.14.0-beta24

一、介绍

1.1、解决什么问题

2023 年初 ChatGPT 热潮中,Python / JS 有大量 LLM(大语言模型)框架,而 Java 生态存在空白,于是 LangChain4j(LangChain for Java) 应运而生,其提供了从模型调用、上下文管理、工具调用到 RAG(检索增强生成)的一整套能力封装。

LangChain4j 相对于 Python 的 LangChain 框架来说,并不是简单的代码移植,而是一个专为 Java 生态设计、注重 Java 语言原生习惯的 LLM 开发框架,比如强类型、注解、Builder 模式、模块化依赖、声明式 API 等,以及与 Spring Boot / Quarkus 等框架的无缝集成,可以简单方便地将各种大语言模型(如 GPT、Ollama、通义千问、DeepSeek 等)集成到 Java 应用。

1.2、模块化架构

LangChain4j 采用模块化设计,核心理念是“按需引入”,只需要引入自己需要的特定模块,而不是整个框架,从而有效避免依赖冲突。

  • langchain4j-core:核心模块,定义了核心接口、抽象类和数据模型(如 ChatModel, ChatMessage 等),是其他所有模块的基础

  • langchain4j:主要的用户接口模块,提供了 AI Services(声明式接口)、文档加载器、分割器、聊天记忆等高级功能与实现

  • langchain4j-{integration}:大量的集成扩展模块,例如:

    • 模型厂商集成

      • 大语言模型 (LLM):langchain4j-open-ailangchain4j-google-ai-geminilangchain4j-dashscopelangchain4j-ollama 等众多的主流模型厂商和本地推理模型
      • 向量嵌入/重排序模型:langchain4j-community-dashscopelangchain4j-onnxlangchain4j-hugging-face
      • 图像生成模型:诸如langchain4j-open-ailangchain4j-dashscope
    • 向量存储:这些模块用于接入各种向量数据库,是构建检索增强生成(RAG)应用的关键,如 langchain4j-qdrantlangchain4j-pineconelangchain4j-milvuslangchain4j-elasticsearchlangchain4j-opensearch

    • 高级功能与应用:Agent 编排(langchain4j-agentic),文档处理(langchain4j-document-parser-apache-pdfbox )、代码执行引擎(langchain4j-graalvm-polyglotlangchain4j-judge0

    • 框架集成:langchain4j-open-ai-spring-boot-starterlangchain4j-spring-boot-starterquarkus-langchain4jlangchain4j-micronaut 等集成扩展模块

1.3、两大抽象层级

LangChain4j 中所有的 API 通过 Low-levelHigh-level 两个抽象层级来平衡“灵活性”与“开发效率”的关系,可以把 LangChain4j 中 Low-levelHigh-level 的区别类比为 原生 JDBCMyBatis 之间的关系。

01

Low-Level(低阶 API)

低阶 API 提供了对 LLM 交互各个环节的原子级控制,开发者可以使用全部基础组件,灵活性最强,但代码量大,需要自己处理很多细节。

  • 核心组件:
    • ChatModel:直接与模型对话的接口
    • UserMessage / AiMessage / SystemMessage:消息对象
    • ChatMemory:会话记忆对象
    • Prompt:消息模板
    • OutputParser:从文本到 Java 对象的转换器
    • EmbeddingStore / Embedding:手动处理向量的存储和检索
  • 操作模式: 编程式(Imperative)。开发者需要手动创建消息列表,手动把对话历史放进 ChatMemory,手动调用模型接口,最后再手动解析返回的字符串
  • 优点:最大灵活性、可完全自定义流程、适合复杂/非标准场景、便于调试和性能调优
  • 缺点:样板代码多、容易出错、代码量大、维护成本高
High-Level(高阶 API)

一般主要指 AI Services(最核心的高层抽象),它将 AI 调用变成了标准的 Java Service 调用。

  • 核心组件:主要是 AI Services、其次是 Chains(较少使用)
  • 操作模式:声明式(Declarative)。开发者只需要定义一个 Java 接口,框架来创建接口的实现类,其原理是反射实现的动态代理
  • 优点:框架自动处理结构化输出、上下文管理等,也能通过其他注解实现工具调用、记忆持久化、RAG、流式输出等高级功能
  • 缺点:对低阶细节的控制力稍弱(但仍可通过注入低层组件来弥补),某些极端自定义场景可能需要回退到低阶 API

1.4、封装不同厂商API

目前市面上众多的 LLM 厂商(如 OpenAI、DeepSeek 等)和向量数据库(如Pinecone或Milvus) 通常采用其专有 API,在项目中进行不同厂商的切换就会显得繁琐。针对于这个问题,LangChain4j 用标准的 Java 接口封装了不同模型提供商的 API 接口,当切换厂商时,只需修改配置,业务代码几乎不用改动,从而确保了业务代码不用依赖具体的模型提供商。

LangChain4j 目前支持 20+ 主流 LLM 模型提供商30+ 向量数据库

不管是否使用 LangChain4j 框架,通过 API 调用 LLM 厂商的模型时都由很重要的三个参数需要关注:

  • ApiKey:从模型厂商的网站上创建
  • 调用地址 BaseUrl:模型厂商的文档会提供
  • 模型名称:模型厂商的文档会提供

关于 ApiKey:为降低公开泄露的风险,使用 ApiKey 通用且保险的做法是将其配置到环境变量中,在项目配置文件中使用 ${环境变量名} 或代码中使用 System.getenv("环境变量名") 的形式引入。

除了 ApiKey 由每个账户单独管理,调用地址和模型名称都能通过各个厂商的官方文档获取。

阿里云百炼文档 | DeepSeek API Docs | 智谱AI开放文档 | 腾讯混元API文档 | Google AI for Developers | API keys - OpenAI API

二、Maven 依赖包

在 Spring Boot 中集成 LangChain4j 对于版本也有要求,JDK 版本 ≥ 17(又多了一个给老项目 Java8 版本升级的理由),Spring Boot 版本 ≥ 3.2。

参考文档:Spring Boot Integration | LangChain4j

使用 BOM (Bill of Materials) 整合包来统一管理 LangChain4j 所有模块的版本,避免版本冲突:

<!-- 版本号单独写成 properties 属性 -->
<properties>
    <langchain4j.version>1.14.0-beta24</langchain4j.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-bom</artifactId>
            <version>${langchain4j.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

再引入模型厂商的依赖包:

<dependencies>
    <!-- 兼容OpenAI协议的模型都可使用这个依赖 -->
    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
        <!-- 当引入了BOM整合包就可以去掉版本号,版本已由BOM整合包统一管理 -->
        <version>1.14.0-beta24</version>
    </dependency>

    <!-- 接入ollama -->
    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j-ollama-spring-boot-starter</artifactId>
        <version>1.14.0-beta24</version>
    </dependency>

    <!-- 接入阿里云百炼平台 -->
    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId>
        <version>1.14.0-beta24</version>
    </dependency>
</dependencies>

引入的第一个包 langchain4j-open-ai 虽然有 “open-ai” 字样,但不仅仅可以调用 OpenAI 的自家模型,也可以调用众多兼容“OpenAI”协议的模型。

在 AI 后端开发中,“OpenAI协议”是目前事实上的行业标准。它本质上是 OpenAI 官方定义的一套 RESTful HTTP API 规范,其响应格式固定,包含choices、usage等字段,最核心的是 POST /v1/chat/completions 接口,支持多轮对话、流式输出(SSE)、函数调用、temperature 等特性。

“OpenAI协议”的最大价值在于生态统一、迁移成本极低:只需修改 base_url、`api_keymodel 三个配置,就能无缝对接 GPT、DeepSeek、阿里通义、腾讯混元、vLLM、Ollama 等几乎所有主流大模型和本地推理引擎。

更多的厂商依赖包可通过官方文档查询:Comparison Table of all supported Language Models | LangChain4j

我个人在学习的过程中,发现 LangChainj 时常会出现拉不到部分依赖包的问题,主要是社区依赖包(如 langchain4j-community-dashscope-spring-boot-starter),当使用较新版本的物料清单 BOM 管理依赖包时出现部分社区依赖包拉取不到的问题时,可以试一试将社区依赖包降低一两个版本,单独给它们指定版本号。

三、低阶 API 整合 SpringBoot

通过 ChatModel 任意实现类的 builder() 方法,设置模型的 apiKeymodelNamebaseUrl,来构造一个实现类对象,再调用其 chat() 方法即可接入大模型:

public static void main(String[] args) {
    OpenAiChatModel model = OpenAiChatModel.builder()
            .baseUrl("http://langchain4j.dev/demo/openai/v1")
            .apiKey("demo")
            .modelName("gpt-4o-mini")
            .build();
    String answer = model.chat("你是谁");
    System.out.println(answer);
}

四、高阶 API 整合 SpringBoot

官方文档:Spring Boot Integration | LangChain4j

额外引入 Maven 依赖:

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-spring-boot-starter</artifactId>
    <version>1.15.0</version>
</dependency>

高阶 API 创建 AI Service 的两种方式:

方式 特点 适合场景
编程式 手动创建 AI Service 灵活、适合测试
声明式 Spring 自动托管 AI Service 复杂的企业开发

4.1、编程式 - 快速创建

最简单的编程式创建 AI Service 的方式是直接调用静态方法 AiServices.create(...),只用几行代码就可以运行,适合在非 Spring 环境下快速调通模型、测试提示词效果。

OpenAiChatModel qwenChatModel = OpenAiChatModel.builder()
        .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
        .apiKey(System.getenv("ApiKey_AliBaiLian"))
        .modelName("qwen-max")
        .build();

Assistant assistant = AiServices.create(Assistant.class, qwenChatModel);
String answer = assistant.chat("你是谁");
System.out.println(answer);

AiServices.create(...) 的内部实现就是 AiServices.builder(…).chatLanguageModel(…).build(),它只有一个入口参数 ChatLanguageModel,无法注入额外的功能组件。

缺点是每次调用都是无状态的,无法维持会话历史,且不支持流式传输、记忆持久化、工具调用、RAG(检索增强生成)等高级能力。

4.2、编程式进阶 - 建造者模式

当应用需要多轮对话记忆、外部工具调用、流式输出、RAG(检索增强生成) 等高级能力时,可以使用 AiServices.builder 来按需搭配组件。

OpenAiChatModel deepseekChatModel = OpenAiChatModel.builder()
        .baseUrl("https://api.deepseek.com")
        .apiKey(System.getenv("ApiKey_Deepseek"))
        .modelName("deepseek-v4-flash")
        .build();

Assistant assistant = AiServices.builder(Assistant.class)
        .chatModel(deepseekChatModel)                // 设置同步聊天模型
        .streamingChatModel(streamingModel)          // 设置流式聊天模型
        .moderationModel(moderationModel)            // 设置内容审查模型
        .chatMemory(chatMemory)                      // 绑定一个对话记忆实例
        .chatMemoryProvider(chatMemoryProvider)      // 绑定记忆提供者,可按 memoryId 获取/创建记忆
        .tools(tools ...)                            // 注册一个或多个包含 @Tool 方法的 Java 对象
        .contentRetriever(contentRetriever)          // 绑定 RAG 检索器,从知识库检索相关片段
        .build();

String answer = assistant.chat("你是谁");
System.out.println(answer);

AiServices.builder底层核心构建器。Spring Boot 集成中,@AiService 注解在框架内部会被解析之后最终等价于调用了一次建造者。因此,编程式建造者是框架运行原理的关键,也是非 Spring 环境或需要动态创建不同配置 AI 服务时的唯一选择。

4.3、声明式

声明式创建 AI 服务进一步降低代码量,包括两种定义模型 Bean 的方式:配置文件(application.yml)和配置类(@Configuration)。它们的共同点是只描述组件的来源和参数,由容器负责组装,而无需在业务代码中手动创建。

最后搭配 @AiService 注解让容器自动完成整个建造者的组装。

方法一:配置文件(application.yml)

在配置文件中配置模型的 apiKeymodelNamebaseUrl

langchain4j:
  # 框架自动创建一个 OpenAiChatModel 类型的 Bean,名称为 openAiChatModel
  open-ai:
    chat-model:
      base-url: https://api.deepseek.com
      api-key: ${ApiKey_Deepseek}
      model-name: deepseek-v4-flash
      temperature: 0.7                  # 控制模型输出的随机性/创造性。取值范围通常为 0.0 ~ 2.0
      max-tokens: 4096                  # 限制模型单次响应最多生成的 Token 数量(不是字符数),根据模型能力灵活配置
      timeout: PT60S                    # HTTP 请求的超时时间,采用 ISO-8601 Duration 格式,根据模型灵活配置
      log-requests: true                # 开发环境开启,打印请求日志,DEBUG 级别
      log-responses: true               # 开发环境开启,打印响应日志,DEBUG 级别

  # 框架自动创建一个 OllamaChatModel 类型的 Bean,名称为 ollamaChatModel
  ollama:
    chat-model:
      base-url: http://localhost:11434
      model-name: llama3.1

  community:
    # 框架自动创建一个 QwenChatModel 类型的 Bean,名称为 qwenChatModel
    dashscope:
      chat-model:
        api-key: ${ApiKey_AliBaiLian}
        model-name: qwen-max

根据以上配置,框架会自动创建 ChatModel 实现类(OpenAiChatModel/ OllamaChatModel / QwenChatModel)的 Bean,名称与实现类的类名相同,首字母小写,例如 OpenAiChatModelopenAiChatModelQwenChatModelqwenChatModel

关于配置中是否应该带连字符 “-” 的问题:

虽然不带连字符目前也能工作(Spring Boot 宽松绑定),但官方文档示例中统一使用的是 open-ai、api-key、base-url 这种带连字符的配置名,因此推荐使用这种配置名。

方法二:配置类(@Configuration)

通过配置类手动声明 Bean,拥有更灵活的控制权(如自定义超时、代理等)。

新建一个配置类 ChatModelConfig,通过建造者模式调用实现类的 builder() 方法,设置模型的 apiKeymodelNamebaseUrl,来构造一个实现类对象,并将其注册为 ChatModel 类型的 Bean:

@Configuration
public class ChatModelConfig {

    @Bean("deepseekChatModel")
    public OpenAiChatModel deepseekChatModel() {
        return OpenAiChatModel.builder()
                .baseUrl("https://api.deepseek.com")
                .apiKey(System.getenv("Key_Deepseek"))
                .modelName("deepseek-v4-flash")
                .temperature(0.7)
                .timeout(Duration.ofSeconds(60))
                .logRequests(true)
                .logResponses(true)
                .maxTokens(4096)
                .build();
    }

    @Bean("ollamaChatModel")
    public OllamaChatModel ollamaChatModel() {
        return OllamaChatModel.builder()
                .baseUrl("http://localhost:11434")
                .modelName("llama3.1")
                .build();
    }

    @Bean("qwenChatModel")
    public QwenChatModel qwenChatModel() {
        return QwenChatModel.builder()
                .apiKey(System.getenv("Key_AliBaiLian"))
                .modelName("qwen-max")
                .build();
    }

}

然后定义一个用 @AiService 标注的接口,通过 wiringMode = EXPLICIT 显式指定要注入的 Bean 名称:

@AiService(wiringMode = WiringMode.EXPLICIT, chatModel = "qwenChatModel")
public interface Assistant {

    // 设置系统提示词
    @SystemMessage("你是一个{{role}}")
    // 定义用户消息模板,可用作补充
    @UserMessage("请用{{language}}回答以下问题:{}")
    String chat(@V("role") String role,
                @V("language") String language,
                String question);

}

@AiService:可以类比理解为 Spring Boot 的 @Service,应用启动时 LangChain4j 会扫描所有带此注解的接口,通过动态代理生成实现类。

wiringMode = EXPLICIT:显式装配模式,当容器中存在多个同类型 Bean 时,必须通过 chatModelstreamingChatModel 等属性明确指定 Bean 名称,避免歧义。可选值还有 AUTOMATIC(按类型自动查找)。

chatModel = "qwenChatModel":指定使用名为 qwenChatModel 的同步聊天模型。

SystemMessage:为当前 AI 服务方法设置系统提示词,是发给 LLM 的最高优先级指令,支持模板占位符 {{变量名}},配合方法参数上的 @V 注解进行动态填充。

@UserMessage:定义用户消息模板,框架会将方法调用时的参数按照这个模板格式化为实际发给 LLM 的用户消息。除了 @V 注解,还可以使用 占位符 {},这是 @UserMessage 特有的简化占位符语法,按方法参数的顺序依次填充。

最后,直接注入使用:

@Service
public class ChatService {

    @Autowired
    Assistant assistant;

    public String chat(String message) {
        String answer = assistant.chat(message);
        return answer;
    }
}

框架在创建 Assistant 代理时,会从容器中取得 qwenChatModel Bean,并调用 AiServices.builder(Assistant.class).chatLanguageModel(qwenChatModel).build(),完全等价于 4.2 节中的编程式建造者。

参考资料:

官方英文文档:Get Started | LangChain4j,API 文档:Overview (LangChain4j)

非官方中文文档:快速开始 | LangChain4j 中文文档

1

评论 (0)

取消