首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Java转AI高薪领域必备:从0到1打通生产级AI Agent开发

Java转AI高薪领域必备:从0到1打通生产级AI Agent开发

原创
作者头像
用户12553991
发布2026-06-25 12:57:34
发布2026-06-25 12:57:34
2160
举报

Java转AI高薪领域必备:从0到1打通生产级AI Agent开发

思否收录 · Java工程师转型AI实战系列

开篇:Java工程师的AI转型,为什么是现在?

2026年,一个让Java开发者既兴奋又焦虑的事实正在发生:

Java生态的AI工具链,在2025年底实现了"跨越式"成熟。

  • Spring AI 正式版发布,将AI集成变为"Spring式"的声明式开发
  • LangChain4j 成为Apache顶级项目,社区活跃度超越Python版LangChain
  • DeepSeek-R1、Qwen2.5等国产模型提供了原生的Java SDK支持
  • JDK 21 + Virtual Threads 让Java在高并发AI推理场景下重获性能优势

这意味着什么?

意味着Java工程师不再需要"转行Python"才能做AI开发。你现有的Spring Boot、微服务、高并发经验,本身就是AI Agent开发中的差异化竞争力——尤其是需要与企业现有系统集成时。

但另一个现实是:大量Java开发者对AI开发的认知还停留在"调API"层面。而真正高薪的岗位,要求的是构建生产级AI Agent系统的能力——包括工具调用、记忆管理、多Agent协作、可观测性等。

本文将从Java工程师的视角出发,系统讲解如何利用Java生态构建生产级AI Agent应用,全程实战、无Python依赖、可直接落地。全文约8000字,覆盖从环境搭建到生产部署的全链路。

一、Java做Agent,为什么现在"真香"了?

1.1 Java vs Python:2026年的真实对比

维度

Python AI生态

Java AI生态(2026)

结论

框架成熟度

成熟但碎片化

Spring AI + LangChain4j 双雄并立

Java正在追赶

性能

GIL限制并发

虚拟线程 + 原生编译

Java胜出

企业集成

需要额外适配层

原生Spring生态

Java胜出

模型支持

最全

主流模型全部支持

持平

学习曲线

平缓(语法简单)

陡峭(需要Spring基础)

Python略优

生产部署

需要大量运维

标准Java部署流程

Java胜出

高薪岗位

多(但竞争激烈)

快速增加(供给不足)

Java机会更大

1.2 Java做Agent的三大核心优势

优势一:与现有系统的"无缝焊接"

大多数企业已有Spring Boot微服务架构。在Java生态中构建AI Agent,天然可以:

  • 直接调用现有的Service层业务逻辑
  • 复用Spring Security的认证授权
  • 使用Spring Cloud的服务发现和配置中心
  • 接入现有监控体系(Micrometer + Prometheus)

优势二:虚拟线程彻底改变并发模型

代码语言:javascript
复制
// Java 21+ 虚拟线程让高并发AI调用变得极其简单
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    var futures = tasks.stream()
        .map(task -> executor.submit(() -> callAI(task)))
        .toList();
    
    // 可以轻松处理数万个并发AI请求
    var results = futures.stream()
        .map(Future::get)
        .toList();
}

优势三:GraalVM原生编译

2026年,Spring Boot 3.x + GraalVM已经成熟,可以将Agent应用编译为原生镜像,启动时间从秒级降至毫秒级,内存占用降低60%+。

1.3 2026年Java AI技术栈速览

代码语言:javascript
复制
┌─────────────────────────────────────────────────────────────────────┐
│                      Java AI Agent 技术栈                          │
│                                                                     │
│   ┌─────────────────────────────────────────────────────────────┐  │
│   │                    应用层(业务代码)                         │  │
│   │          Controller / Service / Repository                  │  │
│   └─────────────────────────────────────────────────────────────┘  │
│                                │                                    │
│   ┌─────────────────────────────────────────────────────────────┐  │
│   │                  AI Agent 框架层                             │  │
│   │   ┌──────────────┐        ┌──────────────┐                │  │
│   │   │ LangChain4j  │        │  Spring AI   │                │  │
│   │   │  (Apache顶级) │        │  (Spring官方) │                │  │
│   │   └──────────────┘        └──────────────┘                │  │
│   └─────────────────────────────────────────────────────────────┘  │
│                                │                                    │
│   ┌─────────────────────────────────────────────────────────────┐  │
│   │                   模型接入层                                 │  │
│   │   OpenAI / 通义千问 / DeepSeek / Ollama / HuggingFace      │  │
│   └─────────────────────────────────────────────────────────────┘  │
│                                │                                    │
│   ┌─────────────────────────────────────────────────────────────┐  │
│   │                   基础设施层                                 │  │
│   │   Redis(缓存) / Milvus/PGVector(向量) / 对象存储        │  │
│   └─────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────┘

二、环境搭建:从零开始

2.1 开发环境要求

组件

版本要求

说明

JDK

21+

Virtual Threads必需

Maven

3.9+

或Gradle 8.5+

Spring Boot

3.3.x+

AI集成的基石

IDE

IDEA 2024+ / VS Code

推荐IDEA

2.2 项目初始化(Spring Boot 3.x + LangChain4j)

代码语言:javascript
复制
<!-- pom.xml 核心依赖 -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.0</version>
    </parent>

    <groupId>com.ai.agent</groupId>
    <artifactId>java-ai-agent-demo</artifactId>
    <version>1.0.0</version>

    <properties>
        <java.version>21</java.version>
        <langchain4j.version>0.36.0</langchain4j.version>
        <spring-ai.version>1.0.0-M5</spring-ai.version>
    </properties>

    <dependencies>
        <!-- Spring Boot 基础 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- LangChain4j 核心 -->
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j</artifactId>
            <version>${langchain4j.version}</version>
        </dependency>

        <!-- OpenAI / 通义千问 集成 -->
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-open-ai</artifactId>
            <version>${langchain4j.version}</version>
        </dependency>

        <!-- 通义千问(国内推荐) -->
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-dashscope</artifactId>
            <version>${langchain4j.version}</version>
        </dependency>

        <!-- 工具调用支持 -->
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-tools</artifactId>
            <version>${langchain4j.version}</version>
        </dependency>

        <!-- 向量存储(内存版 + PGVector) -->
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-embeddings</artifactId>
            <version>${langchain4j.version}</version>
        </dependency>
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-pgvector</artifactId>
            <version>${langchain4j.version}</version>
        </dependency>

        <!-- Redis 缓存 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <!-- 可观测性 -->
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-tracing</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

2.3 配置文件

代码语言:javascript
复制
# application.yml
spring:
  application:
    name: java-ai-agent

  # Redis配置(用于缓存和状态管理)
  data:
    redis:
      host: localhost
      port: 6379
      timeout: 5000ms

  # 虚拟线程配置(Spring Boot 3.2+)
  threads:
    virtual:
      enabled: true

# AI模型配置
ai:
  llm:
    # 主模型(生产环境使用通义千问或DeepSeek)
    provider: qwen
    qwen:
      api-key: ${DASHSCOPE_API_KEY}
      model: qwen-max
      temperature: 0.3
      max-tokens: 2000
    # 备用模型(降级用)
    fallback:
      provider: openai
      openai:
        api-key: ${OPENAI_API_KEY}
        model: gpt-4o-mini

# Agent配置
agent:
  max-iterations: 10        # 最大推理轮数
  memory:
    vector-store: pgvector  # pgvector / chroma / memory
    max-history: 20         # 保留最近20条对话
    summary-size: 5         # 保留5条摘要

# 监控配置
management:
  endpoints:
    web:
      exposure:
        include: health, metrics, prometheus
  metrics:
    export:
      prometheus:
        enabled: true

三、核心实战一:从零构建ReAct Agent

3.1 什么是ReAct模式?

ReAct = Reasoning(推理) + Acting(行动)。Agent在每一步交替进行"思考"和"行动",直到完成任务。

代码语言:javascript
复制
用户: "帮我查一下明天的天气,并据此推荐出行方案"

Agent推理: "我需要先获取天气信息,再基于天气推荐出行方案"
    │
    ▼
Agent行动: 调用天气查询工具
    │
    ▼
工具返回: "明天晴,25-32°C,微风"
    │
    ▼
Agent推理: "天气晴好,适合户外活动,推荐..."
    │
    ▼
Agent行动: 输出最终回答

3.2 Java完整实现

代码语言:javascript
复制
// ReActAgentService.java - ReAct模式Agent核心实现

package com.ai.agent.service;

import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.agent.tool.ToolExecutionRequest;
import dev.langchain4j.agent.tool.ToolSpecification;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.qianfan.QianfanChatModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.tool.ToolExecutor;
import dev.langchain4j.tool.ToolSpecifications;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import jakarta.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Service
@RequiredArgsConstructor
public class ReActAgentService {

    private ChatLanguageModel model;
    private final Map<String, ChatMemory> sessionMemories = new ConcurrentHashMap<>();
    private final Map<String, Integer> sessionIterations = new ConcurrentHashMap<>();
    private static final int MAX_ITERATIONS = 10;

    @PostConstruct
    public void init() {
        // 初始化模型(使用通义千问)
        this.model = QianfanChatModel.builder()
            .apiKey(System.getenv("DASHSCOPE_API_KEY"))
            .modelName("qwen-max")
            .temperature(0.3)
            .maxTokens(2000)
            .build();
        
        log.info("ReAct Agent 初始化完成");
    }

    // ========== 1. 定义工具 ==========
    
    @Tool("获取当前时间,不需要参数")
    public String getCurrentTime() {
        return LocalDateTime.now()
            .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    @Tool("获取当前天气信息,参数为城市名称")
    public String getWeather(String city) {
        // 模拟天气查询,实际可接入和风天气API
        log.info("查询天气: {}", city);
        // 这里模拟返回数据,生产环境替换为真实API调用
        return String.format("""
            🌤️ %s 天气情况:
            温度: 26-33°C
            天气: 晴转多云
            风力: 3-4级
            湿度: 65%%
            空气质量: 良
            温馨提示: 适合户外活动,注意防晒。
            """, city);
    }

    @Tool("执行数学计算,输入数学表达式,返回计算结果")
    public String calculate(String expression) {
        try {
            // 使用Java内置的ScriptEngine,或者更安全的表达式计算库
            var engine = new javax.script.ScriptEngineManager()
                .getEngineByName("JavaScript");
            var result = engine.eval(expression);
            return String.format("计算结果: %s = %s", expression, result);
        } catch (Exception e) {
            return String.format("计算错误: %s", e.getMessage());
        }
    }

    // ========== 2. 获取工具定义 ==========
    
    private List<ToolSpecification> getToolSpecifications() {
        return ToolSpecifications.toolSpecificationsFrom(
            this.getClass()
        );
    }

    // ========== 3. Agent执行 ==========
    
    public String execute(String sessionId, String userInput) {
        log.info("执行Agent: session={}, input={}", sessionId, userInput);
        
        // 获取或创建会话记忆
        ChatMemory memory = sessionMemories.computeIfAbsent(
            sessionId,
            k -> MessageWindowChatMemory.builder()
                .maxMessages(20)
                .build()
        );
        
        // 重置迭代计数
        sessionIterations.put(sessionId, 0);
        
        // 添加用户消息
        memory.add(UserMessage.from(userInput));
        
        // 系统提示词(定义Agent的角色和行为)
        String systemPrompt = """
            你是一个智能助手(Agent),可以帮助用户完成各种任务。
            
            你可以使用以下工具:
            1. getCurrentTime - 获取当前时间
            2. getWeather(city) - 查询指定城市的天气
            3. calculate(expression) - 执行数学计算
            
            工作流程:
            1. 分析用户的问题,判断是否需要使用工具
            2. 如果需要,选择并调用合适的工具
            3. 根据工具返回的结果,给出最终回答
            
            重要规则:
            - 每次只能调用一个工具
            - 如果不需要工具,直接回答问题
            - 必须使用中文回答
            - 如果工具调用失败,尝试其他方法或告知用户
            """;
        
        // 执行ReAct循环
        int iterations = 0;
        while (iterations < MAX_ITERATIONS) {
            iterations++;
            sessionIterations.put(sessionId, iterations);
            
            log.info("Agent迭代: {}", iterations);
            
            // 构建消息列表
            var messages = memory.messages();
            
            // 调用LLM进行推理
            var response = model.generate(
                List.of(SystemMessage.from(systemPrompt)),
                messages
            );
            
            var aiMessage = response.content();
            memory.add(aiMessage);
            
            // 检查是否有工具调用请求
            if (aiMessage.hasToolExecutionRequests()) {
                var toolRequests = aiMessage.toolExecutionRequests();
                for (ToolExecutionRequest request : toolRequests) {
                    log.info("调用工具: {}", request.name());
                    
                    // 执行工具
                    String toolResult = executeTool(request);
                    
                    // 将工具结果添加到记忆
                    memory.add(dev.langchain4j.data.message.ToolExecutionResultMessage.from(
                        request.id(),
                        toolResult
                    ));
                }
                // 继续循环,让模型基于工具结果继续推理
                continue;
            }
            
            // 没有工具调用,返回最终答案
            String finalAnswer = aiMessage.text();
            log.info("Agent完成,迭代次数: {}", iterations);
            return finalAnswer;
        }
        
        // 达到最大迭代次数
        return "任务复杂,需要更多步骤。请简化您的问题或稍后重试。";
    }

    // ========== 4. 工具执行 ==========
    
    private String executeTool(ToolExecutionRequest request) {
        String toolName = request.name();
        Map<String, Object> args = request.arguments();
        
        try {
            return switch (toolName) {
                case "getCurrentTime" -> getCurrentTime();
                case "getWeather" -> {
                    String city = (String) args.get("city");
                    yield getWeather(city);
                }
                case "calculate" -> {
                    String expression = (String) args.get("expression");
                    yield calculate(expression);
                }
                default -> "未知工具: " + toolName;
            };
        } catch (Exception e) {
            log.error("工具执行失败: {}", toolName, e);
            return "工具执行失败: " + e.getMessage();
        }
    }

    // ========== 5. 清理会话 ==========
    
    public void clearSession(String sessionId) {
        sessionMemories.remove(sessionId);
        sessionIterations.remove(sessionId);
        log.info("会话已清理: {}", sessionId);
    }
}

3.3 暴露HTTP接口

代码语言:javascript
复制
// AgentController.java - Agent HTTP接口

package com.ai.agent.controller;

import com.ai.agent.service.ReActAgentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.Map;
import java.util.UUID;

@Slf4j
@RestController
@RequestMapping("/api/agent")
@RequiredArgsConstructor
public class AgentController {

    private final ReActAgentService agentService;

    /**
     * 执行Agent任务
     */
    @PostMapping("/execute")
    public Map<String, Object> execute(@RequestBody AgentRequest request) {
        String sessionId = request.getSessionId();
        if (sessionId == null || sessionId.isBlank()) {
            sessionId = UUID.randomUUID().toString();
        }
        
        long startTime = System.currentTimeMillis();
        String result = agentService.execute(sessionId, request.getQuery());
        long duration = System.currentTimeMillis() - startTime;
        
        log.info("Agent执行完成: session={}, duration={}ms", sessionId, duration);
        
        return Map.of(
            "sessionId", sessionId,
            "answer", result,
            "durationMs", duration
        );
    }

    /**
     * 清理会话
     */
    @DeleteMapping("/session/{sessionId}")
    public Map<String, String> clearSession(@PathVariable String sessionId) {
        agentService.clearSession(sessionId);
        return Map.of("status", "cleared", "sessionId", sessionId);
    }

    /**
     * 获取会话状态
     */
    @GetMapping("/session/{sessionId}/status")
    public Map<String, Object> getStatus(@PathVariable String sessionId) {
        // 实际需要暴露更多状态信息
        return Map.of(
            "sessionId", sessionId,
            "active", true
        );
    }
}

// 请求DTO
@Data
public class AgentRequest {
    private String sessionId;
    private String query;
}

3.4 测试运行

代码语言:javascript
复制
# 启动服务
mvn spring-boot:run

# 测试Agent
curl -X POST http://localhost:8080/api/agent/execute \
  -H "Content-Type: application/json" \
  -d '{"query": "帮我查一下杭州明天的天气,然后计算一下我如果带伞的话,需要多带多少重量。假设一把伞重500克。"}'

# 预期输出:Agent会依次调用 getWeather("杭州") → calculate("500") → 综合回答

四、核心实战二:多工具协作与复杂任务编排

4.1 2026年新范式:Spring AI + LangChain4j混合架构

LangChain4j负责Agent核心逻辑,Spring AI负责模型抽象和工具管理。

代码语言:javascript
复制
// HybridAgentConfig.java - 混合架构配置

package com.ai.agent.config;

import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.dashscope.QwenChatModel;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration
public class HybridAgentConfig {

    /**
     * LangChain4j模型(Agent核心推理)
     */
    @Bean
    @Primary
    public ChatLanguageModel langChainModel() {
        return QwenChatModel.builder()
            .apiKey(System.getenv("DASHSCOPE_API_KEY"))
            .modelName("qwen-max")
            .temperature(0.3)
            .build();
    }

    /**
     * Spring AI模型(特定场景使用)
     */
    @Bean
    public OpenAiChatModel springAiModel() {
        return OpenAiChatModel.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .model("gpt-4o")
            .temperature(0.2)
            .build();
    }

    /**
     * Spring AI ChatClient(流式输出支持)
     */
    @Bean
    public ChatClient chatClient(OpenAiChatModel model) {
        return ChatClient.builder(model).build();
    }

    /**
     * 默认会话记忆配置
     */
    @Bean
    public ChatMemory defaultChatMemory() {
        return MessageWindowChatMemory.builder()
            .maxMessages(30)
            .build();
    }
}

4.2 复杂任务编排:顺序执行与并行执行

代码语言:javascript
复制
// TaskOrchestrator.java - 任务编排引擎

package com.ai.agent.orchestrator;

import dev.langchain4j.agent.tool.Tool;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatLanguageModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

@Slf4j
@Component
@RequiredArgsConstructor
public class TaskOrchestrator {

    private final ChatLanguageModel model;
    
    // 任务计划缓存
    private final Map<String, TaskPlan> taskPlans = new ConcurrentHashMap<>();

    /**
     * 任务计划结构
     */
    public record TaskPlan(
        String goal,           // 任务目标
        List<SubTask> tasks,   // 子任务列表
        boolean parallel       // 是否并行执行
    ) {}

    public record SubTask(
        String id,
        String description,
        String tool,
        Map<String, Object> params,
        String dependsOn  // 依赖的子任务ID
    ) {}

    /**
     * 执行复杂任务
     */
    public String executeComplexTask(String taskId, String goal) {
        log.info("开始执行复杂任务: {}", goal);
        
        // 1. 任务拆解(使用LLM生成任务计划)
        TaskPlan plan = decomposeTask(goal);
        taskPlans.put(taskId, plan);
        
        // 2. 执行任务
        if (plan.parallel()) {
            return executeParallel(taskId, plan);
        } else {
            return executeSequential(taskId, plan);
        }
    }

    /**
     * 使用LLM进行任务拆解
     */
    private TaskPlan decomposeTask(String goal) {
        String prompt = String.format("""
            请将以下任务拆解为可执行的子任务列表。
            任务: %s
            
            可用工具:
            - search_web(query): 搜索互联网信息
            - get_weather(city): 查询天气
            - calculate(expression): 数学计算
            - get_stock_price(symbol): 查询股票价格
            - send_email(to, subject, body): 发送邮件
            
            请以JSON格式输出:
            {
                "goal": "任务目标",
                "parallel": false,
                "tasks": [
                    {"id": "t1", "description": "描述", "tool": "工具名", "params": {"key": "value"}, "dependsOn": null}
                ]
            }
            """, goal);
        
        var response = model.generate(
            List.of(UserMessage.from(prompt))
        );
        
        // 解析LLM返回的JSON(实际代码需要健壮的JSON解析)
        return parseTaskPlan(response.content().text());
    }

    /**
     * 顺序执行
     */
    private String executeSequential(String taskId, TaskPlan plan) {
        var results = new ConcurrentHashMap<String, Object>();
        var sb = new StringBuilder();
        
        for (SubTask task : plan.tasks()) {
            log.info("执行子任务: {} - {}", task.id(), task.description());
            
            // 检查依赖是否完成
            if (task.dependsOn() != null && !results.containsKey(task.dependsOn())) {
                log.warn("依赖任务未完成: {}", task.dependsOn());
                continue;
            }
            
            // 执行工具
            String result = executeTool(task.tool(), task.params());
            results.put(task.id(), result);
            sb.append(task.description()).append(": ").append(result).append("\n");
        }
        
        // 汇总结果
        return generateFinalAnswer(plan.goal(), sb.toString());
    }

    /**
     * 并行执行(使用虚拟线程)
     */
    private String executeParallel(String taskId, TaskPlan plan) {
        var results = new ConcurrentHashMap<String, Object>();
        
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            var futures = new ArrayList<Future<?>>();
            
            for (SubTask task : plan.tasks()) {
                var future = executor.submit(() -> {
                    String result = executeTool(task.tool(), task.params());
                    results.put(task.id(), result);
                    log.info("并行任务完成: {}", task.id());
                });
                futures.add(future);
            }
            
            // 等待所有任务完成
            for (var future : futures) {
                try {
                    future.get();
                } catch (Exception e) {
                    log.error("并行任务执行失败", e);
                }
            }
        }
        
        // 汇总结果
        var sb = new StringBuilder();
        for (SubTask task : plan.tasks()) {
            sb.append(task.description()).append(": ")
              .append(results.getOrDefault(task.id(), "执行失败"))
              .append("\n");
        }
        
        return generateFinalAnswer(plan.goal(), sb.toString());
    }

    /**
     * 工具执行(简化版)
     */
    private String executeTool(String toolName, Map<String, Object> params) {
        // 实际实现:通过反射或工具注册表调用
        return switch (toolName) {
            case "get_weather" -> "杭州: 晴, 26-33°C";
            case "calculate" -> {
                String expr = (String) params.get("expression");
                yield "计算结果: " + expr + " = 42";  // 简化
            }
            case "search_web" -> "搜索结果: 相关文章3篇...";
            default -> "工具执行结果 (模拟)";
        };
    }

    /**
     * 生成最终答案
     */
    private String generateFinalAnswer(String goal, String results) {
        String prompt = String.format("""
            任务目标: %s
            
            子任务执行结果:
            %s
            
            请基于以上结果,生成一个完整、友好的最终回答。
            """, goal, results);
        
        var response = model.generate(List.of(UserMessage.from(prompt)));
        return response.content().text();
    }

    /**
     * 解析任务计划(实际需要健壮的JSON解析)
     */
    private TaskPlan parseTaskPlan(String json) {
        // 简化实现,生产环境使用Jackson
        return new TaskPlan("任务目标", List.of(), false);
    }
}

五、核心实战三:持久化记忆系统

5.1 记忆系统架构

代码语言:javascript
复制
// PersistentMemoryService.java - 持久化记忆服务

package com.ai.agent.memory;

import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.pgvector.PgVectorEmbeddingStore;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Service
public class PersistentMemoryService {

    private final RedisTemplate<String, Object> redisTemplate;
    private final EmbeddingStore<TextSegment> embeddingStore;
    
    // 会话的短期记忆(对话上下文)
    private final ConcurrentHashMap<String, ChatMemory> shortTermMemory = new ConcurrentHashMap<>();
    
    // 会话的长期记忆(向量存储)
    private final ConcurrentHashMap<String, List<String>> longTermMemoryIndex = new ConcurrentHashMap<>();

    public PersistentMemoryService(
            RedisTemplate<String, Object> redisTemplate,
            PgVectorEmbeddingStore embeddingStore) {
        this.redisTemplate = redisTemplate;
        this.embeddingStore = embeddingStore;
    }

    /**
     * 获取或创建会话记忆
     */
    public ChatMemory getMemory(String sessionId) {
        return shortTermMemory.computeIfAbsent(sessionId, id -> {
            // 尝试从Redis恢复
            List<ChatMessage> saved = loadFromRedis(id);
            if (saved != null && !saved.isEmpty()) {
                log.info("从Redis恢复会话记忆: {}", id);
                var memory = MessageWindowChatMemory.builder()
                    .maxMessages(20)
                    .build();
                saved.forEach(memory::add);
                return memory;
            }
            
            // 新建记忆
            return MessageWindowChatMemory.builder()
                .maxMessages(20)
                .build();
        });
    }

    /**
     * 保存对话到长期记忆(向量存储)
     */
    public void saveToLongTermMemory(String sessionId, String userMessage, String agentResponse) {
        String memoryId = UUID.randomUUID().toString();
        
        // 生成摘要
        String summary = String.format("用户: %s | 助手: %s", 
            userMessage.length() > 100 ? userMessage.substring(0, 100) + "..." : userMessage,
            agentResponse.length() > 100 ? agentResponse.substring(0, 100) + "..." : agentResponse
        );
        
        // 存储向量
        embeddingStore.add(
            TextSegment.from(
                summary,
                java.util.Map.of(
                    "sessionId", sessionId,
                    "memoryId", memoryId,
                    "timestamp", System.currentTimeMillis()
                )
            )
        );
        
        // 更新索引
        longTermMemoryIndex.computeIfAbsent(sessionId, k -> new ArrayList<>())
            .add(memoryId);
        
        log.info("已保存长期记忆: session={}, id={}", sessionId, memoryId);
    }

    /**
     * 检索相关长期记忆
     */
    public List<String> retrieveMemories(String sessionId, String query, int maxResults) {
        // 使用向量检索
        var relevant = embeddingStore.findRelevant(query, maxResults);
        return relevant.stream()
            .filter(match -> match.embedded().metadata()
                .getOrDefault("sessionId", "").equals(sessionId))
            .map(match -> match.embedded().text())
            .toList();
    }

    /**
     * 保存到Redis(短期持久化)
     */
    private void saveToRedis(String sessionId, List<ChatMessage> messages) {
        String key = "agent:memory:" + sessionId;
        redisTemplate.opsForValue().set(
            key,
            messages,
            Duration.ofHours(24)  // 保留24小时
        );
    }

    /**
     * 从Redis加载
     */
    @SuppressWarnings("unchecked")
    private List<ChatMessage> loadFromRedis(String sessionId) {
        String key = "agent:memory:" + sessionId;
        Object value = redisTemplate.opsForValue().get(key);
        if (value instanceof List<?>) {
            return (List<ChatMessage>) value;
        }
        return null;
    }

    /**
     * 清理会话
     */
    public void clearSession(String sessionId) {
        shortTermMemory.remove(sessionId);
        longTermMemoryIndex.remove(sessionId);
        redisTemplate.delete("agent:memory:" + sessionId);
        log.info("会话已清理: {}", sessionId);
    }
}

5.2 集成到Agent中

代码语言:javascript
复制
// 在ReActAgentService中集成记忆系统

@Service
public class EnhancedReActAgentService {

    private final PersistentMemoryService memoryService;
    
    // 修改execute方法,加入记忆检索
    public String executeWithMemory(String sessionId, String userInput) {
        // 1. 检索相关长期记忆
        var relevantMemories = memoryService.retrieveMemories(
            sessionId, 
            userInput, 
            3
        );
        
        // 2. 构建增强提示词
        String memoryContext = relevantMemories.isEmpty() 
            ? "" 
            : "相关历史记忆:\n" + String.join("\n", relevantMemories);
        
        // 3. 执行Agent推理
        String response = execute(sessionId, 
            memoryContext + "\n\n当前问题: " + userInput
        );
        
        // 4. 保存到长期记忆
        memoryService.saveToLongTermMemory(sessionId, userInput, response);
        
        return response;
    }
}

六、生产级监控与可观测性

6.1 关键指标与监控

代码语言:javascript
复制
// AgentMetrics.java - 监控指标

package com.ai.agent.monitoring;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import lombok.Getter;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;

@Component
public class AgentMetrics {

    private final MeterRegistry registry;
    
    @Getter
    private Counter totalRequests;
    @Getter
    private Counter successRequests;
    @Getter
    private Counter errorRequests;
    @Getter
    private Counter toolCalls;
    @Getter
    private Timer requestTimer;
    @Getter
    private Timer llmCallTimer;

    public AgentMetrics(MeterRegistry registry) {
        this.registry = registry;
    }

    @PostConstruct
    public void init() {
        this.totalRequests = Counter.builder("agent.requests.total")
            .description("Total Agent requests")
            .register(registry);
            
        this.successRequests = Counter.builder("agent.requests.success")
            .description("Successful Agent requests")
            .register(registry);
            
        this.errorRequests = Counter.builder("agent.requests.error")
            .description("Failed Agent requests")
            .register(registry);
            
        this.toolCalls = Counter.builder("agent.tool.calls")
            .description("Total tool calls")
            .register(registry);
            
        this.requestTimer = Timer.builder("agent.request.duration")
            .publishPercentiles(0.5, 0.95, 0.99)
            .register(registry);
            
        this.llmCallTimer = Timer.builder("agent.llm.duration")
            .publishPercentiles(0.5, 0.95, 0.99)
            .register(registry);
    }

    public void recordSuccess() {
        successRequests.increment();
    }

    public void recordError() {
        errorRequests.increment();
    }

    public void recordToolCall() {
        toolCalls.increment();
    }

    public <T> T recordRequest(Timer.Sample sample) {
        sample.stop(requestTimer);
        return null;
    }

    public <T> T recordLLMCall(Timer.Sample sample) {
        sample.stop(llmCallTimer);
        return null;
    }
}

6.2 日志链路追踪

代码语言:javascript
复制
# logback-spring.xml - 添加traceId支持
<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] [%X{traceId}] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
    </root>
</configuration>
代码语言:javascript
复制
// TraceInterceptor.java - 链路追踪拦截器

@Component
public class TraceInterceptor implements HandlerInterceptor {
    
    private static final String TRACE_ID_HEADER = "X-Trace-Id";
    private static final String TRACE_ID_KEY = "traceId";
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String traceId = request.getHeader(TRACE_ID_HEADER);
        if (traceId == null || traceId.isBlank()) {
            traceId = UUID.randomUUID().toString();
        }
        MDC.put(TRACE_ID_KEY, traceId);
        return true;
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        MDC.remove(TRACE_ID_KEY);
    }
}

七、部署与生产化

7.1 容器化部署

代码语言:javascript
复制
# Dockerfile
FROM eclipse-temurin:21-jre-alpine

WORKDIR /app

# 复制jar包
COPY target/java-ai-agent-*.jar app.jar

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s CMD wget --spider http://localhost:8080/actuator/health || exit 1

# 启动参数:GraalVM原生优化
ENTRYPOINT ["java", \
    "-Xmx2g", \
    "-XX:+UseZGC", \
    "-XX:+EnableDynamicAgentLoading", \
    "-jar", "app.jar"]

7.2 生产配置(application-prod.yml)

代码语言:javascript
复制
# application-prod.yml
server:
  tomcat:
    threads:
      max: 200
      min-spare: 20
    connection-timeout: 60s

spring:
  ai:
    retry:
      max-attempts: 3
      backoff:
        initial-interval: 2s
        multiplier: 2
        max-interval: 30s

ai:
  llm:
    timeout: 30s
    retry-on-rate-limit: true

agent:
  timeout: 60s
  max-iterations: 8
  parallel-execution: true

logging:
  level:
    com.ai.agent: DEBUG

八、Java AI Agent工程师的成长路径

8.1 技能雷达图

代码语言:javascript
复制
         Spring Boot + Java
              ★★★★★
                  │
    Agent框架 ★★★★┼★★★ 大模型API
                  │
    向量数据库 ★★★★┼★★★ 提示词工程
                  │
    多Agent协作 ★★★┼★★★ 可观测性
                  │
    性能优化 ★★★┼★★★ 安全与合规
              ★★★★★
          企业集成能力

8.2 学习路径

阶段

目标

学习内容

标志性产出

第1-2周

基础认知

Spring AI快速入门、LangChain4j基础

跑通第一个AI调用接口

第3-4周

Agent入门

ReAct模式实现、工具定义与调用

完成一个多工具Agent

第5-6周

进阶能力

记忆系统设计、RAG集成

带记忆的客服Agent

第7-8周

复杂场景

多Agent协作、任务编排

多角色协作系统

第9-12周

生产化

监控、性能优化、部署

生产级Agent服务上线

8.3 高薪方向建议

方向

薪资区间

核心要求

企业AI Agent平台开发

50-100万

Spring生态 + LangChain4j + 高并发

垂直领域Agent解决方案

60-120万

领域知识 + Agent架构设计

Agent基础设施(工具链/框架)

70-150万

框架源码阅读 + 中间件开发

写在最后

Java工程师转型AI Agent开发,不是"重学一门语言",而是用你已有的Java生态优势,切入一个高增长的新领域

Spring生态的成熟、虚拟线程的性能优势、GraalVM的部署优化——这些Java独有的能力,正是构建生产级AI Agent系统的核心竞争力。

未来的高薪岗位,属于"懂Java、懂AI、懂系统"的复合型人才。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java转AI高薪领域必备:从0到1打通生产级AI Agent开发
    • 开篇:Java工程师的AI转型,为什么是现在?
    • 一、Java做Agent,为什么现在"真香"了?
      • 1.1 Java vs Python:2026年的真实对比
      • 1.2 Java做Agent的三大核心优势
      • 1.3 2026年Java AI技术栈速览
    • 二、环境搭建:从零开始
      • 2.1 开发环境要求
      • 2.2 项目初始化(Spring Boot 3.x + LangChain4j)
      • 2.3 配置文件
    • 三、核心实战一:从零构建ReAct Agent
      • 3.1 什么是ReAct模式?
      • 3.2 Java完整实现
      • 3.3 暴露HTTP接口
      • 3.4 测试运行
    • 四、核心实战二:多工具协作与复杂任务编排
      • 4.1 2026年新范式:Spring AI + LangChain4j混合架构
      • 4.2 复杂任务编排:顺序执行与并行执行
    • 五、核心实战三:持久化记忆系统
      • 5.1 记忆系统架构
      • 5.2 集成到Agent中
    • 六、生产级监控与可观测性
      • 6.1 关键指标与监控
      • 6.2 日志链路追踪
    • 七、部署与生产化
      • 7.1 容器化部署
      • 7.2 生产配置(application-prod.yml)
    • 八、Java AI Agent工程师的成长路径
      • 8.1 技能雷达图
      • 8.2 学习路径
      • 8.3 高薪方向建议
    • 写在最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档