LangChain4j 是面向 Java 生态的大模型应用开发框架,让你用声明式接口、工具调用与 RAG,几行代码就把大模型接进 Spring Boot 服务。相比手写 HTTP 调用,它把模型抽象、记忆、检索与结构化输出统一成一整套类型安全的 API,是 Java 团队落地 AI 功能最顺手的轮子之一。
一、LangChain4j 解决什么痛点
早期在 Java 里接大模型,基本是拼 HTTP 请求、手动解析 JSON、自己攒对话历史。一旦要上工具调用、向量检索、多轮记忆,样板代码会迅速膨胀。LangChain4j 把这些能力抽象成三层:模型层(ChatLanguageModel)、服务层(AI Services 声明式接口)、编排层(记忆、检索、工具)。开发者只写接口和注解,框架负责把 Java 对象与大模型消息互相转换。本站此前介绍过 Spring AI 接入大模型 的另一种思路,两者定位相近但风格不同:Spring AI 更贴合 Spring 体系,LangChain4j 则提供了更”对话式”的 AI Services 写法。
二、快速接入:依赖与基础调用
以 Maven 为例,引入核心包与具体的模型实现(这里用 OpenAI,换成 Ollama、通义或智谱只需替换artifactId):
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>0.35.0</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>0.35.0</version>
</dependency>
最基础的生成只需三行,ChatLanguageModel 是和具体厂商解耦的抽象:
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("gpt-4o-mini")
.build();
String answer = model.generate("用一句话解释什么是向量数据库");
System.out.println(answer);
注意 modelName 与 apiKey 都走构建器注入,生产环境务必从配置中心或环境变量读取,不要硬编码密钥。这也和 Spring Boot 3 升级踩坑 里强调的外部化配置原则一致。
三、AI Services:声明式接口才是精髓
LangChain4j 最迷人的地方是把”和大模型对话”变成定义一个 Java 接口。你只需写方法签名和提示词注解,框架在运行时生成实现类,自动完成消息拼装与结果解析:
interface Assistant {
@SystemMessage("你是资深 Java 工程师,回答简洁务实")
String chat(@UserMessage("{{it}}") String userMessage);
}
Assistant assistant = AiServices.builder(Assistant.class)
.chatLanguageModel(model)
.build();
System.out.println(assistant.chat("Spring Boot 3 怎么优雅关闭?"));
@UserMessage("{{it}}") 表示把方法入参整体填进提示词;也可以用 @UserMessage("帮我把 {{dish}} 做成菜谱") 配合 @V("dish") 做变量绑定。这种写法让业务代码完全不感知大模型细节,单元测试也好 mock。
3.1 工具调用:让模型动手而不是只动嘴
当模型需要查实时数据或执行动作时,用 @Tool 把任意 Java 方法暴露给它。下面这个计算器工具,模型会在用户问”3 加 5 等于多少”时自动选择调用:
class Calculator {
@Tool("计算两个整数的和")
int add(@P("第一个整数") int a, @P("第二个整数") int b) {
return a + b;
}
}
Assistant assistant = AiServices.builder(Assistant.class)
.chatLanguageModel(model)
.tools(new Calculator())
.build();
工具调用本质是把模型输出转成一次本地函数执行,再喂回上下文。关于工具设计的可靠性与回退策略,可参考本站 大模型 Function Calling 实战。
四、多轮记忆:ChatMemory
无状态的 generate 每次都是新对话。要支持多轮上下文,注入一个 ChatMemory,框架会自动维护消息窗口:
ChatMemory memory = MessageWindowChatMemory.withMaxMessages(10);
Assistant assistant = AiServices.builder(Assistant.class)
.chatLanguageModel(model)
.chatMemory(memory)
.build();
assistant.chat("我叫小王,做后端"); // 模型记住上下文
assistant.chat("我刚才说我是做什么的?"); // 能正确回答
withMaxMessages(10) 是滑动窗口,超出部分丢弃,避免历史无限膨胀撑爆上下文。需要持久化会话时,可换成 Redis 或数据库实现的 ChatMemory,配合 Java 21 虚拟线程 的高并发场景也很稳。
五、RAG 落地:把私有文档接进模型
RAG(检索增强生成)是让模型回答私有知识的关键。LangChain4j 把”切分文档→向量化→检索→注入提示”封装得很干净:
EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName("text-embedding-3-small")
.build();
EmbeddingStore embeddingStore = new InMemoryEmbeddingStore<>();
List<Document> docs = FileSystemDocumentLoader.loadDocuments("docs/");
DocumentSplitter splitter = DocumentSplitters.recursive(500, 100);
EmbeddingStoreIngestor.ingest(docs, embeddingStore, embeddingModel, splitter);
ContentRetriever retriever = EmbeddingStoreContentRetriever.builder()
.embeddingStore(embeddingStore)
.embeddingModel(embeddingModel)
.maxResults(3)
.build();
Assistant assistant = AiServices.builder(Assistant.class)
.chatLanguageModel(model)
.contentRetriever(retriever)
.build();
注入 contentRetriever 后,每次提问框架都会先检索最相关的 3 段文档,拼进提示词再生成答案。检索质量直接决定回答质量,关于混合检索与重排序的进阶技巧,见本站 RAG 进阶实战。本地部署 Embedding 模型可借助 Ollama 私有化 免 API 费用。
六、结构化输出:直接拿到 POJO
很多场景下你要的不是一段文本,而是一个对象。LangChain4j 能按返回类型自动约束模型输出 JSON 并反序列化:
class Recipe {
public String title;
public List<String> ingredients;
public int minutes;
}
interface Chef {
Recipe createRecipe(@UserMessage("{{it}}") String dish);
}
Chef chef = AiServices.builder(Chef.class)
.chatLanguageModel(model)
.build();
Recipe r = chef.createRecipe("番茄炒蛋");
System.out.println(r.title + " 需 " + r.minutes + " 分钟");
这种方法比自己正则解析稳定得多,适合把模型接入表单填充、工单分类、报表生成等结构化流水线。
七、生产环境几点建议
| 关注点 | 建议 |
| 模型切换 | 面向 ChatLanguageModel 编程,厂商通过 builder 注入,上线后热切换不影响业务 |
| 超时与重试 | OpenAiChatModel.builder().timeout(Duration.ofSeconds(30)),外层加重试与熔断 |
| 流式输出 | 用 streamingChatLanguageModel 或 TokenStream,前端逐字渲染见 Spring AI 流式篇 |
| 成本控制 | maxTokens、maxResults 收紧;高频问答加语义缓存降本 |
流式输出如果你用的是 Spring Boot,可结合 Spring AI 流式对话 的实现做对照;两者都能让前端像打字机一样实时显示回答。
八、三个容易踩的坑
从 demo 走到生产,最常卡在三类问题。第一,结构化输出偶尔拿不到合法 JSON:模型可能多解释一句,或用 Markdown 代码块把结果包起来,导致 POJO 反序列化直接抛异常。稳妥做法是给接口加 @StructuredPrompt 明确字段格式,并在调用层做失败重试与兜底解析,别把模型当百分百可靠的函数。
第二,RAG 检索为空或答非所问:多数情况是切分粒度不对——一段太长模型抓不住重点,太短又丢掉上下文语义;也可能是 embedding 模型维度与检索器不匹配。正确做法是先用小样本人工核验 top-3 召回质量,确认命中相关段落再谈上线,而不是盲目堆文档数量。
第三,上下文超限触发 429:多轮对话窗口开太大、或一次性把整篇长文档塞进提示,都会撑爆 token 上限。按业务把 withMaxMessages 收到 8–10,超长文本改为先摘要再入上下文;高频相似问答再叠加语义缓存,既能降成本也能减少限流。把这三点提前处理好,LangChain4j 的服务才真正扛得住线上流量。
九、小结
LangChain4j 用 AI Services 把”接大模型”这件事从一堆样板代码收敛成几个接口与注解:基础调用三行搞定,工具调用让模型能动手,ChatMemory 支撑多轮,contentRetriever 一行接入 RAG,返回类型还能直接映射成 POJO。对已经用 Spring Boot 的 Java 团队来说,它是把 AI 能力塞进现有服务最低摩擦的路径。下一步可以顺着工具链把 Embedding 模型私有化、给记忆接上持久化,逐步把 demo 打磨成可上线的智能助手。




