博客 / 詳情

返回

Agent設計模式學習(基於langchain4j實現)(1) - 基礎Agent用法

自近年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 }
View Code

運行結果:

 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   *20192020*  
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 *簡歷內容基於提供的經歷信息整理,未添加任何編造內容,可隨時進一步優化格式與重點。*
View Code

 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 }
View Code

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 }
View Code

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 }
View Code

輸出:

 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年)"
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

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.