news 2026/10/27 11:43:50

Java工程师AI应用开发指南:LangChain4j从入门到RAG与Agent实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java工程师AI应用开发指南:LangChain4j从入门到RAG与Agent实战

1. 为什么 Java 工程师现在要盯紧 LangChain4j

1.1 一个真实的技术落差场景

我身边有不少写了五六年业务代码的 Java 工程师,Spring Boot、MyBatis-Plus、Redis 那一套玩得很溜,但一提到 AI 应用开发,第一反应就是"那不是 Python 的活儿吗"。这个认知在前两年确实没太大问题,LangChain、LlamaIndex 这些主流框架都是 Python 生态先跑起来的,Java 这边要么调个 HTTP 接口,要么干脆用 Python 写个服务再让 Java 去调。

但这两年情况变了。企业里真正跑核心业务的后端系统,绝大多数还是 Java 写的。你让一个电商团队为了做个智能客服,专门维护一套 Python 服务,运维成本、人员成本、链路排查成本全都上来了。LangChain4j 就是在这个背景下被推到台前的——它把 LangChain 那套"链式编排 + 大模型调用 + 向量检索"的思路,用 Java 的语法和工程习惯重新实现了一遍。

说白了,LangChain4j 是给 Java 工程师准备的一套 AI 应用开发工具箱,让你不用切语言、不用换技术栈,在熟悉的 Maven 工程里就能把大模型、Embedding、RAG、AI Agent 这些东西串起来。它解决的核心问题是:降低 Java 团队接入 AI 能力的门槛,把"要不要为了 AI 重构技术栈"这个纠结直接抹掉。

这篇文章适合谁看?如果你是有 Java 基础、想往 AI 应用方向转的工程师,或者你所在团队正在评估"用 Java 做 RAG 知识库"的可行性,再或者你面试时被问到"Java 怎么做 AI Agent"答不上来,那这篇内容就是给你准备的。我会从环境搭建一路讲到 RAG 多路召回和 Agent 编排,把踩过的坑和能直接抄的代码都放出来。

1.2 LangChain4j 到底解决了哪些具体问题

很多人第一次接触 LangChain4j,会把它理解成"Java 版的 LangChain",这个说法对但不全对。它确实借鉴了 LangChain 的核心抽象,但在工程落地上做了不少针对 Java 生态的取舍。

第一,统一了模型接入层。OpenAI、通义千问、DeepSeek、Ollama 本地模型,这些在 LangChain4j 里都有对应的ChatLanguageModel实现,你换模型基本只改一行配置。这对企业来说太重要了,因为模型选型是会变的,今天用这个明天可能换那个,业务代码不该跟着模型厂商的 SDK 走。

第二,把 RAG 的整套流程标准化了。文档加载、切分、Embedding、存向量库、检索、拼 Prompt,这一长串步骤在 LangChain4j 里有现成的组件,你不用自己造轮子。尤其是 Embedding 模型和向量库的对接,它抽象得比较干净,换 Embedding 模型或者换向量库,改动量可控。

第三,AI Agent 和工具调用有原生支持。这是最近热词里反复出现的方向。LangChain4j 的AiServices可以把一个 Java 接口自动实现成能调用大模型、能调工具、能带记忆的 Agent,写法上非常"Java"——定义接口、加注解、注入使用,跟写 Spring Service 的感觉很像。

第四,和 Spring Boot 集成顺滑。有专门的langchain4j-spring-boot-starter,配置写在application.yml里,Bean 自动装配,这对习惯了 Spring 全家桶的团队来说几乎没有学习断层。

提示:LangChain4j 的版本迭代比较快,API 在不同大版本之间有过调整。建议新手直接锁定一个稳定版本(比如 0.35.x 或 1.x 的某个具体版本),不要盲目追最新,否则网上搜到的教程和你的实际代码对不上,会很痛苦。

2. 环境准备与第一个可运行 Demo

2.1 JDK、Maven 与依赖选型

LangChain4j 对 JDK 的要求不算高,JDK 17 是推荐的基线,JDK 8 在早期版本还能跑,但新版本很多特性(比如 record、文本块)用上了,建议直接上 17。如果你机器上装了多个 JDK,记得用JAVA_HOME切干净,我见过太多"明明装了 17 却报语法错误"的情况,最后发现是环境变量指向了 8。

Maven 依赖这块,核心就几个坐标,但要注意BOM(Bill of Materials)的用法。LangChain4j 拆了很多模块,版本号如果一个个手写很容易对不齐,用 BOM 统一管理最省心:

<dependencyManagement> <dependencies> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-bom</artifactId> <version>0.35.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- 核心 --> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j</artifactId> </dependency> <!-- OpenAI 兼容模型接入 --> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai</artifactId> </dependency> <!-- 内存向量库,入门够用 --> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-embeddings-all-minilm-l6-v2</artifactId> </dependency> </dependencies>

这里解释一下为什么入门阶段我推荐用langchain4j-embeddings-all-minilm-l6-v2这个本地 Embedding 模型。它把模型权重打包进了 jar 里,不需要你额外下载、不需要联网、不需要 API Key,开箱即用。虽然效果比不上那些排行榜上靠前的大模型,但用来跑通流程、验证代码逻辑完全够。等你流程跑通了,再换成线上 Embedding 服务,改动很小。

2.2 最小可运行示例:三行代码调通大模型

先别急着上 RAG,第一步是把"能跟模型说上话"这件事跑通。下面这段代码是 LangChain4j 最基础的用法:

import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.model.chat.ChatLanguageModel; public class FirstDemo { public static void main(String[] args) { ChatLanguageModel model = OpenAiChatModel.builder() .baseUrl("https://api.deepseek.com/v1") // 换成你用的服务地址 .apiKey(System.getenv("LLM_API_KEY")) .modelName("deepseek-chat") .temperature(0.7) .build(); String answer = model.generate("用一句话解释什么是 RAG"); System.out.println(answer); } }

几个关键点值得说清楚。baseUrl这个参数是 LangChain4j 兼容 OpenAI 协议的关键,只要你的模型服务遵循 OpenAI 的接口规范,就能接进来,这也是为什么它能同时支持那么多厂商。apiKey千万别硬编码在代码里,用环境变量或者配置中心,这是基本的安全习惯。temperature控制输出的随机性,做知识问答类应用建议调低到 0.2 到 0.3,让回答更稳定、更贴事实;做创意类内容再调高。

注意:如果你用的是本地 Ollama 跑的模型,把依赖换成langchain4j-ollama,baseUrl填http://localhost:11434,modelName填你ollama list里看到的模型名即可。本地模型的好处是数据不出内网,适合对数据敏感的场景。

2.3 用 AiServices 把接口变成 AI 能力

LangChain4j 里我觉得最"Java 味"的设计就是AiServices。你可以定义一个普通接口,然后用它自动生成实现:

interface Assistant { String chat(String userMessage); } Assistant assistant = AiServices.create(Assistant.class, model); String reply = assistant.chat("帮我写一个冒泡排序的 Java 方法");

这段代码背后,LangChain4j 用动态代理帮你把方法调用转成了对模型的请求,返回值再解析回来。你不需要写任何 HTTP 调用、JSON 解析的代码。如果加上@SystemMessage注解,还能给这个接口设定角色:

interface Assistant { @SystemMessage("你是一个严谨的 Java 技术顾问,回答要给出可运行的代码") String chat(String userMessage); }

这个设计的好处是,业务代码里看不到任何 AI 框架的痕迹,就是一个接口调用。将来换模型、换框架,只要接口不变,上层业务几乎不用动。这也是我在实际项目里最推荐的组织方式。

3. RAG 知识库:从文档到可检索的向量

3.1 RAG 到底在解决什么问题

先说清楚 RAG 是什么。大模型的知识是训练时"冻结"的,它不知道你公司内部的文档、不知道你昨天刚更新的产品手册。你直接问它,它要么答不上来,要么一本正经地胡说八道。RAG(Retrieval-Augmented Generation,检索增强生成)的思路很朴素:先去你的知识库里把相关内容找出来,再把找到的内容连同问题一起塞给模型,让它基于这些材料回答。

打个比方,模型是个博学但没看过你公司资料的顾问,RAG 就是每次提问前,你先帮他从档案柜里翻出相关文件递给他,他再基于文件回答。这样既用上了模型的表达能力,又保证了答案有据可依。

RAG 的完整链路是:文档加载 → 文本切分 → 向量化(Embedding)→ 存入向量库 → 用户提问时向量化 → 相似度检索 → 拼接 Prompt → 模型生成。LangChain4j 把这条链路上的每一步都做成了可替换的组件。

3.2 文档加载与切分:最容易被忽视的关键环节

新手最容易犯的错,就是觉得"切分嘛,随便按字数切一下就行"。实际上,切分策略直接决定 RAG 的上限。切得太碎,语义不完整,检索出来的片段答非所问;切得太大,噪声太多,模型抓不住重点,还浪费 token。

LangChain4j 提供了DocumentSplitter,常用的有按段落切、按句子切、按固定字符数带重叠切几种。我一般推荐按段落切 + 设置重叠窗口的组合:

DocumentSplitter splitter = DocumentSplitters.recursive( 500, // 每段最大字符数 50, // 相邻段重叠字符数 new OpenAiTokenizer() );

为什么要有重叠?因为一句话可能正好被切在边界上,前半句在上一段、后半句在下一段,检索时两段都不完整。重叠 50 个字符,能保证边界处的语义至少在一段里是完整的。这个参数没有标准答案,中文文档我一般设 30 到 80 之间,英文可以小一点。

加载器方面,FileSystemDocumentLoader能读本地文件,ClassPathDocumentLoader读 classpath 下的资源。如果你要处理 PDF、Word,需要额外引入对应的langchain4j-document-parser-apache-pdfbox之类的模块。这里有个坑:扫描版 PDF 是图片,解析出来是空的,得先做 OCR,这个 LangChain4j 不管,得你自己在预处理阶段解决。

3.3 Embedding 模型怎么选

Embedding 就是把文本变成一串数字向量,语义相近的文本,向量距离也近。选 Embedding 模型主要看几个维度:效果、成本、语言支持、部署方式。

模型类型代表优势适用场景
本地小模型all-MiniLM-L6-v2免费、离线、快入门验证、数据敏感
云端通用OpenAI text-embedding-3效果好、稳定通用中英文场景
中文优化BGE、M3E 系列中文语义强中文知识库为主
多语言multilingual-e5跨语言检索多语言文档

我个人的经验是:中文知识库优先选中文优化的模型,通用模型在中文上的表现经常不如专门优化的。另外要注意,Embedding 模型一旦选定,建库和检索必须用同一个模型,换了模型就得重新建库,因为向量空间完全变了,旧向量和新查询向量没法比。

3.4 向量库选型与内存库快速验证

向量库这块,入门阶段我强烈建议先用InMemoryEmbeddingStore,它把向量存在内存里,重启就没了,但胜在零配置、零依赖,用来验证流程再合适不过:

EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>(); EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder() .documentSplitter(splitter) .embeddingModel(embeddingModel) .embeddingStore(store) .build(); ingestor.ingest(Document.from("你的文档内容..."));

等流程跑通、效果验证过了,再换成生产级向量库。常见的选择有PgVector(如果你已经在用 PostgreSQL,加个扩展就行,运维成本最低)、Milvus(专业向量库,性能强,适合大规模)、Redis Stack(如果团队已经在用 Redis)。选型的核心原则是:优先选团队已经熟悉的存储,别为了向量检索专门引入一套新的运维体系。

4. 多路召回与检索效果优化

4.1 单一向量检索的瓶颈在哪

纯向量检索有个天然短板:它擅长"语义相似",但不擅长"精确匹配"。比如用户问"订单号 A12345 的状态",向量检索可能给你返回一堆讲订单状态的文档,但就是没命中那个具体订单号。这就是热词里说的"RAG 瓶颈"之一。

另一个问题是召回率。用户的问题表述千变万化,向量检索有时会漏掉真正相关的内容。解决办法就是多路召回——用多种检索方式并行找,再把结果合并去重。

4.2 多路召回的三种常见组合

第一种是向量检索 + 关键词检索。向量管语义,关键词(比如 BM25)管精确匹配,两路结果合并。LangChain4j 本身对 BM25 支持有限,实践中常用 Elasticsearch 或 Lucene 做关键词那一路,然后自己写合并逻辑。

第二种是多 Embedding 模型召回。用两个不同的 Embedding 模型各检索一遍,取并集。好处是不同模型的"盲区"不一样,互补性强;代价是建库成本翻倍。

第三种是多粒度召回。同一份文档,既按段落切一份,又按整篇切一份,检索时两路都查。段落粒度精准,整篇粒度上下文完整。

合并多路结果时,重排序(Rerank)是关键一步。简单做法是按相似度分数加权合并,进阶做法是引入专门的 Rerank 模型对候选集重新打分。LangChain4j 有ReRankingContentAggregator可以对接 Cohere 等 Rerank 服务。

ContentAggregator aggregator = ReRankingContentAggregator.builder() .reRankingModel(cohereReRankModel) .build(); RetrievalAugmentor augmentor = DefaultRetrievalAugmentor.builder() .contentAggregator(aggregator) .build();

提示:多路召回不是越多越好。每加一路,延迟和成本都涨。我的经验是先上两路(向量 + 关键词),看效果提升是否明显,再决定要不要加第三路。盲目堆路数,最后可能延迟上去了、效果没涨多少。

4.3 检索参数调优的实操经验

几个关键参数值得反复调:

  • topK:每次检索返回几条。太小可能漏,太大噪声多。一般从 5 开始试,中文知识库常用 3 到 8。
  • 相似度阈值:低于阈值的结果直接丢弃。设太高会漏召回,设太低会引入噪声。建议先不设阈值,观察实际分数分布再定。
  • 切分粒度:前面说过,500 字符是个不错的起点,但要看你的文档类型。技术文档可以小一点,法律合同这种需要完整上下文的要大一点。

我踩过的一个坑是:topK 设成 10,结果模型被无关内容带偏了。后来发现是知识库里有很多相似但不相关的文档,检索分数都很接近。解决办法是加 Rerank,或者提高相似度阈值把低分的过滤掉。

5. AI Agent 与工具调用实战

5.1 Agent 和普通对话的本质区别

普通对话是"你问我答",Agent 是"你给目标,我自己想办法"。区别在于Agent 能调用工具。比如你问"北京今天天气怎么样",普通模型只能基于训练数据瞎猜,Agent 会去调用一个天气查询工具,拿到真实数据再回答。

LangChain4j 里实现工具调用很直接,定义一个方法加@Tool注解就行:

class WeatherTools { @Tool("查询指定城市的当前天气") String getWeather(@P("城市名称") String city) { // 实际调用天气 API return "晴,25 度"; } } interface WeatherAgent { String ask(String question); } WeatherAgent agent = AiServices.builder(WeatherAgent.class) .chatLanguageModel(model) .tools(new WeatherTools()) .build(); String result = agent.ask("北京今天天气怎么样");

模型会自己判断要不要调工具、调哪个工具、传什么参数。这个能力在 LangChain4j 里叫Function Calling,底层依赖模型本身支持工具调用协议。

5.2 Agent 的记忆机制

默认情况下,Agent 是无状态的,每次对话都是全新的。要让它记住上下文,得加ChatMemory:

WeatherAgent agent = AiServices.builder(WeatherAgent.class) .chatLanguageModel(model) .chatMemory(MessageWindowChatMemory.withMaxMessages(20)) .tools(new WeatherTools()) .build();

MessageWindowChatMemory只保留最近 N 条消息,超出就丢弃最早的。为什么要有上限?因为模型的上下文窗口是有限的,而且 token 是要花钱的。20 条是个经验值,具体看你的对话轮次和单条消息长度。

进阶一点可以用TokenWindowChatMemory,按 token 数而不是消息条数来控制,更精确。还有持久化的记忆(存数据库),适合需要跨会话记住用户的场景。

5.3 Agent 的常见架构模式

热词里提到"AI Agent 主流架构",实践中常见的有几种:

ReAct 模式:推理(Reasoning)和行动(Acting)交替。模型先想一步,决定调什么工具,拿到结果再想下一步,直到能回答。这是最经典的 Agent 模式,LangChain4j 的工具调用本质上就是这个思路。

Plan-and-Execute 模式:先让模型制定完整计划,再逐步执行。适合复杂多步任务,但实现复杂度高,LangChain4j 原生支持有限,需要自己编排。

多 Agent 协作:多个各有所长的 Agent 分工合作。比如一个负责检索、一个负责总结、一个负责校验。这种模式在 LangChain4j 里需要自己用代码串起来,没有开箱即用的封装。

我的建议是:新手从单 Agent + 工具调用开始,把这一种模式吃透,再考虑复杂架构。很多场景其实单 Agent 就够了,硬上多 Agent 反而增加调试难度。

6. 常见问题排查与避坑清单

6.1 依赖冲突与版本问题

LangChain4j 依赖了不少第三方库,最容易冲突的是Jackson和OkHttp。如果你项目里已经有这两个库的旧版本,可能出现NoSuchMethodError。排查方法是mvn dependency:tree看版本,用<exclusions>排掉旧版本,或者用 BOM 统一版本。

另一个高频问题是Embedding 模型 jar 太大,本地模型动辄几百 MB,打包进 Docker 镜像会让镜像膨胀。解决办法是把模型文件外置,通过配置指定路径加载,而不是打进 jar。

6.2 检索效果差的排查思路

检索效果不好,按这个顺序排查:

  1. 先看切分结果。把切分后的文本片段打印出来,看看是不是切得莫名其妙。切分不对,后面全白搭。
  2. 再看 Embedding 是否合适。中文文档用英文模型,效果肯定差。换中文优化的模型试试。
  3. 然后看检索分数。把 topK 结果的相似度分数打出来,如果分数普遍很低,说明知识库里可能根本没有相关内容,或者 Embedding 模型不匹配。
  4. 最后看 Prompt 拼接。检索对了但回答不对,往往是 Prompt 没写好,模型没被正确引导。

6.3 常见问题速查表

现象可能原因解决方向
启动报 NoSuchMethodError依赖版本冲突用 BOM 统一版本,排查 dependency:tree
检索结果不相关切分粒度不当调整切分大小和重叠
中文检索效果差Embedding 模型不适配换中文优化模型,重建索引
回答胡编乱造Prompt 未约束加强 SystemMessage,要求基于材料回答
响应特别慢topK 太大或模型太慢减小 topK,换更快的模型
工具调用不触发模型不支持 Function Calling换支持工具调用的模型
内存溢出本地 Embedding 模型加载增大堆内存或改用云端 Embedding
上下文丢失未配置 ChatMemory添加 MessageWindowChatMemory

6.4 几个我踩过的坑

坑一:以为换了 Embedding 模型只改配置就行。实际上向量空间变了,必须重新建库,否则检索结果全是乱的。这个坑我在一个项目里踩过,排查了大半天才反应过来。

坑二:Prompt 里塞了太多检索内容。一开始觉得多给点材料总没错,结果模型被无关内容干扰,回答质量反而下降。后来严格控制 topK 和内容长度,效果明显好转。

坑三:忽略 token 成本。RAG 每次请求都要把检索到的内容拼进 Prompt,token 消耗比普通对话大得多。上线前一定要估算成本,尤其是高频调用的场景。

坑四:本地模型和线上模型混用。开发时用本地小模型图快,上线换大模型,结果 Prompt 效果完全不一样。建议开发和上线用同一类模型,避免这种落差。

7. 从 Demo 到生产:还需要补哪些课

跑通 Demo 只是第一步,真正上线还有几件事要做。

第一是知识库的更新机制。文档是会变的,你得有一套流程在文档更新时重新切分、重新 Embedding、更新向量库。全量重建成本高,增量更新实现复杂,这块要提前设计。

第二是效果评估。怎么知道你的 RAG 好不好?得有一批测试问题 + 标准答案,定期跑评估。LangChain4j 本身评估能力有限,实践中常自己写脚本,或者对接专门的评估工具。

第三是监控和日志。每次请求的检索结果、模型输入输出、耗时、token 消耗,都要记录下来。出问题时这些日志是唯一的排查依据。

第四是降级方案。模型服务挂了怎么办?检索超时怎么办?生产系统必须有兜底逻辑,不能模型一挂整个功能就不可用。

第五是权限控制。不同用户能访问的知识库范围可能不同,检索时必须带上权限过滤,否则会出现越权访问数据的问题。这个在 LangChain4j 里需要在检索层自己实现过滤逻辑。

我个人在实际项目里的体会是,LangChain4j 把"能跑起来"这件事的门槛降得很低,但"跑得好、跑得稳"依然需要大量工程投入。框架帮你省掉的是重复造轮子的时间,省不掉的是对业务的理解、对数据的处理、对效果的打磨。新手最容易高估框架的作用、低估数据质量的重要性——实际上,一个切分合理、内容干净的知识库,比任何花哨的检索技巧都管用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/27 11:43:35

人工智能导论复习地图:五条主线与高频考点全梳理

简介&#xff1a;这份资料面向软件工程、计算机等专业修读《人工智能导论》的学生&#xff0c;聚焦教材第五版中的简答题与名词解释&#xff0c;帮助梳理概念、应对课程考核与期末复习。内容围绕逻辑思维、形象思维与顿悟思维的差异&#xff0c;符号表示法与连接机制表示法&…

作者头像 李华
网站建设 2026/10/27 11:41:40

JAX与PyTorch分布式训练对比:从DDP到XLA分片实战

1. 从一次多卡踩坑说起&#xff1a;为什么我要对比 JAX 和 PyTorch去年年底接手一个 8 卡 A100 的节点&#xff0c;任务是把一个 7B 级别的 Transformer 从单卡跑到多卡。团队里大部分人平时写 PyTorch&#xff0c;我自己之前也主要用 PyTorch 做实验&#xff0c;但这次因为项目…

作者头像 李华
网站建设 2026/10/27 11:40:53

VI/VIM编辑器:程序员必备的高效文本编辑工具

1. 为什么VI编辑器至今仍是程序员的必备技能 在2024年的今天&#xff0c;各类现代化编辑器层出不穷&#xff0c;但VI/VIM仍然是Linux系统管理员、后端开发者和运维工程师的标配工具。最近在Stack Overflow的开发者调查中&#xff0c;VI/VIM依然保持着近30%的活跃使用率。这个诞…

作者头像 李华
网站建设 2026/10/27 11:40:33

基于改进Mask R-CNN的自卸车部件识别与优化实践

1. 项目背景与核心挑战 自卸车作为工程机械领域的重要运输工具&#xff0c;其关键部件&#xff08;如货箱、液压缸、车架等&#xff09;的实时识别与状态监测对智能运维和自动化作业至关重要。传统人工检测方式存在效率低、成本高、主观性强等问题&#xff0c;而基于深度学习的…

作者头像 李华
网站建设 2026/10/27 11:40:22

解耦微调提升大模型工具调用准确率至95%

1. 项目背景&#xff1a;工具调用准确率的困境与突破去年底我在部署Qwen-7B模型处理企业工单系统时&#xff0c;遇到了工具调用准确率卡在60%的瓶颈。这个数字意味着每10次API调用就有4次失败&#xff0c;在客服机器人场景下直接导致30%的工单需要人工介入。经过两周的排查&…

作者头像 李华
网站建设 2026/10/27 11:40:04

零基础大模型考点精讲:从Transformer到RAG与本地部署

在AI大模型这股浪潮里&#xff0c;“零基础却要应对考点”可能是最让人头疼的处境。整理一段时间以来各种社群和课程里的高频提问&#xff0c;你会发现大家不是在问“大模型能做什么”&#xff0c;而是集中在“大模型底层理论到底考什么”“微调、RAG、上下文长度这些词到底怎么…

作者头像 李华