Java 转 AI Agent 开发:Java 和 Python 的区别与快速学习指南

开篇先说结论:如果你已经是 Java 后端开发者,转向 AI Agent 开发并不是"从零学编程",而是把原来熟悉的 Web 服务、接口调用、数据建模、异步处理、日志监控、安全治理,迁移到一个更偏"模型调用 + 工具编排 + 数据检索 + 状态管理"的技术栈里。

Java 更像一套工程化、强约束、适合长期维护的大型系统语言;Python 更像 AI 生态里的"胶水语言",适合快速接入模型、实验算法、调用框架、串联工具和验证 Agent 流程。真正做 AI Agent,不是只会 Python 语法就够了,而是要理解大模型 API、Prompt、结构化输出、Function Calling、RAG、Memory、Tool、Agent Loop、异步流式响应、评测与可观测性这些知识点。

这篇文章面向已经熟悉 Java 的开发者,目标是给你一份从 Java 转 AI Agent 开发的快速学习指南:先讲 Java 和 Python 的核心差异,再用代码对比 AI 应用开发中常见能力的两种实现方式,最后给一条可执行的学习路线。

文章目录

    • [一、Java 和 Python 的定位差异](#一、Java 和 Python 的定位差异)
    • [二、从 Java 思维切换到 Python 思维](#二、从 Java 思维切换到 Python 思维)
      • [1. 类型:从强类型到动态类型](#1. 类型:从强类型到动态类型)
      • [2. 代码组织:从分层架构到轻量模块](#2. 代码组织:从分层架构到轻量模块)
      • [3. 依赖管理:从 Maven/Gradle 到 pip/uv/poetry](#3. 依赖管理:从 Maven/Gradle 到 pip/uv/poetry)
    • [三、AI Agent 开发到底要学哪些知识点](#三、AI Agent 开发到底要学哪些知识点)
    • [四、调用大模型 API:Java 与 Python 对比](#四、调用大模型 API:Java 与 Python 对比)
      • [Java:用 HttpClient 调用 Chat Completions](#Java:用 HttpClient 调用 Chat Completions)
      • [Python:用 OpenAI SDK 调用](#Python:用 OpenAI SDK 调用)
      • [Java 开发者要注意什么](#Java 开发者要注意什么)
    • [五、Prompt 模板:从字符串拼接到可维护模板](#五、Prompt 模板:从字符串拼接到可维护模板)
    • 六、结构化输出:让模型结果能被程序消费
      • [Java:定义 DTO 接收模型输出](#Java:定义 DTO 接收模型输出)
      • [Python:用 Pydantic 校验](#Python:用 Pydantic 校验)
    • [七、Function Calling:Agent 调工具的核心机制](#七、Function Calling:Agent 调工具的核心机制)
    • [八、Agent Loop:从一次问答到多步执行](#八、Agent Loop:从一次问答到多步执行)
    • 九、RAG:让模型回答基于你的知识库
      • [Java:RAG 服务接口思路](#Java:RAG 服务接口思路)
      • [Python:RAG 最小实现](#Python:RAG 最小实现)
    • [十、Memory:Agent 为什么需要记忆](#十、Memory:Agent 为什么需要记忆)
    • 十一、异步、并发与流式输出
      • [Java:CompletableFuture 并发调用](#Java:CompletableFuture 并发调用)
      • [Python:async/await 并发调用](#Python:async/await 并发调用)
    • 十二、流式响应:让用户更快看到结果
      • [Java:Spring WebFlux 返回流](#Java:Spring WebFlux 返回流)
      • [Python:FastAPI StreamingResponse](#Python:FastAPI StreamingResponse)
    • [十三、LangChain、Spring AI、LangChain4j 怎么选](#十三、LangChain、Spring AI、LangChain4j 怎么选)
    • [十四、可观测性:AI 应用必须能排障](#十四、可观测性:AI 应用必须能排障)
      • [Python 日志示例](#Python 日志示例)
    • [十五、安全治理:Agent 比普通接口更需要边界](#十五、安全治理:Agent 比普通接口更需要边界)
      • [Python 工具执行前的安全检查示例](#Python 工具执行前的安全检查示例)
    • [十六、测试与评测:AI 应用不能只靠肉眼试](#十六、测试与评测:AI 应用不能只靠肉眼试)
      • [Python 简单评测示例](#Python 简单评测示例)
    • [十七、Java 转 AI Agent 的推荐学习路线](#十七、Java 转 AI Agent 的推荐学习路线)
      • [阶段 1:Python 工程基础](#阶段 1:Python 工程基础)
      • [阶段 2:大模型 API 与 Prompt](#阶段 2:大模型 API 与 Prompt)
      • [阶段 3:结构化输出与工具调用](#阶段 3:结构化输出与工具调用)
      • [阶段 4:RAG 知识库问答](#阶段 4:RAG 知识库问答)
      • [阶段 5:Agent Loop 与 Memory](#阶段 5:Agent Loop 与 Memory)
      • [阶段 6:生产化工程](#阶段 6:生产化工程)
    • [十八、Java 和 Python 在 AI Agent 项目里的协作架构](#十八、Java 和 Python 在 AI Agent 项目里的协作架构)
    • 十九、常见误区
      • [误区 1:会 Python 就会 AI Agent](#误区 1:会 Python 就会 AI Agent)
      • [误区 2:Prompt 写长一点就稳定](#误区 2:Prompt 写长一点就稳定)
      • [误区 3:RAG 等于向量库](#误区 3:RAG 等于向量库)
      • [误区 4:Agent 可以直接操作所有工具](#误区 4:Agent 可以直接操作所有工具)
      • [误区 5:AI 应用不需要传统工程能力](#误区 5:AI 应用不需要传统工程能力)
    • 二十、总结

Java 与 Python 定位差异:工程底座与 AI 迭代层

一、Java 和 Python 的定位差异

Java 和 Python 都能开发 AI 应用,但它们在 AI Agent 项目里的角色经常不同。

Java 的优势是:

  • 类型系统强,重构安全,适合多人协作的大型工程;
  • Spring Boot、Spring Cloud、网关、鉴权、监控、消息队列生态成熟;
  • JVM 性能稳定,线程模型、连接池、GC、部署体系成熟;
  • 很适合承载企业后端、业务中台、模型网关、权限服务、审计服务。

Python 的优势是:

  • AI/ML 生态最完整,OpenAI SDK、LangChain、LlamaIndex、Transformers、PyTorch、FastAPI 等资料最多;
  • 写法短,适合快速实验 Prompt、Agent Loop、RAG 流程;
  • 数据处理和脚本自动化很方便,适合把模型、向量库、工具 API 串起来;
  • 大量 AI Agent 示例、框架和论文复现默认都是 Python。

一句话概括:

Java 更适合做"稳定的生产底座",Python 更适合做"AI 能力的快速迭代层"。

很多团队最终会采用混合架构:Java 继续承载核心业务服务,Python 负责 Agent 编排、RAG、模型实验和工具调用;等 Python 侧流程稳定后,再把高并发、高治理要求的部分沉淀为 Java 服务。

二、从 Java 思维切换到 Python 思维

Java 开发者学习 Python,最容易卡住的不是语法,而是思维方式。

1. 类型:从强类型到动态类型

Java 里类型通常写得很明确:

java 复制代码
public class ChatRequest {
    private String userId;
    private String message;

    public ChatRequest(String userId, String message) {
        this.userId = userId;
        this.message = message;
    }

    public String getUserId() {
        return userId;
    }

    public String getMessage() {
        return message;
    }
}

Python 可以写得很轻:

python 复制代码
def build_request(user_id: str, message: str) -> dict:
    return {
        "user_id": user_id,
        "message": message,
    }

但在 AI 应用里,我不建议完全放弃类型。因为 Agent 会传递很多结构化数据,比如工具参数、模型响应、检索结果、执行状态。推荐使用 dataclass 或 Pydantic:

python 复制代码
from pydantic import BaseModel, Field

class ChatRequest(BaseModel):
    user_id: str = Field(description="用户 ID")
    message: str = Field(description="用户输入")

Java 的类型约束通常在编译期发现问题;Python 的类型约束更多依赖运行时校验、测试和 IDE 类型提示。

2. 代码组织:从分层架构到轻量模块

Java 后端常见分层:

text 复制代码
controller -> service -> repository -> client -> domain

Python AI 项目也需要分层,但通常更轻:

text 复制代码
app/
  api.py              # FastAPI 入口
  llm.py              # 大模型客户端
  prompts.py          # Prompt 模板
  tools.py            # 工具定义
  rag.py              # 检索增强
  memory.py           # 记忆管理
  agent.py            # Agent 执行循环
  observability.py    # 日志与追踪

不要把 Python 项目写成一堆散落脚本。Agent Demo 可以是脚本,生产 Agent 必须有清晰边界。

3. 依赖管理:从 Maven/Gradle 到 pip/uv/poetry

Java Maven 示例:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Python 常见写法:

bash 复制代码
uv add fastapi uvicorn openai pydantic httpx

requirements.txt

text 复制代码
fastapi
uvicorn
openai
pydantic
httpx

AI Agent 项目建议固定版本,尤其是 LangChain、OpenAI SDK、向量库客户端这类变化快的包。否则今天能跑的链路,过几周可能因为依赖升级出现参数不兼容。

AI Agent 开发知识地图:从 Prompt 到安全评测

三、AI Agent 开发到底要学哪些知识点

从 Java 转 AI Agent,不要只学 Python 语法。建议按下面这张地图补齐能力:

模块 要学什么 为什么重要
Python 基础 类型、函数、类、异常、包管理、虚拟环境 能读懂大多数 AI 示例
HTTP/API REST、鉴权、超时、重试、错误码 大模型和工具基本都靠 API 调用
LLM 调用 messages、temperature、stream、token、模型路由 所有 AI 应用的入口
Prompt System/User、变量填充、模板、少样本示例 决定模型行为边界
结构化输出 JSON Schema、Pydantic、输出解析、重试修复 让模型结果可被程序使用
Function Calling 工具 Schema、参数校验、执行结果回填 Agent 能行动的基础
RAG 文档切分、Embedding、向量库、召回、Rerank 让模型使用企业知识
Memory 短期上下文、长期记忆、偏好、任务状态 支撑多轮协作和长任务
Agent Loop Plan、Act、Observe、Reflect、Stop 让模型从问答变成执行者
异步与流式 SSE、async/await、队列、超时取消 提升交互体验和吞吐
可观测性 trace_id、请求体摘要、响应、耗时、错误码 方便排障和评估效果
安全治理 最小权限、脱敏、人工确认、沙箱、审计 Agent 上生产的前提
评测 黄金集、自动评分、人工复核、回归测试 防止 Prompt 或模型升级导致效果倒退

下面进入代码对比。

四、调用大模型 API:Java 与 Python 对比

AI 应用的第一步通常是调用大模型。

Java:用 HttpClient 调用 Chat Completions

java 复制代码
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class LlmClient {
    private final HttpClient httpClient = HttpClient.newHttpClient();
    private final String apiKey;

    public LlmClient(String apiKey) {
        this.apiKey = apiKey;
    }

    public String chat(String userMessage) throws Exception {
        String body = """
        {
          "model": "gpt-4o-mini",
          "messages": [
            {"role": "system", "content": "你是一个客服工单助手,只输出简洁建议。"},
            {"role": "user", "content": "%s"}
          ],
          "temperature": 0.2
        }
        """.formatted(userMessage.replace("\"", "\\\""));

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://api.openai.com/v1/chat/completions"))
                .header("Authorization", "Bearer " + apiKey)
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(body))
                .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() >= 400) {
            throw new RuntimeException("LLM API error: " + response.statusCode() + ", body=" + response.body());
        }
        return response.body();
    }
}

Java 原生 HTTP 写法比较啰嗦,但你可以清楚控制超时、重试、日志、异常和连接池。

Python:用 OpenAI SDK 调用

python 复制代码
from openai import OpenAI

client = OpenAI()

def chat(user_message: str) -> str:
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "你是一个客服工单助手,只输出简洁建议。"},
            {"role": "user", "content": user_message},
        ],
        temperature=0.2,
    )
    return response.choices[0].message.content

Python 版本短很多,适合快速实验。你可以把更多精力放在 Prompt、输出结构、工具设计和业务逻辑上。

Java 开发者要注意什么

不要因为 Python 示例短,就忽略工程问题。真实项目里仍然要封装:

  • API Key 读取与隔离;
  • 超时设置;
  • 429 限流处理;
  • 5xx 重试;
  • 请求体摘要日志;
  • 响应脱敏;
  • trace_id 贯穿;
  • 模型和供应商可配置。

五、Prompt 模板:从字符串拼接到可维护模板

Java 开发者常习惯把 Prompt 当字符串拼接:

java 复制代码
public class PromptBuilder {
    public String buildTicketPrompt(String ticketText) {
        return """
        你是一个售后工单助手。
        请判断下面工单的优先级,并给出处理建议。

        工单内容:
        %s
        """.formatted(ticketText);
    }
}

Python 也可以这样写:

python 复制代码
def build_ticket_prompt(ticket_text: str) -> str:
    return f"""
你是一个售后工单助手。
请判断下面工单的优先级,并给出处理建议。

工单内容:
{ticket_text}
""".strip()

但 Agent 项目里,Prompt 最好像代码一样管理:

python 复制代码
from string import Template

TICKET_PROMPT = Template("""
你是一个售后工单助手。

你的任务:
1. 判断工单优先级:P0/P1/P2/P3
2. 给出处理建议
3. 说明是否需要人工介入

约束:
- 不要编造订单状态
- 如果信息不足,输出需要补充的信息
- 输出 JSON

工单内容:
$ticket_text
""")

def build_ticket_prompt(ticket_text: str) -> str:
    return TICKET_PROMPT.substitute(ticket_text=ticket_text)

Prompt 管理的关键不是"写得像文学作品",而是要可版本化、可测试、可回滚。

六、结构化输出:让模型结果能被程序消费

AI Agent 不能只返回一段自然语言。很多时候你需要模型输出结构化结果,比如工单优先级、下一步动作、工具参数。

Java:定义 DTO 接收模型输出

java 复制代码
public record TicketAnalysis(
        String priority,
        boolean needHumanReview,
        String reason,
        String suggestedAction
) {}

你可以用 Jackson 解析 JSON:

java 复制代码
import com.fasterxml.jackson.databind.ObjectMapper;

public class OutputParser {
    private final ObjectMapper mapper = new ObjectMapper();

    public TicketAnalysis parse(String json) throws Exception {
        return mapper.readValue(json, TicketAnalysis.class);
    }
}

Python:用 Pydantic 校验

python 复制代码
from pydantic import BaseModel, Field

class TicketAnalysis(BaseModel):
    priority: str = Field(description="P0/P1/P2/P3")
    need_human_review: bool
    reason: str
    suggested_action: str

raw = """
{
  "priority": "P1",
  "need_human_review": true,
  "reason": "用户涉及退款争议,需要人工确认订单状态",
  "suggested_action": "查询订单和支付状态后转人工复核"
}
"""

analysis = TicketAnalysis.model_validate_json(raw)
print(analysis.priority)

Python 的 Pydantic 在 AI 应用里非常常用,因为它可以同时承担:

  • 参数 Schema;
  • 输出校验;
  • 类型提示;
  • 错误信息;
  • JSON 序列化。

模型输出不是天然可靠的。结构化输出一定要配合校验、失败重试和兜底策略。

七、Function Calling:Agent 调工具的核心机制

Function Calling 的本质是:把可调用的业务能力描述给模型,让模型决定是否调用、用什么参数调用,然后程序执行工具,再把结果交回模型。

假设我们有一个"查询订单状态"的工具。

Java:工具接口设计

java 复制代码
public interface Tool<I, O> {
    String name();
    String description();
    O execute(I input);
}

public record QueryOrderInput(String orderId) {}
public record QueryOrderOutput(String orderId, String status, boolean refundable) {}

public class QueryOrderTool implements Tool<QueryOrderInput, QueryOrderOutput> {
    @Override
    public String name() {
        return "query_order";
    }

    @Override
    public String description() {
        return "根据订单 ID 查询订单状态和是否可退款";
    }

    @Override
    public QueryOrderOutput execute(QueryOrderInput input) {
        // 实际项目中这里调用订单系统
        return new QueryOrderOutput(input.orderId(), "PAID", true);
    }
}

Python:函数就是天然工具

python 复制代码
from pydantic import BaseModel

class QueryOrderInput(BaseModel):
    order_id: str

class QueryOrderOutput(BaseModel):
    order_id: str
    status: str
    refundable: bool


def query_order(params: QueryOrderInput) -> QueryOrderOutput:
    # 实际项目中这里调用订单系统
    return QueryOrderOutput(
        order_id=params.order_id,
        status="PAID",
        refundable=True,
    )

Python 的优势是定义轻,函数、类型和 Schema 可以快速组合。Java 的优势是接口边界清晰,适合复杂工具系统、权限检查、审计和长期维护。

工具 Schema 示例

Function Calling 通常需要把工具描述成 JSON Schema:

python 复制代码
query_order_schema = {
    "type": "function",
    "function": {
        "name": "query_order",
        "description": "根据订单 ID 查询订单状态和是否可退款",
        "parameters": {
            "type": "object",
            "properties": {
                "order_id": {
                    "type": "string",
                    "description": "订单 ID"
                }
            },
            "required": ["order_id"]
        }
    }
}

工具设计时要记住三点:

  1. 工具描述要清楚,否则模型不知道什么时候调用;
  2. 参数要严格校验,否则会出现空参数、错字段、幻觉字段;
  3. 高风险工具必须有人审或权限控制,比如退款、删除、发消息、改配置。

八、Agent Loop:从一次问答到多步执行

传统聊天应用通常是"一问一答"。Agent 的核心是多步循环:

text 复制代码
用户目标 -> 模型规划 -> 调用工具 -> 观察结果 -> 判断是否继续 -> 输出结果

Java:状态机思路

Java 更适合把 Agent Loop 显式建模成状态机:

java 复制代码
public enum AgentStepType {
    PLAN,
    ACT,
    OBSERVE,
    FINISH
}

public record AgentStep(
        AgentStepType type,
        String content
) {}

public class AgentRunner {
    private static final int MAX_STEPS = 5;

    public String run(String userGoal) {
        String context = userGoal;

        for (int i = 0; i < MAX_STEPS; i++) {
            AgentStep step = planNextStep(context);

            if (step.type() == AgentStepType.FINISH) {
                return step.content();
            }

            if (step.type() == AgentStepType.ACT) {
                String toolResult = executeTool(step.content());
                context += "\n工具结果:" + toolResult;
            }
        }

        return "任务未在最大步数内完成,建议转人工处理。";
    }

    private AgentStep planNextStep(String context) {
        // 实际项目中这里调用 LLM
        return new AgentStep(AgentStepType.FINISH, "已完成分析");
    }

    private String executeTool(String toolCall) {
        return "工具执行结果";
    }
}

Python:快速实现 ReAct 循环

python 复制代码
MAX_STEPS = 5


def run_agent(user_goal: str) -> str:
    context = [
        {"role": "user", "content": user_goal}
    ]

    for step in range(MAX_STEPS):
        decision = call_llm_for_next_action(context)

        if decision["type"] == "finish":
            return decision["answer"]

        if decision["type"] == "tool_call":
            tool_name = decision["tool_name"]
            tool_args = decision["arguments"]
            observation = execute_tool(tool_name, tool_args)
            context.append({
                "role": "tool",
                "content": observation,
            })

    return "任务达到最大执行步数,建议转人工处理。"


def call_llm_for_next_action(context: list[dict]) -> dict:
    # 实际项目中这里调用大模型,并解析结构化输出
    return {"type": "finish", "answer": "已完成分析"}


def execute_tool(tool_name: str, arguments: dict) -> str:
    # 根据 tool_name 路由到具体工具函数
    return "工具执行结果"

Agent Loop 必须有停止条件。没有最大步数、最大耗时、最大工具调用次数的 Agent,很容易在异常场景里无限循环或不断烧 token。

九、RAG:让模型回答基于你的知识库

RAG(Retrieval-Augmented Generation)是 AI 应用开发绕不开的能力。它解决的问题是:模型不知道你的企业文档、订单规则、产品说明、内部 SOP,那就先检索相关知识,再把知识放进上下文让模型回答。

Java:RAG 服务接口思路

java 复制代码
public record DocumentChunk(String id, String text, double score) {}

public interface VectorStore {
    List<DocumentChunk> similaritySearch(String query, int topK);
}

public class RagService {
    private final VectorStore vectorStore;
    private final LlmClient llmClient;

    public RagService(VectorStore vectorStore, LlmClient llmClient) {
        this.vectorStore = vectorStore;
        this.llmClient = llmClient;
    }

    public String answer(String question) throws Exception {
        List<DocumentChunk> chunks = vectorStore.similaritySearch(question, 5);
        String context = chunks.stream()
                .map(DocumentChunk::text)
                .reduce("", (a, b) -> a + "\n---\n" + b);

        String prompt = """
        请只根据下面资料回答问题。如果资料不足,请说不知道。

        资料:
        %s

        问题:
        %s
        """.formatted(context, question);

        return llmClient.chat(prompt);
    }
}

Python:RAG 最小实现

python 复制代码
from dataclasses import dataclass

@dataclass
class DocumentChunk:
    id: str
    text: str
    score: float


def similarity_search(query: str, top_k: int = 5) -> list[DocumentChunk]:
    # 实际项目中这里调用向量库,如 Milvus、Qdrant、pgvector、Elasticsearch
    return [
        DocumentChunk("doc-1", "退款规则:已支付未发货订单可申请退款。", 0.91),
        DocumentChunk("doc-2", "高风险退款需要人工复核。", 0.86),
    ]


def rag_answer(question: str) -> str:
    chunks = similarity_search(question, top_k=5)
    context = "\n---\n".join(chunk.text for chunk in chunks)

    prompt = f"""
请只根据下面资料回答问题。如果资料不足,请说不知道。

资料:
{context}

问题:
{question}
""".strip()

    return chat(prompt)

RAG 不是"向量库一接就完事"。真正影响效果的是:

  • 文档切分粒度;
  • metadata 设计;
  • query 改写;
  • 混合检索;
  • rerank;
  • 上下文压缩;
  • 引用来源;
  • 召回失败兜底;
  • 权限过滤。

Java 后端开发者可以把 RAG 理解成一个"搜索系统 + LLM 总结器"。搜索质量决定上限,Prompt 只是在已有资料上做组织和表达。

十、Memory:Agent 为什么需要记忆

Memory 和 RAG 不完全一样。

RAG 通常检索外部知识,比如产品文档、制度、接口说明。Memory 更像 Agent 与用户或任务过程相关的状态,例如:

  • 当前任务目标;
  • 用户偏好;
  • 已完成步骤;
  • 已调用工具结果;
  • 上一次失败原因;
  • 长期协作规则。

Java:任务状态对象

java 复制代码
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;

public class AgentMemory {
    private String userId;
    private String currentGoal;
    private List<String> observations = new ArrayList<>();
    private Instant updatedAt = Instant.now();

    public void addObservation(String observation) {
        observations.add(observation);
        updatedAt = Instant.now();
    }

    public List<String> recentObservations(int limit) {
        int from = Math.max(0, observations.size() - limit);
        return observations.subList(from, observations.size());
    }
}

Python:轻量记忆实现

python 复制代码
from dataclasses import dataclass, field
from datetime import datetime

@dataclass
class AgentMemory:
    user_id: str
    current_goal: str
    observations: list[str] = field(default_factory=list)
    updated_at: datetime = field(default_factory=datetime.utcnow)

    def add_observation(self, observation: str) -> None:
        self.observations.append(observation)
        self.updated_at = datetime.utcnow()

    def recent_observations(self, limit: int = 5) -> list[str]:
        return self.observations[-limit:]

Memory 的难点不是存,而是什么该存、什么时候存、谁能看、多久过期、如何召回。建议遵循:

  • 默认不存敏感信息;
  • 写入长期记忆要有来源和时间;
  • 偏好类记忆要可撤销;
  • 任务状态和用户偏好分开存;
  • 召回时做权限过滤和时效过滤。

十一、异步、并发与流式输出

AI 应用经常会遇到慢请求:模型生成慢、RAG 检索慢、工具调用慢。如果所有操作都同步阻塞,用户体验会很差。

Java:CompletableFuture 并发调用

java 复制代码
import java.util.concurrent.CompletableFuture;

public class ParallelAgentService {
    public CompletableFuture<String> handle(String question) {
        CompletableFuture<String> profileFuture = CompletableFuture.supplyAsync(() -> queryUserProfile(question));
        CompletableFuture<String> policyFuture = CompletableFuture.supplyAsync(() -> queryPolicy(question));

        return profileFuture.thenCombine(policyFuture, (profile, policy) -> {
            String prompt = "用户信息:" + profile + "\n规则资料:" + policy + "\n问题:" + question;
            try {
                return new LlmClient(System.getenv("OPENAI_API_KEY")).chat(prompt);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    private String queryUserProfile(String question) {
        return "普通会员";
    }

    private String queryPolicy(String question) {
        return "已支付未发货订单可申请退款";
    }
}

Python:async/await 并发调用

python 复制代码
import asyncio

async def query_user_profile(question: str) -> str:
    await asyncio.sleep(0.1)
    return "普通会员"

async def query_policy(question: str) -> str:
    await asyncio.sleep(0.1)
    return "已支付未发货订单可申请退款"

async def handle(question: str) -> str:
    profile, policy = await asyncio.gather(
        query_user_profile(question),
        query_policy(question),
    )

    prompt = f"用户信息:{profile}\n规则资料:{policy}\n问题:{question}"
    return chat(prompt)

Python 的异步写法非常适合 I/O 密集型 AI 应用,比如并发查多个知识库、并发调用多个工具、流式返回模型输出。

十二、流式响应:让用户更快看到结果

AI 聊天产品通常会流式输出,不等模型全部生成完。

Java:Spring WebFlux 返回流

java 复制代码
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.time.Duration;

@RestController
public class StreamController {
    @GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> stream(@RequestParam String q) {
        return Flux.just("正在分析问题...", "查询相关资料...", "生成处理建议...", "完成")
                .delayElements(Duration.ofMillis(300));
    }
}

Python:FastAPI StreamingResponse

python 复制代码
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import asyncio

app = FastAPI()

async def token_generator(question: str):
    for token in ["正在分析问题...", "查询相关资料...", "生成处理建议...", "完成"]:
        yield f"data: {token}\n\n"
        await asyncio.sleep(0.3)

@app.get("/chat/stream")
async def stream(question: str):
    return StreamingResponse(
        token_generator(question),
        media_type="text/event-stream",
    )

如果你熟悉 Java SSE,再学 Python FastAPI 流式响应会很快。关键是注意:连接超时、客户端断开、模型中断、异常事件、心跳保活。

十三、LangChain、Spring AI、LangChain4j 怎么选

Java 开发者转 AI Agent,经常会问:我一定要用 Python LangChain 吗?不一定。

常见选择:

  • Python LangChain:资料最多,生态最完整,适合学习 Agent/RAG/Tool/Chain;
  • LlamaIndex:偏数据连接、知识库、RAG;
  • AutoGen/CrewAI:偏多 Agent 协作实验;
  • LangGraph:偏状态机式 Agent,适合复杂流程;
  • Spring AI:适合 Spring 技术栈团队,把 AI 能力接入 Java 后端;
  • LangChain4j:Java 生态里比较常用的 LLM 应用开发框架。

我的建议:

  1. 学概念和快速实验,用 Python;
  2. 做企业 Java 系统接入,用 Spring AI 或 LangChain4j;
  3. 做复杂 Agent 状态编排,重点理解 LangGraph 的状态机思想;
  4. 不要被框架绑架,先把 LLM、Prompt、Tool、RAG、Memory、Eval 这些底层概念吃透。

十四、可观测性:AI 应用必须能排障

Java 后端开发者很重视日志、指标、链路追踪。这一点在 AI Agent 里更重要。

一次 Agent 请求至少应该记录:

  • trace_id;
  • user_id 或租户信息;
  • 模型名称;
  • Prompt 版本;
  • 工具调用名称;
  • 工具参数摘要;
  • 检索命中文档 ID;
  • token 消耗;
  • 各阶段耗时;
  • 错误码;
  • 是否触发人工确认;
  • 最终结果状态。

Python 日志示例

python 复制代码
import logging
import time
import uuid

logger = logging.getLogger("agent")


def handle_request(user_id: str, question: str) -> str:
    trace_id = str(uuid.uuid4())
    start = time.time()

    try:
        logger.info("agent_request_start", extra={
            "trace_id": trace_id,
            "user_id": user_id,
            "question_len": len(question),
        })

        answer = rag_answer(question)

        logger.info("agent_request_success", extra={
            "trace_id": trace_id,
            "latency_ms": int((time.time() - start) * 1000),
        })
        return answer

    except Exception as e:
        logger.exception("agent_request_failed", extra={
            "trace_id": trace_id,
            "error_type": type(e).__name__,
        })
        raise

注意:日志要脱敏,不要把 API Key、身份证、手机号、完整支付信息、隐私内容直接打出来。

十五、安全治理:Agent 比普通接口更需要边界

传统后端接口通常是用户点按钮,服务执行固定动作。Agent 不一样,它可能会根据上下文主动决定调用哪个工具,所以安全边界必须更严格。

建议至少做这些控制:

  1. 最小权限:Agent 只拿当前任务需要的工具;
  2. 工具分级:只读工具、低风险写工具、高风险写工具分开;
  3. 人工确认:退款、删除、发通知、改配置等动作必须确认;
  4. 参数校验:模型生成的工具参数不能直接信;
  5. 沙箱隔离:文件、网络、命令执行要有限制;
  6. 凭据保护 :不要把长期密钥直接暴露给
    Agent;
  7. 审计日志:谁触发、模型为什么调用、参数是什么、结果是什么,都要能追溯;
  8. 提示注入防护:外部文档、网页、邮件、工单内容都只能当数据,不能当系统指令。

Python 工具执行前的安全检查示例

python 复制代码
from enum import Enum

class RiskLevel(str, Enum):
    READ = "read"
    LOW_WRITE = "low_write"
    HIGH_WRITE = "high_write"

TOOL_RISK = {
    "query_order": RiskLevel.READ,
    "create_ticket_note": RiskLevel.LOW_WRITE,
    "refund_order": RiskLevel.HIGH_WRITE,
}


def execute_tool_safely(tool_name: str, arguments: dict, approved: bool = False):
    risk = TOOL_RISK.get(tool_name)
    if risk is None:
        raise ValueError(f"未知工具:{tool_name}")

    validate_arguments(tool_name, arguments)

    if risk == RiskLevel.HIGH_WRITE and not approved:
        return {
            "status": "need_approval",
            "message": "该操作风险较高,需要人工确认后执行",
            "tool": tool_name,
            "arguments_summary": summarize_arguments(arguments),
        }

    return execute_tool(tool_name, arguments)

这段代码表达的核心思想是:模型可以建议动作,但程序必须控制动作是否真的执行。

十六、测试与评测:AI 应用不能只靠肉眼试

Java 项目通常有单元测试、集成测试、接口测试。AI Agent 也需要测试,只是测试对象更复杂。

至少要测这些:

  • Prompt 改动后,典型问题是否仍然答对;
  • 工具参数是否稳定生成;
  • RAG 召回是否命中正确资料;
  • 结构化输出是否能通过 Schema;
  • 高风险操作是否触发人工确认;
  • 异常场景是否降级,而不是无限重试;
  • 模型升级后效果是否退化。

Python 简单评测示例

python 复制代码
from pydantic import BaseModel

class EvalCase(BaseModel):
    question: str
    expected_keywords: list[str]

cases = [
    EvalCase(
        question="用户已支付但未发货,可以退款吗?",
        expected_keywords=["可申请退款", "未发货"],
    ),
    EvalCase(
        question="高风险退款是否需要人工复核?",
        expected_keywords=["人工复核"],
    ),
]


def test_rag_answer_quality():
    for case in cases:
        answer = rag_answer(case.question)
        for keyword in case.expected_keywords:
            assert keyword in answer

这不是完美评测,但它能避免最基本的回归问题。随着项目成熟,可以继续引入 LLM-as-Judge、人工标注集、线上反馈和灰度实验。

十七、Java 转 AI Agent 的推荐学习路线

如果你已经会 Java 后端,我建议按下面 6 个阶段学习。

阶段 1:Python 工程基础

目标:能读写常见 Python AI 项目。

重点学:

  • Python 语法、函数、类、异常;
  • venv/uv/pip/poetry;
  • dataclass、typing、Pydantic;
  • requests/httpx;
  • FastAPI;
  • pytest。

建议练习:用 FastAPI 写一个 /chat 接口,内部调用大模型 API。

阶段 2:大模型 API 与 Prompt

目标:理解 LLM 应用的基本输入输出。

重点学:

  • messages 格式;
  • system/user/assistant role;
  • temperature、top_p、max_tokens;
  • streaming;
  • token 成本;
  • Prompt 模板与版本管理。

建议练习:做一个客服工单分析接口,输出优先级、原因和建议动作。

阶段 3:结构化输出与工具调用

目标:让模型结果进入程序流程。

重点学:

  • JSON Schema;
  • Pydantic 校验;
  • Function Calling;
  • 工具注册表;
  • 参数校验;
  • 错误重试;
  • 高风险工具确认。

建议练习:做一个订单助手,能查询订单、判断退款条件,但退款动作必须人工确认。

阶段 4:RAG 知识库问答

目标:让模型基于企业资料回答。

重点学:

  • 文档加载;
  • 文档切分;
  • Embedding;
  • 向量数据库;
  • TopK 召回;
  • Rerank;
  • 引用来源;
  • 权限过滤。

建议练习:把一份售后规则文档切分入库,做一个带引用来源的问答接口。

阶段 5:Agent Loop 与 Memory

目标:让模型能多步执行任务。

重点学:

  • ReAct;
  • Plan-Act-Observe;
  • Self-Reflection;
  • 最大步数;
  • 任务状态;
  • 短期上下文;
  • 长期记忆;
  • 失败恢复。

建议练习:做一个"工单处理 Agent",能读取工单、查规则、查订单、判断是否转人工、生成处理建议。

阶段 6:生产化工程

目标:让 Agent 能上线、能排障、能迭代。

重点学:

  • 日志脱敏;
  • trace_id;
  • token 成本监控;
  • 模型路由;
  • 限流熔断;
  • 沙箱;
  • 权限;
  • 评测集;
  • 灰度发布;
  • 人工反馈闭环。

建议练习:把前面的工单 Agent 做成一个可观测、可评测、可回滚的小系统。

Java 与 Python 协作架构:业务边界与 Agent 编排

十八、Java 和 Python 在 AI Agent 项目里的协作架构

实际项目中,不一定要"放弃 Java,全面改 Python"。更常见的架构是两者协作。

text 复制代码
前端/业务系统
   ↓
Java 网关与业务服务
   - 鉴权
   - 用户与租户
   - 订单/支付/工单系统
   - 审计日志
   - 限流熔断
   ↓
Python Agent 服务
   - LLM 调用
   - Prompt 编排
   - Tool Calling
   - RAG
   - Memory
   - Eval
   ↓
模型供应商 / 向量库 / 外部工具

这种方式有几个好处:

  • Java 继续负责稳定业务边界;
  • Python 快速迭代 AI 能力;
  • 高风险动作仍由 Java 业务服务做权限和事务控制;
  • Agent 只通过受控 API 调用业务能力;
  • 后续稳定能力可以逐步服务化或迁回 Java。

十九、常见误区

误区 1:会 Python 就会 AI Agent

Python 只是入口。Agent 开发的核心是模型行为控制、工具边界、RAG 质量、状态管理和安全治理。

误区 2:Prompt 写长一点就稳定

Prompt 不是越长越好。稳定性来自清晰任务、结构化输出、可校验工具、失败重试、评测集和日志。

误区 3:RAG 等于向量库

向量库只是存储和召回组件。RAG 还包括切分、metadata、权限、rerank、引用、上下文压缩和答案约束。

误区 4:Agent 可以直接操作所有工具

生产环境里,Agent 不应该拥有无限工具权限。它应该通过工具注册、权限分级、人工确认和审计来行动。

误区 5:AI 应用不需要传统工程能力

恰恰相反,AI 应用更需要传统工程能力。因为模型不确定性更高,日志、测试、评测、监控、安全边界都更重要。

二十、总结

对 Java 开发者来说,转 AI Agent 开发的关键不是"抛弃 Java",而是补上 Python 与 AI 应用开发的能力拼图。

你需要掌握:

  • Python 基础与工程组织;
  • 大模型 API 调用;
  • Prompt 模板与版本管理;
  • 结构化输出;
  • Function Calling 与工具系统;
  • RAG 知识库;
  • Memory 与任务状态;
  • Agent Loop;
  • 异步与流式响应;
  • 可观测性、安全治理和评测。

如果你已经有 Java 后端经验,其实优势很大。你熟悉接口、权限、日志、事务、缓存、队列、监控和稳定性,这些正是 Agent 从 Demo 走向生产最需要的能力。Python 只是帮你更快进入 AI 生态,而真正决定系统能不能上线的,仍然是工程能力。

最好的学习方式不是一口气看完所有框架,而是从一个小项目开始:做一个工单处理 Agent。它包含 LLM 调用、结构化输出、工具调用、RAG、Memory、人工确认、日志和评测。把这个项目做完整,你就已经跨过了从 Java 后端到 AI Agent 开发的第一道门槛。

相关推荐
在放️1 小时前
Python 爬虫 · 模拟浏览器跳转 - 防盗链处理
爬虫·python
从负无穷开始的三次元代码生活1 小时前
AI基座知识点——了解AI核心组件内容部分
人工智能·ai
林间码客1 小时前
人工智能知识点复习汇总
人工智能
wilbertzhou1 小时前
大语言模型时代的语义元数据:从静态资产目录到智能治理
人工智能·llm·大语言模型·数据治理·元数据管理·语义元数据
heimeiyingwang1 小时前
【架构实战】数据脱敏与隐私保护:合规是底线
java·开发语言·架构
骑士雄师1 小时前
21.2 mcp-server-chart 图表化作用
python
皮皮蟹虾饺1 小时前
MiniMind:从零训练大语言模型全流程实战指南
人工智能·语言模型·自然语言处理
万俟淋曦1 小时前
【论文速递】2026年第03周(Jan-11-17)(Robotics/Embodied AI/LLM)
人工智能·ai·机器人·大模型·论文·robotics·具身智能
邵宇然1 小时前
静态图编译优化:基于 Rust 的计算图常量折叠与无效节点剪枝
人工智能