找回密码
 立即注册
首页 业界区 科技 Agent设计模式学习(基于langchain4j实现)(1) - 基础Agen ...

Agent设计模式学习(基于langchain4j实现)(1) - 基础Agent用法

士沌 6 小时前

自近年AI智能体火爆以来,各种相关的框架和最佳实践也不断涌现,Anthropic公司2024年发布的Building Effective AI Agents \ Anthropic 无疑是最有影响力的指导文章之一,langchain4j在此影响之下,也实现一系列的workflow编排&Agent功能。

本文将在langchain4j官方示例基础上(不熟悉langchain4j的朋友,请移步langchain4j学习系列),介绍几个主要模式的用法,今天先来看最基本的Agent如何实现

为方便讨论,先交待一下这一系列的业务背景

  • 假设有1个公司要招聘,将利用Agent来实现简历生成(通过个人介绍)、简历筛选、简历优化 等一系列功能。
  • 候选人的个人资料 user_life_stody.txt
  1. John Doe 现居比利时安特卫普(Rue des Carmes 12, 2000 Antwerp),联系方式为 john.doe.dev@protonmail.com 或 +32 495 67 89 23。他在 LinkedIn 和 GitHub 上保持活跃。
  2. - 2020 年完成夜间 Java 集训营(2019–2020)后从机械工程领域转型至软件开发。
  3. - 拥有 4 年软件开发经验,其中最近 2 年专注于 Java 后端开发(Spring Boot、PostgreSQL、Kafka 基础)。
  4. - 开发了一款内部报价工具,将报价周转时间缩短约 35%。
  5. - 领导 3 人专项小组,将遗留 SOAP 服务迁移至 REST 架构。
  6. - 熟悉 Docker 与 CI 流水线(GitHub Actions)。
  7. - 具备 React 使用经验,曾开发内部管理面板(非核心优势)。
  8. - 重视代码整洁与可维护性,乐于指导实习生。
  9. - 偏好产品开发而非外包项目;不喜冗长会议,注重交付实际价值。
  10. - 语言:荷兰语(母语)、英语(C1)、法语(B1)。
  11. - 教育背景:机械工程学士(2016 年),Java 集训营(2019–2020)。
  12. - 个人项目包括一款小型预算管理应用(Spring + Vue)和一套家庭物联网系统(ESP32 + MQTT)。
复制代码

  

一、定义Agent接口

  1. 1 public interface CvGenerator {
  2. 2 @UserMessage("""
  3. 3 以下是我的个人生活和职业经历信息,
  4. 4 请将其整理成一份清晰、完整的简历。
  5. 5
  6. 6 注意事项:
  7. 7 1. 不要编造任何事实
  8. 8 2. 不要遗漏任何技能或经历
  9. 9 3. 这份简历后续会进一步优化,请确保内容完整
  10. 10
  11. 11 我的个人经历:{{lifeStory}}
  12. 12 """)
  13. 13 @Agent("基于用户提供的信息生成规范的简历")
  14. 14 String generateCv(@V("lifeStory") String userInfo);
  15. 15 }
复制代码

这个正是langchain4j中的AiService,只不过这里我们使用了@Agent这个注解,需要添加下面的依赖

  1. 1 <dependency>
  2. 2 <groupId>dev.langchain4j</groupId>
  3. 3 langchain4j-agentic</artifactId>
  4. 4 <version>1.10.0-beta18</version>
  5. 5 </dependency>
复制代码

 

二、最基础的Agent示例

1.gif
2.gif
  1. 1 /**
  2. 2 该示例演示了如何实现一个基础Agent(改编自langchain4j官网示例)
  3. 3 注意:Agent只有与其他Agent结合使用时才更有用,后续步骤中将展示这一点。
  4. 4 如果只有一个Agent,使用 AiService 会是更好的选择。
  5. 5 这个基础Agent将用户的个人简介转换成一个简洁而完整的简历。
  6. 6 注意:运行此程序可能需要一些时间,因为输出的简历会相当长,LLM也需要一些时间处理。
  7. 7 @author 菩提树下的杨过(yjmyzz.cnblogs.com)
  8. 8 @see _1a_Basic_Agent_Example
  9. 9 */
  10. 10 @SpringBootApplication
  11. 11 public class _1a_Basic_Agent_Example {
  12. 12
  13. 13 public static void main(String[] args) throws IOException {
  14. 14 ConfigurableApplicationContext context = SpringApplication.run(AgentDesignPatternApplication.class, args);
  15. 15 ChatModel model = context.getBean("ollamaChatModel", ChatModel.class);
  16. 16
  17. 17 CvGenerator cvGenerator = AgenticServices
  18. 18 .agentBuilder(CvGenerator.class)
  19. 19 .chatModel(model)
  20. 20 //定义输出对象的键
  21. 21 .outputKey("masterCv")
  22. 22 .build();
  23. 23
  24. 24 // 加载个人介绍
  25. 25 String lifeStory = StringLoader.loadFromResource("/documents/user_life_story.txt");
  26. 26
  27. 27 // 让 agent 生成简历
  28. 28 String cv = cvGenerator.generateCv(lifeStory);
  29. 29
  30. 30 // 打印简历
  31. 31 System.out.println("=== 简历 ===");
  32. 32 System.out.println(cv);
  33. 33 }
  34. 34
  35. 35
  36. 36 }
复制代码
View Code

运行结果:

3.gif
4.gif
  1. 1 2026-01-11T19:36:17.012+08:00 INFO 16080 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request:
  2. 2 - method: POST
  3. 3 - url: http://localhost:11434/api/chat
  4. 4 - headers: [Content-Type: application/json]
  5. 5 - body: {
  6. 6 "model" : "deepseek-v3.1:671b-cloud",
  7. 7 "messages" : [ {
  8. 8 "role" : "user",
  9. 9 "content" : "以下是我的个人生活和职业经历信息,\n请将其整理成一份清晰、完整的简历。\n\n注意事项:\n1. 不要编造任何事实\n2. 不要遗漏任何技能或经历\n3. 这份简历后续会进一步优化,请确保内容完整\n\n我的个人经历:John Doe 现居比利时安特卫普(Rue des Carmes 12, 2000 Antwerp),联系方式为 john.doe.dev@protonmail.com 或 +32 495 67 89 23。他在 LinkedIn 和 GitHub 上保持活跃。\r\n\r\n- 2020 年完成夜间 Java 集训营(2019–2020)后从机械工程领域转型至软件开发。\r\n- 拥有 4 年软件开发经验,其中最近 2 年专注于 Java 后端开发(Spring Boot、PostgreSQL、Kafka 基础)。\r\n- 开发了一款内部报价工具,将报价周转时间缩短约 35%。\r\n- 领导 3 人专项小组,将遗留 SOAP 服务迁移至 REST 架构。\r\n- 熟悉 Docker 与 CI 流水线(GitHub Actions)。\r\n- 具备 React 使用经验,曾开发内部管理面板(非核心优势)。\r\n- 重视代码整洁与可维护性,乐于指导实习生。\r\n- 偏好产品开发而非外包项目;不喜冗长会议,注重交付实际价值。\r\n- 语言:荷兰语(母语)、英语(C1)、法语(B1)。\r\n- 教育背景:机械工程学士(2016 年),Java 集训营(2019–2020)。\r\n- 个人项目包括一款小型预算管理应用(Spring + Vue)和一套家庭物联网系统(ESP32 + MQTT)。\n"
  10. 10 } ],
  11. 11 "options" : {
  12. 12 "stop" : [ ]
  13. 13 },
  14. 14 "stream" : false,
  15. 15 "tools" : [ ]
  16. 16 }
  17. 17
  18. 18 2026-01-11T19:36:24.079+08:00 INFO 16080 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP response:
  19. 19 - status code: 200
  20. 20 - headers: [content-type: application/json; charset=utf-8], [date: Sun, 11 Jan 2026 11:36:24 GMT], [transfer-encoding: chunked]
  21. 21 - body: {"model":"deepseek-v3.1:671b-cloud","remote_model":"deepseek-v3.1:671b","remote_host":"https://ollama.com:443","created_at":"2026-01-11T11:36:23.745953889Z","message":{"role":"assistant","content":"# John Doe - 简历\n\n**地址** \nRue des Carmes 12, 2000 Antwerp, Belgium \n**邮箱** \njohn.doe.dev@protonmail.com \n**电话** \n+32 495 67 89 23 \n**在线资料** \nLinkedIn | GitHub \n\n---\n\n## 职业摘要\n拥有4年软件开发经验的Java后端开发者,其中最近2年专注于Java生态系统(Spring Boot、PostgreSQL、Kafka)。具备从机械工程成功转型至软件开发的背景,擅长构建可维护的代码、优化流程,并乐于指导团队成员。注重产品价值交付,偏好产品导向的开发环境。\n\n---\n\n## 技能专长\n- **后端开发**: Java, Spring Boot, REST API, PostgreSQL, Kafka (基础)\n- **工具与流程**: Docker, CI/CD (GitHub Actions), Git\n- **前端经验**: React (内部工具开发), Vue.js (个人项目)\n- **软技能**: 代码整洁与可维护性、团队协作、指导实习生、问题解决\n- **语言**: 荷兰语 (母语), 英语 (C1), 法语 (B1)\n\n---\n\n## 职业经历\n**软件开发工程师** \n*2020年至今* \n- 开发内部报价工具,将报价周转时间缩短约35%。\n- 领导3人专项小组,完成遗留SOAP服务至REST架构的迁移。\n- 使用Spring Boot和PostgreSQL构建后端服务,并集成Kafka进行事件驱动通信。\n- 通过Docker容器化应用,利用GitHub Actions设置CI流水线以提高部署效率。\n- 曾开发React内部管理面板以支持业务运营(非核心职责)。\n- 积极指导实习生,提倡代码可读性与系统可维护性。\n\n---\n\n## 教育背景\n- **Java 夜间集训营** \n *2019–2020* \n 集中学习Java编程、数据结构、Web开发与团队项目协作。\n\n- **机械工程学士** \n *2016年毕业* \n 具备工程问题分析与系统化解决能力。\n\n---\n\n## 个人项目\n- **预算管理应用** \n 使用Spring Boot与Vue.js构建的个人预算跟踪工具,支持支出分类与可视化报表。\n \n- **家庭物联网系统** \n 基于ESP32微控制器与MQTT协议搭建的自动化家居监控系统,实现传感器数据采集与远程控制。\n\n---\n\n## 备注\n- 偏好产品导向的开发环境,注重交付实际价值而非冗长会议。\n- 对技术充满热情,持续通过个人项目与实践深化全栈技能。\n\n---\n*简历内容基于提供的经历信息整理,未添加任何编造内容,可随时进一步优化格式与重点。*"},"done":true,"done_reason":"stop","total_duration":6020764924,"prompt_eval_count":387,"eval_count":566}
  22. 22
  23. 23
  24. 24 === 简历 ===
  25. 25 # John Doe - 简历
  26. 26
  27. 27 **地址**
  28. 28 Rue des Carmes 12, 2000 Antwerp, Belgium
  29. 29 **邮箱**
  30. 30 john.doe.dev@protonmail.com
  31. 31 **电话**
  32. 32 +32 495 67 89 23
  33. 33 **在线资料**
  34. 34 LinkedIn | GitHub
  35. 35
  36. 36 ---
  37. 37
  38. 38 ## 职业摘要
  39. 39 拥有4年软件开发经验的Java后端开发者,其中最近2年专注于Java生态系统(Spring Boot、PostgreSQL、Kafka)。具备从机械工程成功转型至软件开发的背景,擅长构建可维护的代码、优化流程,并乐于指导团队成员。注重产品价值交付,偏好产品导向的开发环境。
  40. 40
  41. 41 ---
  42. 42
  43. 43 ## 技能专长
  44. 44 - **后端开发**: Java, Spring Boot, REST API, PostgreSQL, Kafka (基础)
  45. 45 - **工具与流程**: Docker, CI/CD (GitHub Actions), Git
  46. 46 - **前端经验**: React (内部工具开发), Vue.js (个人项目)
  47. 47 - **软技能**: 代码整洁与可维护性、团队协作、指导实习生、问题解决
  48. 48 - **语言**: 荷兰语 (母语), 英语 (C1), 法语 (B1)
  49. 49
  50. 50 ---
  51. 51
  52. 52 ## 职业经历
  53. 53 **软件开发工程师**
  54. 54 *2020年至今*
  55. 55 - 开发内部报价工具,将报价周转时间缩短约35%。
  56. 56 - 领导3人专项小组,完成遗留SOAP服务至REST架构的迁移。
  57. 57 - 使用Spring Boot和PostgreSQL构建后端服务,并集成Kafka进行事件驱动通信。
  58. 58 - 通过Docker容器化应用,利用GitHub Actions设置CI流水线以提高部署效率。
  59. 59 - 曾开发React内部管理面板以支持业务运营(非核心职责)。
  60. 60 - 积极指导实习生,提倡代码可读性与系统可维护性。
  61. 61
  62. 62 ---
  63. 63
  64. 64 ## 教育背景
  65. 65 - **Java 夜间集训营**
  66. 66 *2019–2020*
  67. 67 集中学习Java编程、数据结构、Web开发与团队项目协作。
  68. 68
  69. 69 - **机械工程学士**
  70. 70 *2016年毕业*
  71. 71 具备工程问题分析与系统化解决能力。
  72. 72
  73. 73 ---
  74. 74
  75. 75 ## 个人项目
  76. 76 - **预算管理应用**
  77. 77 使用Spring Boot与Vue.js构建的个人预算跟踪工具,支持支出分类与可视化报表。
  78. 78
  79. 79 - **家庭物联网系统**
  80. 80 基于ESP32微控制器与MQTT协议搭建的自动化家居监控系统,实现传感器数据采集与远程控制。
  81. 81
  82. 82 ---
  83. 83
  84. 84 ## 备注
  85. 85 - 偏好产品导向的开发环境,注重交付实际价值而非冗长会议。
  86. 86 - 对技术充满热情,持续通过个人项目与实践深化全栈技能。
  87. 87
  88. 88 ---
  89. 89 *简历内容基于提供的经历信息整理,未添加任何编造内容,可随时进一步优化格式与重点。*
复制代码
View Code

 24-82行,就是基于“个人资料”生成的简历。

 

三、结构化输出

如果希望生成的简历,以结构化输出(即:直接输出POJO对象实例),可以稍微改进:

3.1 定义简历POJO类Cv

5.gif
6.gif
  1. 1 /**
  2. 2 * 简历类
  3. 3 */
  4. 4 public class Cv {
  5. 5 @Description("候选人的专业技能,逗号串接")
  6. 6 private String skills;
  7. 7
  8. 8 @Description("候选人的专业经历")
  9. 9 private String professionalExperience;
  10. 10
  11. 11 @Description("候选人的教育背景")
  12. 12 private String studies;
  13. 13
  14. 14 @Override
  15. 15 public String toString() {
  16. 16 return "CV:\n" +
  17. 17 "专业技能 = "" + skills + ""\n" +
  18. 18 "专业经历 = "" + professionalExperience + ""\n" +
  19. 19 "教育背景 = "" + studies + ""\n";
  20. 20 }
  21. 21 }
复制代码
View Code

3.2 定义结构化Agent接口

7.gif
8.gif
  1. 1 public interface CvGeneratorStructuredOutput {
  2. 2 @UserMessage("""
  3. 3 以下是我的个人生活和职业经历信息,
  4. 4 请将其整理成一份清晰、完整的简历。
  5. 5
  6. 6 注意事项:
  7. 7 1. 不要编造任何事实
  8. 8 2. 不要遗漏任何技能或经历
  9. 9 3. 这份简历后续会进一步优化,请确保内容完整
  10. 10
  11. 11 我的个人经历:{{lifeStory}}
  12. 12 """)
  13. 13 @Agent("基于用户提供的信息生成规范的简历")
  14. 14 Cv generateCv(@V("lifeStory") String userInfo);
  15. 15 }
复制代码
View Code

3.3 结构化输出Agent

9.gif
10.gif
  1. 1 public class _1b_Basic_Agent_Example_Structured {
  2. 2
  3. 3 public static void main(String[] args) throws IOException {
  4. 4 ConfigurableApplicationContext context = SpringApplication.run(AgentDesignPatternApplication.class, args);
  5. 5 ChatModel model = context.getBean("ollamaChatModel", ChatModel.class);
  6. 6
  7. 7 CvGeneratorStructuredOutput cvGenerator = AgenticServices
  8. 8 .agentBuilder(CvGeneratorStructuredOutput.class)
  9. 9 .chatModel(model)
  10. 10 .build();
  11. 11
  12. 12 // 加载个人介绍
  13. 13 String lifeStory = StringLoader.loadFromResource("/documents/user_life_story.txt");
  14. 14
  15. 15 // 让 agent 生成简历
  16. 16 Cv cvStructured = cvGenerator.generateCv(lifeStory);
  17. 17
  18. 18 // 打印简历
  19. 19 System.out.println("=== 简历 ===");
  20. 20 System.out.println(cvStructured);
  21. 21 }
  22. 22 }
复制代码
View Code

输出:

11.gif
12.gif
  1. 1 2026-01-11T19:58:32.855+08:00 INFO 16512 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request:
  2. 2 - method: POST
  3. 3 - url: http://localhost:11434/api/chat
  4. 4 - headers: [Content-Type: application/json]
  5. 5 - body: {
  6. 6 "model" : "deepseek-v3.1:671b-cloud",
  7. 7 "messages" : [ {
  8. 8 "role" : "user",
  9. 9 "content" : "以下是我的个人生活和职业经历信息,\n请将其整理成一份清晰、完整的简历。\n\n注意事项:\n1. 不要编造任何事实\n2. 不要遗漏任何技能或经历\n3. 这份简历后续会进一步优化,请确保内容完整\n\n我的个人经历:John Doe 现居比利时安特卫普(Rue des Carmes 12, 2000 Antwerp),联系方式为 john.doe.dev@protonmail.com 或 +32 495 67 89 23。他在 LinkedIn 和 GitHub 上保持活跃。\r\n\r\n- 2020 年完成夜间 Java 集训营(2019–2020)后从机械工程领域转型至软件开发。\r\n- 拥有 4 年软件开发经验,其中最近 2 年专注于 Java 后端开发(Spring Boot、PostgreSQL、Kafka 基础)。\r\n- 开发了一款内部报价工具,将报价周转时间缩短约 35%。\r\n- 领导 3 人专项小组,将遗留 SOAP 服务迁移至 REST 架构。\r\n- 熟悉 Docker 与 CI 流水线(GitHub Actions)。\r\n- 具备 React 使用经验,曾开发内部管理面板(非核心优势)。\r\n- 重视代码整洁与可维护性,乐于指导实习生。\r\n- 偏好产品开发而非外包项目;不喜冗长会议,注重交付实际价值。\r\n- 语言:荷兰语(母语)、英语(C1)、法语(B1)。\r\n- 教育背景:机械工程学士(2016 年),Java 集训营(2019–2020)。\r\n- 个人项目包括一款小型预算管理应用(Spring + Vue)和一套家庭物联网系统(ESP32 + MQTT)。\n\nYou must answer strictly in the following JSON format: {\n"skills": (候选人的专业技能,逗号串接; type: string),\n"professionalExperience": (候选人的专业经历; type: string),\n"studies": (候选人的教育背景; type: string)\n}"
  10. 10 } ],
  11. 11 "options" : {
  12. 12 "stop" : [ ]
  13. 13 },
  14. 14 "stream" : false,
  15. 15 "tools" : [ ]
  16. 16 }
  17. 17
  18. 18 2026-01-11T19:58:36.010+08:00 INFO 16512 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP response:
  19. 19 - status code: 200
  20. 20 - headers: [content-type: application/json; charset=utf-8], [date: Sun, 11 Jan 2026 11:58:35 GMT], [transfer-encoding: chunked]
  21. 21 - body: {"model":"deepseek-v3.1:671b-cloud","remote_model":"deepseek-v3.1:671b","remote_host":"https://ollama.com:443","created_at":"2026-01-11T11:58:35.375858113Z","message":{"role":"assistant","content":"{\n"skills": "Java, Spring Boot, PostgreSQL, Kafka, REST API, Docker, CI/CD (GitHub Actions), React, 代码整洁与可维护性, 指导与协作, 荷兰语(母语), 英语(C1), 法语(B1)",\n"professionalExperience": "拥有4年软件开发经验,其中最近2年专注于Java后端开发。开发了一款内部报价工具,将报价周转时间缩短约35%。领导一个3人专项小组,成功将遗留SOAP服务迁移至REST架构。具备Docker与CI流水线(GitHub Actions)实践经验。有React使用经验,曾开发内部管理面板。重视代码质量,乐于指导实习生。偏好产品开发,注重交付实际价值。个人项目包括一款小型预算管理应用(Spring + Vue)和一套家庭物联网系统(ESP32 + MQTT)。",\n"studies": "机械工程学士(2016年毕业),Java集训营(2019-2020年)"\n}"},"done":true,"done_reason":"stop","total_duration":1828432886,"prompt_eval_count":444,"eval_count":212}
  22. 22
  23. 23
  24. 24 === 简历 ===
  25. 25 CV:
  26. 26 专业技能 = "Java, Spring Boot, PostgreSQL, Kafka, REST API, Docker, CI/CD (GitHub Actions), React, 代码整洁与可维护性, 指导与协作, 荷兰语(母语), 英语(C1), 法语(B1)"
  27. 27 专业经历 = "拥有4年软件开发经验,其中最近2年专注于Java后端开发。开发了一款内部报价工具,将报价周转时间缩短约35%。领导一个3人专项小组,成功将遗留SOAP服务迁移至REST架构。具备Docker与CI流水线(GitHub Actions)实践经验。有React使用经验,曾开发内部管理面板。重视代码质量,乐于指导实习生。偏好产品开发,注重交付实际价值。个人项目包括一款小型预算管理应用(Spring + Vue)和一套家庭物联网系统(ESP32 + MQTT)。"
  28. 28 教育背景 = "机械工程学士(2016年毕业),Java集训营(2019-2020年)"
复制代码
View Code

24-28行输出,即为Cv实例的toString结果。

 

小结:

本文示例了利用AgenticServices+@Agent注解生成1个最基本的Agent,虽然单就本例而言,还体现不出Agent与AiService的区别,但从下一篇开始,就能看到多个Agent之间的workflow编排。

 

文中示例代码:

https://github.com/yjmyzz/agentic_turoial_with_langchain4j

 

参考:

Building Effective AI Agents \ Anthropic

[译] AI Workflow & AI Agent:架构、模式与工程建议(Anthropic,2024)

Agents and Agentic AI | LangChain4j


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册