1. 1. 始める前に

ようこそ。この Codelab では、人気の高い LangChain4j フレームワークとその新しい Google GenAI モジュールを使用して、Java でエージェント型 AI アプリケーションを構築する方法を学びます。
エージェント型 AI とは、LLM がプロンプトに応答するだけでなく、複雑な複数ステップの目標を自律的に達成するためのツール、メモリ、計画機能を備えたシステムを指します。
まず、シンプルな構成から始め、ローカルツールと構造化された出力を使用してエージェントを構築し、最後に高度なマルチエージェント オーケストレーション パターンを試して、目標指向アクション プランニング(GOAP)エージェント システムを完成させます。
演習内容
- Gemini に接続するように新しい
GoogleGenAiChatModelを構成します。 - デバッグを容易にするために、リクエスト/レスポンス ロギングを有効にします。
- ツールを使用して、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 に次の依存関係を追加します。LangChain4j Google GenAI モジュールと Agentic モジュールの最新バージョン 1.16.1-beta26 を使用していることに注意してください。
<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] をクリックします。
- 新しいキーを作成します(または既存のキーを選択します)。
- ターミナルで環境変数として設定します。
export GEMINI_API_KEY="your-api-key-here"
3. 3. Gemini Chat モデルを構成する
次に、GoogleGenAiChatModel をインスタンス化してテスト プロンプトを送信するシンプルな「Hello World」アプリケーションを作成します。
新しい GoogleGenAiChatModel は、Gemini モデルへの統合アクセスを提供する統合 Google GenAI SDK を使用します。
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) が有効になっているため、Google の API に送信されたリクエスト ペイロードと、受信した未加工の JSON レスポンスの詳細を示す SLF4J ログが表示され、その後に次の出力が表示されます。
--- 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 ツールを定義する
LLM は強力ですが、トレーニング データによって制限されます。ツール(関数呼び出しとも呼ばれます)を提供することで、機能を拡張できます。
LangChain4j では、ツールはメソッドに @Tool のアノテーションが付けられたシンプルな Java クラスです。
2 つの日付の間の日数を計算する簡単なツールを作成しましょう。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 エージェント フレームワークでは、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. 構造化出力を定義する
多くの場合、LLM にはプレーン テキストではなく、特定の構造化形式(スキーマに一致する JSON など)でデータを返すことが求められます。
LangChain4j では、エージェントまたはサービス メソッドの戻り値の型として POJO または Java record を指定すると、この処理が自動的に行われます。
書籍の抽出を表す 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. マルチエージェント ワークフローのオーケストレーション: 順次
一般的なエージェント パターンは、シーケンシャル ワークフローです。このパターンでは、エージェントは事前定義された順序で実行されます。1 つのエージェントの出力は、次のエージェントの入力として渡されます。
CreativeWriter が書いたストーリーを特定のスタイル(コメディ、ドラマなど)に合わせて編集する 2 つ目のエージェント StyleEditor を定義しましょう。
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!";
}
}
このツールを使用する src/main/java/com/example/StoryFinder.java エージェントに 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. クリーンアップ
リソースをクリーンアップするには:
- API キーを使用しなくなった場合は、Google AI Studio から削除してください。
- ターミナルで環境変数の設定を解除します。
unset GEMINI_API_KEY
10. 11. 完了
おめでとうございます!LangChain4j と新しい Google 生成 AI モジュールを使用して、一連のエージェント型 AI アプリケーションを正常に構築しました。
スキルをさらに高めるには、LangChain4j Google GenAI モジュールの公式ドキュメントを参照して、LangChain4j でエージェントを作成する方法について学習することをおすすめします。
学習した内容
GoogleGenAiChatModelを構成する方法。- ローカル Java ツールとリクエスト/レスポンス ロギングの使用方法。
- 構造化された POJO データの出力方法。
@Agentを使用して単一目的のエージェントを構築する方法。- シーケンシャル、パラレル、Goal-Oriented Action Planning(GOAP)のエージェント ワークフローをオーケストレートする方法。