Java开发者极简入门大模型应用开发:从本地部署到RAG实战
1. 从“Java开发”到“大模型应用开发”的认知跃迁最近和不少做Java后端的朋友聊天发现一个挺有意思的现象大家普遍对“大模型应用开发”既感到焦虑又觉得无从下手。焦虑的是感觉不学点AI就要被淘汰了无从下手的是面对铺天盖地的概念——RAG、Agent、微调、LangChain、Spring AI——完全不知道从哪里开始感觉和熟悉的Spring Boot、MyBatis是另一个世界的东西。我完全理解这种感受因为我也是从纯后端开发转过来的。今天我就结合自己踩过的坑和实际项目经验给各位Java背景的开发者梳理一条从易到难、可快速上手的“大模型应用开发”极简入门路线。这条路线的核心思想是不要一上来就想着去训练或者微调一个大模型那不是应用开发者的首要任务。我们的核心价值在于利用现有的、强大的大模型能力结合我们擅长的工程化、架构设计和业务逻辑去解决实际的业务问题。你可以把它理解为以前我们调用的是支付宝的支付API、微信的登录API现在我们调用的是更智能的“大脑API”。我们的工作从“业务逻辑编排”部分转向了“智能逻辑编排”。基于这个思路整个学习路径可以清晰地分为四个阶段环境与认知准备 → 基础API调用与对话应用 → RAG知识库应用实战 → Agentic智能体应用进阶。我会在每个阶段告诉你重点学什么、用什么工具、以及如何与你已有的Java技能结合。2. 第一阶段环境准备与核心概念扫盲在写第一行代码之前我们需要先把“场子”搭起来并把几个最核心的概念搞清楚。这个阶段的目标是消除陌生感让你能本地运行起一个大模型并理解后续所有操作的基础。2.1 本地大模型部署从Ollama开始对于初学者我强烈不建议一上来就去申请什么GPT-4的API或者折腾复杂的云端GPU服务器。成本高、网络不稳定而且不利于我们理解模型本身。最好的起点是在本地电脑上运行一个轻量级开源模型。这里首推Ollama。Ollama是一个极其简单的本地大模型运行和管理的工具它把模型下载、加载、运行、提供API接口这些繁琐步骤全部打包好了你只需要几条命令。为什么选它第一它支持Mac、Windows、Linux安装就是下载一个安装包或者一行命令的事。第二它有丰富的模型库从很小的到能力不错的都有。第三它直接提供了类OpenAI的API接口这意味着你以后换到真正的OpenAI API时代码几乎不用改。实操步骤安装Ollama去官网下载对应操作系统的安装包安装过程无脑下一步。拉取模型打开终端或命令行输入ollama run qwen2.5:0.5b。这个命令会下载并运行一个只有5亿参数的“千问”模型非常小几乎任何电脑都能跑起来。qwen2.5:0.5b就是模型名称和标签。验证运行运行后会进入一个交互式对话界面你可以直接输入“你好”它会用中文回复你。恭喜你的第一个本地大模型已经跑起来了探索更多模型你可以尝试ollama run llama3.2:1bMeta的小模型或ollama run qwen2.5:7b能力更强的7B模型需要电脑有8G以上空闲内存。用ollama list查看已下载的模型。注意运行更大的模型如7B、14B需要足够的内存。如果遇到insufficient memory报错要么加内存要么就老老实实用小参数模型如0.5B、1B做学习和开发测试完全够用。应用开发阶段我们更关注如何“用”模型而不是“跑”多大的模型。2.2 核心概念五分钟速通在模型跑起来的时候我们快速过一下接下来会频繁出现的几个词大模型 (Large Language Model, LLM)你就把它理解为一个“万事通”的文本生成器。你给它一段输入提示词它根据海量数据训练出的规律生成一段相关的输出。它不“懂”知识只是概率预测。我们本地跑的Qwen、Llama就是具体的模型实例。API (Application Programming Interface)模型的能力如何被我们的程序调用就是通过API。Ollama本地运行后会在http://localhost:11434提供一个API服务。我们写的Java程序通过发送HTTP请求到这个地址就能让模型干活。以后用阿里云、百度云、OpenAI的模型也是类似的道理只是换一个API地址和密钥。提示词 (Prompt)这是你与模型沟通的“指令”。它的质量直接决定模型输出的质量。不是简单地把问题丢进去而是需要精心设计。例如比起“写一篇散文”更好的提示词是“你是一位优秀的散文家请以‘故乡的秋天’为题写一篇300字左右、情感细腻、略带伤感的散文。”RAG (Retrieval-Augmented Generation检索增强生成)这是当前大模型应用落地的核心范式。核心思想是模型本身的知识可能过时或不专业我们不让它凭空编造而是先从我们自己的知识库比如公司文档、产品手册、法律条文里找到相关材料然后把“问题材料”一起交给模型让它基于这些材料生成答案。这样答案更准确、更可控。你可以把它想象成一个“开卷考试”模型可以翻看我们提供的参考资料再答题。Agent (智能体)这不是一个具体工具而是一种设计模式。一个Agent可以理解为一个能自主调用工具来完成复杂任务的AI程序。比如你告诉Agent“帮我分析一下上周的销售数据并写一份总结报告”它可能会自主执行以下步骤1. 调用数据库查询工具获取数据2. 调用数据分析工具生成图表3. 调用大模型结合数据和图表撰写报告。Agent的核心是“规划-执行-反思”的循环能力。理解了这些你就有了一个基本的地图。接下来我们开始用Java来真正“驱动”这个模型。3. 第二阶段用Java连接大模型构建第一个对话应用现在我们进入熟悉的Java世界。目标是用我们擅长的Java代码去调用刚才在本地运行的Ollama模型实现一个简单的命令行或Web对话应用。这里有两条路原生的HTTP客户端和Spring AI。3.1 方案一使用HTTP客户端直连理解本质我建议所有人都从这里开始因为它能让你最清晰地理解底层发生了什么。我们使用Java里常见的HttpClientJDK 11自带或OkHttp3。核心逻辑构造一个符合Ollama API格式的JSON请求发送POST请求到http://localhost:11434/api/generate然后解析返回的JSON响应。Maven依赖如果使用OkHttp3dependency groupIdcom.squareup.okhttp3/groupId artifactIdokhttp/artifactId version4.12.0/version /dependency dependency groupIdcom.fasterxml.jackson.core/groupId artifactIdjackson-databind/artifactId version2.15.2/version /dependency一个极简的示例代码片段import okhttp3.*; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap; import java.util.Map; public class OllamaSimpleClient { private static final String OLLAMA_URL http://localhost:11434/api/generate; private static final MediaType JSON MediaType.get(application/json; charsetutf-8); private final OkHttpClient client new OkHttpClient(); private final ObjectMapper mapper new ObjectMapper(); public String chat(String model, String prompt) throws Exception { MapString, Object requestBody new HashMap(); requestBody.put(model, model); // 例如 qwen2.5:0.5b requestBody.put(prompt, prompt); requestBody.put(stream, false); // 先关闭流式输出简化处理 String json mapper.writeValueAsString(requestBody); RequestBody body RequestBody.create(json, JSON); Request request new Request.Builder().url(OLLAMA_URL).post(body).build(); try (Response response client.newCall(request).execute()) { if (!response.isSuccessful()) throw new RuntimeException(Unexpected code response); String responseBody response.body().string(); // 解析响应提取 response 字段 MapString, Object result mapper.readValue(responseBody, Map.class); return (String) result.get(response); } } public static void main(String[] args) throws Exception { OllamaSimpleClient client new OllamaSimpleClient(); String answer client.chat(qwen2.5:0.5b, 为什么天空是蓝色的); System.out.println(模型回答 answer); } }运行这段代码如果你的Ollama服务正在运行你就会在控制台看到模型的回答。这个过程和你调用任何一个第三方RESTful API没有任何本质区别。这就是大模型应用开发最基础的一环API调用。3.2 方案二使用Spring AI框架提升效率如果你熟悉Spring生态那么Spring AI绝对是你的福音。它就像Spring Data对数据库的操作一样为AI模型调用提供了一层优雅的抽象。你不需要再手动拼装JSON、解析响应而是通过声明式的AiClient和自动配置来完成。首先引入Spring AI的依赖。注意Spring AI的版本迭代较快目前主推的是基于Spring Boot 3.x的版本。!-- 在Spring Boot项目中 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-ollama-spring-boot-starter/artifactId !-- 请查看Spring AI官方文档获取最新版本号 -- version0.8.1/version /dependency然后在application.yml中配置spring: ai: ollama: base-url: http://localhost:11434 # Ollama服务地址 chat: options: model: qwen2.5:0.5b # 默认使用的模型最后在代码中注入AiClient并使用import org.springframework.ai.client.AiClient; import org.springframework.ai.client.AiResponse; import org.springframework.ai.prompt.Prompt; import org.springframework.ai.prompt.SystemPromptTemplate; import org.springframework.ai.prompt.messages.UserMessage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; RestController public class ChatController { Autowired private AiClient aiClient; GetMapping(/chat) public String chat(RequestParam String message) { // 构建一个简单的用户消息Prompt Prompt prompt new Prompt(new UserMessage(message)); // 调用模型 AiResponse response aiClient.generate(prompt); // 提取结果 return response.getGeneration().getText(); } // 更复杂的例子使用System消息设定角色 GetMapping(/chat/poet) public String chatWithPoet(RequestParam String topic) { String systemText 你是一位才华横溢的唐代诗人擅长创作七言绝句。请根据用户提供的主题创作一首符合格律、意境深远的诗。; SystemPromptTemplate systemPromptTemplate new SystemPromptTemplate(systemText); Prompt prompt new Prompt(systemPromptTemplate.createMessage(), new UserMessage(主题 topic)); AiResponse response aiClient.generate(prompt); return response.getGeneration().getText(); } }启动Spring Boot应用访问/chat?message你好和/chat/poet?topic明月你就能得到模型的回应。可以看到Spring AI极大地简化了调用流程让你能更专注于业务逻辑比如设计提示词、处理返回结果而不是底层的HTTP通信。实操心得我建议你先用方案一HTTP客户端写一个简单的demo理解整个数据流。然后再用方案二Spring AI进行正式项目开发。这能让你在遇到Spring AI的配置或封装问题时有能力进行底层调试。永远不要让自己的技术栈完全建立在你不理解的黑盒之上。4. 第三阶段构建你的第一个RAG知识库应用掌握了基础调用我们就可以解决大模型“胡说八道”和“知识陈旧”的核心痛点了。这就是RAG的用武之地。我们来构建一个最简单的RAG应用一个基于本地文档的问答系统。4.1 RAG的核心工作流程拆解一个典型的RAG流程分为索引Indexing和检索生成Retrieval Generation两个阶段索引阶段预处理知识库加载文档从各种来源TXT、PDF、Word、网页、数据库加载文本。分割文本大模型有上下文长度限制比如4096个token。不能把整本书塞给它。需要把长文档按语义切分成大小合适的“文本块”Chunk比如每块500字。向量化嵌入这是最关键的一步。使用一个“嵌入模型”Embedding Model将每个文本块转换成一个高维度的数值向量比如768维。这个向量代表了文本的语义信息。语义相近的文本其向量在空间中的距离也相近。存储向量将这些向量和对应的原始文本块存储到专门的“向量数据库”中。检索生成阶段用户提问时用户提问。向量化问题使用同一个嵌入模型将用户的问题也转换成一个向量。相似度检索在向量数据库中寻找与“问题向量”最相似的几个“文本块向量”通常使用余弦相似度计算。这一步就是“开卷考试”中的“翻书找答案”。组合提示词将找到的最相关的几个文本块作为“参考材料”和用户原始问题一起组合成一个新的、更详细的提示词。例如“请基于以下材料回答问题材料1... 材料2... 问题...”。调用大模型生成将这个组合后的提示词发给大模型让它基于材料生成最终答案。4.2 基于Spring AI 本地向量库的极简实现Spring AI目前对RAG有初步支持我们可以用它快速搭建一个原型。这里我们使用一个简单的内存向量库避免引入复杂的外部数据库。步骤1添加依赖除了之前的Ollama依赖还需要嵌入模型和向量存储的依赖。我们可以继续用Ollama提供的嵌入模型。dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-ollama-spring-boot-starter/artifactId version0.8.1/version /dependency dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-transformers-spring-boot-starter/artifactId version0.8.1/version /dependency !-- 使用简单的内存向量库 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-vector-store-simple/artifactId version0.8.1/version /dependency步骤2准备知识库文档在项目的resources目录下创建一个docs文件夹里面放一些.txt文件比如company_rules.txt内容可以是公司的请假制度、报销流程等。步骤3编写RAG服务核心代码import org.springframework.ai.document.Document; import org.springframework.ai.embedding.EmbeddingClient; import org.springframework.ai.reader.TextReader; import org.springframework.ai.transformer.splitter.TokenTextSplitter; import org.springframework.ai.vectorstore.SimpleVectorStore; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.stereotype.Service; import jakarta.annotation.PostConstruct; import java.io.IOException; import java.util.List; import java.util.stream.Collectors; Service public class SimpleRagService { Autowired private EmbeddingClient embeddingClient; // 嵌入模型客户端Spring AI会自动配置使用Ollama private VectorStore vectorStore; // 项目启动时加载并索引文档 PostConstruct public void init() throws IOException { // 1. 初始化一个简单的内存向量库 this.vectorStore new SimpleVectorStore(embeddingClient); // 2. 加载资源文件下的所有txt文档 PathMatchingResourcePatternResolver resolver new PathMatchingResourcePatternResolver(); Resource[] resources resolver.getResources(classpath:docs/*.txt); ListDocument documents new java.util.ArrayList(); for (Resource resource : resources) { TextReader textReader new TextReader(resource); textReader.getCustomMetadata().put(filename, resource.getFilename()); documents.addAll(textReader.get()); } // 3. 分割文本将长文档切成小块 TokenTextSplitter splitter new TokenTextSplitter(500, 100); // 每块约500token重叠100token ListDocument splitDocuments splitter.apply(documents); // 4. 将分割后的文档存入向量库会自动调用EmbeddingClient生成向量 vectorStore.add(splitDocuments); System.out.println(知识库文档索引完成共 splitDocuments.size() 个文本块。); } // RAG检索与生成 public String ragQuery(String question) { // 1. 相似度检索在向量库中查找与问题最相关的4个文本块 ListDocument similarDocuments vectorStore.similaritySearch(question, 4); // 2. 构建增强后的提示词 StringBuilder context new StringBuilder(); for (Document doc : similarDocuments) { context.append(doc.getContent()).append(\n---\n); } String enhancedPrompt String.format( 请严格根据以下提供的信息来回答问题。如果信息中没有明确答案请直接说“根据现有资料无法回答”。 信息 %s 问题%s 答案 , context.toString(), question); // 3. 调用大模型生成答案这里需要注入AiClient代码略 // AiResponse response aiClient.generate(new Prompt(enhancedPrompt)); // return response.getGeneration().getText(); return 【模拟答案】基于检索到的信息答案是... 提示词已构建:\n enhancedPrompt; } }步骤4创建控制器暴露接口RestController RequestMapping(/rag) public class RagController { Autowired private SimpleRagService ragService; GetMapping(/ask) public String ask(RequestParam String q) { return ragService.ragQuery(q); } }启动应用访问/rag/ask?q公司年假有多少天。如果你的company_rules.txt文档里有相关描述RAG服务就会先找到那段话然后让模型基于那段话生成答案。踩坑实录与核心要点文本分割是门艺术TokenTextSplitter的参数块大小、重叠大小极大影响效果。块太大可能包含无关信息块太小可能割裂语义。通常需要根据你的文档类型技术文档、小说、法律条文进行调优。重叠是为了避免一个答案恰好被切到两个块中间。嵌入模型的选择我们这里偷懒用了Ollama的嵌入模型通常是nomic-embed-text对于中文场景可以探索更好的开源嵌入模型如bge-large-zh但需要单独部署。Spring AI也支持OpenAI的嵌入API效果更好但需付费。向量数据库选型我们这个例子用了内存存储重启就没了。生产环境必须用持久化的向量数据库如PgVectorPostgreSQL插件、Milvus、Qdrant、Chroma等。Spring AI对其中一些有starter支持。提示词工程上面例子里的提示词“请严格根据以下提供的信息...”非常关键它强制模型“照本宣科”减少幻觉。这是RAG提示词的核心技巧。5. 第四阶段迈向Agentic智能体与生产级考量当你成功构建了RAG应用意味着你已经掌握了当前大模型应用开发最主流、最实用的模式。接下来可以朝着更自动化的Agent智能体和更生产级的架构去探索。5.1 从RAG到Agentic RAG传统的RAG是被动的用户问系统检索然后生成。Agentic RAG则让系统变得更主动。例如用户问“我们公司去年在云计算方面的投入和收益情况如何”一个简单的RAG可能直接在财务文档里搜索“云计算 投入”。而一个Agentic RAG可能会规划理解问题拆解成子任务a) 查找去年财务报告b) 在报告中定位“云计算”或“IT基础设施”相关章节c) 提取投入成本数据d) 查找云计算业务带来的营收数据e) 进行对比分析。执行针对每个子任务可能调用不同的工具或检索策略。比如任务a和b用向量检索任务c和d可能用更精确的关键词提取或表格解析工具。反思检查提取到的数据是否完整、是否矛盾必要时重新规划或检索。生成综合所有信息形成一份结构化的分析报告。Spring AI 2.0 版本开始大力推广Function Calling和Agent的概念。你可以通过定义Bean类型的Tool工具让AiClient在对话中自主选择调用。例如定义一个查询天气的Tool一个查询数据库的Tool。当用户说“北京天气怎么样顺便看看我今天的日程”模型可以自主决定先调用天气Tool再调用日程查询Tool最后把结果总结给用户。这就是智能体的雏形。5.2 生产级架构与学习路线延伸要把Demo变成真正可用的服务还需要考虑很多工程问题稳定性与监控大模型API调用可能超时、限流。需要实现重试、熔断、降级策略可用Resilience4j或Sentinel。监控每次调用的耗时、token消耗、费用。性能优化缓存对常见的、不变的问题答案进行缓存避免重复调用模型和检索。异步处理对于耗时的文档索引、复杂Agent任务采用异步队列处理。流式响应像ChatGPT一样一个字一个字地输出提升用户体验。Ollama和Spring AI都支持。安全与合规输入输出过滤防止用户输入恶意提示词Prompt Injection导致模型越狱或输出有害内容。数据隐私敏感数据不上传公有云API用本地或私有化部署的模型。审计日志记录所有的用户问答用于效果分析和合规审查。持续学习与迭代评估与反馈建立评估体系收集用户对回答的“点赞/点踩”用于优化检索策略和提示词。深入微调当通用模型在特定领域如医疗、法律表现不佳时可以考虑用LlamaFactory等工具对开源模型进行领域微调但这需要数据、算力和更深的专业知识。5.3 给Java开发者的学习资源与心态建议学习路线图总结基础认知理解LLM、Prompt、RAG、Agent概念。环境搭建用Ollama在本地跑通一个小模型。API调用用Java HTTP Client或Spring AI连接模型完成简单对话。RAG实战用Spring AI 向量数据库从Simple到PgVector构建知识库问答。Agent进阶学习Spring AI的Function Calling设计工具链构建能自动执行任务的智能体。生产深化关注性能、安全、监控、评估等工程化问题。资源推荐官方文档永远是第一选择Spring AI项目文档、Ollama文档。开源项目参考在GitHub上搜索spring-ai rag example、qwen java demo等关键词参考别人的实现。社区与资讯关注Hugging Face、知乎、掘金上相关领域的技术博主。心态建议 别被“AI”、“大模型”这些词吓到。对于应用层开发者来说它本质上是一种新的、能力更强的“外部服务”。我们过去集成短信服务、支付服务、地图服务现在集成“智能服务”。你的Java功底、你的系统设计能力、你的工程化思维不仅没有过时反而因为要处理AI的不确定性幻觉、延迟、成本而变得更加重要。从今天开始动手跑通第一个本地模型写出第一行调用代码你就已经上路了。这条路和你当年学习Spring Boot、学习微服务一样充满挑战但也充满机遇。