Java后端AI应用开发:DeepSeek+LangChain4j实现RAG与Agent实战

📅 发布时间:2026/8/30 16:40:44
Java后端AI应用开发:DeepSeek+LangChain4j实现RAG与Agent实战 2026年了Java 后端做 AI 应用还难吗说实话难的不是接入大模型而是把大模型真正接进业务系统。很多 Java 开发者刚开始接触 AI 编程时第一反应是“这是 Python 的活”然后去搜 LangChain、LlamaIndex、Dify绕了一圈发现跟自己的 Spring Boot 业务代码很难融合。真正的问题不是“模型不够聪明”而是“工程链路没有理顺”。这篇文章想给你一条 Java AI 应用开发的完整路线用 DeepSeek 作为大模型底座用 LangChain4j 作为 Java 生态的 LLM 编排框架把 Tools、RAG、Agent 这三件套逐个跑通同时对比 Spring AI 2.0 的官方方案帮你判断在 2026 年的项目里到底该怎么选型。读完你能收获三样东西一套可以照抄的 Java AI 项目骨架、一个能跑通 RAG 和 Agent 的最小示例以及一份避开常见坑的排查清单。先说我的核心判断2026 年的 Java AI 开发真正的分水岭不是“会不会调 API”而是“能不能用工具调用和知识库把模型变成业务能力”。这里的关键不是模型本身而是工程链路——也就是下面要展开的 Tools、RAG 和 Agent。1. Java 生态做 AI为什么今年才真正值得做过去几年 Java 开发者在 AI 领域的存在感很低原因是早期大模型生态的工具链全是 Python 优先Java 开发者想接一个 RAG 应用得自己写 HTTP 调用、自己处理流式输出、自己管理向量检索等于把 LangChain 的核心代码重写一遍而且写出来还不一定有社区维护。现在情况变了主要有三个信号。第一个信号是 DeepSeek 等国产模型把 API 调用成本拉到了极低水平。对开发者来说这意味着可以用很低的成本做大量实验试错门槛下来了Java 后端接大模型从一个“公司级项目”变成了一个“周末就能跑通”的事情。第二个信号是 Java 生态的 AI 框架成熟了。LangChain4j 已经覆盖了聊天、工具调用、RAG、Agent、多模态等主流能力Spring AI 也已经发展到了 2.0 时代。Java 开发者不再需要从零造轮子可以直接在 Spring 体系内把模型接进业务。第三个信号是 AI 应用正在从“Demo”走向“生产”。2024 年大家还在做聊天机器人2025 年开始做知识库问答2026 年大家已经在思考 Agent 如何稳定地执行多步任务。生产级应用需要事务、日志、监控、权限、降级这些恰恰是 Java 后端最擅长的领域。所以我的判断是Java 开发者做 AI 应用的最佳窗口已经打开而且越往后走Java 的工程化优势会越明显。2. 技术选型Spring AI 2.0 还是 LangChain4j先回答一个很多人纠结的问题我已经用了 Spring Boot是不是直接用 Spring AI 就行还需要 LangChain4j 吗从官方定位看Spring AI 2.0 是 Spring 官方给的 AI 集成方案目标是让 AI 能力像 Spring Data、Spring Cloud 一样成为标准组件。它支持 ChatModel、EmbeddingModel、VectorStore、Tool Calling 等抽象且天然适配 Spring 的配置体系和自动装配。如果你要把 AI 能力嵌入一个已经跑了很多年的 Spring Boot 项目Spring AI 2.0 的体验会非常顺滑配置上基本走 application.yml 就能完成模型接入。LangChain4j 则更接近 Java 版本的 LangChain它设计时借鉴了 LangChain 的抽象但 API 更贴近 Java 开发者的习惯。它的优势在于模型和工具的支持面广AiServices 这套做 Agent 和工具调用的抽象非常直观社区里也有大量现成的集成模块包括向量数据库、Embedding 模型、文档加载器等。从实际项目看更务实的做法不是二选一而是按需求分工维度Spring AI 2.0LangChain4j定位Spring 官方 AI 框架Java 生态 LLM 编排框架Spring Boot 集成天然集成也有 Spring Boot Starter模型接入抽象统一配置化抽象统一功能更细Agent 工具调用已支持仍处于演进中AiServices 设计成熟RAG 组件内置 VectorStore 抽象文档加载、切块、重排更全上手成本如果你熟悉 Spring上手快需要理解模型抽象社区活跃度官方推动更新快社区活跃模块丰富我的建议是如果你的项目是全新的且主导者熟悉 Spring 官方生态可以优先考虑 Spring AI 2.0因为它的长期演进方向更清晰如果你需要灵活组合各种模型、向量库、Agent 工具或者想参考更丰富的社区案例LangChain4j 更成熟。本文的实战代码以 LangChain4j 为主线它能把 DeepSeek、Tools、RAG、Agent 的完整链路讲清楚而 Spring AI 2.0 的接入方式我也会给出对应的配置参考。3. 先弄懂四个关键词Chat、Tools、RAG、Agent在写代码之前先把概念对齐否则容易在后面绕晕。3.1 Chat 是大模型最基础的形态Chat 就是一个对话补全接口你输入一段文本模型返回一段文本。在代码层面它就是一个 ChatLanguageModel 对象调用 generate 方法即可完成。很多 Java 开发者以为接入大模型就是从零写 HTTP 请求实际上框架已经帮你封装好了流式、超时、重试、Token 统计这些事情。3.2 Tools 是让模型拥有“手”的机制大模型本身只能输入文本、输出文本它不知道数据库里有哪些订单也查不了天气。Tools也就是工具调用 / Function Calling的核心机制是你定义好一个 Java 方法把方法名、参数描述、功能描述告诉模型模型在回答问题时如果发现需要调用外部能力会生成一个结构化的调用请求框架负责解析请求、执行你的 Java 方法、把结果回传给模型最终由模型基于结果生成回复。这里有一个新手最容易混淆的地方Tools 不是让模型去执行代码而是让模型“决定是否调用某个函数”真正的执行逻辑还是你的 Java 代码。你可以理解为模型是大脑Tools 是手框架是神经回路。3.3 RAG 是给模型接上“企业知识库”RAGRetrieval-Augmented Generation检索增强生成解决的是“模型不知道你公司内部资料”的问题。它的核心流程是把文档切分成片段用 Embedding 模型转换成向量存入向量数据库用户提问时把问题也转成向量在向量库中检索最相关的片段最后把检索结果和问题一起交给模型生成答案。关键词是“检索增强”。模型本身没有实时知识但通过检索你可以在不重新训练的情况下让模型基于特定文档回答问题。3.4 Agent 是让模型像人一样拆解任务Agent 是建立在 Chat Tools 记忆之上的更复杂形态。一个简单的 Agent 会判断要完成这个任务需要调用哪些工具、按什么顺序调用、如果中间出错怎么处理。在 LangChain4j 里Agent 通常不是一个大而全的类而是通过 AiServices 把 ChatLanguageModel、Tools、RAG 的 ContentRetriever 组合起来形成一个具备自主决策能力的服务对象。在实际项目中Chat 用来做一次性的问答RAG 用来做基于知识库的问答Agent 用来做“需要多个步骤才能完成”的任务比如“查一下上个月的销售数据分析波动原因并生成一段日报摘要”。4. 环境准备与基础配置先说一句非常重要的提醒下面示例中的版本号并非固定值2026 年的框架版本迭代很快请以 Maven 中央仓库和官方文档的最新版本为准。本文重点演示通用思路你不需要精确复刻版本号但要理解每个依赖的作用。4.1 基础环境JDK 17 及以上Java 21 更推荐虚拟线程对 AI 场景的并发提升明显Maven 3.8 或 Gradle 8DeepSeek API Key可以在 DeepSeek 开放平台申请可选Docker用于启动 Milvus 或其它向量数据库IDEIntelliJ IDEA 或 Eclipse 均可4.2 创建 Maven 工程并在 pom.xml 中加入依赖?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdcom.example/groupId artifactIdjava-ai-demo/artifactId version1.0.0/version properties maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler.target project.build.sourceEncodingUTF-8/project.build.sourceEncoding /properties dependencies !-- LangChain4j 核心 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j/artifactId version1.x/version /dependency !-- LangChain4j 的 OpenAI 兼容协议适配DeepSeek 走的就是这个 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-open-ai/artifactId version1.x/version /dependency !-- 日志输出 -- dependency groupIdorg.slf4j/groupId artifactIdslf4j-simple/artifactId version2.0.16/version /dependency /dependencies /projectDeepSeek 的 API 兼容 OpenAI 协议所以在 LangChain4j 里用 open-ai 模块然后改 baseUrl 指向 DeepSeek 即可这是目前最常见、最稳妥的接入方式。4.3 配置 DeepSeek API Key不要把 API Key 写在代码里。推荐用环境变量注入在 IDEA 的运行配置中设置DEEPSEEK_API_KEY或者启动时传入export DEEPSEEK_API_KEYsk-你的密钥保留环境变量的好处是项目代码可以放心提交到 Git不会被扫描到密钥不同环境测试、预发、生产通过不同 Key 互相隔离。5. 最小示例用 Java 调用 DeepSeek 对话现在用一段最小代码把整条链路跑通。它只做一件事让 DeepSeek 回答一个问题如果控制台能看到中文回复说明环境已经通了。5.1 核心代码// 文件路径src/main/java/com/example/ai/DeepSeekChatExample.java package com.example.ai; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.openai.OpenAiChatModel; import java.time.Duration; public class DeepSeekChatExample { public static void main(String[] args) { ChatLanguageModel model OpenAiChatModel.builder() .baseUrl(https://api.deepseek.com/v1) .apiKey(System.getenv(DEEPSEEK_API_KEY)) .modelName(deepseek-chat) .timeout(Duration.ofSeconds(60)) .logRequests(true) .logResponses(true) .build(); String answer model.generate(请用一句话介绍 Java 21 的虚拟线程); System.out.println(answer); } }这段代码的关键点在三个地方baseUrl指向https://api.deepseek.com/v1这是 DeepSeek 兼容 OpenAI 协议的服务地址。modelName使用的是deepseek-chat这是 DeepSeek 的通用对话模型如果你需要更强的推理能力可以换成deepseek-reasoner。logRequests(true)和logResponses(true)会打印 HTTP 请求和响应日志第一次调试时强烈建议打开。5.2 运行与验证直接运行 main 方法即可。正常情况你会看到类似下面的输出虚拟线程是 JDK 19 引入、JDK 21 正式支持的轻量级线程 可以让 Java 应用以极低的线程开销处理高并发任务。如果这一步出现 JSON 解析错误或者 401优先检查 API Key 是否配置正确、baseUrl 是否拼写正确。网络服务所在区域也需要提前确认是否符合你的业务合规要求。6. Tools 实战让 DeepSeek 学会调用 Java 方法对话只解决了“说话”的问题Tools 解决的是“干活”的问题。下面演示一个最容易理解的场景模型需要查询天气。它本身没有天气数据但我在 Java 里定义了一个天气查询方法模型会按需调用它。6.1 定义工具方法// 文件路径src/main/java/com/example/ai/tool/WeatherTool.java package com.example.ai.tool; import dev.langchain4j.agent.tool.Tool; public class WeatherTool { Tool(查询指定城市的当天天气) public String getWeather(String city) { // 真实项目中这里会调用第三方天气 API并做好缓存 return 城市 city 天气晴气温26℃风力3级; } }注意Tool注解里的描述非常重要模型是靠这段描述来判断“什么时候该调用这个工具”的。描述写得越准确模型越不容易瞎调用。6.2 通过 AiServices 装配带工具的助手// 文件路径src/main/java/com/example/ai/ToolsExample.java package com.example.ai; import com.example.ai.tool.WeatherTool; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.service.AiServices; import dev.langchain4j.service.SystemMessage; import java.time.Duration; public class ToolsExample { interface WeatherAssistant { SystemMessage(你是一个贴心的生活助手回答要简洁、准确。) String chat(String userMessage); } public static void main(String[] args) { ChatLanguageModel model OpenAiChatModel.builder() .baseUrl(https://api.deepseek.com/v1) .apiKey(System.getenv(DEEPSEEK_API_KEY)) .modelName(deepseek-chat) .timeout(Duration.ofSeconds(60)) .build(); WeatherAssistant assistant AiServices.builder(WeatherAssistant.class) .chatLanguageModel(model) .tools(new WeatherTool()) .chatMemory(MessageWindowChatMemory.withMaxMessages(20)) .build(); String answer assistant.chat(北京今天适合跑步吗); System.out.println(answer); } }这里最关键的是AiServices.builder。它把接口、模型、工具和记忆组合在一起WeatherAssistant是一个普通接口AiServices会在运行时动态生成它的实现。当我们问“北京今天适合跑步吗”时DeepSeek 会判断这个问题需要天气数据适合调用getWeather(北京)于是返回一个工具调用请求框架自动执行方法把结果回传给模型最终生成类似这样的回答适合。北京今天晴26℃风力 3 级非常适合户外跑步。你可以看到对调用方来说代码只是一个普通的assistant.chat()方法工具调用的细节全部被框架隐藏了。这就是 LangChain4j 的 Agent 基础能力你实际上已经在这个最小示例中跑通了一个具备工具调用能力的 Agent 雏形。7. RAG 实战构建一个 Java 知识库问答系统RAG 是 AI 应用里最容易踩坑也最常被问到的部分。这里的坑不只是“不会用向量数据库”更多是“流程没走全”。下面从文档加载、切块、向量化、存储、检索、回答把完整链路走一遍。7.1 准备知识文档在项目的src/main/resources目录下新建一个简单的 Markdown 文件faq.md# 业务系统 FAQ ## 如何重置用户密码 管理员登录后台后在用户管理页面找到对应用户点击“重置密码” 系统会生成临时密码用户首次登录时必须修改密码。 密码策略要求至少 8 位包含大小写字母和数字。 ## 如何导出月度报表 在报表中心选择月份点击“导出”按钮系统会生成 CSV 文件。 超过 10 万行的报表将通过异步任务生成完成后会发送下载通知。这是模拟企业内部的制度文档模型本身不可能知道这些内容必须通过 RAG 喂给模型。7.2 引入向量数据库相关依赖这里以后续实战中常见的 Milvus 向量数据库为例。如果你本地不方便启动 Milvus也可以先用内存向量库把流程跑通后续再切换。dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-milvus/artifactId version1.x/version /dependency# 使用 Docker 快速启动 Milvus具体版本和端口以官方文档为准 docker run -d --name milvus \ -p 19530:19530 \ milvusdb/milvus:latest7.3 文档加载、切块与向量化// 文件路径src/main/java/com/example/ai/rag/RagIngestExample.java package com.example.ai.rag; import dev.langchain4j.data.document.Document; import dev.langchain4j.data.document.loader.FileSystemDocumentLoader; import dev.langchain4j.data.document.splitter.DocumentSplitters; import dev.langchain4j.data.document.parser.TextDocumentParser; import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.store.embedding.EmbeddingStore; import dev.langchain4j.store.embedding.milvus.MilvusEmbeddingStore; import java.nio.file.Path; import java.util.List; public class RagIngestExample { public static void main(String[] args) { // 1. 加载文档解析为纯文本 Document document FileSystemDocumentLoader.loadDocument( Path.of(src/main/resources/faq.md), new TextDocumentParser() ); // 2. 切块每块 500 字符重叠 50 字符 ListTextSegment segments DocumentSplitters.recursive(500, 50).split(document); // 3. 向量化不同 Embedding 模块的构建方式不同这里仅示意 EmbeddingModel embeddingModel QwenEmbeddingModel.builder() .apiKey(System.getenv(DASHSCOPE_API_KEY)) .modelName(text-embedding-v4) .build(); // 4. 把段落转为向量 ListEmbedding embeddings embeddingModel.embedAll(segments).content(); // 5. 存入 Milvus EmbeddingStoreTextSegment embeddingStore MilvusEmbeddingStore.builder() .uri(http://localhost:19530) .collectionName(java_rag_demo) .dimension(1024) .build(); embeddingStore.addAll(embeddings, segments); System.out.println(成功写入段落数量 segments.size()); } }这里要特别说明QwenEmbeddingModel的具体类名取决于你引入的 Embedding 模块比如有些模块叫DashScopeEmbeddingModel有些是BgeEmbeddingModel核心接口都是EmbeddingModel。切块参数(500, 50)表示每块 500 个字符、相邻块重叠 50 个字符这个参数直接影响检索效果后面会详细讲。7.4 检索并生成回答RAG 的第一步是把文档灌进向量库第二步才是用户问答。这里用 LangChain4j 的EmbeddingStoreContentRetriever把检索能力接入聊天。// 文件路径src/main/java/com/example/ai/rag/RagQueryExample.java package com.example.ai.rag; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.rag.content.retriever.ContentRetriever; import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever; import dev.langchain4j.service.AiServices; import dev.langchain4j.store.embedding.EmbeddingStore; import dev.langchain4j.store.embedding.milvus.MilvusEmbeddingStore; import java.time.Duration; public class RagQueryExample { interface RagAssistant { String chat(String userMessage); } public static void main(String[] args) { ChatLanguageModel model OpenAiChatModel.builder() .baseUrl(https://api.deepseek.com/v1) .apiKey(System.getenv(DEEPSEEK_API_KEY)) .modelName(deepseek-chat) .timeout(Duration.ofSeconds(60)) .build(); EmbeddingModel embeddingModel QwenEmbeddingModel.builder() .apiKey(System.getenv(DASHSCOPE_API_KEY)) .modelName(text-embedding-v4) .build(); EmbeddingStoreTextSegment embeddingStore MilvusEmbeddingStore.builder() .uri(http://localhost:19530) .collectionName(java_rag_demo) .dimension(1024) .build(); ContentRetriever contentRetriever EmbeddingStoreContentRetriever.builder() .embeddingStore(embeddingStore) .embeddingModel(embeddingModel) .maxResults(3) .minScore(0.5) .build(); RagAssistant assistant AiServices.builder(RagAssistant.class) .chatLanguageModel(model) .contentRetriever(contentRetriever) .build(); String answer assistant.chat(用户忘了密码怎么办); System.out.println(answer); } }运行后DeepSeek 会先拿到向量库检索出的相关段落然后基于这些段落生成回答。如果一切正常你会得到类似“管理员可以通过用户管理页面重置密码临时密码首次登录时必须修改”的回答而不是模型自己胡编的答案。从工程角度看RAG 有四个参数直接影响效果maxResults控制返回多少片段minScore控制相似度阈值切块大小决定关注单元的粒度Embedding 模型决定语义向量质量。这些参数需要根据实际语料调优不存在一劳永逸的默认值。8. Agent 实战把 Tools 和 RAG 组合成自主 AgentRAG 和 Tools 单独用都很简单但真实业务里它们往往是组合出现的。一个用户可能既问知识库里的制度又需要工具查询实时数据。LangChain4j 的AiServices可以同时接收 Tools 和 ContentRetriever这就是一个具备完整能力的 Agent。// 文件路径src/main/java/com/example/ai/agent/CustomerServiceAgentExample.java package com.example.ai.agent; import com.example.ai.tool.WeatherTool; import com.example.ai.tool.OrderQueryTool; import com.example.ai.rag.RagQueryExample.RagAssistant; import dev.langchain4j.memory.chat.MessageWindowChatMemory; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.rag.content.retriever.ContentRetriever; import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever; import dev.langchain4j.service.AiServices; import dev.langchain4j.service.SystemMessage; import java.time.Duration; public class CustomerServiceAgentExample { interface CustomerServiceAgent { SystemMessage(你是企业智能客服回答要简洁准确。如果拿不准请直接说明。) String chat(String userMessage); } public static void main(String[] args) { // 组装模型 ChatLanguageModel model OpenAiChatModel.builder() .baseUrl(https://api.deepseek.com/v1) .apiKey(System.getenv(DEEPSEEK_API_KEY)) .modelName(deepseek-chat) .timeout(Duration.ofSeconds(60)) .build(); // 组装 RAG 检索器 ContentRetriever retriever EmbeddingStoreContentRetriever.builder() .embeddingStore(embeddingStore) .embeddingModel(embeddingModel) .maxResults(3) .minScore(0.5) .build(); // 同时注入 Tools RAG 记忆 CustomerServiceAgent agent AiServices.builder(CustomerServiceAgent.class) .chatLanguageModel(model) .chatMemory(MessageWindowChatMemory.withMaxMessages(20)) .tools(new WeatherTool(), new OrderQueryTool()) .contentRetriever(retriever) .build(); String answer agent.chat(帮我查一下订单 SM20260101 的物流状态然后告诉我今天天气适合收货吗); System.out.println(answer); } }在这个代码里CustomerServiceAgent同时具备三种能力从知识库检索相关业务规范RAG调用订单查询工具获取实时物流Tools基于聊天记忆理解上下文中的订单编号Memory。你会发现 Agent 并不是什么神秘的东西它本质上就是“模型 工具 知识 记忆”的组合。真正的难点不在代码而在工程化一个 Agent 要稳定执行任务需要设计好工具的描述、控制模型调用的频率、设置超时和降级策略、记录完整的调用链路日志。9. Spring AI 2.0 的接入方式参考前面提到 Spring AI 2.0 是官方方案。如果你决定用 Spring AI下面是配置 DeepSeek 的通用思路。注意 Spring AI 2.0 中可能已经提供独立的 DeepSeek Starter具体依赖以官方文档为准这里的逻辑是演示“如何把 DeepSeek 作为 OpenAI 协议端点接入”。dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-starter-model-openai/artifactId /dependency# application.yml spring: ai: openai: base-url: https://api.deepseek.com/v1 api-key: ${DEEPSEEK_API_KEY} chat: options: model: deepseek-chat然后注入ChatModel到 Service 层// 文件路径src/main/java/com/example/service/AiChatService.java package com.example.service; import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.stereotype.Service; Service public class AiChatService { private final ChatModel chatModel; public AiChatService(ChatModel chatModel) { this.chatModel chatModel; } public String chat(String message) { return chatModel.call(new Prompt(message)) .getResult() .getOutput() .getText(); } }Spring AI 2.0 的优势在配置一致性和与 Spring Boot Actuator、Spring Cloud 的联动。如果你准备长期往 Spring 官方生态靠建议保持关注。但从社区模块的丰富度看LangChain4j 仍然是 Java 生态里做 Agent 和 RAG 最灵活的选择。10. 常见问题与排查思路下面这些问题是 Java DeepSeek RAG Agent 项目里最常见的坎我把排查顺序也一并写出来。问题现象可能原因排查方式解决方案调用 DeepSeek 返回 401API Key 缺失或失效检查环境变量和代码中的读取方式重新生成 API Key确认环境变量已正确注入返回结果 content 为空但调用成功使用了 reasoner 模型推理内容走了 reasoning_content 字段打印完整响应 JSON切换为 deepseek-chat或按模型的响应结构取正确字段Agent 执行超时工具调用耗时过长或模型多轮回溯导致请求时间过长查看耗时日志和工具调用日志调大 timeout限制工具调用次数为慢工具增加缓存RAG 检索结果不相关切块粒度不合适或 minScore 过低打印检索出的文本片段人工判断调整切块大小提高 minScore换更适合业务的 Embedding 模型Milvus 连接失败容器未启动或 IP/端口配置错误执行 docker ps 和端口连通性测试确认容器状态核对 uri 地址引入 langchain4j 各模块后依赖冲突不同模块版本不一致执行 mvn dependency:tree统一 langchain4j 版本使用 BOM 管理依赖另外特别提醒一个问题在 Spring AI 项目中接入 DeepSeek 后有些版本会出现“调用成功但控制台没有输出 content”的情况。这通常不是因为配置错误而是因为模型返回的内容写在了一个不同的响应字段里或者是流式输出未正确消费。排查时先打开完整响应日志再判断是模型选择、参数解析还是流式消费的问题。11. 最佳实践与工程建议最后把工程经验沉淀成几条硬建议。第一API Key 一律走环境变量或配置中心禁止硬编码。AI 项目的成本直接跟着 Key 走密钥泄露不仅涉及安全还涉及费用风险。生产环境还应该配置调用频控和预算告警。第二RAG 的切块策略要按文档类型调整。技术手册适合按章节切规章制度适合按条目切长文本适合滑动窗口重叠切。不要指望默认参数适配所有语料建议准备一份评估集用“检索命中率”来量化调参效果。第三混合检索加 Rerank 是提升 RAG 效果的关键。纯向量检索处理不了精确关键词场景建议在 Milvus 等向量库中同时启用标量过滤或 BM25 混合检索再用 Rerank 模型对召回结果精排。这个方案在大规模知识库项目中非常常见也是 RAG 项目从 Demo 走向生产的分水岭。第四一定要做引用溯源。问答系统输出一个答案时应该同时返回命中了哪些文档段落。这样用户能核对更重要的是系统出错了能排查这在实际知识库项目里几乎是必须的。第五Agent 的日志比代码更重要。它的执行链路可能涉及模型多轮调用、工具多次调用排查问题必须依赖 trace_id 和完整的调用日志。建议每个 Agent 请求都生成唯一请求 ID把每次工具调用的入参、出参、耗时全部记录下来。第六线上环境一定要有降级方案。模型服务可能超时向量库可能不可用不能因为这些辅助能力的抖动拖垮核心业务。对非关键 AI 功能做好熔断降级对关键功能要有本地兜底答案。12. 总结与下一步这篇文章从 Java 开发者的真实痛点出发走了一条完整的 Java AI 应用开发路线DeepSeek 作为模型底座LangChain4j 作为编排框架Chat 是基础能力Tools 让模型能调用 Java 方法RAG 让模型能回答业务知识Agent 则是这几者的组合体。整体看真正需要花时间理解的是 RAG 的链路和 Tools 的设计代码本身的复杂度并不高。如果你想继续深入建议按这个顺序做三个练习先把最小 Chat 示例跑通再把自己手上的某一个业务接口包装成 Tool做一个客服助手最后把团队内部的一份文档做成 RAG 知识库并尝试回答真实问题。只有把一个项目完整跑通你才会理解模型能力之外的那些工程细节有多重要。下一篇内容可以围绕 RAG 的切块策略与混合检索调优展开这部分是目前 Java AI 项目里最值得深挖也最容易产生价值的方向。建议收藏本文等到真要动手写代码的时候再拿出来对照排查。