1. 1. Trước khi bắt đầu

Chào mừng bạn! Trong lớp học lập trình này, bạn sẽ tìm hiểu cách xây dựng các ứng dụng AI có tác nhân bằng Java, sử dụng khung LangChain4j phổ biến và mô-đun Google GenAI mới.
AI tác nhân đề cập đến các hệ thống trong đó LLM (mô hình ngôn ngữ lớn) không chỉ phản hồi câu lệnh mà còn được trang bị các công cụ, bộ nhớ và khả năng lập kế hoạch để tự động hoàn thành các mục tiêu phức tạp, nhiều bước.
Bạn sẽ bắt đầu với các cấu hình đơn giản, tiến tới xây dựng các tác nhân bằng các công cụ cục bộ và đầu ra có cấu trúc, rồi khám phá các mẫu điều phối nhiều tác nhân nâng cao, kết thúc bằng hệ thống có tác nhân Lập kế hoạch hành động theo mục tiêu (GOAP).
Bạn sẽ thực hiện
- Định cấu hình
GoogleGenAiChatModelmới để kết nối với Gemini. - Bật tính năng ghi nhật ký yêu cầu/phản hồi để dễ dàng gỡ lỗi.
- Cấp cho Gemini quyền truy cập vào mã Java cục bộ bằng Công cụ.
- Thi hành định dạng Đầu ra có cấu trúc (POJO) từ Gemini.
- Xác định và xây dựng Tác nhân một mục đích bằng chú thích
@Agent. - Điều phối quy trình công việc nhiều tác nhân Tuần tự và Song song.
- Xây dựng hệ thống Lập kế hoạch hành động theo mục tiêu (GOAP) để lập kế hoạch thực thi tác nhân một cách linh hoạt.
Bạn cần có
- Bộ phát triển Java (JDK) 17 trở lên.
- Đã cài đặt Maven 3.5+.
- Khoá Gemini API từ Google AI Studio.
2. 2. Thiết lập: Khoá dự án và API
Để bắt đầu, chúng ta cần tạo một dự án Maven mới và định cấu hình khoá Gemini API.
Tạo dự án Maven
Tạo một thư mục mới cho dự án của bạn và khởi chạy thư mục đó bằng tệp pom.xml.
Thêm các phần phụ thuộc sau vào pom.xml. Xin lưu ý rằng chúng tôi đang sử dụng phiên bản mới nhất 1.16.1-beta26 của các mô-đun LangChain4j Google GenAI và 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>
Lấy khoá Gemini API
- Chuyển đến Google AI Studio.
- Nhấp vào Lấy khoá API.
- Tạo khoá mới (hoặc chọn khoá hiện có).
- Đặt khoá đó làm biến môi trường trong thiết bị đầu cuối:
export GEMINI_API_KEY="your-api-key-here"
3. 3. Định cấu hình mô hình trò chuyện Gemini
Bây giờ, hãy tạo một ứng dụng "Hello World" đơn giản để khởi tạo GoogleGenAiChatModel và gửi câu lệnh kiểm thử.
GoogleGenAiChatModel mới sử dụng SDK Google GenAI hợp nhất, cung cấp quyền truy cập hợp nhất vào các mô hình Gemini.
Tạo một lớp có tên HelloWorld.java trong src/main/java/com/example/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);
}
}
Chạy lớp này. Vì logRequestsAndResponses(true) được bật, bạn sẽ thấy nhật ký SLF4J chi tiết về tải trọng yêu cầu chính xác được gửi đến API của Google và phản hồi JSON thô nhận được, tiếp theo là kết quả được in:
--- 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. Xác định các công cụ Java cục bộ
LLM rất mạnh mẽ, nhưng bị giới hạn bởi dữ liệu huấn luyện. Chúng ta có thể mở rộng khả năng của LLM bằng cách cung cấp cho chúng Công cụ (còn gọi là gọi hàm).
Trong LangChain4j, các công cụ là các lớp Java đơn giản, trong đó các phương thức được chú thích bằng @Tool.
Hãy viết một công cụ đơn giản để tính số ngày giữa hai ngày. Tạo DateTools.java trong src/main/java/com/example/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);
}
}
Để sử dụng công cụ này, chúng ta sẽ xác định Dịch vụ AI. Trong khung Agentic LangChain4j, chúng ta có thể xây dựng khung này bằng cách sử dụng AgenticServices.agentBuilder().
Tạo ToolDemo.java trong src/main/java/com/example/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);
}
}
Khi bạn chạy mã này, Gemini sẽ phân tích câu lệnh, nhận ra rằng cần gọi daysBetween, tạo yêu cầu gọi công cụ, LangChain4j sẽ thực thi phương thức Java cục bộ của bạn, gửi kết quả trở lại Gemini và Gemini sẽ định dạng phản hồi cuối cùng bằng ngôn ngữ tự nhiên.
Bạn sẽ thấy kết quả tương tự như:
Response: There are 180 days between 2026-01-01 and 2026-06-30.
5. 5. Xác định đầu ra có cấu trúc
Thông thường, bạn muốn LLM trả về dữ liệu ở một định dạng có cấu trúc cụ thể (ví dụ: JSON khớp với một giản đồ) thay vì văn bản thuần tuý.
LangChain4j tự động xử lý việc này khi bạn chỉ định POJO hoặc record Java làm kiểu dữ liệu trả về của phương thức tác nhân phần mềm hoặc dịch vụ.
Hãy xác định record Java đại diện cho việc trích xuất sách:
Tạo Book.java trong src/main/java/com/example/Book.java:
package com.example;
public record Book(String title, String author, int publicationYear) {}
Bây giờ, hãy tạo một giao diện tác nhân trả về Book. Tạo StructuredOutputDemo.java trong src/main/java/com/example/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 hỗ trợ đầu ra giản đồ JSON nghiêm ngặt. LangChain4j tạo giản đồ JSON từ bản ghi Book, hướng dẫn Gemini điền giản đồ đó và giải tuần tự hoá phản hồi JSON trở lại bản ghi Book.
Bạn sẽ thấy kết quả tương tự như:
Extracted POJO: Book[title=Project Hail Mary, author=Andy Weir, publicationYear=2021]
6. 6. Tạo tác nhân đầu tiên
Trong khung langchain4j-agentic, Tác nhân được xác định bằng cách sử dụng chú thích @Agent trên phương thức của giao diện. Chú thích này cung cấp tên/mô tả mà các hệ thống điều phối (như trình lập kế hoạch) có thể sử dụng.
Hãy tạo một tác nhân đơn giản lấy một chủ đề và soạn một câu chuyện rất ngắn về chủ đề đó.
Tạo CreativeWriter.java trong src/main/java/com/example/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);
}
Hãy kiểm thử từng tác nhân này. Tạo AgentDemo.java trong src/main/java/com/example/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);
}
}
Bạn sẽ thấy kết quả tương tự như:
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.
Bằng cách thêm chú thích @Agent, lớp này hiện đã sẵn sàng tham gia vào các quy trình công việc phức tạp hơn, chẳng hạn như chuỗi tuần tự.
7. 7. Điều phối quy trình công việc nhiều tác nhân: Tuần tự
Một mẫu tác nhân phổ biến là Quy trình công việc tuần tự, trong đó các tác nhân thực thi theo thứ tự được xác định trước. Đầu ra của một tác nhân được truyền làm đầu vào của tác nhân tiếp theo.
Hãy xác định tác nhân thứ hai, StyleEditor, tác nhân này sẽ chỉnh sửa câu chuyện do CreativeWriter viết để phù hợp với một phong cách cụ thể (ví dụ: hài hước, kịch tính).
Tạo StyleEditor.java trong src/main/java/com/example/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);
}
Bây giờ, hãy kết nối CreativeWriter và StyleEditor theo tuần tự bằng cách sử dụng AgenticServices.sequenceBuilder().
Chúng ta sẽ sử dụng UntypedAgent đại diện cho chuỗi, cho phép chúng ta truyền đầu vào và thu thập đầu ra thông qua một bản đồ dùng chung.
Tạo SequentialWorkflowDemo.java trong src/main/java/com/example/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);
}
}
Bạn sẽ thấy kết quả tương tự như:
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.
Giới thiệu về AgenticScope
Trong quá trình thực thi, LangChain4j quản lý AgenticScope.
- Bản đồ đầu vào
{"topic": "...", "style": "..."}được ghi vào phạm vi. CreativeWriterthực thi. Tác nhân này yêu cầutopic, tác nhân này đọc từ phạm vi. Tác nhân này xuấtstory, được lưu trở lại phạm vi.StyleEditorthực thi. Tác nhân này yêu cầustory(do người viết tạo) vàstyle(từ đầu vào ban đầu). Tác nhân này xuấtedited_storyvào phạm vi.- Quy trình công việc hoàn tất và trả về giá trị của
edited_story.
8. 8. Điều phối quy trình công việc nhiều tác nhân: Song song
Trong một số trường hợp, các tác nhân phụ có thể hoạt động độc lập trên cùng một đầu vào và các tác vụ của chúng có thể được thực thi song song.
Ví dụ: hãy tạo một cố vấn du lịch hỏi một chuyên gia về phim và một chuyên gia về ẩm thực để được đề xuất cho một thành phố, sau đó kết hợp các đề xuất đó.
Tạo MovieExpert.java trong src/main/java/com/example/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);
}
Tạo DiningExpert.java trong src/main/java/com/example/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);
}
Bây giờ, hãy xây dựng hệ thống tác nhân song song. Chúng ta sẽ xác định một giao diện cho điều phối viên cấp cao nhất: TravelAdvisorAgent.
Tạo TravelAdvisorAgent.java trong src/main/java/com/example/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);
}
Tạo ParallelWorkflowDemo.java trong src/main/java/com/example/ParallelWorkflowDemo.java để liên kết các tác nhân:
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);
}
}
Bạn sẽ thấy kết quả tương tự như:
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; }
}
Tạo Sign.java trong src/main/java/com/example/Sign.java:
package com.example;
public record Sign(String signName) {
@Override public String toString() { return signName; }
}
2. Xác định các tác nhân phụ
Tạo HoroscopeGenerator.java trong src/main/java/com/example/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);
}
Tạo PersonExtractor.java trong src/main/java/com/example/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);
}
Tạo SignExtractor.java trong src/main/java/com/example/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);
}
Tạo AmusingWriter.java trong src/main/java/com/example/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. Xác định công cụ tìm câu chuyện
Chúng ta sẽ tạo một lớp công cụ tìm kiếm đơn giản trả về một câu chuyện mô phỏng. Tạo MockSearchTool.java trong src/main/java/com/example/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!";
}
}
Tạo StoryFinder.java trong src/main/java/com/example/StoryFinder.java tác nhân sử dụng công cụ này:
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. Xây dựng và chạy hệ thống tác nhân GOAP
Tạo GoapDemo.java trong src/main/java/com/example/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);
}
}
Cách GOAP giải quyết vấn đề:
Khi được gọi:
- Hệ thống phát hiện trạng thái ban đầu chỉ chứa
prompt. - Mục tiêu mong muốn là
writeup. - Hệ thống này xây dựng một biểu đồ phần phụ thuộc và tính toán đường dẫn:
prompt->PersonExtractor->personprompt->SignExtractor->signperson+sign->HoroscopeGenerator->horoscopesign->StoryFinder->storyperson+horoscope+story->AmusingWriter->writeup
- Thứ tự thực thi được tính toán là:
[PersonExtractor, SignExtractor, HoroscopeGenerator, StoryFinder, AmusingWriter]. - Hệ thống này thực thi từng tác nhân phụ theo thứ tự và trả về kết quả cuối cùng.
Bạn sẽ thấy kết quả cho thấy đường dẫn thực thi và bản viết cuối cùng, tương tự như:
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. Dọn dẹp
Cách dọn dẹp tài nguyên:
- Đảm bảo xoá mọi khoá API khỏi Google AI Studio nếu bạn không còn sử dụng các khoá đó.
- Huỷ đặt biến môi trường trong thiết bị đầu cuối:
unset GEMINI_API_KEY
10. 11. Xin chúc mừng
Xin chúc mừng! Bạn đã xây dựng thành công một loạt ứng dụng AI tác nhân bằng LangChain4j và mô-đun Google GenAI mới.
Để nâng cao kỹ năng của mình, bạn nên xem tài liệu chính thức về mô-đun LangChain4j Google GenAI và tìm hiểu thêm về cách tạo tác nhân bằng LangChain4j.
Kiến thức bạn học được
- Cách định cấu hình
GoogleGenAiChatModel. - Cách sử dụng các công cụ Java cục bộ và tính năng ghi nhật ký yêu cầu/phản hồi.
- Cách xuất dữ liệu POJO có cấu trúc.
- Cách xây dựng các tác nhân một mục đích bằng
@Agent. - Cách điều phối quy trình công việc có tác nhân tuần tự, song song và Lập kế hoạch hành động theo mục tiêu (GOAP).