做Java这几年,我听到最多的一句话是:Java是不是要被AI淘汰了?尤其是大模型相关的新闻铺天盖地,招Java岗的JD里也开始写“熟悉AI应用开发优先”,很多Java老哥开始慌——我是不是得转Python?要不要辞职去读个AI方向?说实话,这种焦虑我也有过。但当我按着一条清晰的路线图,把Java侧的AI工具链真正用起来之后,我反而觉得:Java开发者入场AI,不但不是劣势,反而是被大多数人低估的巨大优势。这篇文章没有鸡汤,就是把我在“Java开发者如何入门AI”这件事上踩过的坑、验证过的路线图、用顺手的工具链,原原本本捋一遍。你要做的不是放弃Java换赛道,而是在Java的底盘上,把AI能力叠上去。
1. 为什么Java开发者应该入坑AI:先破除三个认知误区
好多Java开发者不敢碰AI,就是因为脑子里有三座大山挡着。我先一个个拆开来说。这些不是空洞的情绪鼓励,而是我在实际项目里得出的判断,你看完之后再决定要不要继续往下走。
1.1 误区一:AI等于Python,Java什么忙都帮不上
AI这个词在媒体里被无限放大了,实际上AI是一条完整链条:数据清洗、模型训练、模型调优、模型推理服务化、业务系统集成、监控运维。真正花在“训练模型”这个环节上的时间,在大规模工程化项目里其实比例不高;而推理服务化和业务系统集成,恰恰是Java和JVM生态的主场。举个真实例子,你现在做一个企业知识库问答系统,模型选好之后,后面跟业务打交道的全是Spring Boot服务的事。用户提问进来要鉴权、要限流、要做线程池控制、要接中间件、要写审计日志,这些全是Java工程师的看家本领。模型推理这一步,你可以用ONNX Runtime Java或者DJL在JVM里直接加载模型,也可以部署一个独立的推理服务,Java通过HTTP或gRPC调用。整个链路走下来,没有哪一步是“必须换成Python才能干”的。
更直接地说,Python在AI领域强在训练和研究环节,而Java在AI工程化和生产落地环节有天然优势。现在大厂的AI系统里,模型训练只是冰山一角,海量的特征服务、模型网关、数据管道、业务编排都是Java生态撑起来的。你在Java上积累的并发编程、性能调优、分布式系统经验,到了AI工程化场景不仅不过时,反而是最稀缺的。
1.2 误区二:调API就是AI的全部,没啥技术含量
如果你把“调API”理解为填一个Key、发一个HTTP请求,那确实没含量。但实际AI应用的价值在于:如何拆解复杂任务、如何设计提示词与上下文结构、如何让模型按约束输出、如何配合检索增强回答(RAG)、如何让模型通过函数调用(Function Calling)操作你的业务系统、如何评估模型输出质量并且持续改进。这些能力,本质上就是软件工程的系统工程能力,不是“发个请求拿个回答”那么简单。Java开发者天天跟高并发、缓存、事务打交道,天然具备“把不确定的东西装进确定框架”的思维。大模型恰好充满不确定性,而工程化AI要做的就是把不确定变成可控。这恰恰是很多纯AI出身的人头疼的部分,Java开发者反而如鱼得水。
我见过太多团队,模型demo跑得很溜,但一上生产就崩:要么并发一上来超时一大片,要么提示词被用户绕过导致输出失控,要么模型回答的内容没有审计记录无法追溯。这些问题,靠的都不是花哨的数学功底,而是扎实的工程能力。Java开发者的老本行,在这些地方全是加分项。
1.3 误区三:Java的AI生态不成熟,能用的东西太少
这个说法放在三年前勉强成立,放在现在真的过时了。我可以负责任地说,Java AI生态现在已经有几大支柱:Spring AI(Spring官方出的AI开发框架)、LangChain4j(LangChain的Java移植版)、Deep Java Library(DJL,Apache孵化项目)。再往下还有ONNX Runtime的Java绑定、各种向量数据库的Java客户端。国内各种大模型服务也都提供Java SDK或者OpenAI兼容接口,接入方式非常成熟。所以问题从来不是“Java能不能做AI”,而是“你愿不愿意花几周时间,把Java侧这套工具链捡起来”。我后面会给出非常具体的清单和路线,你照着走就行。
2. 路线图:Java开发者入门AI的四阶段设计
在给具体工具之前,我先把路线图铺开。这个路线图是我自己实践后总结的,也参考了一些成功转型者的经验,适合一个日常写业务代码、周末能抽出5到10个小时学习的Java开发者。整体时长大概在12周左右,你可以根据自己的节奏弹性伸缩,但阶段顺序不建议打乱。
2.1 阶段一:补齐机器学习与数据基础(建议4到6周)
第一周,先别碰框架,先把机器学习的基本盘概念搞清楚。不需要去啃整本《统计学习方法》,那会直接劝退。你需要掌握的是这几个点。
向量与矩阵的基础:不用会手推求导,但要知道向量、矩阵、点积、余弦相似度是什么。为什么重要?因为你后面做RAG,要把文档转成一串数字组成的向量,然后通过向量的相似度做检索。不理解余弦相似度,你就只能把向量数据库当黑盒用,出了问题根本不知道怎么排查。
机器学习核心流程:训练集、验证集、测试集,过拟合、欠拟合,精确率、召回率、F1这几个概念。这些东西在你评估模型效果时会反复用到。学的时候不要停留在背定义,建议配合一个具体的分类任务去找感觉,比如垃圾邮件分类、房价预测,跑通一个demo比看十遍PPT都有用。
深度学习框架知识:神经网络是怎么回事、梯度下降大意、反向传播大意,然后重点理解Transformer结构为什么是现在大模型的基石。注意这里追求的是“知道它在干什么”,而不是“能从头实现Attention”。你要的是一个全局画面感,知道模型内部有那些环节就够用了。
最后要理解嵌入(Embedding)到底是什么。把词、句子变成固定维度的向量,这是连接传统Java世界和AI世界的一座桥。后面所有RAG应用都建立在这个概念上。我推荐看这些免费课程入门:吴恩达的《Machine Learning Specialization》讲基础概念非常稳,李宏毅的《机器学习》讲得深一点但幽默不枯燥,3Blue1Brown的神经网络系列动画能帮你建立直觉。不要贪多,每个看前三四章就够了。
2.2 阶段二:掌握Java侧AI核心工具链(建议3到4周)
基础概念有了之后,马上切换到Java更有效。我强烈建议你先从Spring AI入手,原因很简单:如果你已经有Spring Boot经验,它的抽象风格你会非常熟悉,学习曲线是平的。
Spring AI提供了一套类似Spring Data的抽象,把“大模型调用”封装成ChatClient、EmbeddingModel、VectorStore这些接口。你的业务代码不用绑定具体厂商,今天接OpenAI兼容接口,明天换国产模型,只需要改配置,代码主体不用动。然后是LangChain4j,它更偏开源,提供了比较完整的Agent、Tool、RAG支持,适合需要编排复杂多步骤任务的场景。如果Spring AI的自动装配给你太多约束,可以试试LangChain4j,它的管线风格更接近写代码的直觉。
最后是DJL,这个更底层一些。如果你需要离线在JVM里直接加载模型跑推理,比如内网环境、不能访问外网API的场景,DJL是首选。它支持PyTorch、TensorFlow、ONNX等格式的模型,Java世界里很少有哪个库能做到这个灵活度。这个阶段的目标不是把每样都学透,而是每个工具都跑通一个最小demo,建立对它们的能力边界的认知。
2.3 阶段三:学会“够用”的Python协同能力(建议2到3周)
这是很多Java程序员最抵触的一步:又让我学Python?别误会,你的目标不是成为Python开发者,而是达到“能跑通AI脚本人脚本”的水平。具体来说,你要会:建虚拟环境(conda或venv)、知道pip怎么用、能在Hugging Face的模型库页面上找到模型并把模型下载下来、能跑通一个最简单的transformers推理脚本、能把PyTorch模型导出成ONNX格式。做到这些,你就能在Java和Python之间架起一座桥:模型下载、格式转换这种“脏活累活”让Python做完,Java侧只负责加载、推理和业务集成。
Python在这条链路里的定位是工具间的一座桥,不是新的职业方向。我知道有些Java老哥一学Python就上头,把Pandas、NumPy、FastAPI全学一遍,岗位倒是没转,时间已经浪费了。把Python限制在“能跑AI脚本”的范围内,才是效率最高的姿势。
2.4 阶段四:聚焦AI工程化,持续落地业务场景(持续进行)
基础打通之后,就要把AI真正装进你的业务系统。我的建议是顺着下面四个项目逐步深入,每做一个能力就沉淀一层。
第一个项目:给现有系统加一个“智能客服助手”,用大模型根据FAQ文档回答问题。你需要完成文档加载、文本切分、向量化、检索、生成答案这五件事,全链路用Java就能搞定。这个项目能让你把RAG流程彻底跑通,做的过程中你会理解什么叫“检索之上做生成”。
第二个项目:做一个小型Agent,让模型能够调用你系统里的已有接口。比如用户说“帮我查一下订单状态”,用Function Calling让模型决定调用哪个方法、填入哪些参数,你的Java代码拿到结果后再组织话术回复用户。这一步开始真正发挥Java工程师在服务编排上的优势,模型的“脑子”加上你系统的“手脚”,出来的东西已经有点智能产品的意思了。
第三个项目:做一个有业务含义的评估迭代项目,比如给AI客服的回答质量打分。你会用上精确率、召回率、人工评测这些在第一阶段学的概念,也会开始建立“评测集”的意识。没有评测集的AI系统等于盲人开车,方向对不对全凭感觉,这个项目做完你就摆脱这种感觉了。
第四个项目:把模型推理收敛到几类标准做法中:云端API调用、本地ONNX推理、隔离的推理服务。实践经验证明,一个团队往往只需要两三种推理模式就能覆盖绝大多数业务。这个阶段你会开始关注模型量化、并发连接、成本控制,这些是AI系统上生产前必须解决的问题。
3. 工具链详解:2025年Java AI全家桶怎么选
工具选型是最容易让人纠结的,因为AI方向的Java库不像Spring生态那么统一。我把当前Java侧主流的工具整理成一张大表,后面再针对每类工具讲讲我的实际体验和取舍标准。
3.1 一张表看清Java AI工具全景
先上个总览表,后面逐类展开,你可以把它当作自己的选型备忘。
| 类别 | 主要工具 | 适用场景 | 上手难度 | 备注 |
|---|---|---|---|---|
| 推理框架 | DJL | JVM内直接加载模型推理 | 中 | 支持PyTorch/TensorFlow/ONNX |
| 推理框架 | ONNX Runtime Java | 高性能ONNX模型推理 | 中 | 微软出品,性能稳定 |
| 应用框架 | Spring AI | Spring Boot项目快速接入大模型 | 低 | Spring官方,版本迭代快 |
| 应用框架 | LangChain4j | 复杂Agent/多步编排 | 中 | 功能全但API偏底层 |
| 向量存储 | Redis Stack+RediSearch | 中小项目向量检索 | 低 | 复用已有Redis |
| 向量存储 | Milvus | 大规模向量检索 | 高 | 需要独立部署和运维 |
| 向量存储 | PostgreSQL+pgvector | 结构化+向量混合查询 | 中 | 适合已有PG业务 |
| 本地模型 | Ollama | 本地跑开源模型 | 低 | 一键启动,适合开发调试 |
| 本地模型 | llama.cpp Java绑定 | 轻量化CPU推理 | 中 | 硬件要求低 |
| 大模型API | OpenAI兼容服务 | 在线调用标准模型 | 低 | 选择合规服务商并配好密钥 |
这个表格只是让你有一个全局视野,真正选型时要结合团队情况。比如你们团队已经重度使用Redis,那向量检索直接用Redis Stack就能省掉一个Milvus集群;如果你们有PostgreSQL,用pgvector做向量存储,结构化查询和向量查询能写在一条SQL里,业务代码会清爽很多。
3.2 推理层:DJL与ONNX Runtime怎么选
DJL的核心价值是可以在JVM里直接跑深度学习模型。它自带ModelZoo,也能从Hugging Face导入模型。我最喜欢的是它的Translator机制,你定义好输入输出如何转换,就能把一个图片分类、文本嵌入或问答模型包成Java对象,用起来非常“Java”。不过DJL的学习成本在于,你要理解模型仓库、引擎、设备这些概念,初次上手会有点绕。
ONNX Runtime则是微软主导的推理引擎,特点是非常稳定、性能好、文档全。如果你的团队已经有Python侧把PyTorch模型导出成ONNX的习惯,Java端直接用ONNX Runtime接住即可,两边技术栈干净解耦。选型建议很简单:只在JVM内推理的场景,优先ONNX Runtime,因为它稳定、少魔法;如果模型格式多样、还要动态加载不同框架的模型,那DJL更灵活。
另外说一个实际生产里用得最多的模式:调远程推理服务。你部署一个独立的模型推理服务(常见的有vLLM、TGI,团队如果有AI工程师通常由他们负责),或者直接用商业API,Java侧只需要HTTP客户端和JSON解析。Weway这样所有高并发问题都可以用你熟悉的连接池、限流组件、降级策略解决。这个模式的好处是模型和业务彻底解耦,模型升级不影响Java应用,Java应用发版也不用重启模型。
3.3 应用框架层:Spring AI与LangChain4j的核心概念
这两个框架关系有点微妙。LangChain4j先出现,理念是模仿Python界的LangChain,提供Chain、Tool、RAG等一整套抽象。Spring AI是Spring生态的正规军,2023年底进入Spring Initializr,策略是用Spring的惯例(Bean注册、Starter、AutoConfiguration)去封装AI能力。如果你已经熟悉Spring Boot,Spring AI的入门体验会非常丝滑。
我在Spring AI里最常用的就是ChatClient这个API,写法和RestTemplate很像,但背后帮你做了完整的会话管理:
ChatResponse response = chatClient.prompt() .system("你是一名资深Java顾问,请用简洁的话回答问题") .user("Java 8升级到Java 21最重要的三个理由是什么?") .call(); String content = response.getResult().getOutput().getText();流式输出也一样简单,返回一个Flux,配合WebFlux可以做打字机效果:
Flux<ChatResponse> stream = chatClient.prompt() .user("给我写一个用Spring Boot实现定时任务的示例") .stream();LangChain4j则更强调“可编程的管线”。它把RAG的每一步拆成Source、Splitter、Embedder、VectorStore、Retriever、Generator,你可以在中间插入日志、校验、多路召回。如果你的RAG链路比较复杂,比如需要多路召回加重排,LangChain4j的灵活性更好。选择建议是:团队以Spring为主、业务相对标准,就选Spring AI;要做深度定制的AI管线,就选LangChain4j。我个人的习惯是Spring AI做常规业务接入,LangChain4j做复杂实验性项目,两者并不是你死我活的关系。
3.4 模型加载与本地化:Ollama与模型量化避坑
开发阶段我非常依赖Ollama。它把模型下载、运行、暴露API整个流程简化成一两条命令,比如在本地跑通义家族的Qwen 2.5 7B模型:
ollama pull qwen2.5:7b ollama run qwen2.5:7b它默认在本机11434端口起一个兼容OpenAI的接口,Java侧Spring AI的ollama模块可以直接对接。在开发机上用CPU跑7B模型虽然慢一点,但对调试RAG链路完全够用,不需要一开始就花钱上GPU。
线上私有化场景,我建议走ONNX Runtime加载量化模型。对Java开发者最直观的体感是:把FP32模型换成INT8量化模型之后,JVM堆内存占用可能下降50%到75%,推理速度也能提升,代价是模型精度轻微下降。具体怎么取舍,要看业务对准确率的敏感程度。比如客服问答这种场景,稍微损失一点精度换来成本和延迟的大幅优化,非常划算;但医疗、法务这种对准确性极其敏感的场景,就要谨慎用量化。
3.5 别急着重复造轮子,用标准模式起步
很多Java开发者接手AI项目时,第一反应是自己实现一遍“文档切分、向量化、检索”的流程,理由是这些逻辑不难。我劝你把这个冲动压一压。AI链路里的坑不在“能不能实现”,而在“边界问题是否处理充分”:文本切分时编码格式不一致、向量检索时维度没对齐、模型输入超出了上下文窗口。这些Edge Case,框架已经帮你踩过一遍了。先用Spring AI或LangChain4j的标准模式把链路跑通,再按需替换里边的组件,才是效率最高的做法。等你真正理解了每个组件的职责边界,再去自研组件也不迟。
4. 实操过程:用Spring AI搭一个RAG知识库问答服务
理论讲完了,现在直接上实操。我要带你搭一个能跑起来的最小知识库问答服务:用户提问,系统先在文档库中检索相关片段,然后让大模型基于这些片段作答。这是目前企业落地最普遍的AI应用形式,也是“Java开发者入门AI”最好上手的练习项目。
4.1 环境准备:JDK、Maven与模型来源
先交代我的推荐环境:JDK 21(LTS版本,Spring AI要求JDK 17起步,直接上21省得以后升)、Maven 3.9以上、Spring Boot 3.4.x。模型来源有两个选择:本地装Ollama,拉一个开源小模型比如qwen2.5:3b或者7b,完全离线开发;或者准备一个国内合规大模型的API密钥,阿里的通义千问、智谱、Moonshot这些都提供OpenAI兼容接口,接入方式是一样的。用Ollama时,Spring AI对应的依赖坐标是:
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-ollama-spring-boot-starter</artifactId> </dependency>配置文件也很简单:
spring: ai: ollama: base-url: http://localhost:11434 chat: model: qwen2.5:7b如果你用云端API,就把starter换成对应厂商的,比如阿里云百炼平台,配置里填上你的api-key和model名字就行。很多Java开发者在这里会卡一步:依赖拉不下来。解决办法是确认Maven仓库配置了阿里云镜像或其他可用的国内镜像仓库,配置好之后下载速度会快很多。
4.2 核心代码:完成一次带检索的问答
我打算用LangChain4j写这个例子,因为它把RAG管线的各个环节暴露得更清楚,你修改每个环节时心里有数。首先在pom里引入依赖:
<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j</artifactId> <version>1.0.0-beta2</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-ollama</artifactId> </dependency>第一步先建一个配置类,声明嵌入模型和对话模型。这里baseUrl指向Ollama暴露的OpenAI兼容端点,modelName换成你拉取的模型名:
@Configuration public class RagConfig { @Bean public EmbeddingModel embeddingModel() { return OpenAiEmbeddingModel.builder() .baseUrl("http://localhost:11434/v1") .apiKey("local") .modelName("nomic-embed-text") .build(); } @Bean public ChatLanguageModel chatModel() { return OpenAiChatModel.builder() .baseUrl("http://localhost:11434/v1") .apiKey("local") .modelName("qwen2.5:7b") .temperature(0.2) .build(); } }注意这里的apiKey填local,因为Ollama本地端点不做真正的密钥校验。如果切到云端API,就把baseUrl和apiKey换成服务商提供的真实值,其他代码基本不用动。这个设计让我在开发阶段和线上阶段之间切换时,只改配置不碰代码,非常舒服。
第二步是写入阶段:读文档、切块、embedding、入库。先用内存向量存储InMemoryEmbeddingStore,适合快速验证链路,生产环境再换成Redis Store或Milvus Store:
@Service public class KnowledgeIndexer { private final EmbeddingModel embeddingModel; private final InMemoryEmbeddingStore<TextSegment> store; public KnowledgeIndexer(EmbeddingModel embeddingModel) { this.embeddingModel = embeddingModel; this.store = new InMemoryEmbeddingStore<>(); } public void index(String filePath) throws IOException { String text = Files.readString(Path.of(filePath)); List<TextSegment> segments = new DocumentByParagraphSplitter(200, 50).split(text); List<Embedding> embeddings = embeddingModel.embedAll(segments).content(); store.addAll(segments, embeddings); } public List<MemoryEmbedding> search(String query, int maxResults) { return store.findRelevant(query, maxResults); } }切分器我故意选了按段落切分、每块200字符带50字符重叠。这个参数仅供参考,但你要理解背后的逻辑:块太小,上下文不全,模型回答容易断章取义;块太大,向量检索的精确度下降,很容易把不相关内容混进来。重叠字符是为了保证被切在边界附近的语义不丢失。实际做项目时,这个参数要根据你的文档类型反复调,没有一劳永逸的值。
第三步是问答链路:拿到检索片段,拼进提示词,让模型基于给定资料回答,同时加上约束防止模型自由发挥:
@Service public class QaService { private final ChatLanguageModel chatModel; private final KnowledgeIndexer indexer; public String answer(String question) { List<MemoryEmbedding> hits = indexer.search(question, 3); String context = hits.stream() .map(h -> h.embedding().text()) .reduce("", (a, b) -> a + "\n---\n" + b); String prompt = """ 请根据以下资料回答问题,如果资料中没有答案,请直接说"资料中未找到相关信息",不要编造。 资料: %s 问题:%s """.formatted(context, question); return chatModel.chat(prompt); } }这个示例虽然短,但把RAG最核心的两点表达清楚了:一是“检索”,从库里找出跟问题最相关的片段;二是“约束生成”,让大模型只基于给的资料回答。很多新手在这里犯的错误是:把检索回来的片段一股脑全塞给模型,既不限制数量也不检查质量。结果模型被大量弱相关片段干扰,回答反而比不检索还差。检索的质量直接决定生成质量,这条铁律要刻在脑子里。
4.3 把链路接到Spring Boot接口上
上面几步完成之后,对外接口就很简单了:
@RestController @RequestMapping("/api/qa") public class QaController { private final QaService qaService; @PostMapping public Result ask(@RequestBody QuestionReq req) { long start = System.currentTimeMillis(); String answer = qaService.answer(req.question()); return Result.ok(answer, System.currentTimeMillis() - start); } }整个项目从零到能跑,我自己的体感是:一个Java基础扎实、熟悉Spring Boot的老哥,一个周末就能跑通。你再加上参数校验、日志、限流、缓存,就能上生产。这个例子最有意思的地方在于,你的老本行——Spring MVC、依赖注入、分层架构——全都在发光。AI不是来取代你的,是来给你手头这些Java技能加杠杆的。
4.4 关键参数:temperature与上下文长度的取舍
调试这类服务的时候,最容易踩的坑就是模型输出质量问题。既然是做工程,就要有可调参数的概念。我把最常用的几个参数列在下面,这些都是我调了无数个模型以后沉淀下来的经验值。temperature控制随机性,0到1之间,默认通常是0.7或0.8。知识库问答建议调到0.2到0.4,让模型更忠实于资料;写文案、头脑风暴可以调高到0.7以上,让回答更有创造性。max-tokens限制生成的最大token数,它决定回答长度上限,也直接影响成本和延迟。知识库回答设置512到1024就够了,写代码或长文再放宽。设置太高会让单次请求变慢,而且按token计费的服务会心疼。top-p是采样的累积概率阈值,跟temperature类似但作用机制不同。常规做法是固定temperature,微调top-p,不建议两个同时大幅调,否则输出会变得飘忽不定。
上下文长度要单独留意。不是所有模型都支持无限长的输入。RAG场景下,检索返回的片段拼接后可能超出模型上下文,超了就会被截断,答案质量立刻下降。我通常的做法是控制总片段token数在模型上下文的三分之一以内,留出生成空间。比如模型上下文是8K,我给检索片段的上限就控制在2.5K左右,这样模型既有充足的资料参考,又有足够的空间生成答案。
5. 常见问题与避坑实录
最后这一节我最想写,因为这些坑全是真金白银换出来的。每条都是我或者我带过的同学真实踩过的,属于那种常规文档里不会写的经验。
5.1 依赖冲突与版本兼容:先崩溃的还是Maven
Spring AI版本迭代很快,新版本经常调整依赖,一不留神就会跟项目里已有的库冲突。我这里给一个稳妥的组合:JDK 21加Spring Boot 3.4.x加Spring AI当前稳定版。不要随便尝鲜RC版本,除非你想在凌晨三点体会人生。如果你项目里已经有大量老依赖,先从Spring AI的独立客户端类库开始,避免把你整个Spring Boot版本带上去。遇到依赖冲突的标准动作是用mvn dependency:tree -Dverbose找到冲突点,再决定用exclusion排除还是升级版本。新老版本共存的方案不如直接统一版本,省得以后埋雷。
5.2 模型加载慢、内存爆掉
JVM内直接加载大模型最容易OOM,这个问题几乎每个用DJL或ONNX Runtime的人都会遇到。模型初始化一定要放在启动过程,不要放在首个请求到达时,不然第一个用户会被卡到怀疑人生。堆内存要留足,比如7B量化模型加载后可能占4到6GB,你JVM至少要给6到8GB,还要预留业务代码需要的空间。调JVM启动参数时不要只调-Xmx,建议同时调-XX:MaxDirectMemorySize,因为很多推理引擎用的是堆外内存。我见过一个案例是-Xmx给了很高的值但没调堆外内存,跑了几小时后Direct Buffer溢出,整个服务挂掉,排查了半天才找到原因。
5.3 大模型回答不稳定,时好时坏
这不是玄学,多半是下面几个原因。一是提示词里没给足约束,比如没说明“不知道就说不清楚,不要编造”;二是检索回来的资料不够相关,被模型当噪声忽略;三是temperature设太高,输出方差大。我的排查顺序是:先降低temperature到0.2,再增强system提示词的边界约束,然后检查检索到的片段匹配度,最后实在不行再加一个重排(Rerank)步骤,把Top K的结果重新按相关度排序。通常做到重排这一步,召回准确率能明显上来。如果你用的是云端API,还建议把完整请求和响应记录下来,方便事后复盘。有个小技巧:在日志里同时打印检索到的片段ID和模型最终输出,一旦发现回答质量异常,可以先判断是“没检索到”还是“检索到了但模型不用”,两个方向的处理思路完全不同。
5.4 Java岗位里的“AI要求”到底要什么
很多Java同学问我:我直接去刷AI面试题、背八股文行不行?我的真实建议是:可以先背,但如果没有动手跑通过一个RAG项目、一个Agent项目,面试官问深两句就现形了。当前企业对Java岗位里“熟悉AI应用开发”的诉求,集中在几个方向:把大模型能力整合进现有业务系统,做AI基础设施和内网私有化服务,用AI改造研发流程比如代码生成、测试生成。这些方向全部以工程能力为底座,Java经验不过期,反而值钱。硬要说需要补什么,我认为有三个:对模型能力的边界感,也就是知道哪些任务该用模型、哪些用规则更好;对数据流的敏感,文本怎么清洗、切分、向量化才能保证效果;快速测试验证的动手习惯,想到一个方案马上能写demo验证。
5.5 并发与流式输出:线上服务的稳定之道
把AI接口暴露给线上业务后,并发控制就是第一重要的事。大模型API的响应延迟通常是秒级,比起普通数据库查询慢了一个数量级,意味着线程会被长时间占用。如果不做隔离,一个AI接口就能把整个应用的线程池拖垮。我的做法是用信号量隔离或者独立的线程池来处理AI调用,超时时间根据模型响应时间设置,通常15到30秒比较合理。另外要把流式输出用起来,用户不需要等整个回答生成完才看到内容,通过SSE一有token就推给前端,体验完全不同。Spring AI的ChatClient配合WebFlux做流式响应,代码量很小,但这个细节决定你的AI功能像不像个正经产品。
5.6 给Java开发者的学习资源清单
最后整理一份我实际用下来觉得值得看的资源清单,帮你少走弯路。入门课程方面,吴恩达的机器学习课程和李宏毅的机器学习课程各看前几章就行,3Blue1Brown的神经网络动画必看。模型原理方面,推荐读几篇通俗的Transformer解析文章,重点看Attention机制,不要陷进数学细节。Java侧的学习资料,Spring AI官方文档和LangChain4j的官方文档都是第一手资料,虽然有点干,但信息密度高,遇到问题最可靠。动手项目方面,除了前面说的RAG问答服务,可以再看两个开源项目:一个是用Spring AI写的知识库助手,一个是用LangChain4j写的Agent示例,从里面挑一个改造成自己的项目,收获会很大。
我在实际做这些项目的过程中,最大的体会是:Java开发者入门AI,真正的障碍不是技术,而是心态。很多人总以为AI是另一个世界的事情,觉得自己要先去学一堆数学、再学Python、再学深度学习,才能碰AI。其实以Java开发者的工程能力,完全可以用两周时间把RAG跑通,再用两周时间把Agent跑通,然后你会发现,AI应用开发并没有想象中那么神秘,它就是你熟悉的软件工程,只是多了一个充满不确定性的组件。这个组件的脾气你要慢慢摸,但你手里的工程手段足够驯服它。
最后再分享一个技巧:学习AI的路上,一定要给自己留一个“玩具项目”,不计产出、纯粹为了好玩的那种。我自己的玩具项目是一个用Java写的私人知识库,专门用来整理平时收藏的技术文章。每次新技术一出来,我就往这个项目里塞,试新框架、调新参数、踩新坑。这个项目没有KPI,但它让我对Java AI工具链的熟悉程度远超那些只看文档不写代码的人。我强烈建议你也搞一个,它会是你在AI路上最好的陪练。