这次我们来看一个用 Java 和 Spring AI Alibaba Graph 搭建 HR 自动化 AI Agent 的实战项目。这个项目不是空谈概念而是聚焦于如何将大模型能力与 Spring 生态结合落地到 HR 招聘、员工服务等具体业务场景。对于 Java 开发者来说这意味着无需切换技术栈就能在自己的“主场”玩转 AI Agent。这个项目的核心价值在于它提供了一个跨行业的通用实战案例将 AI Agent 开发中涉及的模型调用、工具集成、工作流编排、状态管理等 20 个核心技术点串联起来。无论你是想快速搭建一个智能面试助手还是希望构建一个自动化的员工问答机器人这个案例都能提供清晰的实现路径和代码参考。本文将带你从零开始理解 Spring AI Alibaba Graph 的核心概念并一步步搭建一个具备实际功能的 HR AI Agent。1. 核心能力速览在深入代码之前我们先快速了解这个技术栈能做什么以及它的关键特性。能力项说明技术栈Java 17 Spring Boot 3.x Spring AI Alibaba Graph核心模型支持通义千问、DeepSeek 等主流国产大模型也可对接 OpenAI 兼容接口主要功能构建具备规划、执行、反思能力的 AI Agent支持工具调用、工作流编排、状态管理硬件门槛无特殊 GPU 要求依赖远程 API 调用本地开发机即可运行启动方式标准的 Spring Boot 应用通过mvn spring-boot:run或 IDE 直接启动接口能力提供 RESTful API可轻松集成到现有 HR 系统或前端应用批量任务支持异步处理可结合 Spring Batch 或消息队列处理批量简历筛选、面试邀约等任务适合场景HR 自动化简历初筛、面试问题生成、员工自助问答、企业内部智能助手、跨部门流程自动化这个方案最大的优势是“Java 原生”。你不需要去学习 Python 的 LangChain 或 LlamaIndex而是使用熟悉的 Spring 注解和设计模式来构建 AI 应用。Spring AI Alibaba Graph 作为编排框架负责管理 Agent 的思考链路和工具执行。2. 适用场景与使用边界2.1 适合谁解决什么问题这个项目主要面向两类开发者Java 后端工程师希望将 AI 能力集成到现有 Java 微服务中不想引入额外的技术栈复杂度。对 AI Agent 感兴趣的实践者想通过一个完整的、业务导向的案例吃透 Agent 的架构、状态机和工具调用等核心概念。它能解决的 HR 场景问题包括简历智能初筛根据 JD职位描述自动分析简历匹配度并给出理由。面试问题生成针对特定岗位和候选人简历生成个性化的面试问题。新员工入职引导通过对话形式回答新员工关于公司制度、流程的常见问题。员工自助服务处理如年假查询、报销政策咨询等标准化问答。2.2 不适合什么场景需要本地大模型推理的场景本项目默认通过 API 调用云端大模型不适合要求完全离线、数据不出域的私有化部署虽然可通过部署本地模型服务解决但非本案例重点。极度复杂的多模态处理当前案例以文本处理为核心如果涉及大量图片简历解析、视频面试分析需要额外集成视觉模型。完全替代人工决策AI Agent 应作为辅助工具核心的人事决策仍需 HR 专业人员复核。2.3 合规与安全边界数据隐私处理候选人简历、员工信息等敏感数据时必须确保 API 调用符合公司数据安全政策必要时对数据进行脱敏处理。模型偏见大模型可能存在训练数据带来的偏见生成的面试问题或评价需人工审核避免造成歧视。授权与告知在招聘自动化流程中使用 AI应考虑对候选人进行告知。结果可解释性AI 做出的判断如简历不匹配应能提供可追溯、可解释的理由这是系统设计时必须考虑的。3. 环境准备与前置条件开始编码前请确保你的开发环境满足以下要求。Java 开发环境JDK: 版本 17 或更高推荐 17 或 21。检查命令java -version构建工具: Apache Maven 3.6 或 Gradle。本文使用 Maven。IDE: IntelliJ IDEA, Eclipse 或 VS Code需安装 Java 扩展。Spring Boot 项目骨架使用 Spring Initializr 快速生成项目选择以下依赖Spring Boot: 3.2.xDependencies:Spring Web,Spring AI Alibaba,Lombok(可选简化代码)大模型 API 密钥本项目需要调用大模型 API。以阿里云灵积平台通义千问为例前往 阿里云官网 注册账号。开通灵积DashScope服务。在控制台创建 API-KEY并确保有足够的额度。网络与代理确保你的开发环境能够访问所选大模型的 API 地址如dashscope.aliyuncs.com或api.openai.com。4. 项目初始化与核心依赖首先我们创建一个 Spring Boot 项目并引入关键依赖。生成项目通过 Spring Initializr 创建项目或手动创建pom.xml。关键依赖在pom.xml中添加 Spring AI Alibaba 和 Web 依赖。?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.2.5/version !-- 使用稳定版本 -- relativePath/ /parent groupIdcom.example/groupId artifactIdhr-ai-agent/artifactId version0.0.1-SNAPSHOT/version namehr-ai-agent/name descriptionHR Automation AI Agent with Spring AI Alibaba/description properties java.version17/java.version spring-ai-alibaba.version0.8.1/spring-ai-alibaba.version !-- 请检查最新版本 -- /properties dependencies !-- Web 支持提供 REST API -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Spring AI Alibaba 核心 -- dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-alibaba-spring-boot-starter/artifactId version${spring-ai-alibaba.version}/version /dependency !-- 工具类 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !-- 测试 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId /plugin /plugins /build /project配置 API 密钥在application.yml或application.properties中配置。# application.yml spring: application: name: hr-ai-agent ai: alibaba: dashscope: api-key: ${DASHSCOPE_API_KEY:your-api-key-here} # 建议使用环境变量 chat: options: model: qwen-max # 模型名称如 qwen-plus, qwen-max, qwen-turbo temperature: 0.7 # 创造性0-1重要切勿将 API Key 硬编码在代码中或提交到版本控制系统。推荐使用环境变量export DASHSCOPE_API_KEYyour-real-api-key5. 理解 Spring AI Alibaba Graph 核心概念在编码前需要理解几个关键抽象这是构建 Agent 的基石。Model即大模型本身如通义千问。Spring AI 提供了统一的ChatClient接口进行调用。ToolAgent 可以调用的外部函数。例如“查询数据库”、“调用天气 API”、“计算器”。在 HR 场景下可以是“获取岗位信息”、“查询面试官日程”。Agent一个具备自主能力的实体它可以根据目标Goal、规划Plan、执行Execute和反思Reflect的循环来工作。它通过调用 Tools 和 Model 来完成复杂任务。Graph用于编排 Agent 执行流程的组件。它定义了状态State的流转可以包含条件分支、循环、并行等复杂逻辑。Graph是 Spring AI Alibaba 提供的核心编排能力。我们的 HR Agent 将围绕一个Graph来构建状态中包含了用户的问题、上下文、已执行的工具结果等。6. 构建 HR AI Agent20个核心技术点拆解下面我们围绕一个“智能面试问题生成”场景将20个核心技术点融入代码实现中。6.1 定义 Agent 状态 (State)状态是 Graph 中流动的数据载体。我们定义一个InterviewState类。import lombok.Data; import java.util.List; import java.util.Map; Data public class InterviewState { // 输入 private String jobDescription; // 职位描述 private String candidateResume; // 候选人简历 private String userQuery; // 用户原始问题如“为这个候选人生成5个技术面试问题” // 中间处理结果 private String extractedSkills; // 从JD和简历中提取的关键技能 private ListString generatedQuestions; // 生成的面试问题列表 private String evaluation; // 对候选人与岗位的匹配度初步评估 // 元数据 private MapString, Object metadata; // 存放其他信息如调用次数、错误信息 private Boolean isComplete false; // 任务是否完成 }6.2 实现自定义 ToolTool 是 Agent 的手和脚。我们实现一个从“数据库”获取岗位详细要求的 Tool此处模拟。import org.springframework.ai.alibaba.tool.annotation.Tool; import org.springframework.ai.alibaba.tool.annotation.ToolParam; import org.springframework.stereotype.Component; import java.util.Map; Component public class HrTools { /** * 核心技术点1: 定义Tool。根据岗位ID获取详细的职位要求。 * param jobId 岗位ID * return 岗位要求详情 */ Tool(name getJobRequirements, description 根据岗位ID获取详细的技能要求和职责描述) public String getJobRequirements(ToolParam(description 岗位的唯一标识ID) String jobId) { // 模拟从数据库或HR系统查询 MapString, String jobDb Map.of( JAVA_DEV_001, 精通Java熟悉Spring Cloud, MySQL, Redis有高并发系统设计经验。, FRONTEND_002, 精通React/Vue熟悉TypeScript, Webpack有性能优化经验。 ); return jobDb.getOrDefault(jobId, 未找到该岗位信息。); } /** * 核心技术点2: 多参数Tool。评估简历与岗位的匹配度。 */ Tool(name evaluateResumeMatch, description 初步评估简历与岗位要求的匹配度并返回关键技能差距) public String evaluateResumeMatch( ToolParam(description 职位描述文本) String jobDesc, ToolParam(description 候选人简历文本) String resume) { // 这里可以集成更复杂的NLP算法本例仅模拟 if (jobDesc.contains(Java) resume.contains(Spring Boot)) { return 匹配度较高。核心技能‘Java’和‘Spring Boot’吻合。建议关注其项目中的并发处理经验。; } else { return 匹配度一般。简历中未突出显示岗位要求的关键技能。; } } }关键点Tool注解让 Spring AI 能自动发现并描述该工具供大模型调用。ToolParam注解描述了参数帮助模型理解。6.3 配置大模型 ChatClientSpring AI 会自动配置ChatClient我们只需在需要时注入。import org.springframework.ai.chat.client.ChatClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class AiConfig { // ChatClient 已由 starter 自动配置这里可以定义一些自定义的Bean如提示词模板 // 核心技术点3: 注入统一的ChatClient进行模型调用 }6.4 构建 Agent 执行图 (Graph)这是最核心的部分。我们定义一个Graph它描述了从接收输入到产出面试问题的完整流程。import org.springframework.ai.alibaba.graph.Graph; import org.springframework.ai.alibaba.graph.Node; import org.springframework.ai.alibaba.graph.State; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class InterviewGraphConfig { Bean public GraphInterviewState interviewQuestionGraph( ChatClient chatClient, HrTools hrTools) { return Graph.InterviewStatebuilder() // 节点1: 提取关键信息 (核心技术点4: 使用Model进行信息提取) .addNode(Node.InterviewStatebuilder() .name(extractInfoNode) .action(state - { String prompt 你是一个资深的HR专家。请从以下职位描述和简历中提取出岗位要求的核心技能和候选人具备的核心技能。 职位描述%s 候选人简历%s 请以清晰的列表格式输出分别列出“岗位核心要求”和“候选人匹配技能”。 .formatted(state.getJobDescription(), state.getCandidateResume()); String extraction chatClient.prompt() .user(prompt) .call() .content(); state.setExtractedSkills(extraction); return state; }) .build()) // 节点2: 调用Tool获取详细岗位要求 (核心技术点5: 工具调用集成) .addNode(Node.InterviewStatebuilder() .name(fetchJobDetailNode) .action(state - { // 假设我们从state中或通过模型解析出了jobId // 这里简化处理直接使用一个示例ID String jobDetails hrTools.getJobRequirements(JAVA_DEV_001); // 将获取的详情合并到职位描述中 state.setJobDescription(state.getJobDescription() \n\n岗位详情 jobDetails); return state; }) .build()) // 节点3: 初步匹配度评估 (核心技术点6: 条件判断与流程分支) .addNode(Node.InterviewStatebuilder() .name(evaluateMatchNode) .action(state - { String evaluation hrTools.evaluateResumeMatch( state.getJobDescription(), state.getCandidateResume() ); state.setEvaluation(evaluation); // 核心技术点7: 状态判断决定后续流程 if (evaluation.contains(匹配度较高)) { state.getMetadata().put(proceedToGenerate, true); } else { state.getMetadata().put(proceedToGenerate, false); state.getMetadata().put(stopReason, 初步匹配度不足); } return state; }) .build()) // 节点4: 生成面试问题 (核心技术点8: 基于上下文的提示工程) .addNode(Node.InterviewStatebuilder() .name(generateQuestionsNode) .condition(state - (Boolean) state.getMetadata().getOrDefault(proceedToGenerate, false)) .action(state - { String prompt 你是一位技术面试官。请基于以下信息为候选人生成5个专业、有深度的技术面试问题。 注意问题要覆盖其知识广度、项目深度和问题解决能力。 提取的关键信息 %s 初步评估意见 %s 请以JSON数组格式输出问题每个元素包含“question”问题文本和“focusArea”考察点字段。 .formatted(state.getExtractedSkills(), state.getEvaluation()); String questionsJson chatClient.prompt() .user(prompt) .call() .content(); // 简化这里应解析JSON本例直接存储字符串 state.setGeneratedQuestions(List.of(questionsJson)); // 实际应解析为ListString return state; }) .build()) // 节点5: 生成拒绝或建议 (核心技术点9: 处理异常或否定分支) .addNode(Node.InterviewStatebuilder() .name(generateSuggestionNode) .condition(state - !(Boolean) state.getMetadata().getOrDefault(proceedToGenerate, true)) .action(state - { String suggestion 根据初步评估候选人与岗位匹配度一般。建议1. 重新审视简历关键词2. 考虑其他更匹配的岗位。; state.setGeneratedQuestions(List.of(suggestion)); return state; }) .build()) // 节点6: 结束节点标记完成 (核心技术点10: 状态终结) .addNode(Node.InterviewStatebuilder() .name(finalizeNode) .action(state - { state.setIsComplete(true); return state; }) .build()) // 定义边连接关系(核心技术点11: 图编排) .addEdge(extractInfoNode, fetchJobDetailNode) .addEdge(fetchJobDetailNode, evaluateMatchNode) // 条件边根据评估结果决定下一步 .addEdge(evaluateMatchNode, generateQuestionsNode, state - (Boolean) state.getMetadata().getOrDefault(proceedToGenerate, false)) .addEdge(evaluateMatchNode, generateSuggestionNode, state - !(Boolean) state.getMetadata().getOrDefault(proceedToGenerate, true)) .addEdge(generateQuestionsNode, finalizeNode) .addEdge(generateSuggestionNode, finalizeNode) .build(); } }这个Graph定义了一个清晰的流程信息提取 - 获取详情 - 评估 - 根据评估结果生成问题或建议 - 结束。condition方法实现了条件分支。6.5 创建控制器 (Controller) 暴露 API现在我们将这个 Agent 能力通过 REST API 暴露出来。import org.springframework.ai.alibaba.graph.Graph; import org.springframework.ai.alibaba.graph.State; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.web.bind.annotation.*; import java.util.Map; RestController RequestMapping(/api/hr-agent) public class HrAgentController { private final GraphInterviewState interviewGraph; public HrAgentController(Qualifier(interviewQuestionGraph) GraphInterviewState interviewGraph) { this.interviewGraph interviewGraph; } /** * 核心技术点12: 提供同步处理接口 */ PostMapping(/generate-questions) public MapString, Object generateInterviewQuestions(RequestBody InterviewRequest request) { // 1. 初始化状态 InterviewState initialState new InterviewState(); initialState.setJobDescription(request.getJobDescription()); initialState.setCandidateResume(request.getResumeText()); initialState.setUserQuery(生成技术面试问题); initialState.setMetadata(new java.util.HashMap()); // 2. 执行Graph (核心技术点13: 图执行触发) StateInterviewState resultState interviewGraph.execute(initialState); // 3. 返回结果 InterviewState finalState resultState.getData(); return Map.of( success, finalState.getIsComplete(), evaluation, finalState.getEvaluation(), questions, finalState.getGeneratedQuestions(), metadata, finalState.getMetadata() ); } /** * 核心技术点14: 支持异步处理使用CompletableFuture或消息队列 */ PostMapping(/async-generate-questions) public MapString, String asyncGenerateQuestions(RequestBody InterviewRequest request) { // 这里可以返回一个任务ID实际处理放入线程池或消息队列 String taskId TASK_ System.currentTimeMillis(); // 异步执行 interviewGraph.execute(...) return Map.of(taskId, taskId, status, accepted); } } // 简单的请求体 Data class InterviewRequest { private String jobDescription; private String resumeText; }6.6 测试与验证启动应用后使用curl或 Postman 进行测试。# 启动应用 mvn spring-boot:run # 发送测试请求 curl -X POST http://localhost:8080/api/hr-agent/generate-questions \ -H Content-Type: application/json \ -d { jobDescription: 招聘高级Java开发工程师要求精通Spring Boot、微服务架构有高并发系统设计经验。, resumeText: 张三5年Java开发经验熟悉Spring Cloud全家桶在上一家公司主导了订单系统的重构QPS达到10万。 }预期返回一个 JSON包含评估结果和生成的面试问题列表。7. 剩余核心技术点解析上面我们已经实现了14个核心点下面简要阐述其余6个点它们同样是构建健壮 Agent 的关键。核心技术点15: 提示词模板化与管理不应将提示词硬编码在代码中。应使用PromptTemplate或存储在数据库/配置文件中便于管理和 A/B 测试。核心技术点16: 流式响应 (Streaming)对于耗时的生成任务可以通过ChatClient的流式 API 实现 SSEServer-Sent Events让前端实时显示生成过程。核心技术点17: 对话历史与记忆 (Memory)对于多轮对话场景如员工问答需要将历史对话存入State或外部存储如 Redis并在每次调用时带入上下文。核心技术点18: 工具调用结果的后处理与验证Agent 调用工具返回的结果可能需要清洗、验证或格式化再交给模型进行下一步推理。这可以在 Tool 方法内或 Graph 的独立节点中完成。核心技术点19: 异常处理与重试机制在图节点action中需要妥善处理网络超时、模型 API 限流、工具调用失败等异常并设计重试或降级策略。核心技术点20: 可观测性与监控集成 Micrometer 等指标库记录每个 Graph 节点的执行时间、Tool 调用次数、Token 消耗等便于监控和优化。8. 接口 API 与批量任务实践8.1 扩展 REST API除了生成问题可以扩展更多端点PostMapping(/resume-screening) public MapString, Object screenResume(RequestBody ScreeningRequest request) { // 实现简历自动筛选逻辑返回匹配度和理由 } PostMapping(/onboarding-qa) public MapString, Object answerOnboardingQuestion(RequestBody QaRequest request) { // 实现新员工问答结合知识库Tool }8.2 实现批量简历处理对于批量任务可以结合 Spring Batch 或简单的线程池。Service public class BatchResumeService { Async // 启用异步执行 public void processBatchResumes(ListResume resumes, String jobId) { for (Resume resume : resumes) { InterviewState state new InterviewState(); state.setCandidateResume(resume.getContent()); state.setJobDescription(fetchJobDesc(jobId)); // 执行Graph评估每个简历 interviewGraph.execute(state); // 将结果保存到数据库或发送通知 saveScreeningResult(state); } } }需要在Application类上添加EnableAsync注解。9. 资源占用与性能观察由于本项目主要调用远程大模型 API本地资源消耗主要在应用本身和网络 I/O。内存占用一个典型的 Spring Boot 应用启动后JVM 堆内存占用约 200-500 MB取决于模型上下文缓存大小。可以通过-Xmx参数调整。CPU 使用JSON 解析、逻辑处理会消耗少量 CPU通常不是瓶颈。网络 I/O主要性能开销在于大模型 API 调用的网络延迟。建议配置合理的连接超时和读取超时如 30s。对非实时任务使用异步处理避免阻塞主线程。考虑使用模型 API 的批量处理功能如果支持。Token 消耗与成本这是核心成本。需要监控提示词 (Prompt) Token 数输入给模型的文本长度。补全 (Completion) Token 数模型生成的文本长度。可以在ChatClient调用前后记录日志或使用 Spring AI 的Observation机制进行监控。优化提示词是降低成本的关键。10. 常见问题与排查方法问题现象可能原因排查方式解决方案应用启动失败提示No qualifying bean of type ChatClientSpring AI Alibaba 依赖未正确引入或配置错误检查pom.xml依赖和版本检查application.yml中spring.ai.alibaba.dashscope.api-key配置确认依赖已添加API Key 配置正确且有效调用 API 返回 401 或 403 错误API Key 无效、过期或没有对应模型的权限查看控制台日志在阿里云控制台检查 API Key 状态和模型服务开通情况更换或续费 API Key在控制台开通对应模型服务调用 Tool 时模型不识别或参数错误Tool注解的描述或ToolParam描述不清晰检查 Tool 方法的命名和描述是否准确易懂优化 Tool 的名称和描述使其更符合自然语言习惯Graph 执行卡在某个节点不继续节点condition条件判断逻辑有误或节点action抛出未处理的异常在节点action中添加日志检查State中的数据流调试condition逻辑在action中添加 try-catch 并记录异常生成的面试问题质量不高或无关提示词 (Prompt) 设计不佳或提供给模型的上下文信息不足审查发送给模型的完整 Prompt 内容迭代优化提示词提供更明确的指令、示例Few-shot和格式要求处理长简历时 API 调用超时输入文本过长超过模型上下文长度或网络处理时间监控输入 Token 数查看 API 返回的错误信息对长文本进行分段、摘要后再输入调整 API 超时时间设置批量处理时速度慢同步顺序调用导致检查代码是否为顺序执行改为使用Async异步或线程池并行处理注意 API 速率限制11. 最佳实践与使用建议提示词工程化将提示词剥离到配置文件或数据库中便于管理和迭代。可以设计不同的提示词模板用于不同场景筛选、生成问题、回答政策。工具设计原则Tool 应保持功能单一、接口明确。复杂的业务逻辑应在 Tool 内部或 Java Service 中完成Tool 只负责提供标准化的调用接口。状态设计State对象应包含任务所需的所有数据并清晰区分输入、输出和中间状态。避免在Graph节点间通过全局变量传递数据。Graph 编排保持Graph的清晰性和可维护性。复杂的流程可以拆分为多个子图Subgraph。为关键节点添加详细的日志。错误处理与降级对于模型 API 调用失败应有重试机制和友好的降级响应如“服务繁忙请稍后再试”。测试策略单元测试针对每个Tool和Graph的Node进行测试。集成测试测试完整的Graph执行流程可以使用 Mock 来模拟模型 API 和外部服务。端到端测试模拟真实用户请求验证从 API 到最终输出的全链路。安全与合规API 密钥管理使用环境变量或专业的密钥管理服务如 Vault。输入输出过滤对用户输入的简历文本和模型输出的内容进行必要的敏感信息过滤和审核。访问控制对暴露的 Agent API 实施认证和授权。通过这个完整的实战案例你不仅学会了如何使用 Spring AI Alibaba Graph 搭建一个 HR AI Agent更重要的是掌握了构建生产级 AI Agent 应用的整套方法论。从环境搭建、核心概念理解、代码实现到性能优化和问题排查这20个技术点覆盖了开发全过程。接下来你可以尝试将其扩展到更复杂的场景例如集成向量数据库构建简历知识库或结合工作流引擎实现全自动的招聘流程。