你不知道的LangChain4j 那些事

张开发
2026/4/18 10:11:30 15 分钟阅读

分享文章

你不知道的LangChain4j 那些事
这是一篇风格化很重的LangChain4j实践教程。我不想给你看一个标准的技术文档模板我想给你看一个真实的、会踩坑、会骂街、最终又能解决问题的Java开发者的实战记录。LangChain4j顾名思义是LangChain的Java移植版。它的目标很明确让Java开发者也能像Python开发者一样丝滑地构建大模型应用。目前它已经支持接入OpenAI、Azure、Ollama等超过20家模型提供商还有内存管理、RAG、函数调用等一整套工具链。我会从搭建环境开始中间穿插我踩过的坑和学到的教训然后重点讲RAG和Tool Calling这两个核心功能最后聊几句LangChain4j和Spring AI到底怎么选。1. 环境准备先别急着写代码选对版本很重要LangChain4j的版本迭代挺快的写这篇文章时最新稳定版是1.0.0-beta1。注意这个beta后缀——很多功能还在打磨你用的版本可能和我用的不太一样。如果你是Spring Boot项目Maven里加上这些dependencygroupIddev.langchain4j/groupIdartifactIdlangchain4j/artifactIdversion1.0.0-beta1/version/dependencydependencygroupIddev.langchain4j/groupIdartifactIdlangchain4j-open-ai/artifactIdversion1.0.0-beta1/version/dependency如果你是纯Java项目不用Spring也可以只是多写几行配置代码的事。API Key别硬编码到代码里这是血的教训。用环境变量或者配置文件管理。2. 别用Low-Level APIAI Services才是正解刚上手时我犯过一个错误直接用ChatLanguageModel来调大模型。代码大概长这样ChatLanguageModelmodelOpenAiChatModel.builder().apiKey(apiKey).modelName(gpt-3.5-turbo).build();Stringresponsemodel.generate(Hello, world!);能跑但问题很快就来了每次都要手动处理对话历史想加个RAG还得自己拼Prompt代码越写越乱。后来才发现LangChain4j的设计精髓根本不在这里而是在AI Services——你只需要定义一个接口框架帮你生成实现。publicinterfaceAssistant{Stringchat(Stringmessage);}AssistantassistantAiServices.builder(Assistant.class).chatLanguageModel(model).chatMemory(MessageWindowChatMemory.withMaxMessages(10)).build();这叫什么这叫“声明式AI开发”。你声明你想要什么框架帮你搞定怎么做到。3. 第一个坑对话记忆存MySQL我踩过的雷说实话LangChain4j的官方文档现在确实还不够完善。有个开发者朋友在掘金上吐槽说他想把对话记录存到MySQL结果从下午一直折腾到晚上11点半。问题出在哪他把模型从阿里百炼换成OpenAI后所有问题竟然都消失了。这说明什么LangChain4j对不同模型提供商的适配程度是不一样的有些SDK还藏着bug。如果你也遇到莫名其妙的持久化问题不妨先换个模型试试先确认是框架问题还是模型适配问题。如果要用ChatMemory持久化到数据库建议用框架官方支持的ChatMemoryStore实现别自己瞎折腾。目前比较靠谱的方案是用MongoDB或Redis存对话记录。4. RAG从“极简版”到“实战版”的进化RAG检索增强生成是LangChain4j最亮眼的功能之一。说白了就是给大模型配一个“小抄本”让它回答前先查一下你的私有知识库。4.1 极简版三分钟跑通RAG先跑通再说别一上来就追求完美。引入langchain4j-easy-rag依赖dependencygroupIddev.langchain4j/groupIdartifactIdlangchain4j-easy-rag/artifactIdversion1.0.0-beta1/version/dependency然后几行代码就能跑起来// 1. 加载文档ListDocumentdocumentsFileSystemDocumentLoader.loadDocuments(src/main/resources/docs);// 2. 转换成向量并存到内存EmbeddingStoreTextSegmentembeddingStorenewInMemoryEmbeddingStore();EmbeddingStoreIngestor.ingest(documents,embeddingStore);// 3. 构建AI Service并绑定检索器AssistantassistantAiServices.builder(Assistant.class).chatLanguageModel(model).contentRetriever(EmbeddingStoreContentRetriever.from(embeddingStore)).build();极简版的特点是“一切皆默认”——内置Embedding模型、内存向量存储、默认分块策略。很适合快速验证想法。4.2 实战版换掉默认优化效果极简版跑通后你会发现几个问题内存存储重启就没了默认的Embedding模型效果一般文档分块策略太粗暴。向量数据库的选择生产环境别用内存存储。我推荐两个方向PgVector如果你的项目已经在用PostgreSQL这是最省事的选择直接用现有数据库存向量。MongoDB Atlas如果你需要的是开箱即用的云服务MongoDB的Vector Search功能很成熟而且和LangChain4j有官方集成模块。以PgVector为例配置大概这样EmbeddingStoreTextSegmentembeddingStorePgVectorEmbeddingStore.builder().host(localhost).port(5432).database(rag_db).user(postgres).password(password).table(embeddings).dimension(1536)// OpenAI embedding的维度.build();Embedding模型的选择默认的Embedding模型效果一般。生产环境建议换成OpenAI的text-embedding-3-small或Cohere的embed模型中文场景可以试试阿里的通义千问Embedding。5. Tool Calling让AI学会调用你的Java方法如果说RAG是给AI配了本参考书那Tool Calling就是给了AI一双能干活的手。当用户问“今天天气怎么样”时AI知道自己答不上来但可以调用你写的getWeather工具来获取实时数据。5.1 基础用法用Tool注解标记你想让AI调用的方法publicclassWeatherTools{Tool(获取指定城市的当前天气)publicStringgetWeather(P(城市名称)Stringcity){// 这里调用真实的天气APIreturncity今天晴朗温度22°C;}Tool(计算两个数的和)publicdoublesum(P(第一个数)doublea,P(第二个数)doubleb){returnab;}}然后在构建AI Service时注册这些工具AssistantassistantAiServices.builder(Assistant.class).chatLanguageModel(model).tools(newWeatherTools()).build();现在你可以问AI“北京天气怎么样”或者“帮我算一下156加243”它会自动判断需要调用哪个工具。5.2 第二个坑工具调用无限循环我遇到过一个问题AI在一个对话里反复调用同一个工具token烧得飞起。有开发者说他看着AI对话转了半个小时花了将近100万token。原因是什么记忆窗口太小了。LangChain4j默认只保留最近几条对话记录当工具调用次数多了之后AI会“忘记”自己刚才已经调用过这个工具了于是重复调用。解决方案也很简单调大MessageWindowChatMemory的容量MessageWindowChatMemorychatMemoryMessageWindowChatMemory.withMaxMessages(35);// 默认是10调到35这个值需要根据你的实际场景调整太小容易循环太大token消耗多。5.3 多个工具怎么让AI选对如果你的工具有很多关键是把Tool注解里的描述写清楚。AI是根据你的描述来判断该用哪个工具的。描述要写清楚“这个工具是干什么的”、“什么时候应该用”。写得好不好直接影响AI选工具的准确率。6. 流式输出别把用户晾在那干等LangChain4j的流式输出确实比Spring AI麻烦一些。Spring AI里call是全量stream是流式很直觉。但LangChain4j需要单独用StreamingChatLanguageModel还要加langchain4j-reactor依赖。如果用AI Services方式实现流式代码是这样的publicinterfaceStreamingAssistant{TokenStreamchat(Stringmessage);}StreamingAssistantassistantAiServices.builder(StreamingAssistant.class).streamingChatLanguageModel(streamingModel).chatMemory(chatMemory).build();TokenStreamtokenStreamassistant.chat(讲个笑话);tokenStream.onNext(token-System.out.print(token)).onComplete(response-System.out.println(\n完成)).onError(Throwable::printStackTrace).start();返回类型用TokenStream然后通过onNext逐个处理token。如果你用Spring Boot WebFlux可以直接把TokenStream转成FluxString然后通过Server-Sent Events推给前端实现ChatGPT那种逐字输出的效果。7. 本地模型部署Ollama DeepSeek不想每次都调OpenAI的付费APIOllama是你最好的朋友。Ollama是一个本地大模型运行平台支持CPU和GPU能跑DeepSeek、Llama、Mistral等各种开源模型。安装和运行很简单# 安装Ollamacurl-fsSLhttps://ollama.com/install.sh|sh# 拉取DeepSeek-R1模型14b参数本地可跑ollama pull deepseek-r1:14b# 启动服务ollama serve然后在LangChain4j里这样配置ChatLanguageModelmodelOllamaChatModel.builder().baseUrl(http://localhost:11434).modelName(deepseek-r1:14b).build();这样就完全本地化了不用API Key不用联网数据安全也更有保障。8. LangChain4j vs Spring AI我到底该怎么选这个问题我被问过很多次。简单说LangChain4j适合你如果你需要丰富的功能RAG、Agent、工具调用都很成熟你不一定要用Spring生态纯Java、Quarkus都可以你需要兼容多种模型提供商Spring AI适合你如果你已经在用Spring Boot/Cloud全家桶你追求和Spring生态的无缝集成依赖注入、配置管理、可观测性你能接受功能相对较少但更稳定的状态我的个人选择如果是Spring项目我会用LangChain4j做核心AI逻辑因为它的功能确实更全配置文件管理、依赖注入这些基础设施就交给Spring。两者不冲突可以一起用。写在最后LangChain4j现在确实还有很多不完美的地方官方文档不够详细某些功能还带着beta标签不同模型提供商的适配程度参差不齐。但它在快速迭代而且社区活跃度很高。如果你是一个想用Java做大模型应用的开发者LangChain4j是目前最好的选择之一。不要被它的不完美吓到——Python的LangChain一开始也是这样的。技术都是在踩坑中成长的LangChain4j在成长我们也是。希望这篇文章能帮你少踩几个坑。如果你在实践中遇到什么问题欢迎留言交流。

更多文章