自近年AI智能體火爆以來,各種相關的框架和最佳實踐也不斷涌現,Anthropic公司2024年發佈的Building Effective AI Agents \ Anthropic 無疑是最有影響力的指導文章之一,langchain4j在此影響之下,也實現一系列的workflow編排&Agent功能。
本文將在langchain4j官方示例基礎上(不熟悉langchain4j的朋友,請移步langchain4j學習系列),介紹幾個主要模式的用法,今天先來看最基本的Agent如何實現
為方便討論,先交待一下這一系列的業務背景:
- 假設有1個公司要招聘,將利用Agent來實現簡歷生成(通過個人介紹)、簡歷篩選、簡歷優化 等一系列功能。
- 候選人的個人資料 user_life_stody.txt
John Doe 現居比利時安特衞普(Rue des Carmes 12, 2000 Antwerp),聯繫方式為 john.doe.dev@protonmail.com 或 +32 495 67 89 23。他在 LinkedIn 和 GitHub 上保持活躍。 - 2020 年完成夜間 Java 集訓營(2019–2020)後從機械工程領域轉型至軟件開發。 - 擁有 4 年軟件開發經驗,其中最近 2 年專注於 Java 後端開發(Spring Boot、PostgreSQL、Kafka 基礎)。 - 開發了一款內部報價工具,將報價週轉時間縮短約 35%。 - 領導 3 人專項小組,將遺留 SOAP 服務遷移至 REST 架構。 - 熟悉 Docker 與 CI 流水線(GitHub Actions)。 - 具備 React 使用經驗,曾開發內部管理面板(非核心優勢)。 - 重視代碼整潔與可維護性,樂於指導實習生。 - 偏好產品開發而非外包項目;不喜冗長會議,注重交付實際價值。 - 語言:荷蘭語(母語)、英語(C1)、法語(B1)。 - 教育背景:機械工程學士(2016 年),Java 集訓營(2019–2020)。 - 個人項目包括一款小型預算管理應用(Spring + Vue)和一套家庭物聯網系統(ESP32 + MQTT)。
一、定義Agent接口
1 public interface CvGenerator { 2 @UserMessage(""" 3 以下是我的個人生活和職業經歷信息, 4 請將其整理成一份清晰、完整的簡歷。 5 6 注意事項: 7 1. 不要編造任何事實 8 2. 不要遺漏任何技能或經歷 9 3. 這份簡歷後續會進一步優化,請確保內容完整 10 11 我的個人經歷:{{lifeStory}} 12 """) 13 @Agent("基於用户提供的信息生成規範的簡歷") 14 String generateCv(@V("lifeStory") String userInfo); 15 }
這個正是langchain4j中的AiService,只不過這裏我們使用了@Agent這個註解,需要添加下面的依賴
1 <dependency> 2 <groupId>dev.langchain4j</groupId> 3 <artifactId>langchain4j-agentic</artifactId> 4 <version>1.10.0-beta18</version> 5 </dependency>
二、最基礎的Agent示例
1 /** 2 該示例演示瞭如何實現一個基礎Agent(改編自<a href="https://github.com/langchain4j/langchain4j-examples">langchain4j官網示例</a>) 3 注意:Agent只有與其他Agent結合使用時才更有用,後續步驟中將展示這一點。 4 如果只有一個Agent,使用 AiService 會是更好的選擇。 5 這個基礎Agent將用户的個人簡介轉換成一個簡潔而完整的簡歷。 6 注意:運行此程序可能需要一些時間,因為輸出的簡歷會相當長,LLM也需要一些時間處理。 7 @author 菩提樹下的楊過(yjmyzz.cnblogs.com) 8 @see <a href="https://github.com/langchain4j/langchain4j-examples/blob/main/agentic-tutorial/src/main/java/_1_basic_agent/_1a_Basic_Agent_Example.java">_1a_Basic_Agent_Example</a> 9 */ 10 @SpringBootApplication 11 public class _1a_Basic_Agent_Example { 12 13 public static void main(String[] args) throws IOException { 14 ConfigurableApplicationContext context = SpringApplication.run(AgentDesignPatternApplication.class, args); 15 ChatModel model = context.getBean("ollamaChatModel", ChatModel.class); 16 17 CvGenerator cvGenerator = AgenticServices 18 .agentBuilder(CvGenerator.class) 19 .chatModel(model) 20 //定義輸出對象的鍵 21 .outputKey("masterCv") 22 .build(); 23 24 // 加載個人介紹 25 String lifeStory = StringLoader.loadFromResource("/documents/user_life_story.txt"); 26 27 // 讓 agent 生成簡歷 28 String cv = cvGenerator.generateCv(lifeStory); 29 30 // 打印簡歷 31 System.out.println("=== 簡歷 ==="); 32 System.out.println(cv); 33 } 34 35 36 }
運行結果:
1 2026-01-11T19:36:17.012+08:00 INFO 16080 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request: 2 - method: POST 3 - url: http://localhost:11434/api/chat 4 - headers: [Content-Type: application/json] 5 - body: { 6 "model" : "deepseek-v3.1:671b-cloud", 7 "messages" : [ { 8 "role" : "user", 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 } ], 11 "options" : { 12 "stop" : [ ] 13 }, 14 "stream" : false, 15 "tools" : [ ] 16 } 17 18 2026-01-11T19:36:24.079+08:00 INFO 16080 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP response: 19 - status code: 200 20 - headers: [content-type: application/json; charset=utf-8], [date: Sun, 11 Jan 2026 11:36:24 GMT], [transfer-encoding: chunked] 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 23 24 === 簡歷 === 25 # John Doe - 簡歷 26 27 **地址** 28 Rue des Carmes 12, 2000 Antwerp, Belgium 29 **郵箱** 30 john.doe.dev@protonmail.com 31 **電話** 32 +32 495 67 89 23 33 **在線資料** 34 LinkedIn | GitHub 35 36 --- 37 38 ## 職業摘要 39 擁有4年軟件開發經驗的Java後端開發者,其中最近2年專注於Java生態系統(Spring Boot、PostgreSQL、Kafka)。具備從機械工程成功轉型至軟件開發的背景,擅長構建可維護的代碼、優化流程,並樂於指導團隊成員。注重產品價值交付,偏好產品導向的開發環境。 40 41 --- 42 43 ## 技能專長 44 - **後端開發**: Java, Spring Boot, REST API, PostgreSQL, Kafka (基礎) 45 - **工具與流程**: Docker, CI/CD (GitHub Actions), Git 46 - **前端經驗**: React (內部工具開發), Vue.js (個人項目) 47 - **軟技能**: 代碼整潔與可維護性、團隊協作、指導實習生、問題解決 48 - **語言**: 荷蘭語 (母語), 英語 (C1), 法語 (B1) 49 50 --- 51 52 ## 職業經歷 53 **軟件開發工程師** 54 *2020年至今* 55 - 開發內部報價工具,將報價週轉時間縮短約35%。 56 - 領導3人專項小組,完成遺留SOAP服務至REST架構的遷移。 57 - 使用Spring Boot和PostgreSQL構建後端服務,並集成Kafka進行事件驅動通信。 58 - 通過Docker容器化應用,利用GitHub Actions設置CI流水線以提高部署效率。 59 - 曾開發React內部管理面板以支持業務運營(非核心職責)。 60 - 積極指導實習生,提倡代碼可讀性與系統可維護性。 61 62 --- 63 64 ## 教育背景 65 - **Java 夜間集訓營** 66 *2019–2020* 67 集中學習Java編程、數據結構、Web開發與團隊項目協作。 68 69 - **機械工程學士** 70 *2016年畢業* 71 具備工程問題分析與系統化解決能力。 72 73 --- 74 75 ## 個人項目 76 - **預算管理應用** 77 使用Spring Boot與Vue.js構建的個人預算跟蹤工具,支持支出分類與可視化報表。 78 79 - **家庭物聯網系統** 80 基於ESP32微控制器與MQTT協議搭建的自動化家居監控系統,實現傳感器數據採集與遠程控制。 81 82 --- 83 84 ## 備註 85 - 偏好產品導向的開發環境,注重交付實際價值而非冗長會議。 86 - 對技術充滿熱情,持續通過個人項目與實踐深化全棧技能。 87 88 --- 89 *簡歷內容基於提供的經歷信息整理,未添加任何編造內容,可隨時進一步優化格式與重點。*
24-82行,就是基於“個人資料”生成的簡歷。
三、結構化輸出
如果希望生成的簡歷,以結構化輸出(即:直接輸出POJO對象實例),可以稍微改進:
3.1 定義簡歷POJO類Cv
1 /** 2 * 簡歷類 3 */ 4 public class Cv { 5 @Description("候選人的專業技能,逗號串接") 6 private String skills; 7 8 @Description("候選人的專業經歷") 9 private String professionalExperience; 10 11 @Description("候選人的教育背景") 12 private String studies; 13 14 @Override 15 public String toString() { 16 return "CV:\n" + 17 "專業技能 = \"" + skills + "\"\n" + 18 "專業經歷 = \"" + professionalExperience + "\"\n" + 19 "教育背景 = \"" + studies + "\"\n"; 20 } 21 }
3.2 定義結構化Agent接口
1 public interface CvGeneratorStructuredOutput { 2 @UserMessage(""" 3 以下是我的個人生活和職業經歷信息, 4 請將其整理成一份清晰、完整的簡歷。 5 6 注意事項: 7 1. 不要編造任何事實 8 2. 不要遺漏任何技能或經歷 9 3. 這份簡歷後續會進一步優化,請確保內容完整 10 11 我的個人經歷:{{lifeStory}} 12 """) 13 @Agent("基於用户提供的信息生成規範的簡歷") 14 Cv generateCv(@V("lifeStory") String userInfo); 15 }
3.3 結構化輸出Agent
1 public class _1b_Basic_Agent_Example_Structured { 2 3 public static void main(String[] args) throws IOException { 4 ConfigurableApplicationContext context = SpringApplication.run(AgentDesignPatternApplication.class, args); 5 ChatModel model = context.getBean("ollamaChatModel", ChatModel.class); 6 7 CvGeneratorStructuredOutput cvGenerator = AgenticServices 8 .agentBuilder(CvGeneratorStructuredOutput.class) 9 .chatModel(model) 10 .build(); 11 12 // 加載個人介紹 13 String lifeStory = StringLoader.loadFromResource("/documents/user_life_story.txt"); 14 15 // 讓 agent 生成簡歷 16 Cv cvStructured = cvGenerator.generateCv(lifeStory); 17 18 // 打印簡歷 19 System.out.println("=== 簡歷 ==="); 20 System.out.println(cvStructured); 21 } 22 }
輸出:
1 2026-01-11T19:58:32.855+08:00 INFO 16512 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP request: 2 - method: POST 3 - url: http://localhost:11434/api/chat 4 - headers: [Content-Type: application/json] 5 - body: { 6 "model" : "deepseek-v3.1:671b-cloud", 7 "messages" : [ { 8 "role" : "user", 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 } ], 11 "options" : { 12 "stop" : [ ] 13 }, 14 "stream" : false, 15 "tools" : [ ] 16 } 17 18 2026-01-11T19:58:36.010+08:00 INFO 16512 --- [langchain4j-study] [ main] d.l.http.client.log.LoggingHttpClient : HTTP response: 19 - status code: 200 20 - headers: [content-type: application/json; charset=utf-8], [date: Sun, 11 Jan 2026 11:58:35 GMT], [transfer-encoding: chunked] 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 23 24 === 簡歷 === 25 CV: 26 專業技能 = "Java, Spring Boot, PostgreSQL, Kafka, REST API, Docker, CI/CD (GitHub Actions), React, 代碼整潔與可維護性, 指導與協作, 荷蘭語(母語), 英語(C1), 法語(B1)" 27 專業經歷 = "擁有4年軟件開發經驗,其中最近2年專注於Java後端開發。開發了一款內部報價工具,將報價週轉時間縮短約35%。領導一個3人專項小組,成功將遺留SOAP服務遷移至REST架構。具備Docker與CI流水線(GitHub Actions)實踐經驗。有React使用經驗,曾開發內部管理面板。重視代碼質量,樂於指導實習生。偏好產品開發,注重交付實際價值。個人項目包括一款小型預算管理應用(Spring + Vue)和一套家庭物聯網系統(ESP32 + MQTT)。" 28 教育背景 = "機械工程學士(2016年畢業),Java集訓營(2019-2020年)"
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