不用学算法也能玩转 AI?普通 Java 程序员转 AI 应用开发路线

摘要:Java 程序员转向 AI,不等于从头去卷模型训练,也不等于只会调用一个聊天接口。真正适合大多数后端开发者的方向,是 AI 应用工程:把模型接进业务系统,用 RAG 连接私有知识,用 Tool Calling 执行确定性能力,再用权限、评估、观测和成本控制把 Demo 变成产品。本文给出一条 12 周可执行路线,包含技术地图、Spring AI 代码、RAG 与工具调用示例、项目设计、踩坑复盘和求职作品集建议。

开场:我也被"要不要先学高数"劝退过

很多 Java 程序员第一次认真看 AI,搜索结果通常会把人带到两个极端。

一个极端是算法路线:线性代数、概率论、反向传播、Transformer、分布式训练、CUDA。课程表一打开,像要重新读一遍大学。

另一个极端是"零代码 AI":拖几个节点、写一段提示词,半小时搭出聊天机器人。演示确实能跑,但当你想接公司的用户体系、权限、订单、知识库和审计日志时,很快又会发现只拖节点不够。

我后来才把这件事想明白:AI 行业不是只有模型算法工程师,也需要大量 AI 应用工程师。

算法工程师关注模型怎么训练、怎么微调、怎么优化推理;AI 应用工程师关注模型如何可靠地进入真实业务。两者有交集,但起点、日常工作和评价标准不同。

对于已经做过 Java 后端的人,最现实的转型不是清空技能树,而是在原来的工程能力上增加一层"模型能力":

text 复制代码
已有能力:Java + Spring Boot + MySQL + Redis + MQ + Docker
新增能力:Prompt + 模型 API + RAG + Tool Calling + Agent + 评估
工程补强:权限 + 观测 + 成本 + 安全 + 人工兜底

所以本文标题里的答案是:

不做算法研究,也能进入 AI 应用开发;但"不学算法"不等于"不懂原理",更不等于只会复制 API 示例。

一、先分清三条路线,别用错别人的学习清单

路线 主要工作 常见核心能力 Java 后端转型难度
模型/算法工程 训练、微调、评测、推理优化 Python、PyTorch、数学、GPU、论文 较高,需要系统补课
AI 平台工程 模型网关、资源调度、推理服务、数据平台 云原生、分布式、GPU、可观测性 中等,后端经验可迁移
AI 应用工程 RAG、Agent、工作流、业务集成、评估 后端、模型 API、检索、工具、产品思维 最适合多数 Java 开发者

这三条路线没有高低之分。问题只在于你的目标是什么。

如果你真的喜欢读论文、训练模型、研究损失函数,那应该走算法路线,数学不能绕开。如果你更擅长理解业务、设计接口、处理并发和数据一致性,那么 AI 应用工程更能复用已有优势。

现实项目里,一个企业知识助手要解决的问题往往是:

  • 用户能查哪些文档;
  • 文档更新后如何重建索引;
  • 回答必须引用哪一版制度;
  • 模型超时后如何降级;
  • 一次问答花了多少 Token;
  • 哪些答案需要人工确认;
  • 用户反馈如何进入评估集;
  • 服务如何接入已有 SSO、审计和监控。

这些问题没有一道要求你手推梯度,但每一道都需要工程判断。

二、Java 程序员已有的能力,比想象中更值钱

转型时最容易产生的错觉是:"Python 才是 AI,Java 经验没用了。"

如果目标是训练模型,Python 生态确实更主流;但在企业应用层,Java 的价值非常直接。

你已有的 Java 能力 在 AI 应用中的对应位置
Spring Boot 接口开发 模型网关、问答 API、管理后台
MySQL / PostgreSQL 会话、反馈、文档元数据、评估结果
Redis 会话缓存、限流、幂等、短期记忆
MQ / 异步任务 文档解析、Embedding、批量评测
权限模型 知识库隔离、工具调用授权
日志与链路追踪 模型调用、检索、工具执行的 Trace
Docker / CI/CD Dify、向量库、观测平台部署
领域建模 把模糊的"智能助手"拆成稳定业务能力

真正需要补的是模型这一层的特殊性:

  1. 输出具有概率性,同样输入不一定逐字相同;
  2. 上下文有长度和成本,不能无限塞资料;
  3. 模型会生成看似合理但没有证据的内容;
  4. 工具调用是"模型提出意图,系统执行动作",权限不能交给模型决定;
  5. 效果不能只靠"我试了一下挺好",需要评估集。

这些差异决定了 AI 应用不是普通 CRUD 加一个接口,但它仍然是工程。

三、AI 应用开发的完整技术地图

我把需要学习的内容分成七层:
#mermaid-svg-numiixutvcmELdx6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-numiixutvcmELdx6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-numiixutvcmELdx6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-numiixutvcmELdx6 .error-icon{fill:#552222;}#mermaid-svg-numiixutvcmELdx6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-numiixutvcmELdx6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-numiixutvcmELdx6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-numiixutvcmELdx6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-numiixutvcmELdx6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-numiixutvcmELdx6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-numiixutvcmELdx6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-numiixutvcmELdx6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-numiixutvcmELdx6 .marker.cross{stroke:#333333;}#mermaid-svg-numiixutvcmELdx6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-numiixutvcmELdx6 p{margin:0;}#mermaid-svg-numiixutvcmELdx6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-numiixutvcmELdx6 .cluster-label text{fill:#333;}#mermaid-svg-numiixutvcmELdx6 .cluster-label span{color:#333;}#mermaid-svg-numiixutvcmELdx6 .cluster-label span p{background-color:transparent;}#mermaid-svg-numiixutvcmELdx6 .label text,#mermaid-svg-numiixutvcmELdx6 span{fill:#333;color:#333;}#mermaid-svg-numiixutvcmELdx6 .node rect,#mermaid-svg-numiixutvcmELdx6 .node circle,#mermaid-svg-numiixutvcmELdx6 .node ellipse,#mermaid-svg-numiixutvcmELdx6 .node polygon,#mermaid-svg-numiixutvcmELdx6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-numiixutvcmELdx6 .rough-node .label text,#mermaid-svg-numiixutvcmELdx6 .node .label text,#mermaid-svg-numiixutvcmELdx6 .image-shape .label,#mermaid-svg-numiixutvcmELdx6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-numiixutvcmELdx6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-numiixutvcmELdx6 .rough-node .label,#mermaid-svg-numiixutvcmELdx6 .node .label,#mermaid-svg-numiixutvcmELdx6 .image-shape .label,#mermaid-svg-numiixutvcmELdx6 .icon-shape .label{text-align:center;}#mermaid-svg-numiixutvcmELdx6 .node.clickable{cursor:pointer;}#mermaid-svg-numiixutvcmELdx6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-numiixutvcmELdx6 .arrowheadPath{fill:#333333;}#mermaid-svg-numiixutvcmELdx6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-numiixutvcmELdx6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-numiixutvcmELdx6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-numiixutvcmELdx6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-numiixutvcmELdx6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-numiixutvcmELdx6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-numiixutvcmELdx6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-numiixutvcmELdx6 .cluster text{fill:#333;}#mermaid-svg-numiixutvcmELdx6 .cluster span{color:#333;}#mermaid-svg-numiixutvcmELdx6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-numiixutvcmELdx6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-numiixutvcmELdx6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-numiixutvcmELdx6 .icon-shape,#mermaid-svg-numiixutvcmELdx6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-numiixutvcmELdx6 .icon-shape p,#mermaid-svg-numiixutvcmELdx6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-numiixutvcmELdx6 .icon-shape .label rect,#mermaid-svg-numiixutvcmELdx6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-numiixutvcmELdx6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-numiixutvcmELdx6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-numiixutvcmELdx6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 业务与产品层

场景、用户、指标、风险
应用编排层

Prompt、Workflow、Agent
上下文层

会话、RAG、记忆、权限
模型接入层

Chat、Embedding、多模态
工具与数据层

API、数据库、搜索、MCP
工程治理层

评估、观测、成本、安全
基础设施层

Docker、向量库、模型网关

很多教程从第四层"调用模型"开始,到模型返回一句话就结束。真正的项目难点集中在第三层和第六层:给模型什么上下文,以及如何证明结果可用。

1. 模型基础:懂输入输出,不急着研究训练

入门阶段至少要理解这些词:

  • Token:模型处理文本的基本单位,直接影响上下文和成本;
  • Context Window:一次请求能携带的信息上限;
  • Temperature:影响输出随机性,但不是"准确率旋钮";
  • System/User/Assistant Message:对话中不同来源的消息;
  • Structured Output:让结果遵守 JSON Schema 或对象结构;
  • Embedding:把文本映射成向量,用于相似度检索;
  • Tool Calling:模型生成结构化工具调用意图,由程序执行;
  • RAG:先检索外部资料,再基于资料生成回答。

你不需要第一周推导注意力公式,但需要知道模型为什么会"说得像真的"、为什么把整本手册塞进 Prompt 不是好方案。

2. 应用框架:Spring AI 与 LangChain4j 二选一先学

Spring AI 提供 ChatClient、模型接口、向量库、Tool Calling、Advisor 和可观测能力,使用方式比较贴近 Spring 开发者。LangChain4j 也为 Java 提供统一模型 API、AI Services、RAG、Chat Memory 和 Tools。

初学者不必同时精通两个框架。选一个做完项目,再比较抽象差异。框架只是脚手架,重点仍是请求、上下文、检索、工具和评估。

3. 低代码平台:Dify 用来提速,不用来替代工程判断

Dify 很适合快速验证:

  • 提示词和变量是否够用;
  • 工作流应该分几步;
  • 哪种模型适合任务;
  • 知识库检索效果如何;
  • 产品界面是否有人愿意用。

但上线后仍要考虑账号、权限、数据源、版本、备份和监控。我的建议是:用 Dify 验证流程,用 Java 承接稳定业务边界。

四、第一段可运行代码:用 Spring AI 做一个最小问答接口

下面示例刻意保持简单,具体模型 Provider、版本和密钥配置以所选服务的官方文档为准。依赖版本建议由项目 BOM 统一管理,不要从旧博客复制一个固定版本。

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>

配置密钥时使用环境变量:

yaml 复制代码
spring:
  ai:
    openai:
      api-key: ${AI_API_KEY}

不要把真实密钥写进 application.yml 再提交到 Git。

Controller 可以写成:

java 复制代码
@RestController
@RequestMapping("/api/ai")
class AiChatController {

    private final ChatClient chatClient;

    AiChatController(ChatClient.Builder builder) {
        this.chatClient = builder
                .defaultSystem("""
                        你是 Java 技术助手。
                        不确定时必须明确说明,不要编造类名、版本和 API。
                        给出代码时同时说明验证方式。
                        """)
                .build();
    }

    @GetMapping("/explain")
    Map<String, String> explain(@RequestParam String question) {
        String answer = chatClient.prompt()
                .user(question)
                .call()
                .content();

        return Map.of("answer", answer);
    }
}

这段代码能让你理解最基本的调用链:

text 复制代码
HTTP 请求 -> 业务服务 -> ChatClient -> 模型 Provider -> 文本结果

但它离生产还很远。至少还缺:

  • 输入长度限制;
  • 身份认证和速率限制;
  • 超时、重试与熔断;
  • 敏感内容处理;
  • 调用日志与成本统计;
  • 输出校验;
  • 降级方案。

第一周能跑通接口就够了,不要把 Demo 当产品。

五、第二段关键代码:让模型返回对象,而不是一段"差不多的 JSON"

真实业务更需要结构化结果。例如把客服工单分为 BUGCONSULTCOMPLAINT,同时给出优先级和摘要。

java 复制代码
public record TicketResult(
        TicketType type,
        int priority,
        String summary,
        boolean needHumanReview) {
}

public enum TicketType {
    BUG, CONSULT, COMPLAINT, OTHER
}

调用时明确规则:

java 复制代码
TicketResult result = chatClient.prompt()
        .system("""
                你负责工单预分类。
                priority 只能是 1 到 5。
                涉及退款、账号封禁、法律威胁时,
                needHumanReview 必须为 true。
                """)
        .user(ticketContent)
        .call()
        .entity(TicketResult.class);

这里仍然不能省略程序校验:

java 复制代码
void validate(TicketResult result) {
    if (result.priority() < 1 || result.priority() > 5) {
        throw new IllegalArgumentException("invalid priority");
    }
    if (result.summary() == null || result.summary().isBlank()) {
        throw new IllegalArgumentException("summary is required");
    }
}

一个很重要的工程原则是:

模型输出是外部输入,哪怕它长得像 Java 对象,也要按不可信数据处理。

如果分类会直接触发退款、封号或生产变更,模型只能给建议,不能绕过人工或确定性规则。

六、RAG:Java 程序员最值得优先掌握的 AI 场景

RAG 的基本流程并不神秘:
大模型 向量库 Java应用 用户 大模型 向量库 Java应用 用户 #mermaid-svg-pzhLfkqU34GKFGjW{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pzhLfkqU34GKFGjW .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pzhLfkqU34GKFGjW .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pzhLfkqU34GKFGjW .error-icon{fill:#552222;}#mermaid-svg-pzhLfkqU34GKFGjW .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pzhLfkqU34GKFGjW .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pzhLfkqU34GKFGjW .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pzhLfkqU34GKFGjW .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pzhLfkqU34GKFGjW .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pzhLfkqU34GKFGjW .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pzhLfkqU34GKFGjW .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pzhLfkqU34GKFGjW .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pzhLfkqU34GKFGjW .marker.cross{stroke:#333333;}#mermaid-svg-pzhLfkqU34GKFGjW svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pzhLfkqU34GKFGjW p{margin:0;}#mermaid-svg-pzhLfkqU34GKFGjW .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-pzhLfkqU34GKFGjW text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-pzhLfkqU34GKFGjW .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-pzhLfkqU34GKFGjW .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-pzhLfkqU34GKFGjW .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-pzhLfkqU34GKFGjW .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-pzhLfkqU34GKFGjW #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-pzhLfkqU34GKFGjW .sequenceNumber{fill:white;}#mermaid-svg-pzhLfkqU34GKFGjW #sequencenumber{fill:#333;}#mermaid-svg-pzhLfkqU34GKFGjW #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-pzhLfkqU34GKFGjW .messageText{fill:#333;stroke:none;}#mermaid-svg-pzhLfkqU34GKFGjW .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-pzhLfkqU34GKFGjW .labelText,#mermaid-svg-pzhLfkqU34GKFGjW .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-pzhLfkqU34GKFGjW .loopText,#mermaid-svg-pzhLfkqU34GKFGjW .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-pzhLfkqU34GKFGjW .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-pzhLfkqU34GKFGjW .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-pzhLfkqU34GKFGjW .noteText,#mermaid-svg-pzhLfkqU34GKFGjW .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-pzhLfkqU34GKFGjW .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-pzhLfkqU34GKFGjW .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-pzhLfkqU34GKFGjW .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-pzhLfkqU34GKFGjW .actorPopupMenu{position:absolute;}#mermaid-svg-pzhLfkqU34GKFGjW .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-pzhLfkqU34GKFGjW .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-pzhLfkqU34GKFGjW .actor-man circle,#mermaid-svg-pzhLfkqU34GKFGjW line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-pzhLfkqU34GKFGjW :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 提问用问题做相似度检索返回相关文档片段做权限/版本/来源过滤问题 + 证据片段 + 回答规则带引用的答案答案、来源、置信提示

RAG 的难点不是"接一个向量数据库",而是证据治理:

  • 文档是否是当前有效版本;
  • 不同用户是否能看到不同资料;
  • Chunk 是否切断了完整语义;
  • 检索到的是"相关"内容还是"可作为答案依据"的内容;
  • 没找到资料时,系统是否愿意说不知道;
  • 回答里能否展示来源。

以 Spring AI 的思路为例,可以通过 Advisor 把向量检索接入 ChatClient。不同版本的具体 API 可能变化,下面展示的是结构而不是让你机械复制:

java 复制代码
@Service
class PolicyAssistant {

    private final ChatClient chatClient;

    PolicyAssistant(ChatClient.Builder builder, VectorStore vectorStore) {
        this.chatClient = builder
                .defaultAdvisors(QuestionAnswerAdvisor.builder(vectorStore).build())
                .build();
    }

    String answer(String tenantId, String question) {
        return chatClient.prompt()
                .system("""
                        只能依据检索到的制度回答。
                        如果证据不足,回答"当前资料无法确认"。
                        不要把其他租户或过期制度作为依据。
                        """)
                .user(question)
                .advisors(advisor -> advisor.param(
                        "FILTER_EXPRESSION",
                        "tenant_id == '%s' && enabled == true".formatted(tenantId)
                ))
                .call()
                .content();
    }
}

生产代码中,租户过滤不能只写在 Prompt 里。Prompt 是行为提示,不是安全边界。真正的权限必须在检索层和数据层执行。

RAG 入门项目的正确顺序

不要第一天就导入十万份 PDF。更好的顺序是:

  1. 选 20 份结构清晰、你熟悉答案的文档;
  2. 手写 30 个问题和标准证据;
  3. 先测纯关键词检索;
  4. 再加入 Embedding 检索;
  5. 比较不同 Chunk、TopK 和重排;
  6. 记录"没找到""找错版本""答非所问";
  7. 最后才扩大文档量。

没有问题集,你只能凭感觉调 RAG;有了问题集,优化才有方向。

七、Tool Calling:模型负责选择,Java 负责执行

很多人把 Tool Calling 误解成"模型直接调用数据库"。更准确的过程是:

  1. 程序把工具名称、描述和参数结构告诉模型;
  2. 模型根据问题生成调用意图;
  3. Java 程序校验参数和权限;
  4. 程序执行真实方法;
  5. 执行结果返回给模型组织语言。

例如查询物流:

java 复制代码
@Component
class LogisticsTools {

    private final LogisticsService logisticsService;

    LogisticsTools(LogisticsService logisticsService) {
        this.logisticsService = logisticsService;
    }

    @Tool(description = "根据订单号查询物流,只能用于当前登录用户自己的订单")
    LogisticsView queryLogistics(String orderNo) {
        String userId = CurrentUser.requiredUserId();

        if (!logisticsService.belongsTo(orderNo, userId)) {
            throw new AccessDeniedException("order does not belong to current user");
        }

        return logisticsService.query(orderNo);
    }
}

注册工具后,模型可以决定何时请求调用:

java 复制代码
String answer = chatClient.prompt()
        .user("帮我查订单 SO20260725001 到哪里了")
        .tools(logisticsTools)
        .call()
        .content();

注意权限校验写在工具方法里,而不是相信模型会遵守"只能查自己的订单"。模型可能选错工具、填错参数,也可能受到提示注入影响。工具执行层必须像普通 API 一样做认证、授权、参数校验、审计和限流。

对于删除、付款、发消息、改生产配置等动作,还应加入人工确认和幂等机制。

八、Agent:先做固定工作流,再做自主规划

初学者很容易被 Agent 吸引,因为它看起来最像"真正的 AI":自己拆任务、自己调用工具、自己循环。

但越自主,越需要护栏。我的建议是:

text 复制代码
单次问答
  -> 结构化输出
  -> 固定工作流
  -> 带条件分支的工作流
  -> 有限工具调用
  -> 最后才是自主 Agent

如果一个业务流程本来就能明确写成:
#mermaid-svg-j6WkrmWzqKFSKm8x{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-j6WkrmWzqKFSKm8x .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-j6WkrmWzqKFSKm8x .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-j6WkrmWzqKFSKm8x .error-icon{fill:#552222;}#mermaid-svg-j6WkrmWzqKFSKm8x .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-j6WkrmWzqKFSKm8x .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-j6WkrmWzqKFSKm8x .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-j6WkrmWzqKFSKm8x .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-j6WkrmWzqKFSKm8x .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-j6WkrmWzqKFSKm8x .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-j6WkrmWzqKFSKm8x .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-j6WkrmWzqKFSKm8x .marker{fill:#333333;stroke:#333333;}#mermaid-svg-j6WkrmWzqKFSKm8x .marker.cross{stroke:#333333;}#mermaid-svg-j6WkrmWzqKFSKm8x svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-j6WkrmWzqKFSKm8x p{margin:0;}#mermaid-svg-j6WkrmWzqKFSKm8x .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-j6WkrmWzqKFSKm8x .cluster-label text{fill:#333;}#mermaid-svg-j6WkrmWzqKFSKm8x .cluster-label span{color:#333;}#mermaid-svg-j6WkrmWzqKFSKm8x .cluster-label span p{background-color:transparent;}#mermaid-svg-j6WkrmWzqKFSKm8x .label text,#mermaid-svg-j6WkrmWzqKFSKm8x span{fill:#333;color:#333;}#mermaid-svg-j6WkrmWzqKFSKm8x .node rect,#mermaid-svg-j6WkrmWzqKFSKm8x .node circle,#mermaid-svg-j6WkrmWzqKFSKm8x .node ellipse,#mermaid-svg-j6WkrmWzqKFSKm8x .node polygon,#mermaid-svg-j6WkrmWzqKFSKm8x .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-j6WkrmWzqKFSKm8x .rough-node .label text,#mermaid-svg-j6WkrmWzqKFSKm8x .node .label text,#mermaid-svg-j6WkrmWzqKFSKm8x .image-shape .label,#mermaid-svg-j6WkrmWzqKFSKm8x .icon-shape .label{text-anchor:middle;}#mermaid-svg-j6WkrmWzqKFSKm8x .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-j6WkrmWzqKFSKm8x .rough-node .label,#mermaid-svg-j6WkrmWzqKFSKm8x .node .label,#mermaid-svg-j6WkrmWzqKFSKm8x .image-shape .label,#mermaid-svg-j6WkrmWzqKFSKm8x .icon-shape .label{text-align:center;}#mermaid-svg-j6WkrmWzqKFSKm8x .node.clickable{cursor:pointer;}#mermaid-svg-j6WkrmWzqKFSKm8x .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-j6WkrmWzqKFSKm8x .arrowheadPath{fill:#333333;}#mermaid-svg-j6WkrmWzqKFSKm8x .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-j6WkrmWzqKFSKm8x .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-j6WkrmWzqKFSKm8x .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-j6WkrmWzqKFSKm8x .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-j6WkrmWzqKFSKm8x .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-j6WkrmWzqKFSKm8x .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-j6WkrmWzqKFSKm8x .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-j6WkrmWzqKFSKm8x .cluster text{fill:#333;}#mermaid-svg-j6WkrmWzqKFSKm8x .cluster span{color:#333;}#mermaid-svg-j6WkrmWzqKFSKm8x div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-j6WkrmWzqKFSKm8x .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-j6WkrmWzqKFSKm8x rect.text{fill:none;stroke-width:0;}#mermaid-svg-j6WkrmWzqKFSKm8x .icon-shape,#mermaid-svg-j6WkrmWzqKFSKm8x .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-j6WkrmWzqKFSKm8x .icon-shape p,#mermaid-svg-j6WkrmWzqKFSKm8x .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-j6WkrmWzqKFSKm8x .icon-shape .label rect,#mermaid-svg-j6WkrmWzqKFSKm8x .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-j6WkrmWzqKFSKm8x .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-j6WkrmWzqKFSKm8x .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-j6WkrmWzqKFSKm8x :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

读取工单
分类
高风险?
进入人工队列
检索知识库
生成回复草稿
规则校验
人工发送

那就先用固定工作流。固定流程更容易测试、计费、审计和回滚。只有当任务路径确实无法预先枚举,而且模型自主选择工具能带来明显收益时,才考虑 Agent。

Agent 的核心不是"能跑起来",而是:

  • 最大步骤数;
  • 最大 Token 和费用;
  • 可用工具白名单;
  • 每个工具的权限;
  • 失败重试与停止条件;
  • 人工确认点;
  • 全链路 Trace。

九、12 周学习路线:每周必须有产物

下面这条路线按每周 8~12 小时设计。时间不是硬标准,重点是每一阶段都要交付可以演示和验证的东西。

周次 学习重点 必须产出的东西
第 1 周 Token、消息、参数、上下文、幻觉 模型调用命令与错误记录
第 2 周 Prompt、结构化输出、输出校验 工单分类 API
第 3 周 Spring AI 或 LangChain4j 流式聊天后端
第 4 周 会话、限流、超时、重试 带 Redis 会话的聊天服务
第 5 周 Embedding、Chunk、向量检索 20 份文档的小知识库
第 6 周 RAG、引用、过滤、重排 带来源的制度问答
第 7 周 Tool Calling、权限、幂等 只读订单查询助手
第 8 周 Dify Workflow / Chatflow 同一场景的低代码原型
第 9 周 Agent、停止条件、人工确认 有限步骤的工单助手
第 10 周 评估集、准确率、拒答率 50 道题的自动评测报告
第 11 周 Trace、成本、延迟、安全 调用看板和数据脱敏方案
第 12 周 Docker、文档、演示、复盘 可部署作品集项目

第 1~2 周:不要追新模型,先把输入输出搞清楚

目标是能够解释一次请求为什么成功、为什么失败。练习错误处理、超时、限流和结构化输出。把每次失败记录下来,比收藏模型排行榜更有用。

第 3~4 周:把模型接进一个正常的 Java 服务

加入 Controller、Service、配置、异常、测试和日志。你要证明自己做的是服务,不是命令行截图。此时可以补充流式输出,但不要为了"打字机效果"牺牲错误处理。

第 5~6 周:专心做 RAG

学习文档解析、切片、Embedding、向量检索、元数据过滤、TopK、重排和引用。每改一个参数,都用固定问题集比较,而不是凭肉眼感觉。

第 7~9 周:从工具调用到工作流

先做只读工具,再做需要确认的写操作。用 Dify 快速验证节点设计,再把关键权限和业务能力留在 Java 服务中。Agent 必须设置步数和费用上限。

第 10~12 周:补齐"能上线"的能力

学习评估、Trace、Token 统计、错误样本回放、提示注入防护和部署。一个能展示失败案例与改进记录的项目,比只展示成功对话更有说服力。

十、推荐做的三个项目,难度逐级上升

项目 1:Java 项目文档问答助手

资料只选 README、接口文档和部署手册。功能包括:

  • 文档上传与版本;
  • 语义检索;
  • 回答引用;
  • 无证据拒答;
  • 用户反馈;
  • 管理员查看失败问题。

这个项目能覆盖 RAG 基础,同时不会被复杂业务拖垮。

项目 2:售后工单智能分流

输入一条工单,输出分类、优先级、摘要和是否人工处理。之后检索知识库,生成回复草稿。

重点不是生成文案,而是:

  • 结构化输出校验;
  • 高风险规则兜底;
  • 人工审核;
  • 分类混淆矩阵;
  • Prompt 版本对比。

项目 3:企业订单查询 Agent

让用户用自然语言查询订单、物流和退款进度。只开放只读工具,并按登录用户做权限过滤。

项目亮点可以包括:

  • 工具白名单;
  • 参数校验;
  • 操作 Trace;
  • 超时与降级;
  • 多轮上下文;
  • 恶意提示测试。

这三个项目都不需要训练模型,但足够体现 AI 应用工程能力。

十一、最常见的 8 个学习误区

误区 1:先把所有数学补完再开始

没有项目,数学知识很难建立落点。应用开发可以先跑通模型、RAG 和工具调用,再根据问题补相似度、概率和评估知识。

误区 2:只会聊天界面,不会 API

会用聊天产品不等于会开发 AI 应用。至少要理解鉴权、请求、流式响应、错误码、超时、成本和数据策略。

误区 3:框架 API 背得很熟,却说不清 RAG

框架版本会变,流程和权衡更稳定。面试时能解释为什么要切片、过滤、重排和拒答,比背方法名更重要。

误区 4:知识库能回答就算完成

必须测试错误版本、权限隔离、无答案问题和提示注入。只演示命中的问题,无法证明系统可靠。

误区 5:把 Prompt 当全部技术

Prompt 很重要,但真实效果还取决于上下文、检索、工具、模型、数据、评估和产品交互。

误区 6:一上来就做全自动 Agent

固定工作流还没跑稳,就让模型自主循环,问题只会更难定位。先确定性,后自主性。

误区 7:只追求"本地免费"

本地模型减少了部分 API 成本,但增加硬件、运维和效果验证成本。隐私、性能、质量和维护要一起算。

误区 8:作品集只放截图

好的作品集应该有架构图、启动方式、测试集、指标、已知限制和失败复盘。对工程岗位来说,这些比一张聊天截图有价值。

十二、到底需要学多少 Python 和算法

Python:建议会读、会改、会写小脚本

即使主项目用 Java,Python 仍然常用于:

  • 数据清洗;
  • 批量评测;
  • 文档处理;
  • 调模型 SDK;
  • 运行开源示例。

不必先学到 Web 框架和复杂异步,但要能处理 JSON、CSV、HTTP 和基本包管理。

数学:先理解,再按岗位加深

应用工程入门阶段至少理解:

  • 向量和余弦相似度大概表示什么;
  • 精确率、召回率为什么会权衡;
  • 平均值之外为什么还看 P95 延迟;
  • 抽样评估为什么可能有偏差;
  • 随机性为什么影响复现。

如果后续转模型工程,再系统补线性代数、概率统计、微积分和优化。学习顺序应该服务目标,而不是制造入场焦虑。

十三、判断自己是否入门的清单

如果下面问题能独立回答大半,你已经不是"只会调 API":

  • 能否解释模型、Prompt、RAG、Tool Calling、Agent 的边界?
  • 能否让模型稳定返回 Java 对象并做校验?
  • 能否设计一个带引用和拒答的 RAG?
  • 能否在检索层执行租户权限,而不是只写 Prompt?
  • 能否为工具调用加入认证、幂等和人工确认?
  • 能否建立 50 条左右的评估集?
  • 能否记录一次请求的模型、Prompt、检索、工具、耗时和 Token?
  • 能否说明什么时候该用 Dify,什么时候该写 Java?
  • 能否展示三个失败样本以及如何改进?
  • 能否把项目用 Docker 启动并写清部署步骤?

总结:转型不是推倒重来,而是把后端能力向前延伸

普通 Java 程序员转 AI 应用开发,最值得利用的是已经拥有的工程底座。你知道接口要鉴权、数据库要建模、消息要幂等、服务要监控、变更要回滚。这些经验不会因为模型会生成代码而贬值,反而会成为 AI Demo 与真实产品之间的分水岭。

一条务实的路线是:

text 复制代码
模型 API
  -> 结构化输出
  -> Java 服务化
  -> RAG
  -> Tool Calling
  -> 固定工作流
  -> 有限 Agent
  -> 评估、观测、安全和部署

不要等"全部学会"才开始。选一个你熟悉的业务问题,用两周做出第一个能验证的小项目;再用十周把它补成一个有权限、有测试、有指标、有复盘的作品。

AI 应用工程不是算法路线的简化版,而是一条独立的工程路线。真正的门槛从来不是会不会背 Transformer,而是能不能让一个不确定的模型,在确定的业务系统里安全、稳定、可验证地工作。

/guides/knowledge-base/retrieval)

相关推荐
迷茫中的自我1 小时前
KMP全栈开发:从Android到AI Agent的技术演进与实践
android·人工智能
龍德明宇1 小时前
Emu3的「阳谋」:当AI不再「看」图,它还剩下什么?-龍德明宇
人工智能·大语言模型llm·负主体性·ai存在论
糖果店的幽灵1 小时前
WorkBuddy + 好提示词 = 生产力。43 个场景,复制就能用
人工智能·langgraph
硅谷秋水1 小时前
ABot-M0.5:统一的移动-与-操作世界动作模型
人工智能·深度学习·机器学习·计算机视觉·语言模型·机器人
AI大模型-小华1 小时前
Codex 为什么越用越慢?大型项目中的上下文管理与方案选择
人工智能·chatgpt·软件开发·codex·开发效率·chatgpt plus·chatgpt pro
D202020201 小时前
TikTok达人履约乱象?达秘带你拆解供需权力关系错位的本质
大数据·人工智能
Rocky Ding*1 小时前
一文读懂Kimi k1.5大模型核心基础知识
论文阅读·人工智能·深度学习·机器学习·aigc·ai-native·kimi k1.5
我是唐青枫1 小时前
Java Jetty 实战详解:从嵌入式 HTTP 服务到 Spring Boot 容器替换
java
带刺的坐椅1 小时前
当所有人都在用 TS/Python 写 Agent,我们为什么坚持 Java
java·ai·solon·codex·opencode·soloncode