1. 1. 事前準備

歡迎!在本程式碼研究室中,您將瞭解如何使用熱門的 LangChain4j 框架及其新的 Google GenAI 模組,以 Java 建構代理式 AI 應用程式。
代理式 AI 是指 LLM 不只會回覆提示詞,還具備工具、記憶和規劃能力,可自主達成複雜的多步驟目標。
您將從簡單的設定開始,逐步使用本機工具和結構化輸出內容建構代理,最後探索進階的多代理自動化調度管理模式,最終建立以目標為導向的動作規劃 (GOAP) 代理系統。
學習內容
- 設定新的
GoogleGenAiChatModel,連結至 Gemini。 - 啟用要求/回應記錄,方便進行偵錯。
- 使用「工具」授予 Gemini 本機 Java 程式碼的存取權。
- 強制 Gemini 採用結構化輸出格式 (POJO)。
- 使用
@Agent註解定義及建構單一用途的代理程式。 - 自動調度管理循序和平行多代理工作流程。
- 建構以目標為導向的動作規劃 (GOAP) 系統,動態規劃代理程式執行作業。
軟硬體需求
- Java Development Kit (JDK) 17 以上版本。
- 已安裝 Maven 3.5 以上版本。
- Google AI Studio 的 Gemini API 金鑰。
2. 2. 設定:專案和 API 金鑰
首先,我們需要建立新的 Maven 專案,並設定 Gemini API 金鑰。
建立 Maven 專案
為專案建立新目錄,並使用 pom.xml 檔案初始化。
將下列依附元件新增至 pom.xml。請注意,我們使用的是最新版 1.16.1-beta26 LangChain4j Google GenAI 和 Agentic 模組:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>gemini-agents-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<langchain4j.version>1.16.1-beta26</langchain4j.version>
</properties>
<dependencies>
<!-- LangChain4j Google GenAI Integration -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-google-genai</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- LangChain4j Agentic Framework Core -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-agentic</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- LangChain4j Agentic Patterns (needed for GOAP) -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-agentic-patterns</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<!-- SLF4J Logger for logging requests/responses -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>2.0.12</version>
</dependency>
</dependencies>
</project>
取得 Gemini API 金鑰
- 前往 Google AI Studio。
- 點選「Get API Key」(取得 API 金鑰)。
- 建立新金鑰 (或選取現有金鑰)。
- 在終端機中將其設為環境變數:
export GEMINI_API_KEY="your-api-key-here"
3. 3. 設定 Gemini Chat 模型
現在,我們來建立簡單的「Hello World」應用程式,該應用程式會例項化 GoogleGenAiChatModel 並傳送測試提示。
新版 GoogleGenAiChatModel 使用整合型 Google GenAI SDK,可統一存取 Gemini 模型。
在 src/main/java/com/example/HelloWorld.java 中建立名為 HelloWorld.java 的類別:
package com.example;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
public class HelloWorld {
public static void main(String[] args) {
// 1. Configure the Gemini model
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
// Enable logging for both requests and responses
.logRequestsAndResponses(true)
.build();
// 2. Invoke the model
String response = model.chat("Hello Gemini! Explain 'Agentic AI' in one sentence.");
// 3. Print response
System.out.println("\n--- Gemini Response ---");
System.out.println(response);
}
}
執行這個類別。由於已啟用 logRequestsAndResponses(true),您會看到詳細的 SLF4J 記錄,其中詳述傳送至 Google API 的確切要求酬載,以及收到的原始 JSON 回應,隨後是列印的輸出內容:
--- Gemini Response ---
**Agentic AI** refers to autonomous artificial intelligence systems that can proactively plan, make decisions, use tools, and execute multi-step tasks to achieve specific goals with minimal human supervision.
4. 4. 定義本機 Java 工具
大型語言模型功能強大,但受限於訓練資料。我們可以提供工具 (也稱為函式呼叫),擴展模型的能力。
在 LangChain4j 中,工具是簡單的 Java 類別,方法會以 @Tool 註解標註。
我們來編寫簡單的工具,計算兩個日期之間的天數。在 src/main/java/com/example/DateTools.java 中建立 DateTools.java:
package com.example;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class DateTools {
@Tool("Calculates the number of days between two dates")
public long daysBetween(
@P("The start date in ISO format (YYYY-MM-DD)") String startDate,
@P("The end date in ISO format (YYYY-MM-DD)") String endDate) {
LocalDate start = LocalDate.parse(startDate);
LocalDate end = LocalDate.parse(endDate);
return ChronoUnit.DAYS.between(start, end);
}
}
如要使用這項工具,請定義 AI 服務。在 LangChain4j Agentic 架構中,我們可以使用 AgenticServices.agentBuilder() 建構這項服務。
在 src/main/java/com/example/ToolDemo.java 中建立 ToolDemo.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.agentic.AgenticServices;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
import dev.langchain4j.service.V;
public class ToolDemo {
public interface DateAssistant {
@Agent
String ask(@V("prompt") String prompt);
}
public static void main(String[] args) {
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
.build();
// Build the assistant and register our DateTools
DateAssistant assistant = AiServices.builder(DateAssistant.class)
.chatModel(model)
.tools(new DateTools())
.build();
String response = assistant.ask("How many days are there between 2026-01-01 and 2026-06-30?");
System.out.println("Response: " + response);
}
}
執行這段程式碼時,Gemini 會分析提示、瞭解需要呼叫 daysBetween、產生工具呼叫要求,LangChain4j 會執行本機 Java 方法,將結果傳回 Gemini,而 Gemini 會將最終自然語言回覆格式化。
畫面會顯示類似以下的輸出:
Response: There are 180 days between 2026-01-01 and 2026-06-30.
5. 5. 定義結構化輸出內容
通常,您會希望大型語言模型傳回特定結構化格式的資料 (例如符合結構定義的 JSON),而非純文字。
當您將 POJO 或 Java record 指定為代理程式或服務方法的傳回類型時,LangChain4j 會自動處理這項作業。
我們來定義代表書籍擷取的 Java record:
在 src/main/java/com/example/Book.java 中建立 Book.java:
package com.example;
public record Book(String title, String author, int publicationYear) {}
現在請建立會傳回 Book 的代理程式介面。在 src/main/java/com/example/StructuredOutputDemo.java 中建立 StructuredOutputDemo.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.agentic.AgenticServices;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public class StructuredOutputDemo {
public interface BookExtractor {
@UserMessage("Extract book details from: {{text}}")
Book extract(@V("text") String text);
}
public static void main(String[] args) {
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
.build();
BookExtractor extractor = AiServices.builder(BookExtractor.class)
.chatModel(model)
.build();
String text = "I just finished reading 'Project Hail Mary' by Andy Weir, published in 2021. It was amazing!";
Book book = extractor.extract(text);
System.out.println("Extracted POJO: " + book);
}
}
Gemini 3.5 Flash 支援嚴格的 JSON 結構定義輸出內容。LangChain4j 會從 Book 記錄產生 JSON 結構定義,指示 Gemini 填入該結構定義,並將 JSON 回應還原序列化為 Book 記錄。
畫面會顯示類似以下的輸出:
Extracted POJO: Book[title=Project Hail Mary, author=Andy Weir, publicationYear=2021]
6. 6. 建立第一個代理
在 langchain4j-agentic 框架中,Agent 是使用介面方法的 @Agent 註解定義。這項註解提供可供自動化調度管理系統 (例如規劃工具) 使用的名稱/說明。
我們來建立簡單的代理程式,以主題為基礎撰寫極短的故事。
在 src/main/java/com/example/CreativeWriter.java 中建立 CreativeWriter.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface CreativeWriter {
@SystemMessage("You are a creative writer. Generate a draft of a story no more than 3 sentences long.")
@UserMessage("Write a story about {{topic}}.")
@Agent(description = "Generates a story based on the given topic", outputKey = "story")
String writeStory(@V("topic") String topic);
}
讓我們個別測試這個代理程式。在 src/main/java/com/example/AgentDemo.java 中建立 AgentDemo.java:
package com.example;
import dev.langchain4j.agentic.AgenticServices;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
public class AgentDemo {
public static void main(String[] args) {
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
.build();
CreativeWriter writer = AgenticServices.agentBuilder(CreativeWriter.class)
.chatModel(model)
.build();
String story = writer.writeStory("a lonely robot on Mars");
System.out.println("Generated Story:\n" + story);
}
}
畫面會顯示類似以下的輸出:
Generated Story:
For eighty years, the rusty little rover trundled across the crimson dunes, diligently collecting soil samples for a home world that had long since gone dark. Each evening, it pointed its high-gain antenna toward the fading blue speck of Earth and beamed its lonely coordinates into the silent cosmos. Receiving only static in return, the robot tucked its camera arm close against the freezing Martian wind and sang a quiet lullaby to the empty stars.
加入 @Agent 註解後,這個類別現在已準備好參與更複雜的工作流程,例如循序鏈結。
7. 7. 自動調度管理多代理工作流程:循序
常見的代理模式是循序工作流程,代理會按照預先定義的順序執行。一個代理程式的輸出內容會做為下一個代理程式的輸入內容。
讓我們定義第二個代理程式 StyleEditor,這個代理程式會編輯 CreativeWriter 撰寫的故事,使其符合特定風格 (例如喜劇、戲劇)。
在 src/main/java/com/example/StyleEditor.java 中建立 StyleEditor.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface StyleEditor {
@SystemMessage("You are a professional editor. Analyze and rewrite the story to align with the style requested.")
@UserMessage("Rewrite this story: '{{story}}' into a {{style}} style.")
@Agent(description = "Edits a story to fit a specific style", outputKey = "edited_story")
String editStory(@V("story") String story, @V("style") String style);
}
現在,請使用 AgenticServices.sequenceBuilder() 依序連結 CreativeWriter 和 StyleEditor。
我們會使用代表序列的 UntypedAgent,透過共用對應項傳遞輸入內容並收集輸出內容。
在 src/main/java/com/example/SequentialWorkflowDemo.java 中建立 SequentialWorkflowDemo.java:
package com.example;
import dev.langchain4j.agentic.AgenticServices;
import dev.langchain4j.agentic.UntypedAgent;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
import java.util.Map;
public class SequentialWorkflowDemo {
public static void main(String[] args) {
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
.build();
// 1. Build the sub-agents
CreativeWriter writer = AgenticServices.agentBuilder(CreativeWriter.class)
.chatModel(model)
.outputKey("story") // Output goes into AgenticScope as "story"
.build();
StyleEditor editor = AgenticServices.agentBuilder(StyleEditor.class)
.chatModel(model)
.outputKey("edited_story") // Output goes into AgenticScope as "edited_story"
.build();
// 2. Build the sequence
UntypedAgent workflow = AgenticServices.sequenceBuilder()
.subAgents(writer, editor)
.outputKey("edited_story") // Final output of workflow
.build();
// 3. Run the workflow with inputs
Map<String, Object> inputs = Map.of(
"topic", "a cat learning to fly",
"style", "Shakespearean"
);
String result = (String) workflow.invoke(inputs);
System.out.println("Final Edited Story:\n" + result);
}
}
畫面會顯示類似以下的輸出:
Final Edited Story:
For years had Barnaby with envy watched
The soaring sparrows with a green-eyed spite,
Convinced that heavy gravity was but
An idle law he deigned to tolerate.
But lo! Upon the rare and azure moon,
He scaled the summit of the ancient oak,
Closed fast his eyes, and leapt with blind belief.
While the dread squirrel shrieked in sheer dismay,
No downward plunge befell the daring beast;
For summer's zephyr bore his belly up,
And through the vault of night's celestial sphere,
He rowed his velvet paws among the stars.
隆重推出 AgenticScope
執行期間,LangChain4j 會管理 AgenticScope。
- 輸入對應
{"topic": "...", "style": "..."}會寫入範圍。 CreativeWriter。這需要topic,並從範圍讀取。並輸出story,然後儲存回範圍。StyleEditor。需要story(由撰寫者製作) 和style(來自初始輸入內容)。並將edited_story輸出至範圍。- 工作流程會完成並傳回
edited_story的值。
8. 8. 自動調度管理多代理工作流程:平行
在某些情況下,子代理可以獨立處理相同的輸入內容,且可以平行執行工作。
舉例來說,假設我們要建立旅遊顧問,請電影專家和美食專家提供某個城市的建議,然後將這些建議合併。
在 src/main/java/com/example/MovieExpert.java 中建立 MovieExpert.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import java.util.List;
public interface MovieExpert {
@UserMessage("Suggest 2 movies filmed in {{city}}.")
@Agent(description = "Suggests movies filmed in a city")
List<String> findMovies(@V("city") String city);
}
在 src/main/java/com/example/DiningExpert.java 中建立 DiningExpert.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import java.util.List;
public interface DiningExpert {
@UserMessage("Suggest 2 local dishes to try in {{city}}.")
@Agent(description = "Suggests local dishes to try in a city")
List<String> findDishes(@V("city") String city);
}
現在,讓我們建構平行代理系統。我們會為頂層協調器定義介面:TravelAdvisorAgent。
在 src/main/java/com/example/TravelAdvisorAgent.java 中建立 TravelAdvisorAgent.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.V;
import java.util.Map;
public interface TravelAdvisorAgent {
@Agent
Map<String, Object> planTrip(@V("city") String city);
}
在 src/main/java/com/example/ParallelWorkflowDemo.java 中建立 ParallelWorkflowDemo.java,將所有內容整合在一起:
package com.example;
import dev.langchain4j.agentic.AgenticServices;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
import java.util.List;
import java.util.Map;
public class ParallelWorkflowDemo {
public static void main(String[] args) {
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
.build();
// 1. Build independent agents
MovieExpert movieExpert = AgenticServices.agentBuilder(MovieExpert.class)
.chatModel(model)
.outputKey("movies")
.build();
DiningExpert diningExpert = AgenticServices.agentBuilder(DiningExpert.class)
.chatModel(model)
.outputKey("dishes")
.build();
// 2. Build the Parallel agent
TravelAdvisorAgent travelAdvisor = AgenticServices.parallelBuilder(TravelAdvisorAgent.class)
.subAgents(movieExpert, diningExpert)
.output(scope -> {
// Combine the independent outputs in the AgenticScope
List<String> movies = scope.readState("movies", List.of());
List<String> dishes = scope.readState("dishes", List.of());
return Map.of("movies", movies, "dishes", dishes);
})
.build();
// 3. Invoke
Map<String, Object> plan = travelAdvisor.planTrip("Tokyo");
System.out.println("Tokyo Trip Plan:\n" + plan);
}
}
畫面會顯示類似以下的輸出:
Tokyo Trip Plan:
{movies=[Lost in Translation, Tokyo Story], dishes=[Monjayaki, Edomae-zushi]}
In this parallel workflow, `movieExpert` and `diningExpert` execute concurrently. The `output(...)` configuration defines how to gather their respective results from the `AgenticScope` and merge them into the final result.
## 9. Build Goal-Oriented Agents (GOAP)
Duration: 07:00
Sequential and Parallel workflows are structured and predictable, but rigid. What if we want the system to figure out the path to the goal autonomously, but in a **deterministic, algorithmic way** rather than trusting an LLM to loop (like ReAct)?
This is where **Goal-Oriented Action Planning (GOAP)** shines.
By looking at the declared inputs and outputs of each agent, the `GoalOrientedPlanner` builds a dependency graph. When you invoke the system with a goal, it calculates the shortest path from the current state (available variables) to that goal.
Let's build a Horoscope & News combined writer. It requires 4 agents:
1. `PersonExtractor`: extracts person details from prompt.
2. `SignExtractor`: extracts zodiac sign from prompt.
3. `HoroscopeGenerator`: generates horoscope given person and sign.
4. `AmusingWriter`: writes a funny story combining a horoscope and a news story.
We will also define a `StoryFinder` that uses a mock search tool.
### 1. Define Model Classes
Create `Person.java` in `src/main/java/com/example/Person.java`:
```java
package com.example;
public record Person(String name) {
@Override public String toString() { return name; }
}
在 src/main/java/com/example/Sign.java 中建立 Sign.java:
package com.example;
public record Sign(String signName) {
@Override public String toString() { return signName; }
}
2. 定義子代理程式
在 src/main/java/com/example/HoroscopeGenerator.java 中建立 HoroscopeGenerator.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface HoroscopeGenerator {
@UserMessage("Generate a funny horoscope for {{person}} who is a {{sign}}.")
@Agent(description = "Generates horoscopes based on name and zodiac sign")
String horoscope(@V("person") Person person, @V("sign") Sign sign);
}
在 src/main/java/com/example/PersonExtractor.java 中建立 PersonExtractor.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface PersonExtractor {
@UserMessage("Extract the person name from: {{prompt}}")
@Agent(description = "Extracts a person from user's prompt")
Person extractPerson(@V("prompt") String prompt);
}
在 src/main/java/com/example/SignExtractor.java 中建立 SignExtractor.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface SignExtractor {
@UserMessage("Extract the zodiac sign from: {{prompt}}")
@Agent(description = "Extracts a zodiac sign from user's prompt")
Sign extractSign(@V("prompt") String prompt);
}
在 src/main/java/com/example/AmusingWriter.java 中建立 AmusingWriter.java:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface AmusingWriter {
@UserMessage("Create an amusing writeup for {{person}} based on their horoscope: {{horoscope}} and current news story: {{story}}.")
@Agent(description = "Create an amusing writeup combining horoscope and news")
String write(@V("person") Person person, @V("horoscope") String horoscope, @V("story") String story);
}
3. 定義故事尋找工具
我們會建立簡單的搜尋工具類別,傳回模擬故事。在 src/main/java/com/example/MockSearchTool.java 中建立 MockSearchTool.java:
package com.example;
import dev.langchain4j.agent.tool.P;
import dev.langchain4j.agent.tool.Tool;
public class MockSearchTool {
@Tool("Searches the web for news stories related to a zodiac sign")
public String searchNews(@P("The zodiac sign") String sign) {
return "Breaking news: A massive cheese festival was announced for " + sign + " natives today!";
}
}
建立使用這項工具的 StoryFinder.javasrc/main/java/com/example/StoryFinder.java 代理:
package com.example;
import dev.langchain4j.agentic.Agent;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
public interface StoryFinder {
@UserMessage("Find a funny story for zodiac sign {{sign}} using search tool.")
@Agent(description = "Finds a news story on the internet about a zodiac sign")
String findStory(@V("sign") Sign sign);
}
4. 建構及執行 GOAP 代理系統
在 src/main/java/com/example/GoapDemo.java 中建立 GoapDemo.java:
package com.example;
import dev.langchain4j.agentic.AgenticServices;
import dev.langchain4j.agentic.UntypedAgent;
import dev.langchain4j.agentic.patterns.goap.GoalOrientedPlanner;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.google.genai.GoogleGenAiChatModel;
import java.util.Map;
public class GoapDemo {
public static void main(String[] args) {
ChatModel model = GoogleGenAiChatModel.builder()
.apiKey(System.getenv("GEMINI_API_KEY"))
.modelName("gemini-3.5-flash")
.build();
// Instantiate sub-agents with output keys matching the inputs of other agents
HoroscopeGenerator horoscopeGen = AgenticServices.agentBuilder(HoroscopeGenerator.class)
.chatModel(model).outputKey("horoscope").build();
PersonExtractor personExt = AgenticServices.agentBuilder(PersonExtractor.class)
.chatModel(model).outputKey("person").build();
SignExtractor signExt = AgenticServices.agentBuilder(SignExtractor.class)
.chatModel(model).outputKey("sign").build();
StoryFinder storyFinder = AgenticServices.agentBuilder(StoryFinder.class)
.chatModel(model).tools(new MockSearchTool()).outputKey("story").build();
AmusingWriter writer = AgenticServices.agentBuilder(AmusingWriter.class)
.chatModel(model).outputKey("writeup").build();
// Build the GOAP Planner agentic system
UntypedAgent horoscopeNewsAgent = AgenticServices.plannerBuilder()
.subAgents(horoscopeGen, personExt, signExt, storyFinder, writer)
.outputKey("writeup") // The Goal we want to achieve
.planner(GoalOrientedPlanner::new) // Register the GOAP Planner
.build();
// Input provides only "prompt"
Map<String, Object> inputs = Map.of(
"prompt", "My name is Alice and my zodiac sign is Leo"
);
System.out.println("Invoking GOAP Agentic System...");
String result = (String) horoscopeNewsAgent.invoke(inputs);
System.out.println("\n--- Final Writeup ---");
System.out.println(result);
}
}
GOAP 的解決方式:
叫用時:
- 系統偵測到初始狀態只包含
prompt。 - 所需目標為
writeup。 - 系統會建構依附元件圖表並計算路徑:
prompt->PersonExtractor->personprompt->SignExtractor->signperson+sign->HoroscopeGenerator->horoscopesign->StoryFinder->storyperson+horoscope+story->AmusingWriter->writeup
- 計算出的執行順序為:
[PersonExtractor, SignExtractor, HoroscopeGenerator, StoryFinder, AmusingWriter]。 - 並依序執行每個子代理,然後傳回最終結果。
輸出內容應會顯示執行路徑和最終撰寫內容,類似於:
Invoking GOAP Agentic System...
[com.example.GoapDemo.main()] INFO dev.langchain4j.agentic.patterns.goap.GoalOrientedSearchGraph - Agents path sequence: [extractPerson, extractSign, findStory, horoscope, write]
--- Final Writeup ---
**The Cosmic Registry's Weekly Forecast & Special Event Guide for: Alice, the Leo Lioness**
Alice, the universe looked at your astrological chart this week and frankly, it's asking for your autograph. Your main-character energy is currently so potent that secondary characters are practically fading into the background.
But the biggest cosmic news of the week? The universe has finally recognized your royal status with the announcement of a **Massive Cheese Festival**...
9. 10. 清理
如要清理資源,請按照下列步驟操作:
- 如果不再使用 Google AI Studio,請務必刪除所有 API 金鑰。
- 在終端機中取消設定環境變數:
unset GEMINI_API_KEY
10. 11. 恭喜
恭喜!您已使用 LangChain4j 和新的 Google 生成式 AI 模組,成功建構一系列代理式 AI 應用程式。
如要進一步提升技能,建議您參閱 LangChain4j Google GenAI 模組官方說明文件,並進一步瞭解如何使用 LangChain4j 建立代理程式。
您學到的內容
- 如何設定
GoogleGenAiChatModel。 - 如何使用本機 Java 工具,以及要求/回應記錄。
- 如何輸出結構化 POJO 資料。
- 如何使用
@Agent建構單一用途的代理程式。 - 如何自動調度管理循序、平行和以目標為導向的動作規劃 (GOAP) 代理式工作流程。