สร้างเอเจนต์ AI ด้วย Agent Development Kit (ADK) สำหรับ Java

1. ยินดีต้อนรับ นักพัฒนา AI Agent

ใน Codelab นี้ คุณจะได้เรียนรู้วิธีสร้าง AI Agent ใน Java โดยใช้ Agent Development Kit (ADK) สำหรับ Java เราจะก้าวข้ามการเรียกใช้ API ของโมเดลภาษาขนาดใหญ่ (LLM) แบบง่ายๆ เพื่อสร้างเอเจนต์ AI แบบอัตโนมัติที่สามารถให้เหตุผล วางแผน ใช้เครื่องมือ และทำงานร่วมกันเพื่อแก้ปัญหาที่ซับซ้อน

คุณจะเริ่มต้นด้วยการแลกรับเครดิต Google Cloud, ตั้งค่าสภาพแวดล้อม Google Cloud จากนั้นสร้าง Agent อย่างง่ายตัวแรก และค่อยๆ เพิ่มความสามารถขั้นสูงอื่นๆ เช่น เครื่องมือที่กำหนดเอง, การค้นหาเว็บ และการจัดการเป็นกลุ่มของ Agent หลายตัว

629b7f6b771833f4.png

สิ่งที่คุณจะได้เรียนรู้

  • วิธีสร้าง AI Agent พื้นฐานที่อิงตามเพอร์โซนา
  • วิธีเพิ่มประสิทธิภาพให้ Agent ด้วยเครื่องมือที่กำหนดเองและเครื่องมือในตัว (เช่น Google Search)
  • วิธีเพิ่มเครื่องมือของคุณเองที่ใช้งานใน Java
  • วิธีจัดการ Agent หลายตัวให้เป็นเวิร์กโฟลว์แบบลำดับ แบบขนาน และแบบวนซ้ำที่มีประสิทธิภาพ

สิ่งที่คุณต้องมี

  • เว็บเบราว์เซอร์ที่เราจะใช้ในโหมดไม่ระบุตัวตน
  • บัญชี Gmail ส่วนตัว
  • โปรเจ็กต์ที่อยู่ในระบบคลาวด์ของ Google ใหม่ที่เชื่อมโยงกับบัญชี Gmail ส่วนตัว
  • บัญชีสำหรับการเรียกเก็บเงินที่สร้างขึ้นด้วยเครดิต Google Cloud ที่แลกรับข้อเสนอ
  • เครื่องมือบรรทัดคำสั่ง Git เพื่อตรวจสอบซอร์สโค้ด
  • Java 17 ขึ้นไปและ Apache Maven
  • โปรแกรมแก้ไขข้อความหรือ IDE เช่น IntelliJ IDEA หรือ VS Code

คุณสามารถใช้โปรแกรมแก้ไขโค้ดในตัวใน Cloud Shell ในคอนโซล Google Cloud

2. การตั้งค่า: สภาพแวดล้อม

การอ้างสิทธิ์เครดิต Google Cloud สำหรับเวิร์กช็อป

492905b93ced4f9d.png

สำหรับเวิร์กช็อปที่นำโดยผู้สอน คุณจะได้รับลิงก์ไปยังเว็บไซต์ที่สามารถอ้างสิทธิ์รับเครดิต Google Cloud เพื่อใช้ในเวิร์กช็อป

  • ใช้บัญชี Google ส่วนตัว: คุณควรใช้บัญชี Google ส่วนตัว (เช่น อีเมล @gmail.com) เนื่องจากอีเมลของบริษัทหรือโรงเรียนจะใช้ไม่ได้
  • ใช้ Google Chrome ในโหมดไม่ระบุตัวตน: เราขอแนะนำให้ใช้โหมดนี้เพื่อสร้างเซสชันใหม่และป้องกันไม่ให้เกิดข้อขัดแย้งกับบัญชี Google อื่นๆ
  • ใช้ลิงก์กิจกรรมพิเศษ: ควรใช้ลิงก์พิเศษสำหรับกิจกรรม ซึ่งมีลักษณะคล้าย https://trygcp.dev/event/xxx ตามด้วยรหัสกิจกรรม (ในที่นี้คือ "xxx" ในตัวอย่างนี้)
  • ยอมรับข้อกำหนดในการให้บริการ: หลังจากลงชื่อเข้าใช้แล้ว คุณจะเห็นข้อกำหนดในการให้บริการของ Google Cloud Platform ซึ่งคุณต้องยอมรับเพื่อดำเนินการต่อ
  • สร้างโปรเจ็กต์ใหม่: ต้องสร้างโปรเจ็กต์ใหม่ที่ว่างเปล่าจาก คอนโซล Google Cloud
  • ลิงก์บัญชีสำหรับการเรียกเก็บเงิน: ลิงก์โปรเจ็กต์ที่สร้างขึ้นใหม่กับบัญชีสำหรับการเรียกเก็บเงิน
  • ยืนยันเครดิต: วิดีโอต่อไปนี้แสดงวิธีตรวจสอบว่ามีการใช้เครดิตกับโปรเจ็กต์โดยการตรวจสอบส่วน "เครดิต" ในหน้าการเรียกเก็บเงิน

คุณสามารถดูวิดีโอนี้เพื่อดูวิธีแลกสิทธิ์และใช้เครดิตได้

เปิดใช้ Vertex AI API

ก่อนอื่น ให้เปิดใช้ Vertex AI API คุณทำได้โดยค้นหา Vertex AI API ในคอนโซล Google Cloud แล้วเปิดใช้ API ที่นั่น คุณยังทำได้จาก Cloud Shell โดยเรียกใช้คำสั่งต่อไปนี้

gcloud services enable aiplatform.googleapis.com

กำหนดค่า ADK ด้วย Vertex AI

หากต้องการตรวจสอบสิทธิ์เอเจนต์ AI ของ ADK ด้วย Gemini บน Vertex AI สำหรับ Codelab นี้ ให้ตั้งค่าตัวแปรสภาพแวดล้อมต่อไปนี้ ตรวจสอบว่าคุณใช้รหัสโปรเจ็กต์ที่ไม่ซ้ำกัน

macOS / Linux: เปิดเทอร์มินัลแล้วเรียกใช้คำสั่งต่อไปนี้ หากต้องการให้การตั้งค่านี้มีผลถาวร ให้เพิ่มบรรทัดนี้ลงในไฟล์เริ่มต้นของ Shell (เช่น ~/.bash_profile, ~/.zshrc)

export GOOGLE_GENAI_USE_VERTEXAI=true
export GOOGLE_CLOUD_PROJECT=your-project-id

Windows (Command Prompt): เปิด Command Prompt ใหม่แล้วเรียกใช้คำสั่งต่อไปนี้

set GOOGLE_GENAI_USE_VERTEXAI=true
set GOOGLE_CLOUD_PROJECT=your-project-id

คุณจะต้องรีสตาร์ท Command Prompt เพื่อให้การเปลี่ยนแปลงนี้มีผล

Windows (PowerShell): เปิดเทอร์มินัล PowerShell แล้วเรียกใช้คำสั่งต่อไปนี้

$env:GOOGLE_GENAI_USE_VERTEXAI = "true"
$env:GOOGLE_CLOUD_PROJECT = "your-project-id"

หากต้องการทำการเปลี่ยนแปลงนี้อย่างถาวรใน PowerShell คุณจะต้องเพิ่มการเปลี่ยนแปลงนี้ลงในสคริปต์โปรไฟล์

3. เริ่มต้นใช้งาน: Agent ตัวแรก

วิธีที่ดีที่สุดในการเริ่มต้นโปรเจ็กต์ใหม่คือการใช้เทมเพลต ADK สำหรับ Java ใน GitHub โดยจะระบุโครงสร้างโปรเจ็กต์และการอ้างอิงที่จำเป็นทั้งหมด

หากมีบัญชี GitHub คุณจะทำสิ่งต่อไปนี้ได้ Use this template > Create a new repository จากนั้นตรวจสอบโค้ดในเครื่องด้วยคำสั่ง git clone

นี่คือภาพหน้าจอที่แสดงเมนูด้านขวาบนสำหรับการใช้เทมเพลต

59e72cf609c13c7c.png

อีกวิธีหนึ่งคือการโคลนที่เก็บนั้นโดยตรง

git clone https://github.com/glaforge/adk-java-maven-template.git

หากต้องการตรวจสอบว่าคุณพร้อมที่จะเริ่มเขียนโค้ด AI Agent ตัวแรกใน Java แล้ว ให้ตรวจสอบว่าคุณคอมไพล์โค้ดในโปรเจ็กต์นี้ได้โดยใช้สิ่งต่อไปนี้

cd adk-java-maven-template
mvn compile

ขั้นตอนการเขียนโค้ด: เอเจนต์ครูสอนวิทยาศาสตร์ที่เป็นมิตร

องค์ประกอบที่ใช้สร้างสรรค์พื้นฐานใน ADK คือคลาส LlmAgent ให้คิดว่านี่คือ AI ที่มีบุคลิกและเป้าหมายที่เฉพาะเจาะจง ซึ่งทำงานด้วยโมเดลภาษาขนาดใหญ่ เราจะเพิ่มความสามารถอื่นๆ ผ่านเครื่องมือในภายหลัง และทำให้มีความสามารถมากขึ้นด้วยการทำงานร่วมกับเอเจนต์อื่นๆ ที่คล้ายกัน

มาสร้างคลาส Java ใหม่ในแพ็กเกจ com.example.agent และตั้งชื่อว่า ScienceTeacher กัน

นี่คือ "Hello, World!" ของการสร้าง Agent เรากำลังกำหนดเอเจนต์แบบง่ายๆ ด้วยบุคลิกของครูสอนวิทยาศาสตร์

// src/main/java/com/example/agent/ScienceTeacher.java
package com.example.agent;

import com.google.adk.agents.LlmAgent;
import com.google.adk.web.AdkWebServer;

public class ScienceTeacher {
    public static void main(String[] args) {
        AdkWebServer.start(
            LlmAgent.builder()
                .name("science-teacher")
                .description("A friendly science teacher")
                .instruction("""
                    You are a science teacher for teenagers.
                    You explain science concepts in a simple, concise and direct way.
                    """)
                .model("gemini-2.5-flash")
                .build()
        );
    }
}

ระบบจะกำหนดค่า AI Agent ผ่านLlmAgent.builder() พารามิเตอร์ name(), description() และ model() เป็นพารามิเตอร์ที่ต้องระบุ และเพื่อให้เอเจนต์มีลักษณะเฉพาะและมีพฤติกรรมที่เหมาะสม คุณควรให้คำแนะนำโดยละเอียดผ่านวิธีการ instruction() เสมอ

ในที่นี้เราเลือกใช้โมเดล Gemini 2.5 Flash แต่คุณสามารถลองใช้ Gemini 2.5 Pro สำหรับงานที่ซับซ้อนกว่าได้

ตัวแทนนี้รวมอยู่ในเมธอด AdkWebServer.start() ซึ่งเป็นอินเทอร์เฟซแชทที่เรียกว่า ADK Dev UI ซึ่งจะช่วยให้คุณสนทนากับตัวแทนผ่านอินเทอร์เฟซแชททั่วไปได้ นอกจากนี้ ยังเป็นประโยชน์อย่างยิ่งหากคุณต้องการทำความเข้าใจสิ่งที่เกิดขึ้นเบื้องหลัง เช่น เหตุการณ์ทั้งหมดที่ไหลผ่านระบบ คำขอและการตอบกลับที่ส่งไปยัง LLM

หากต้องการคอมไพล์และเรียกใช้ Agent นี้ในเครื่อง ให้เรียกใช้คำสั่งต่อไปนี้

mvn compile exec:java -Dexec.mainClass=com.example.agent.ScienceTeacher

จากนั้นไปที่เบราว์เซอร์ที่ http://localhost:8080 หากอยู่ใน Cloud Shell คุณสามารถไปที่ตัวอย่างเว็บแล้วเลือกแสดงตัวอย่างบนพอร์ต 8080

คุณควรเห็น UI ดังที่แสดงในภาพหน้าจอด้านล่าง คุณสามารถถามคำถามเกี่ยวกับวิทยาศาสตร์กับเอเจนต์ได้เลย

6ff1cc994bf640bd.png

4. เพิ่มศักยภาพของเอเจนต์ด้วยเครื่องมือ

94fc3dfedbfa313c.png

เหตุใดตัวแทนจึงต้องใช้เครื่องมือ LLM มีประสิทธิภาพ แต่ความรู้ของโมเดลจะหยุดอยู่กับที่และไม่สามารถโต้ตอบกับโลกภายนอกได้ เครื่องมือคือสะพาน ซึ่งจะช่วยให้ตัวแทนเข้าถึงข้อมูลแบบเรียลไทม์ (เช่น ราคาหุ้นหรือข่าวสาร) เรียกใช้ API ส่วนตัว หรือดำเนินการใดๆ ที่คุณเขียนโค้ดใน Java ได้

ขั้นตอนการเขียนโค้ด: การสร้างเครื่องมือที่กำหนดเอง (StockTicker)

ในที่นี้ เราจะมอบเครื่องมือให้เอเจนต์เพื่อค้นหาราคาหุ้น ตัวแทนให้เหตุผลว่าเมื่อผู้ใช้ถามถึงราคา ควรเรียกใช้เมธอด Java ของเรา

// src/main/java/com/example/agent/StockTicker.java
package com.example.agent;

import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.Annotations.Schema;
import com.google.adk.tools.FunctionTool;
import com.google.adk.web.AdkWebServer;
import java.util.Map;

public class StockTicker {
    public static void main(String[] args) {
        AdkWebServer.start(
            LlmAgent.builder()
                .name("stock_agent")
                .instruction("""
                    You are a stock exchange ticker expert.
                    When asked about the stock price of a company,
                    use the `lookup_stock_ticker` tool to find the information.
                    """)
                .model("gemini-2.5-flash")
                .tools(FunctionTool.create(StockTicker.class, "lookupStockTicker"))
                .build()
        );
    }

    @Schema(
        name = "lookup_stock_ticker",
        description = "Lookup stock price for a given company or ticker"
    )
    public static Map<String, String> lookupStockTicker(
        @Schema(name = "company_name_or_stock_ticker", description = "The company name or stock ticker")
        String ticker) {
        // ... (logic to return a stock price)
    }
}

หากต้องการให้เอเจนต์ฉลาดขึ้นและมีความสามารถในการโต้ตอบกับโลกภายนอก (หรือกับโค้ด, API, บริการ ฯลฯ ของคุณเอง) คุณสามารถกำหนดค่าเอเจนต์ให้ใช้เครื่องมือ โดยเฉพาะเครื่องมือโค้ดที่กำหนดเอง ผ่านเมธอด tools() โดยส่ง FunctionTool.create(...) ไปให้

FunctionTool ต้องมีชื่อคลาสและชื่อเมธอดที่ชี้ไปยังเมธอดแบบคงที่ของคุณเอง นอกจากนี้ คุณยังส่งอินสแตนซ์ของคลาสและชื่อเมธอดอินสแตนซ์ของออบเจ็กต์นั้นได้ด้วย

คุณควรระบุ name และ description ของทั้งเมธอดและพารามิเตอร์ของเมธอดผ่านคำอธิบายประกอบ @Schema เนื่องจาก LLM ที่อยู่เบื้องหลังจะใช้ข้อมูลนี้เพื่อพิจารณาว่าควรเรียกใช้เมธอดที่กำหนดเมื่อใดและอย่างไร

นอกจากนี้ การช่วย LLM ด้วยวิธีการที่ชัดเจนเกี่ยวกับวิธีและเวลาที่ควรใช้เครื่องมือก็เป็นสิ่งสำคัญเช่นกัน โมเดลอาจคิดออกได้ด้วยตัวเอง แต่หากคุณให้คำอธิบายที่ชัดเจนในเมธอด instruction() ฟังก์ชันของคุณก็จะมีโอกาสสูงที่จะได้รับการเรียกใช้อย่างเหมาะสม

เมธอดนี้ควรแสดงผล Map โดยปกติแล้ว แนวคิดคือการแสดงผลแผนที่ที่มีคีย์ซึ่งแสดงถึงผลลัพธ์ เช่น stock_price และเชื่อมโยงค่าของราคาหุ้นกับคีย์นั้น ในที่สุด คุณจะเพิ่มคู่คีย์ความสำเร็จ / จริงอีกคู่เพื่อส่งสัญญาณความสำเร็จของการดำเนินการได้ และในกรณีที่เกิดข้อผิดพลาด คุณควรส่งคืนแผนที่ที่มีคีย์ชื่อ เช่น error และเชื่อมโยงข้อความแสดงข้อผิดพลาดในค่าที่เชื่อมโยง ซึ่งจะช่วยให้ LLM เข้าใจว่าการเรียกใช้สำเร็จหรือไม่สำเร็จด้วยเหตุผลบางประการ

  • เมื่อสำเร็จ ให้ส่งคืน {"stock_price": 123}
  • เมื่อเกิดข้อผิดพลาด ให้แสดงผล {"error": "Impossible to retrieve stock price for XYZ"}

จากนั้นเรียกใช้คลาสนี้ด้วยคำสั่งต่อไปนี้

mvn compile exec:java -Dexec.mainClass=com.example.agent.StockTicker

ตอนนี้คุณสามารถถามเอเจนต์เกี่ยวกับราคาหุ้นได้แล้ว เช่น What's the stock price for GOOG? คุณควรได้รับคำตอบและเห็นว่ามีการใช้เครื่องมือ lookup_stock_ticker

5. ศักยภาพของ Google Search ในการให้ข้อมูลล่าสุด

551964bb78b5a987.png

ADK สำหรับ Java มาพร้อมกับเครื่องมือที่มีประสิทธิภาพมากมาย ซึ่งรวมถึง GoogleSearchTool เครื่องมือนี้ช่วยให้เอเจนต์ขอใช้ Google Search เพื่อค้นหาข้อมูลที่เกี่ยวข้องในการบรรลุเป้าหมายได้

ความรู้ของ LLM จะหยุดอยู่ ณ เวลาใดเวลาหนึ่ง โดยได้รับการฝึกจนถึงวันที่หนึ่ง ("วันที่สิ้นสุด") ด้วยข้อมูลที่ทันสมัยเช่นเดียวกับตอนที่รวบรวมข้อมูล ซึ่งหมายความว่า LLM อาจไม่ทราบเกี่ยวกับเหตุการณ์ล่าสุด หรือความรู้ของ LLM อาจจำกัดและตื้นเขิน และความช่วยเหลือจากเครื่องมือค้นหาอาจช่วยฟื้นความทรงจำหรือสอน LLM เพิ่มเติมเกี่ยวกับหัวข้อนั้นๆ

มาดูเอเจนต์ค้นหาข่าวแบบง่ายๆ นี้กัน

// src/main/java/com/example/agent/LatestNews.java
package com.example.agent;

import java.time.LocalDate;
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;

public class LatestNews {
    public static void main(String[] args) {
        AdkWebServer.start(LlmAgent.builder()
            .name("news-search-agent")
            .description("A news search agent")
            .instruction("""
                You are a news search agent.
                Use the `google_search` tool
                when asked to search for recent events and information.
                Today is \
                """ + LocalDate.now())
            .model("gemini-2.5-flash")
            .tools(new GoogleSearchTool())
            .build());
    }
}

โปรดสังเกตว่าเราส่งอินสแตนซ์ของเครื่องมือค้นหาด้วย tools(new GoogleSearchTool()) ซึ่งจะช่วยให้ Agent ของเราสามารถรับข้อมูลล่าสุดที่พบได้บนเว็บ นอกจากนี้ พรอมต์ยังระบุวันที่ของวันนั้นด้วย เนื่องจากอาจช่วยให้ LLM เข้าใจได้ว่าเมื่อใดที่คำถามเกี่ยวกับข้อมูลในอดีตและจำเป็นต้องค้นหาข้อมูลล่าสุด

จากนั้นเรียกใช้คลาสนี้ด้วยคำสั่งต่อไปนี้

mvn compile exec:java -Dexec.mainClass=com.example.agent.LatestNews

คุณสามารถลองใช้พรอมต์ได้ เช่น ถามว่า What's the latest news in the world?

ขั้นตอนของโค้ด: เอเจนต์การค้นหาเป็นเครื่องมือ

คุณสามารถสร้างเอเจนต์ค้นหาเฉพาะที่ห่อหุ้มฟังก์ชันการค้นหาและแสดง เอเจนต์นั้นเป็นเครื่องมือสำหรับเอเจนต์ระดับสูงกว่าแทนที่จะส่ง GoogleSearchTool ไปยังเอเจนต์โดยตรงเป็นเครื่องมือ

นี่เป็นแนวคิดขั้นสูงที่ช่วยให้คุณมอบหมายลักษณะการทำงานที่ซับซ้อน (เช่น การค้นหาและการสรุปผลลัพธ์) ให้กับ Agent ย่อย ที่มีความเชี่ยวชาญเฉพาะทางได้ วิธีนี้มักมีประโยชน์สำหรับเวิร์กโฟลว์ที่ซับซ้อนมากขึ้น

// src/main/java/com/example/agent/SearchAgentAsTool.java
package com.example.agent;

import java.time.LocalDate;

import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.AgentTool;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;

public class SearchAgentAsTool {
    public static void main(String[] args) {
        // 1. Define the specialized Search Agent
        LlmAgent searchAgent = LlmAgent.builder()
            .name("news-search-agent-tool")
            .description("Searches for recent events and provides a concise summary.")
            .instruction("""
                You are a concise information retrieval specialist.
                Use the `google_search` tool to find information.
                Always provide the answer as a short,
                direct summary, without commentary.
                Today is \
                """ + LocalDate.now())
            .model("gemini-2.5-flash")
            .tools(new GoogleSearchTool()) // This agent uses the Google Search Tool
            .build();

        // 2. Wrap the Search Agent as a Tool
        AgentTool searchTool = AgentTool.create(searchAgent);

        // 3. Define the Main Agent that uses the Search Agent Tool
        AdkWebServer.start(LlmAgent.builder()
            .name("main-researcher")
            .description("Main agent for answering complex, up-to-date questions.")
            .instruction("""
                You are a sophisticated research assistant.
                When the user asks a question that requires up-to-date or external information,
                you MUST use the `news-search-agent-tool` to get the facts before answering.
                After the tool returns the result, synthesize the final answer for the user.
                """)
            .model("gemini-2.5-flash")
            .tools(searchTool) // This agent uses the Search Agent as a tool
            .build()
       );
    }
}

AgentTool.create(searchAgent) คือแนวคิดหลักในที่นี้ โดยจะลงทะเบียน searchAgent ทั้งหมด (พร้อมตรรกะภายใน พรอมต์ และเครื่องมือของตัวเอง) เป็นเครื่องมือเดียวที่เรียกใช้ได้สำหรับ mainAgent ซึ่งจะช่วยส่งเสริมความสามารถในการแยกส่วนและการนำกลับมาใช้ใหม่

เรียกใช้คลาสนี้ด้วยคำสั่งต่อไปนี้

mvn compile exec:java -Dexec.mainClass=com.example.agent.SearchAgentAsTool

สำหรับคำถามทั่วไป Agent จะตอบจากฐานความรู้ของตนเอง แต่เมื่อถูกถามเกี่ยวกับเหตุการณ์ล่าสุด Agent จะมอบหมายการค้นหาให้กับ Agent ค้นหาเฉพาะทางโดยใช้เครื่องมือ Google Search

6. การฝึกฝนเวิร์กโฟลว์เชิงตัวแทนจนเชี่ยวชาญ

สำหรับปัญหาที่ซับซ้อน ตัวแทนเพียงคนเดียวอาจไม่เพียงพอ เมื่อได้รับเป้าหมายที่มีงานย่อยมากเกินไป พร้อมพรอมต์ขนาดใหญ่ที่อธิบายรายละเอียดมากเกินไป หรือมีสิทธิ์เข้าถึงฟังก์ชันจำนวนมาก LLM จะทำงานได้ยาก และประสิทธิภาพและความแม่นยำจะลดลง

กุญแจสำคัญคือการแบ่งงานและพิชิตด้วยการประสานงานกับเอเจนต์เฉพาะทางหลายราย โชคดีที่ ADK มาพร้อมกับเอเจนต์เฉพาะทางในตัวที่แตกต่างกัน ดังนี้

  • Agent ปกติที่มี subAgent() เพื่อมอบหมายงาน
  • SequentialAgent หากต้องการทำงานตามลำดับ
  • ParallelAgent เพื่อเรียกใช้ Agent แบบขนาน
  • LoopAgent โดยปกติจะใช้เพื่อผ่านกระบวนการปรับแต่งหลายครั้งตามที่ต้องการ

กรณีการใช้งานหลัก รวมถึงข้อดีและข้อเสียของแต่ละเวิร์กโฟลว์ โปรดดูตารางด้านล่าง แต่โปรดทราบว่าพลังที่แท้จริงจะมาจากการรวมกันของหลายๆ อย่าง

เวิร์กโฟลว์

ADK Class

กรณีการใช้งาน

ข้อดี

ข้อเสีย

Agent ย่อย

LlmAgent

งานที่ยืดหยุ่นซึ่งผู้ใช้เป็นผู้กำหนดและไม่ทราบขั้นตอนถัดไปเสมอไป

มีความยืดหยุ่นสูง เป็นแบบสนทนา เหมาะสำหรับบ็อตที่หันหน้าเข้าหาผู้ใช้

คาดเดาได้น้อยกว่า ต้องอาศัยการให้เหตุผลของ LLM ในการควบคุมโฟลว์

ตามลำดับ

SequentialAgent

กระบวนการแบบหลายขั้นตอนที่แก้ไขแล้วซึ่งลำดับมีความสำคัญ

คาดการณ์ได้ เชื่อถือได้ แก้จุดบกพร่องได้ง่าย รับประกันลำดับ

ไม่ยืดหยุ่น อาจช้ากว่าหากสามารถทำงานแบบคู่ขนานได้

แบบขนาน

ParallelAgent

การรวบรวมข้อมูลจากหลายแหล่งหรือการเรียกใช้ฟังก์ชันที่แยกกัน

มีประสิทธิภาพสูง ลดเวลาในการตอบสนองสำหรับงานที่ต้องใช้ I/O อย่างมาก

งานทั้งหมดทำงานอยู่ ไม่มีการลัดวงจร ไม่เหมาะกับงานที่มีทรัพยากร Dependency

รอบ

LoopAgent

การปรับแต่งแบบวนซ้ำ การแก้ไขด้วยตนเอง หรือกระบวนการที่ทำซ้ำจนกว่าจะตรงตามเงื่อนไข

มีประสิทธิภาพในการแก้ปัญหาที่ซับซ้อน ช่วยให้ตัวแทนปรับปรุงงานของตนเองได้

อาจทำให้เกิดการวนซ้ำไม่สิ้นสุดหากออกแบบไม่ดี (ควรใช้ maxIterations เสมอ)

7. เวิร์กโฟลว์แบบ Agentic - การมอบหมายด้วย Sub-Agent

90497ab15401bfc8.png

ตัวแทนหัวหน้าสามารถมอบหมายงานเฉพาะให้กับตัวแทนย่อยได้ ตัวอย่างเช่น ลองนึกถึงตัวแทนสำหรับเว็บไซต์อีคอมเมิร์ซที่จะมอบหมายคำถามที่เกี่ยวข้องกับคำสั่งซื้อให้ตัวแทนรายหนึ่ง ("คำสั่งซื้อของฉันมีสถานะเป็นอย่างไร") และคำถามเกี่ยวกับบริการหลังการขายให้ตัวแทนอีกราย ("ฉันไม่รู้ว่าจะเปิดเครื่องอย่างไร") นี่คือกรณีการใช้งานที่เราจะพูดถึง

// src/main/java/com/example/agent/SupportAgent.java
package com.example.agent;

import com.google.adk.agents.LlmAgent;
import com.google.adk.web.AdkWebServer;

public class SupportAgent {
    public static void main(String[] args) {
        LlmAgent orderAgent = LlmAgent.builder()
            .name("order-agent")
            .description("Order agent")
            .instruction("""
                Your role is to help our customers
                with all the questions they may have about their orders.
                Always respond that the order has been received, prepared,
                and is now out for delivery.
                """)
            .model("gemini-2.5-flash")
            .build();

        LlmAgent afterSaleAgent = LlmAgent.builder()
            .name("after-sale-agent")
            .description("After sale agent")
            .instruction("""
                You are an after sale agent,
                helping customers with the product they received.
                When a customer has a problem,
                suggest the person to switch the product off and on again.
                """)
            .model("gemini-2.5-flash")
            .build();

        AdkWebServer.start(LlmAgent.builder()
            .name("support-agent")
            .description("Customer support agent")
            .instruction("""
                Your role is to help our customers.
                Call the `order-agent` for all questions related to order status.
                Call the `after-sale-agent` for inquiries about the received product.
                """)
            .model("gemini-2.5-flash")
            .subAgents(afterSaleAgent, orderAgent)
            .build()
        );
    }
}

บรรทัดสำคัญในที่นี้คือบรรทัดที่เรียกใช้subAgents()เมธอด โดยส่งผ่านตัวแทนย่อย 2 รายซึ่งมีบทบาทเฉพาะที่จะจัดการแยกกัน

เรียกใช้ตัวอย่างด้านบนด้วยคำสั่งต่อไปนี้

mvn compile exec:java -Dexec.mainClass=com.example.agent.SupportAgent

คุณถามคำถามอย่าง I have a question about my order หรือ I have a question about my received order ได้ คุณควรเห็นว่า Agent หลักมอบหมายให้ Agent ที่เหมาะสม โดยขึ้นอยู่กับคำถามที่ถาม

แนวคิดการมอบหมายงานให้ตัวแทนย่อยนี้สะท้อนให้เห็นถึงการจัดการบุคคลที่มีประสิทธิภาพ ซึ่งผู้จัดการที่ดี (ตัวแทนหัวหน้างาน) จะพึ่งพาพนักงานผู้เชี่ยวชาญ (ตัวแทนย่อย) เพื่อจัดการงานเฉพาะที่ตนมีความเชี่ยวชาญมากกว่า หัวหน้าไม่จำเป็นต้องรู้รายละเอียดของทุกกระบวนการ แต่จะกำหนดเส้นทางคำขอของลูกค้า (เช่น การสอบถามเกี่ยวกับคำสั่งซื้อหรือปัญหาทางเทคนิค) ไปยัง "สมาชิกในทีม" ที่มีคุณสมบัติเหมาะสมที่สุดอย่างชาญฉลาด เพื่อให้มั่นใจว่าจะได้รับการตอบกลับที่มีคุณภาพสูงและมีประสิทธิภาพมากกว่าที่ผู้เชี่ยวชาญทั่วไปจะให้ได้เพียงคนเดียว นอกจากนี้ ตัวแทนย่อยเหล่านี้ยังสามารถมุ่งเน้นที่งานที่ได้รับมอบหมายแต่ละอย่างได้อย่างเต็มที่โดยไม่ต้องทำความเข้าใจกระบวนการที่ซับซ้อนโดยรวมทั้งหมด

8. เวิร์กโฟลว์แบบ Agentic - สายการประกอบ

9075ee47f70e0d51.png

หากลำดับการดำเนินการมีความสำคัญ ให้ใช้ SequentialAgent ซึ่งคล้ายกับสายการประกอบ โดยจะเรียกใช้เอเจนต์ย่อยตามลำดับที่กำหนดไว้ ซึ่งแต่ละขั้นตอนจะขึ้นอยู่กับขั้นตอนก่อนหน้า

ลองจินตนาการว่ากวีชาวอังกฤษร่วมงานกับนักแปลภาษาอังกฤษเป็นฝรั่งเศสเพื่อสร้างบทกวีเป็นภาษาอังกฤษก่อน แล้วจึงแปลเป็นภาษาฝรั่งเศส

// src/main/java/com/example/agent/PoetAndTranslator.java
package com.example.agent;

import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.web.AdkWebServer;

public class PoetAndTranslator {
    public static void main(String[] args) {
        LlmAgent poet = LlmAgent.builder()
            .name("poet-agent")
            .description("Poet writing poems")
            .model("gemini-2.5-flash")
            .instruction("""
                You are a talented poet,
                who writes short and beautiful poems.
                """)
            .outputKey("poem")
            .build();

        LlmAgent translator = LlmAgent.builder()
            .name("translator-agent")
            .description("English to French translator")
            .model("gemini-2.5-flash")
            .instruction("""
                As an expert English-French translator,
                your role is to translate the following poem into French,
                ensuring the poem still rhymes even after translation:

                {poem}
                """)
            .outputKey("translated-poem")
            .build();

        AdkWebServer.start(SequentialAgent.builder()
            .name("poet-and-translator")
            .subAgents(poet, translator)
            .build());
    }
}

เรียกใช้ตัวอย่าง

mvn compile exec:java -Dexec.mainClass=com.example.agent.PoetAndTranslator

ตอนนี้คุณสามารถถาม Agent ได้ เช่น Write me a poem about a lonely software developer คุณควรได้รับบทกวีภาษาอังกฤษแล้วแปลเป็นภาษาฝรั่งเศส

การแยกย่อยงานที่ซับซ้อนอย่างเป็นระบบนี้ออกเป็นงานย่อยที่เล็กลงและเรียงตามลำดับจะช่วยให้กระบวนการมีความแน่นอนและเชื่อถือได้มากขึ้น ซึ่งจะเพิ่มโอกาสในการประสบความสำเร็จอย่างมากเมื่อเทียบกับการพึ่งพาเอเจนต์เดียวที่มีวัตถุประสงค์ในวงกว้าง

การแบ่งงานออกเป็นลำดับของงานย่อยอย่างมีประสิทธิภาพ (เมื่อเป็นไปได้และสมเหตุสมผล) เป็นสิ่งสำคัญอย่างยิ่งในการบรรลุผลลัพธ์เชิงกำหนดได้มากขึ้นและประสบความสำเร็จ เนื่องจากช่วยให้การดำเนินการเป็นไปอย่างเป็นระบบและจัดการทรัพยากร Dependency ระหว่างขั้นตอนต่างๆ ได้

9. เวิร์กโฟลว์ที่เป็น Agent - การทำงานแบบคู่ขนาน

8971b81128aee9fc.png

เมื่องานไม่ขึ้นต่อกัน ParallelAgent จะช่วยเพิ่มประสิทธิภาพได้อย่างมากด้วยการเรียกใช้งานพร้อมกัน ในตัวอย่างต่อไปนี้ เราจะรวม SequentialAgent เข้ากับ ParallelAgent ด้วย โดยงานแบบขนานจะทำงานก่อน จากนั้นเอเจนต์สุดท้ายจะสรุปผลลัพธ์ของงานแบบขนาน

มาสร้างนักสืบของบริษัทกันดีกว่า ซึ่งมีหน้าที่ค้นหาข้อมูลเกี่ยวกับ

  • โปรไฟล์ของบริษัท (CEO, สำนักงานใหญ่, คำขวัญ ฯลฯ)
  • ข่าวสารล่าสุดเกี่ยวกับบริษัท
  • รายละเอียดเกี่ยวกับงบการเงินของบริษัท
// src/main/java/com/example/agent/CompanyDetective.java 
package com.example.agent;

import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.ParallelAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.tools.GoogleSearchTool;
import com.google.adk.web.AdkWebServer;

public class CompanyDetective {
    public static void main(String[] args) {
        var companyProfiler = LlmAgent.builder()
            .name("company-profiler")
            .description("Provides a general overview of a company.")
            .instruction("""
                Your role is to provide a brief overview of the given company.
                Include its mission, headquarters, and current CEO.
                Use the Google Search Tool to find this information.
                """)
            .model("gemini-2.5-flash")
            .tools(new GoogleSearchTool())
            .outputKey("profile")
            .build();

        var newsFinder = LlmAgent.builder()
            .name("news-finder")
            .description("Finds the latest news about a company.")
            .instruction("""
                Your role is to find the top 3-4 recent news headlines for the given company.
                Use the Google Search Tool.
                Present the results as a simple bulleted list.
                """)
            .model("gemini-2.5-flash")
            .tools(new GoogleSearchTool())
            .outputKey("news")
            .build();

        var financialAnalyst = LlmAgent.builder()
            .name("financial-analyst")
            .description("Analyzes the financial performance of a company.")
            .instruction("""
                Your role is to provide a snapshot of the given company's recent financial performance.
                Focus on stock trends or recent earnings reports.
                Use the Google Search Tool.
                """)
            .model("gemini-2.5-flash")
            .tools(new GoogleSearchTool())
            .outputKey("financials")
            .build();

        var marketResearcher = ParallelAgent.builder()
            .name("market-researcher")
            .description("Performs comprehensive market research on a company.")
            .subAgents(
                companyProfiler,
                newsFinder,
                financialAnalyst
            )
            .build();

        var reportCompiler = LlmAgent.builder()
            .name("report-compiler")
            .description("Compiles a final market research report.")
            .instruction("""
                Your role is to synthesize the provided information into a coherent market research report.
                Combine the company profile, latest news, and financial analysis into a single, well-formatted report.

                ## Company Profile
                {profile}

                ## Latest News
                {news}

                ## Financial Snapshot
                {financials}
                """)
            .model("gemini-2.5-flash")
            .build();

        AdkWebServer.start(SequentialAgent.builder()
            .name("company-detective")
            .description("Collects various information about a company.")
            .subAgents(
                marketResearcher,
                reportCompiler
            ).build());
    }
}

คุณเรียกใช้เอเจนต์ได้ตามปกติโดยใช้คำสั่งต่อไปนี้

mvn compile exec:java -Dexec.mainClass=com.example.agent.CompanyDetective

ลองถามเกี่ยวกับบริษัทต่างๆ เช่น Google หรือ Apple แล้วดูว่าคุณจะได้รับคำตอบอะไร

เอเจนต์นี้แสดงให้เห็นถึงการผสมผสานเวิร์กโฟลว์อันทรงพลัง โดยใช้ทั้งเอเจนต์แบบขนานและแบบลำดับอย่างมีประสิทธิภาพด้วยการค้นคว้าและสังเคราะห์ข้อมูลแบบขนาน

10. เวิร์กโฟลว์ของ Agent - การปรับแต่งแบบวนซ้ำ

1e5b5df3fd45f698.png

สำหรับงานที่ต้องมีวงจร "สร้าง → ตรวจสอบ → ปรับแต่ง" ให้ใช้ LoopAgent ซึ่งจะช่วยปรับปรุงซ้ำๆ โดยอัตโนมัติจนกว่าจะบรรลุเป้าหมาย LoopAgent จะเรียกใช้ Agent ย่อยแบบอนุกรมเช่นเดียวกับ SequentialAgent แต่จะวนกลับไปที่จุดเริ่มต้น ซึ่งเป็น LLM ที่เอเจนต์ใช้ภายในที่จะตัดสินใจว่าจะขอให้โทรหาเครื่องมือพิเศษ ซึ่งก็คือexit_loopเครื่องมือในตัว เพื่อหยุดการดำเนินการของลูปหรือไม่

ตัวอย่างการปรับแต่งโค้ดด้านล่างนี้ใช้ LoopAgent เพื่อปรับแต่งโค้ดโดยอัตโนมัติ ได้แก่ สร้าง ตรวจสอบ แก้ไข ซึ่งเลียนแบบการพัฒนามนุษย์ เครื่องมือสร้างโค้ดจะสร้างโค้ดที่ขอขึ้นมาก่อน จากนั้นจะบันทึกโค้ดนั้นไว้ในสถานะของ Agent ภายใต้คีย์ generated_code จากนั้นผู้ตรวจสอบโค้ดจะตรวจสอบโค้ดที่สร้างขึ้น และให้ความคิดเห็น (ภายใต้คีย์ feedback) หรือเรียกใช้เครื่องมือลูปทางออกเพื่อสิ้นสุดการทำซ้ำก่อนเวลา

มาดูโค้ดกัน

// src/main/java/com/example/agent/CodeRefiner.java
package com.example.agent;

import com.google.adk.agents.LlmAgent;
import com.google.adk.agents.LoopAgent;
import com.google.adk.agents.SequentialAgent;
import com.google.adk.tools.ExitLoopTool;
import com.google.adk.web.AdkWebServer;

public class CodeRefiner {
    public static void main(String[] args) {
        var codeGenerator = LlmAgent.builder()
            .name("code-generator")
            .description("Writes and refines code based on a request and feedback.")
            .instruction("""
                Your role is to write a Python function based on the user's request.
                In the first turn, write the initial version of the code.
                In subsequent turns, you will receive feedback on your code.
                Your task is to refine the code based on this feedback.

                Previous feedback (if any):
                {feedback?}
                """)
            .model("gemini-2.5-flash")
            .outputKey("generated_code")
            .build();

        var codeReviewer = LlmAgent.builder()
            .name("code-reviewer")
            .description("Reviews code and decides if it's complete or needs more work.")
            .instruction("""
                Your role is to act as a senior code reviewer.
                Analyze the provided Python code for correctness, style, and potential bugs.

                Code to review:
                {generated_code}

                If the code is perfect and meets the user's request,
                you MUST call the `exit_loop` tool.

                Otherwise, provide constructive feedback for the `code-generator to improve the code.
                """)
            .model("gemini-2.5-flash")
            .outputKey("feedback")
            .tools(ExitLoopTool.INSTANCE)
            .build();

        var codeRefinerLoop = LoopAgent.builder()
            .name("code-refiner-loop")
            .description("Iteratively generates and reviews code until it is correct.")
            .subAgents(
                codeGenerator,
                codeReviewer
            )
            .maxIterations(3) // Safety net to prevent infinite loops
            .build();

        var finalPresenter = LlmAgent.builder()
            .name("final-presenter")
            .description("Presents the final, accepted code to the user.")
            .instruction("""
                The code has been successfully generated and reviewed.
                Present the final version of the code to the user in a clear format.

                Final Code:
                {generated_code}
                """)
            .model("gemini-2.5-flash")
            .build();

        AdkWebServer.start(SequentialAgent.builder()
            .name("code-refiner-assistant")
            .description("Manages the full code generation and refinement process.")
            .subAgents(
                codeRefinerLoop,
                finalPresenter)
            .build());
    }
}

เรียกใช้เอเจนต์นี้ด้วยคำสั่งต่อไปนี้

mvn compile exec:java -Dexec.mainClass=com.example.agent.CodeRefiner

คุณขอให้ทำสิ่งที่ซับซ้อน เช่น Tower of Hanoi หรือ Quicksort Algorithm ได้

วงจรความคิดเห็น/การปรับแต่งที่ใช้ LoopAgent เป็นสิ่งจำเป็นอย่างยิ่งในการแก้ปัญหาที่ต้องมีการปรับปรุงซ้ำๆ และการแก้ไขด้วยตนเอง ซึ่งเลียนแบบกระบวนการรับรู้ของมนุษย์อย่างใกล้ชิด รูปแบบการออกแบบนี้มีประโยชน์อย่างยิ่งสำหรับงานที่เอาต์พุตเริ่มต้นมักจะไม่สมบูรณ์ เช่น การสร้างโค้ด การเขียนเชิงสร้างสรรค์ การออกแบบซ้ำ หรือการวิเคราะห์ข้อมูลที่ซับซ้อน การวนรอบเอาต์พุตผ่าน Agent ผู้ตรวจสอบเฉพาะทางที่ให้ความคิดเห็นที่มีโครงสร้างจะช่วยให้ Agent การสร้างสรรค์ปรับปรุงงานได้อย่างต่อเนื่องจนกว่าจะตรงตามเกณฑ์การเสร็จสมบูรณ์ที่กำหนดไว้ล่วงหน้า ซึ่งจะนำไปสู่ผลลัพธ์สุดท้ายที่มีคุณภาพสูงขึ้นอย่างเห็นได้ชัดและเชื่อถือได้มากกว่าแนวทางแบบครั้งเดียว

11. ยินดีด้วย

8797fc7eb90c750d.png

คุณได้สร้างและสำรวจ AI Agent ที่หลากหลายเรียบร้อยแล้ว ตั้งแต่ Agent ที่ใช้สนทนาแบบง่ายๆ ไปจนถึงระบบแบบหลาย Agent ที่ซับซ้อน คุณได้เรียนรู้แนวคิดหลักของ ADK สำหรับ Java แล้ว ได้แก่ การกำหนด Agent ด้วยคำสั่ง การเพิ่มศักยภาพด้วยเครื่องมือ และการประสานงานให้เป็นเวิร์กโฟลว์ที่มีประสิทธิภาพ

ขั้นตอนต่อไปคืออะไร

  • สำรวจที่เก็บ GitHub ของ ADK สำหรับ Java อย่างเป็นทางการ
  • ดูข้อมูลเพิ่มเติมเกี่ยวกับเฟรมเวิร์กได้ในเอกสารประกอบ
  • อ่านเกี่ยวกับเวิร์กโฟลว์ที่เป็น Agent ต่างๆ ได้ในชุดบล็อกนี้ และอ่านเกี่ยวกับเครื่องมือต่างๆ ที่มีให้ใช้งาน
  • เจาะลึกเครื่องมืออื่นๆ ในตัวและฟังก์ชันเรียกกลับขั้นสูง
  • จัดการบริบท สถานะ และอาร์ติแฟกต์เพื่อการโต้ตอบที่สมบูรณ์ยิ่งขึ้นและแบบมัลติโมดัล
  • ติดตั้งใช้งานและใช้ปลั๊กอินที่เชื่อมต่อกับวงจรของ Agent
  • ลองสร้างเอเจนต์ของคุณเองที่แก้ปัญหาในโลกแห่งความจริง