
学完 Java AI 实战营之后有个问题我问了自己很多遍“你到底是会调用大模型还是真的能做 AI 应用”答案是以前的我只会调用大模型现在的我勉强算能做 AI 应用。这两者之间的差距比我想象中大得多。这篇文章不聊培训机构的宣传话术只聊我在实战营里从“调通接口”到“上线可用功能”的过程中踩过的坑、想明白的道理以及 Java 这个技术栈在 AI 应用开发里真实的位置。先说个结论摆在这能把大模型 API 调通约等于能拼出一台能点亮的电脑能做 AI 应用是让这台电脑稳定跑业务还要有人愿意天天用。前者是“能通”后者是“能用”中间隔着上下文管理、结构化输出、异常兜底、成本控制、测试评估、安全合规这一整套工程问题。本文就按我自己的认知升级路径把这些环节逐一拆开讲。1. “会调用大模型”和“能做 AI 应用”之间隔着一条真实的技术鸿沟很多刚接触 AI 开发的同学包括实战营前期的我最容易产生的错觉是我写了一段代码调通了 OpenAI 或者国产大模型的接口模型返回了一段合理的话我就“会做 AI 应用”了。这种错觉非常自然因为大模型的能力太强了它把最难的“理解语义”和“生成内容”都帮你做了剩下的看起来就只是 HTTP 请求。但等你真的接手一个业务需求比如“做一个智能客服”“做一个项目复盘助手”“做一个知识库问答系统”你会发现只调接口远远不够。差距主要体现在下面几个层面我列了一张对照表是我在实战营后期反复用来审视自己代码的清单。能力维度会调用大模型能做 AI 应用对话能力能发 prompt、能收回复能管理多轮上下文、能控制输出格式、能处理流式输出稳定性网络好时能跑通网络超时、限流、模型异常时系统不会崩业务贴合模型说什么是什么能强制模型输出 JSON、能校验字段、能自动重试数据接入只用模型自带知识能接企业数据库、文档库做 RAG 检索增强工具使用只靠模型“想”能用 Function Calling 让模型调用外部工具真正“动手”可维护性能跑就行有日志、有监控、有评估、有版本回退机制成本意识每次调用全量请求会做缓存、会控 token、会简化 prompt、会选择合适的模型规格安全合规直接透传用户输入有敏感词过滤、有脱敏、有权限控制、不触碰违规内容可以看到“会调用”是很多能力切片里的第一行而“能做”是整张表的完整覆盖。我在实战营里最大的转变就是不再把时间花在“换更大的模型”或者“调更华丽的 prompt”上而是老老实实把这张表的每一行在项目里逐个打成勾。举一个特别典型的例子。刚开始我做的“AI 问答助手”就是直接把用户输入拼到 prompt 里发给大模型然后模型吐一段 Markdown我原样显示在页面上。看起来没问题对吧直到产品经理说用户如果问“你就是一个模型你的训练数据到什么时候”系统要能优雅地回答用户如果连续问十轮系统要能记住前面几轮的关键信息用户如果传来的是一段乱码或者恶意注入内容系统不能把这段内容原样透传给模型——因为那可能消耗巨额 token还可能触发不可控的回复。这些需求没有一个是“换个大模型”能解决全得靠应用层的工程手段去兜底。2. 实战营里 Java 技术栈的真实定位听懂了一个必然趋势代码量翻倍学 Java AI 实战营之前我有一个至今都在被问的问题AI 应用开发不是应该用 Python 吗Java 来凑什么热闹实战营给了我一个很有说服力的回答AI 应用不是只有模型训练和模型服务一个完整的 AI 应用必然包含业务系统、数据系统、交互系统而这些恰恰是 Java 的主场。你去看真实的企业级 AI 项目底层调大模型的服务可能用 Python 写的但上层承接用户请求、做权限校验、扣费计费、订单管理、工单流转、数据落库的应用服务绝大多数还是 Java。特别是那些已经运行了多年的老系统不可能因为要接入 AI 就把整个后端重写成 Python。更务实的路线是用 Java 写一个 AI 网关层把大模型的能力封装成企业内部服务让既有业务通过 HTTP 或者 RPC 调用这个网关。实战营里我们做的项目本质上就是这个路线。我所在的组做了一个“智能知识库问答助手”整体架构分了三层接入层Spring Boot 提供 REST API对接前端页面和企微机器人。AI 编排层负责会话管理、prompt 组装、上下文裁剪、RAG 检索触发、函数调用分发。模型接入层统一封装各家大模型 API配置化切换模型处理鉴权和重试。这个分层让我意识到Java 在 AI 应用里不是打杂的而是承担了“管好业务流和状态”的核心角色。模型再好也得这些 Java 代码把它组织成一个可以被业务理解、被测试覆盖、被运维监控的稳定服务。另外一个 Java 特有的优势是生态成熟度。我们做 RAG 时用了 Spring AI 里的向量存储抽象替换底层向量数据库只需要改配置做函数调用时用 Jackson 轻松把结构化参数映射到 Java 对象做异步流式响应时用 WebFlux 让 token 逐字推送到前端。这些如果换成其他语言我当然不敢说一定做不出来但 Java 生态确实让你少踩很多轮子。实战营里还有个很小的细节让我印象深刻排查一个问题时只要在 Java 里加上详细的日志链路追踪比如把 traceId 贯穿一次完整请求就能快速定位到底是模型返回异常、prompt 构造问题还是下游检索慢了这种可观测性在 AI 场景里极其重要因为模型返回的结果天然具备不确定性如果没有工程手段去观测调试会变成玄学。3. 从“调通接口”到“可用功能”上下文、流式输出和异常兜底是三个绕不开的硬骨头如果说前面一章是讲技术选型的“为什么”这一章就是实打实的“怎么做”。实战营前几节还比较轻松无非是申请 API Key、看文档、跑通一个 Chat Completion。但从第二周开始难度陡增第一道坎就是上下文管理。大模型本质上是“无状态”的你每次调用它它都不知道之前聊过什么。你自己要负责把历史对话拼进 prompt。听起来很简单hmm做个 list把之前的问题和回答都塞进去不就行了天真。这里有两个致命问题token 总量有限、费用随长度增长。用 GPT-4 这种模型时长上下文的成本高得离谱而且超过上下文窗口还会直接报错。所以你需要设计一个上下文窗口策略保留最近的几轮对话、把老对话做摘要压缩、从业务维度只抽取关键信息。我们在实战营里用的是一个很朴素但有效的方案系统 prompt 固定占一小段存放角色设定和业务规则。对话历史放在中间按 token 数动态截断只保留最近的 6 到 8 轮。请求真正发出去之前先本地用“字符数估算 token 数”的方法算一下总量token数 ≈ 中文字符数 × 1.2是我们项目里用的粗略公式超限就触发历史压缩函数把早前对话交给另一个便宜的小模型总结成一段话塞回到上下文里。这个方案不算高深但它是“会调用”和“能用”的第一个分水岭系统不会因为聊太久了突然报错这就是可用。第二道坎是流式响应。用户提问之后如果页面要等 3 秒才弹出一整段回复体验非常糟糕。但如果像 ChatGPT 那样一个字一个字地往外蹦用户会觉得系统“跟我同步思考”心理等待时间大幅缩短。Java 里实现流式响应最顺手的方案是 Spring WebFlux SSEServer-Sent Events。我们当时自定义了一个事件流大模型端用流式接口返回增量 tokenJava 后端拿到一个 token 就立刻推一个data:事件给前端前端用EventSource事件源监听之后实时渲染 Markdown。这个过程中要特别小心线程模型的转换因为 WebFlux 是非阻塞的如果中间插入一个阻塞操作比如某个同步查询数据库整个流式链路就会被卡住。我当时在这上面折腾了大半天才搞清楚问题不是模型慢而是我在流式管线里加了一次同步 Redis 读取。后来改成异步订阅或者提前把信息查好放进上下文立刻流畅了。第三道坎是异常兜底。大模型 API 不像数据库查询那么稳定你会遇到网络超时、限流、内容审核拦截、返回格式不符合预期、甚至模型服务本身挂掉的情况。实战营里我们建了一张异常处理矩阵这个表我建议所有做 AI 应用的人都抄一份异常类型可能原因兜底策略网络超时机房网络波动、代理不稳定重试两次第二次降低请求超时时间不行就走降级回复限流 429触发了 QPS/Tok 配额退避重试并把请求放进本地队列队列排空后重发请求格式错误 400prompt 序列化或参数类型错误校验并打印完整请求体根据错误码提示排查特定的字段模型返回空内容输入触发了安全过滤记录原始输入并给出友好话术返回 JSON 解析失败模型在生成中途截断捕获解析异常保留原始文本并自动触发一次“请只输出JSON”的重试上下文超过窗口历史累积过长自动触发摘要压缩或直接丢弃最老一轮对话这里有一个很重要的认知AI 应用的兜底目标不是“绝对不失败”而是“失败的时候用户看到的是可控的结果而不是一屏报错堆栈”。比如模型超时了系统应该回一句“AI 服务开小差了请稍后再试”同时把这轮用户问题记录下来方便在模型恢复之后离线补答。这种兜底逻辑才是“能做 AI 应用”这个表述里最有分量的部分。4. RAG 和 AgentAI 应用从“能聊天”到“能干活”的实战营地标实战营后半段我们开始接触 RAG检索增强生成和 Agent这也是我理解“能做 AI 应用”的第二次质变。在此之前我的 AI 应用只有一个能力基于模型自身知识回答。但企业里真正有价值的场景比如“请根据我们公司最新的报销制度回答我发票丢失怎么办”模型知识里根本没有胡编乱造就是灾难。RAG 的思路很简单也很优雅把外部知识切块、向量化、存进向量数据库用户提问时先从知识库里检索最相关的片段然后把片段拼进 prompt让模型基于给定材料回答。但跑起来之后我发现效果不好时八成问题不在模型而在检索链路。我们项目的第一版 RAG直接在本地把一个 PDF 按固定长度切割成块塞进向量数据库然后选了一个向量相似度算法做检索。演示时看起来还行但一问到跨章节的问题比如“报销单必须包含哪些附件如果遗失要怎么补办”模型就开始乱编。踩了几次坑之后我总结出一套稍微靠谱的优化顺序切分策略调整固定字符切分会把语义拦腰截断。我们改成按标题、段落边界切分并把小段落合并到上一个较大块保证每个块是一个相对完整的语义单元。这一改效果立竿见影。检索不只是向量相似度纯向量检索对同义词、指代词、数字敏感度不够。后来我们加了关键词检索BM25做“混合检索”再用一个简单的“重排”逻辑把向量相似度和关键词得分加权融合。又是肉眼可见的提升。引用溯源要求模型回复时在每条结论后面标注引用的文档片段 ID并且应用层只允许模型引用检索到的那几段内容。这样就算答错了用户也能点开对照原文大大降低对“AI 幻觉”的不信任感。这一段实操让我彻底明白一个观念大模型是“大脑”但不是“记忆”。RAG 是给大脑外接了一个可以随时翻阅的数据库工程难点全在外接的这条管道的精度上。在 Java 生态里实现这套我们用 Spring AI 的向量存储抽象统一了多个向量数据库的访问用定时任务把知识库变更同步到向量库再用一个普通的 Service 把检索结果组装成 prompt 片段。坦白讲这套流程如果用脚本语言写会更快但一旦涉及权限控制、增量更新、多租户知识隔离Java 的工程性优势又体现出来了——知识库也是数据是数据就应该有严格的生命周期管理。然后是 Agent这是实战营里听起来最炫、做起来最掉头发的部分。Agent 的本质是让模型自己决定调用什么工具、按什么顺序完成一个任务。比如我做一个“项目复盘助手”它可以自己决定先查项目管理系统的数据、再统计 Git 提交记录、最后生成一份复盘报告。Java 里实现这个最重要的不是调用模型的代码而是给模型准备“合格的工具”以及处理工具调用的循环逻辑。我们的做法是定义一组“函数”每个函数是一个 Java 方法声明好名称、描述、入参 JSON Schema。比如searchProjectIssues(projectId, keyword)。请求模型时在请求体里带上这些函数定义Function Calling 机制。模型在回答时如果觉得需要查询数据不会直接给最终话术而是返回一个tool_calls指令里面包含函数名和参数。Java 后端解析这个指令路由到对应的 Java 方法执行把执行结果作为一条tool角色消息追加到对话再发回给模型。重复以上循环直到模型觉得信息足够了、给出最终回答。这套循环写起来不算复杂真正复杂的是给模型设置“边界”。我们遇到过一个经典事故模型在使用createReport工具生成复盘报告时因为参数漏传了projectName它就自动把多个项目的名字拼接在一起填进去结果生成了一份用户没法用的报告。后来我们在工具定义里给敏感参数加了“必填约束”和“取值枚举”并且在执行工具前做了一层参数校验不合格直接返回错误给模型让它重试。人不能让 Agent 完全自由发挥而是要给它一条“栅栏跑马场”在边界内充分发挥。这是我在 Agent 实战里最深的体会。5. AI 应用要上线测试、监控、成本、安全一个都不能省实战营最后一周的内容也是最验收交付感的一周——把所有功能部署上线。这时候我发现“能跑”和“能上线”之间又是一条巨大的沟。很多 AI 项目死不是死在模型能力不够而是死在没有一套针对不确定性的工程保障机制。这里我分享实战营里最值得反复琢磨的四个方向。5.1 测试给模型表现建立基准传统功能测试可以断言“输入 A 一定得到 B”但大模型不是确定性系统同一个 prompt 换一次调用可能给你两个回答。所以我们建立了一个“评估集”机制准备 30 到 50 条代表性的问题每一条都写好“期望回答包含哪些要点”。发布前批量跑一遍用规则关键词命中、语义相似度自动打分再人工抽检。只要平均分不低于上一版本就认为模型调用链路的变更没有造成业务级回退。AI 应用开发没有“零回归”的概念只能追求“不劣于基线”。这个评估集之后可以逐步扩大变成一个团队内部的模型效果测评资产。5.2 监控做 AI 应用必须分三层看日志普通后端监控看的是 QPS、错误率、时延AI 应用额外要看的更多。第一层是模型调用层哪些模型、耗时多久、token 消耗多少、限流了几次第二层是 Prompt 层每次请求最后的实际 prompt 长什么样、命中哪些上下文片段、检索召回率如何第三层是业务层最终回复里有没有被安全策略拦截、用户对什么类型的问题不满意可以做一个“回答是否有用”的点赞点踩按钮。这层监控最大的价值是让你敢做优化——知道哪里贵、哪里慢、哪里被拒才敢动刀改 prompt 或者换模型。我们在项目里给每个 response 都打印了 token 使用量上线一周后统计发现 60% 的花费来自超长上下文拼入的“历史摘要”于是我们优化了摘要策略费用直接降了一半。5.3 成本AI 应用是“每一句话都值钱”的架构调用大模型是按 token 付费的这决定了 AI 应用架构和普通应用有根本区别你没法无限地“穷举”。我们成本控制三板斧是缓存高频问题的答复相似问题直接命中本地缓存、小模型优先简单分类、摘要任务用便宜的小模型复杂推理才用强模型、限制单轮最长输入超出部分先丢给一个小模型做关键信息抽取再送大模型。此外还做了一个很务实地决定非核心流程里模型只负责输出结构化 JSON展示层自己决定文案而不是让模型连排版带话术一起生成这能省下一大截 token。5.4 安全给 AI 应用装上护栏AI 应用的安全防线和普通应用完全不是一个打法。普通应用做好权限控制就够了AI 应用还要额外考虑用户注入的数据是否会被模型当成指令执行prompt injection、回答生成是否可能泄露公司机密、用户恶意提交超长文本导致巨额扣费、模型本身生成内容是否合规。我们上线前的三个硬性要求一是所有用户输入先经过长度限制和敏感词过滤再进入系统二是系统 prompt 里明确要求模型“只依据给到的资料回答不要推测未提及的信息”三是不论用户身份统一不允许模型直接读取原始知识库路径和系统提示词。说白了AI 应用的安全核心是模型可以强但应用必须给模型划定活动范围并且不能由用户来改写这个范围。这几招做完我们的 AI 应用才算真正从“演示版”变成了“能用版”。我不敢说它是业界最佳但至少它上线之后没有半夜被用户骂醒也经住了运营一周的流量和对话测试。写在最后Java AI 这条路值得走但要用“工程思维”走实战营结束那天有个同学问老师“后面我是不是只用理解 prompt 就能做 AI 应用了”老师反问了一句“你现在已经在用 Java 写完整项目了你觉得 prompt 能替代你写的那些上下文裁剪、异常兜底、权限隔离的代码吗”全场安静了一下。回到标题那句话“会调用大模型”和“能做 AI 应用”之间差的正是这些不可替代的工程代码。大模型把“智能”的门槛拉低了但应用层的复杂度并没有消失而是从“让模型想出来”转移到了“让工程收敛住”。你可以在任何语言里做 AI 应用但如果你的工作场景是企业级业务系统Java 一定是一个极其可靠的选择——它有足够成熟的生态去承载 AI 应用需要的稳定性、可维护性和安全性。我学完实战营后最核心的行动计划也很简单持续把手里几个不起眼的业务场景比如客服工单助手、知识库检索工具逐步 AI 化不强上大模型只在有确定收益的地方引入 AI。这条路走得很踏实。最后分享一个从实战营带出来的习惯每次写一段 AI 相关代码之前先问自己一句“如果模型这次回复完全不按我预期来我的系统会不会还是一套让人用着不难受的系统”如果答案是不确定那就先别写调用代码先把兜底逻辑补齐。这就是我对“能做 AI 应用”最朴素的理解。