Day 4A: Multi-Agent Systems — Roles, Communication, Orchestration
สรุปย่อ
ประเด็นสำคัญจากวิดีโอ
- **ช่อง:** Adspolitan Knowledge Studio · **ความยาว:** ~24 นาที · **ลิงก์:** https://www.youtube.com/watch?v=16QTif1cqoU
# สรุป: Day 4A: Multi-Agent Systems — Roles, Communication, Orchestration - **ช่อง:** Adspolitan Knowledge Studio · **ความยาว:** ~24 นาที · **ลิงก์:** https://www.youtube.com/watch?v=16QTif1cqoU ## ประเด็นหลัก - แม้ชื่อวิดีโอจะระบุ Multi-Agent Systems แต่เนื้อหาจริงของ assignment นี้คือ agent quality ที่มีรากฐานอยู่ที่ observability (การสังเกตการทำงานของเอเจนต์) - เสาหลักของ agent observability มี 3 อย่าง: logs (เกิดอะไรขึ้นตอนไหน) traces (ทำไมผลลัพธ์จึงเป็นแบบนั้น — ลำดับขั้นตอนทั้งหมด) และ metrics (คะแนนว่าเอเจนต์ทำได้ดีแค่ไหน) — อธิบายด้วยอุปมาการทำอาหาร: logs = บันทึกวัตถุดิบ+ขั้นตอน, traces = ทำตามสูตรจริง, metrics = ให้คะแนนอาหาร - ตัวอย่าง bug จริง: root agent ส่ง list ของ paper เป็น string แทน list ของ string ทำให้นับได้ 1690 paper แทนที่จะเป็น 14 — แก้ด้วยการตรวจ invocations ใน ADK web UI เห็น parameter ที่ LLM รับจริง - การ debug ด้วย ADK web UI ใช้ได้ในช่วงพัฒนา แต่ production ไม่มีสิทธิ์เข้า web UI และเอเจนต์อาจรันวันละพันครั้ง — ต้องเก็บ observability data ด้วย log statements แทน - Plugin คือโมดูลโค้ดที่รันอัตโนมัติตามช่วงต่างๆ ของวงจรเอเจนต์ ประกอบด้วย callbacks หลายตัว (before/after agent, before/after model, before/after tool, after error) — callbacks รวมกันเป็น plugin - ตัวอย่าง CountInvocationPlugin นับจำนวนครั้งที่เอเจนต์และ LLM ถูกเรียก โดยเพิ่มค่าทีละหนึ่งใน before callback แต่ละตัว - ไดอะแกรม 6 ขั้นตอนอธิบาย flow: user message → runner → plugin (before agent) → research agent → LLM (plugin ก่อน/หลัง model) → response กลับ — plugin ถูกเรียก 2 ครั้งต่อการรันหนึ่งครั้ง - ADK มี built-in logging plugin ที่เก็บอัตโนมัติ: user messages, agent responses, timing data, LLM request/response, tool calls และ execution traces ทั้งหมด - การใช้งาน: import plugin แล้วเสียบเข้าตอนสร้าง runner — log ที่ได้อ่านง่ายและอธิบายตัวเองได้ ไล่ดู invocation ID, event ID, token ได้ครบ - วิดีโอถัดไป (Day 4B) คือ evaluation — การให้คะแนนคุณภาพคำตอบและการใช้ tool ของเอเจนต์ ## ความเห็นสรุป วิดีโอนี้เดินตาม notebook ทีละ cell เหมือนคลิปก่อนๆ ของซีรีส์ จุดเด่นคือการพา debug bug จริง (string แทน list) จนเห็นกันชัดๆ ว่า observability ช่วยหาสาเหตุได้อย่างไร แล้วต่อยอดสู่ logging แบบ plugin สำหรับ production ครับ ข้อควรระวังอีกอย่างคือชื่อวิดีโอกับเนื้อหาจริงไม่ตรงกันอีกครั้ง (ชื่อบอก Multi-Agent แต่สอน Observability/Logging) ผู้เรียนควรอาศัยคำอธิบายในวิดีโอเป็นหลักแทนชื่อคลิปครับ
คำแปลเต็ม
แปลตามบทสนทนาต้นฉบับ ปรับเป็นภาษาไทยธรรมชาติ
สวัสดีทุกคนครับ ยินดีต้อนรับเข้าสู่ assignment ของ Day 4 ในคอร์ส 5 วันนี้ครับ ใน assignment นี้เราจะเรียนเรื่อง agent quality หรือคุณภาพของเอเจนต์ครับ รากฐานพื้นฐานของเรื่องนี้คือ observability (ความสามารถในการสังเกตการทำงานของระบบ) ครับ โปรดตรวจสอบให้แน่ใจว่าคุณได้ฟังตอนสรุปพอดแคสต์ที่สร้างโดย NotebookLM และ white paper เรื่อง agent quality ซึ่งเป็นข้อมูลประกอบของพอดแคสต์นี้แล้วนะครับ white paper ฉบับนี้จัดการกับความท้าทายในการรับประกันคุณภาพของ AI agents โดยแนะนำกรอบการประเมินผลแบบ holistic หรือแบบองค์รวมครับ
ใน codelab พวกนี้เราจะเข้าใจคุณภาพของเอเจนต์อย่างครบถ้วน codelab แรกเกี่ยวกับวิธีใช้ logs traces และ metrics ส่วนอันที่สองคือการประเมินเอเจนต์ของเรา เพื่อให้คะแนนคุณภาพคำตอบของเอเจนต์และการใช้ tool ครับ ผมจะคลิกที่ implement ซึ่งจะพาไปที่ notebook แล้วผมจะแก้ไขสำเนาของผมจากตรงนี้ครับ
ตอนต้นของ notebook ให้สรุปว่า agent observability คืออะไร agent observability โดยพื้นฐานคือการเข้าใจ error ต่างๆ ติดตามทุกขั้นตอน และบันทึกรายละเอียดต่างๆ เพื่อ debug เมื่อจำเป็นครับ ตัวอย่างเช่น user สั่งว่าหางานวิจัยเรื่อง quantum computing ให้หน่อย แต่เอเจนต์ตอบว่าฉันช่วยเรื่องนี้ไม่ได้ ตอนนี้เราต้องเข้าใจว่า prompt ผิดตรงไหน มี tool ตัวไหนขาดหายไปหรือเปล่า หรือมี error ใน API ครับ ทางแก้ก็คือ agent observability ครับ มันให้มุมมองแบบครบถ้วนเกี่ยวกับกระบวนการตัดสินใจของเอเจนต์ คุณจะเห็นชัดเจนว่า prompt อะไรถูกส่งไปที่ LLM มี tool อะไรให้ใช้บ้าง โมเดลตอบอย่างไร และความล้มเหลวเกิดขึ้นตรงไหนครับ ตัว debug log จะแสดงให้เห็นว่า request นี้ไม่มี functions เลย ซึ่งหมายความว่าเราต้องแทรก Google Search tool ที่ขาดหายไปตรงนี้ครับ และนั่นคือวิธีแก้ไขครับ
เพื่ออธิบายให้เห็นภาพชัดขึ้น มีตัวอย่างหนึ่งครับ เสาหลักของ agent observability คือ logs traces และ metrics ครับ logs บอกเราว่าเกิดอะไรขึ้นในช่วงเวลาหนึ่งๆ traces แสดงให้เห็นว่าทำไมผลลัพธ์สุดท้ายจึงออกมาแบบนั้น โดยเปิดเผยลำดับขั้นตอนทั้งหมด ส่วน metrics คือคะแนน มันจะบอกว่าเอเจนต์ทำงานได้ดีแค่ไหนโดยรวมครับ ในตัวอย่างนี้มันแสดงให้เห็นว่าอาหารจานหนึ่งถูกปรุงขึ้นมาอย่างไร logs ก็เหมือนบันทึกการเตรียม ที่คุณระบุวัตถุดิบและขั้นตอนต่างๆ traces คือการที่คุณทำตามขั้นตอนเหล่านั้นเพื่อสร้างสูตรอาหารจริงๆ ส่วน metrics คือการให้คะแนนอาหารในด้านต่างๆ เช่น รสชาติ การจัดจาน ความคิดสร้างสรรค์ แล้วสรุปเป็นคะแนนรวมของจานนั้นครับ
ใน notebook นี้เราจะตั้งค่า logging configuration สร้างเอเจนต์ที่มีปัญหาที่เราจะแก้ไข แล้วเรียนรู้วิธี implement logging แบบ production รวมถึงเรียนรู้ว่าเมื่อไหร่ควรใช้ built-in logging เทียบกับโซลูชันที่เขียนเองครับ
ในการเริ่มต้น section แรกเป็นเรื่องตั้งค่า environment เสมอ ซึ่งเราทำกันมาในทุกวิดีโอแล้ว ผมจะรีบผ่านๆ ไปเลยนะครับ อย่างแรกคือตั้งค่า Gemini API วิธีทำคือไปที่ add-ons แล้วเลือก secret ตอนนี้เรายังไม่มี key ผมจะไปที่ Google AI Studio คัดลอก key จากตรงนั้น กลับมาที่ notebook กด add secret ใส่ชื่อ label เป็น Google API โปรดตรวจสอบให้แน่ใจว่าใส่ตรงตามนั้นทุกตัวอักษร เพราะมัน sensitive ต่อตัวพิมพ์ใหญ่เล็ก ต้องเหมือนกับที่ระบุในโค้ดตรงนี้เป๊ะครับ กด save แล้วตรวจว่ามันถูกติ๊กแล้วหรือยัง ติ๊กแล้วครับ ตอนนี้กดรัน เราได้รัน setup เรียบร้อย การยืนยันตัวตนและการตั้งค่าเสร็จสมบูรณ์แล้วครับ
ต่อไปเราจะจัดการไฟล์ logging และ cleanup เราจะตั้งค่ามันกัน import logging และ import os เพื่อล้าง log เดิมที่เหลือจากครั้งก่อน รันอันนี้ได้เลย ถ้ามี log file อยู่ใน logger file ใน web tunnel เราจะเอามันออก โดยใช้ path.exists ถ้าคุณมี log file ซึ่งก็ไฟล์พวกนี้ ก็จะลบไฟล์พวกนี้ทิ้ง แล้วพิมพ์ว่า cleaned up ครับ จากนั้นขั้นต่อไปคือ configure logging แบบ debug logging โดย basicConfig คือใส่ logger ตรงนี้ ใช้ level เป็น logging.DEBUG ส่วน format ประกอบด้วยชื่อไฟล์ เลขบรรทัด ระดับ และข้อความ พอรันก็บอกว่า logging configured ครับ
ขั้นต่อไปคือตั้งค่า proxy และ tunneling อันนี้ก็คือ helper function ที่เราทำกันมาแล้วในวิดีโอก่อนๆ ถ้าคุณใช้สภาพแวดล้อม notebook ของ Kaggle คุณต้องทำขั้นตอนนี้ แต่ถ้ารันนอกสภาพแวดล้อม Kaggle ก็ไม่จำเป็นต้องทำครับ ผมจะรันผ่านๆ ไป helper function ถูกนิยามแล้วครับ
มาถึง section สองซึ่งเป็นการ debug แบบลงมือจริงด้วย ADK web UI ครับ อันดับแรกเราจะสร้าง research paper finder agent เอเจนต์หางานวิจัย โดยเป้าหมายคือช่วย user หางานวิจัยวิชาการในหัวข้อใดก็ได้ครับ ตอนนี้คุณจะสังเกตเห็นว่ามันขึ้นว่าโฟลเดอร์ที่ไม่ว่างอยู่แล้ว มันถามว่าจะทับโมเดลที่มีอยู่เดิมของเราไหม y หรือ n คือ yes หรือ no ครับ เหตุผลที่ผมเจอข้อความนี้เพราะผมเคยทำมาแล้วก่อนถ่ายวิดีโอนี้ มันเลยบอกว่าโฟลเดอร์มีอยู่แล้ว ถ้าคุณทำครั้งแรกอาจจะไม่เห็นข้อความนี้ แต่ถ้าทำรอบที่สองเหมือนผมก็จะเจอข้อความนี้ครับ
ตอนนี้คุณเห็นว่ามันยังคง executing อยู่ หมายความว่า notebook กำลังรอ input แบบ interactive แต่เราพิมพ์ y แบบ interactive ภายใน cell ของ notebook ไม่ได้ครับ วิธีแก้คือทำให้มันตอบ yes อัตโนมัติ โดยแก้โค้ดตรงนี้ คือเพิ่ม force flag เข้าไปในคำสั่ง พิมพ์ขีดกลางสองอันแล้วพิมพ์ force ก็จะใช้ได้ครับ ปกติวิธีนี้ใช้ได้ แต่บางครั้งก็ไม่ได้ผล ในกรณีนั้นเราสามารถลบโฟลเดอร์ด้วยตนเองได้ครับ ระหว่างที่มันรันอยู่ ผมจะบอกว่าควรเขียนอะไรไว้ในกรณีที่ใช้ไม่ได้ครับ ให้เขียนว่าเครื่องหมายอัศเจรีย์ตามด้วย rm ครับ แล้วขั้นต่อไปคือรันอันนี้ ขอหยุดอันเดิมก่อนนะครับ โอเค ให้ผมรันอันนี้ก่อน เสร็จแล้ว ตอนนี้ผมจะเอา force ออก ขอโทษทีครับ นี่ไงเห็นไหมครับ
สิ่งที่ผมทำตรงนี้ ผมจะอธิบายให้ฟังนะครับ โค้ดนี้เป็นคำสั่ง shell ที่คุณรันภายใน notebook ของ Kaggle หรือ Jupyter ถ้ารันนอก Kaggle ก็ไม่ต้องมีส่วนนี้ครับ rm ย่อมาจาก remove แล้วก็ recursive กับ force นี่คือชื่อโฟลเดอร์ที่มีอยู่เดิม ผมสั่งให้มันลบ directory ของ research agent ทั้งหมดพร้อมไฟล์ข้างในทั้งหมดทันที ในสภาพแวดล้อม Kaggle หรือสภาพแวดล้อม Jupyter โดยไม่ต้องถามอะไรอีก นี่คือสิ่งที่โค้ดนี้ทำครับ หลังจากนั้นผมรันโค้ดก่อนหน้านี้ซ้ำอีกครั้ง มันจึงสร้าง research agent ใหม่ที่สะอาดเต็มไปหมดครับ
ทีนี้มานิยามเอเจนต์กันที่ตรงนี้ครับ ถ้าดูส่วนประกอบของ ADK ที่เราเคย import แยกในอีก cell หนึ่ง ตอนนี้เรารวมเข้ามาในโค้ดนิยามเอเจนต์เลยครับ ตรงนี้เรากำลัง configure ตัว LlmAgent โดยให้ชื่อ คำอธิบาย และ instructions ครับ ก่อนหน้านั้นขอคุยเรื่องนี้กันก่อน ในการนิยามเอเจนต์แบบนี้ เรามี root agent (เอเจนต์หลัก) ที่มอบหมายงานค้นหาให้ search agent แล้วก็มีอีกเอเจนต์หนึ่งที่ใช้ count_papers ครับ ส่วน import ที่เรียกเข้ามาอันดับแรกคือ agent กับ Gemini แล้วก็ agent tool และ Google Search ครับ ถ้าคุณรู้จักสิ่งเหล่านี้แล้ว เราก็นิยาม retry_config ไว้ในโค้ดเดียวกันนี้เลย แทนที่จะไว้ในส่วน setup ครับ
จากนั้นเราจงใจส่ง data type ที่ผิดพลาด คือส่ง string แทนที่จะเป็น list ของ string ครับ แล้วดูกันว่าจะเกิดอะไรขึ้น นิยาม count_papers โดยรับ papers เป็น string อาร์กิวเมนต์คือ papers ซึ่งเป็น list ของ string โดยแต่ละ string คืองานวิจัยหนึ่งชิ้น มันควรคืนค่าจำนวน paper ใน list นั้น คำสั่งคือ return len(papers) ครับ ต่อไปเรานิยาม Google search agent ให้ชื่อ model description และ instructions ครับ description คือค้นหาข้อมูลโดยใช้ Google Search ส่วน instruction คือให้ใช้เครื่องมือ Google Search ค้นหาข้อมูลในหัวข้อที่กำหนด แล้วคืนผลลัพธ์การค้นหาแบบดิบๆ ถ้า user ขอ list ของ paper ให้ส่ง list งานวิจัยที่เจอให้ ไม่ใช่สรุปย่อครับ เครื่องมือที่เราใช้ตรงนี้คือ Google Search ครับ
ส่วน root agent จะใช้ตัวนี้กับ count_papers ครับ มีชื่อ model และ instructions ว่า ภารกิจของเธอคือหางานวิจัยแล้วนับมัน เธอต้องทำตามขั้นตอนเหล่านี้เสมอ ขั้นแรกหางานวิจัยในหัวข้อที่ user ให้มาโดยใช้ Google search agent ซึ่งเรานิยามไว้ตรงนี้ในส่วน tools จากนั้นส่ง papers ที่ได้ไปที่ count_papers ซึ่งก็เป็น tool ตัวนี้อีกเช่นกัน เพื่อนับจำนวน paper แล้วคืนค่าทั้ง list งานวิจัยและจำนวน paper ทั้งหมดครับ มันต้องคืนผลลัพธ์สองอย่างคือ list กับจำนวน paper ครับ ผมกำลังสร้างเอเจนต์เหล่านี้ เราได้ทับ research agent เดิมแล้ว
ต่อไปเราจะรันเอเจนต์นี้ใน ADK web UI ครับ สำหรับขั้นนี้เราต้องสร้าง proxy ก่อน นี่คือการเข้าถึง URL ของ proxy โดยต้องรันอันนี้ก่อน พอเห็นว่า server เริ่มทำงานแล้ว เราก็พร้อมเริ่มต้นครับ กลับไปที่ section นี้ เปิด ADK web UI โดยคลิกตรงนี้ เห็นไหมครับ ถ้ากลับไปดู มันจะให้คำถามอย่างเช่นให้ทำสิ่งนี้ใน UI คุณต้องเลือก agent ที่ชื่อ research agent แล้วถามใน interface นี้ครับ เราเลือกไว้แล้วโดย default ครับ จะถามว่าหางานวิจัย quantum computing ล่าสุดหน่อย ซึ่งเป็นคำถามที่ระบุไว้ตรงนี้ พิมพ์ลงในช่องแชตครับ แล้วเอเจนต์ควรคืน list งานวิจัยพร้อมจำนวนที่นับได้ครับ
เรากลับมาดูกัน งานวิจัย computing ล่าสุดถูกพบแล้ว ได้ตัวนี้ ตัวนี้ และตัวนี้มา รวมทั้งหมดเป็น 1690 paper ซึ่งดูมหาศาลเกินไปครับ สิ่งที่เราทำคือไปที่ส่วน invocations ทางซ้ายแล้วขยายออก จะเห็นว่าการนับถูกทำอย่างไร นี่คือการเรียกใช้ tool ตัว count_papers ครับ คลิกตรงนี้ มันบอกว่า 1690 ครับ ผู้เขียนคือ research paper finder คุณจะเห็นการเรียก LLM ว่ามันรับ parameter อะไรไปบ้าง ถ้าดูจะเห็นว่ามันรับ text เป็น string แทนที่จะเป็น list นั่นเองครับ นี่จึงเป็นเหตุผลที่เราได้ 1690 paper ครับ
ทีนี้เราจะทำอะไรต่อ ต้องหยุด session ก่อนตรงนี้ครับ มันยังคงพูดเรื่องเดิมอยู่ คือ root agent ส่ง list ของ paper เป็น string แทนที่จะเป็น list ของ string และนั่นคือ bug ที่เราหาเจอครับ สิ่งที่ต้องทำต่อไปคือเปลี่ยน data type ของอาร์กิวเมนต์ papers ใน tool ชื่อ count_papers ให้เป็น list ของ string แล้วรันใหม่ครับ การจะรันใหม่เราต้องหยุดอันเดิมก่อน ถ้าไม่หยุดมันจะรันต่อไปเรื่อยๆ ผมต้องมาตรงนี้แล้วหยุดมันด้วยตนเองครับ โอเค หยุดแล้ว แล้วรันส่วน debug นี้ เราตรวจสอบ log ของ web server เพื่อหาเบาะแสการ debug ครับ
ระหว่างนั้นเราจะอัปเดต data type ของอาร์กิวเมนต์ papers ใน count_papers ให้เป็นแบบนี้กันด้วย กลับไปตรงนี้ นี่คือ count_papers ตรงนี้เดิมเป็น string เราจะเปลี่ยนเป็น list ของ string ครับ ทีนี้รันอันนี้ ทับของเดิม เขียนทับเรียบร้อยแล้ว เรากลับมาแล้วรันส่วนนี้ซ้ำ แล้วเริ่มอันนี้ขึ้นมาใหม่ web server ก็เริ่มทำงานครับ คลิกที่ลิงก์นี้ มันเปิดหน้าเอเจนต์ขึ้นมา สังเกตว่า agent ID กับ session ID ตรงนี้ไม่เหมือนเดิมแล้ว อันก่อนหน้านี้ต่างออกไป เราจึงใช้ตัวใหม่นี้ครับ คัดลอกคำถามเดิมมา ขอกลับไปเอาคำถามนี้ก่อนนะครับ วางแล้วกด enter คุณเห็น output ตรงนี้ไหมครับ ได้ข้อมูลมาแล้ว และอันสุดท้ายคือมี paper รวมทั้งหมด 14 ชิ้น เทียบกับอันก่อนที่บอก 1690 paper ครับ และตรงนี้เราก็สามารถเห็นการ execute ของโค้ดได้อีกเช่นกันครับ
ทีนี้คือ section สามครับ เราสามารถ debug ความล้มเหลวของเอเจนต์โดยใช้ ADK web UI และ debug log ได้ ปัญหาแรกคือ production development ปัญหาที่สองคือระบบอัตโนมัติครับ มีคนพูดว่า ขอเปิด ADK web UI เพื่อตรวจสอบว่าทำไมเอเจนต์ถึงล้มเหลว ทีม DevOps มักจะตอบว่า นี่คือ production server เข้าถึง web UI ไม่ได้ครับ ตอนนี้เราอยากเข้าใจว่าจะ debug ปัญหา production อย่างไร นี่คือสิ่งที่เราอยากจัดการครับ อีกเรื่องที่อยากจัดการคือ เอเจนต์รันวันละพันครั้งใน pipeline ของเราซึ่งรันช้า อัตราความสำเร็จของเราเป็นเท่าไหร่ แล้วคุณคงต้องไปเช็ค web UI ด้วยตนเองเป็นพันครั้ง ไม่ครับ ผมว่าเราไม่ควรทำแบบนั้นครับ
ดังนั้นเราต้องมีวิธีเก็บข้อมูล observability หรือพูดอีกอย่างคือเพิ่ม log เข้าไปในโค้ดของเราครับ นั่นแหละสิ่งที่เราทำกันอยู่ใช่ไหมครับ สำหรับแต่ละ batch เรามี batch run มีข้อมูล job run ครับ ในทำนองเดียวกันเราก็จะมีอะไรทำนองนี้เช่นกันครับ มันบอกว่าในการพัฒนาซอฟต์แวร์แบบดั้งเดิม เราทำโดยเพิ่ม log statement ในฟังก์ชัน Python และเอเจนต์ก็ไม่ต่างกัน เราต้องเพิ่ม log statement เข้าไปในเอเจนต์ของเราครับ แนวทางที่พบบ่อยคือการเพิ่ม log statement ใน plugin ครับ จะเพิ่ม log สำหรับ production observability อย่างไร เราจะทำด้วย plugin ครับ โดย plugin คือโมดูลโค้ดที่กำหนดเองซึ่งรันอัตโนมัติในหลายช่วงของวงจรชีวิตเอเจนต์ครับ แต่ละ plugin จะมี callback ดังที่เห็นในไดอะแกรมนี้ ซึ่งเป็น hook สำหรับแทรกตัวเข้าไปใน flow ของเอเจนต์ครับ
ตัวอย่างเช่น workflow ของเอเจนต์เป็นแบบนี้ครับ user message เข้ามา เอเจนต์คิด เรียกใช้ tool แล้วตอบกลับครับ เมื่อมี plugin hook สิ่งที่เกิดขึ้นคือ ก่อนเอเจนต์เริ่มทำงาน และหลัง tool รัน หรือหลัง response คุณสามารถวาง hook ได้ทุกจุดเลยครับ แล้ว callback คืออะไรกันแน่ มันคือส่วนประกอบย่อยภายใน plugin ครับ เหมือนมีชิ้นเล็กๆ อยู่ข้างใน plugin ไดอะแกรมนี้เราเคยเห็นใน Day 3 แล้ว มันคือฟังก์ชัน Python ที่รันในจุดเวลา specific ต่างๆ ของวงจรชีวิตเอเจนต์ครับ callback ถูกรวมกันเป็นกลุ่มเพื่อสร้าง plugin ครับ เวลาใช้ callback ก็เหมือนที่เราทำเมื่อวานนี้ มี callback แบบ before กับ after ของเอเจนต์ มี before กับ after ของ tool มี before กับ after ของ model และมี callback เมื่อเกิด error ครับ ทั้งหมดนี้คือ callback ที่คุณเสียบเข้าไปได้ครับ
เพื่อให้เห็นภาพชัดขึ้น มาดูกันว่า plugin หน้าตาเป็นอย่างไรครับ นี่คือตัวอย่าง ในโค้ดนี้มันไม่ได้ทำอะไรจริงจัง เราแค่ดูว่ามันทำงานอย่างไร ผมรันเพื่อดูว่า input เป็นอย่างไรครับ ระหว่างรันผมจะเล่าให้ฟังว่าเกิดอะไรขึ้นตรงนี้ คุณมี BaseAgent และมี callback context มี request และมี BasePlugin ครับ จากนั้นคุณใช้ BasePlugin ตัวนี้ใน count invocation plugin ที่คุณจะนิยามขึ้นครับ แล้วมี callback ตัวที่หนึ่ง คุณเขียนว่า self agent คือ BaseAgent ซึ่งเป็นเอเจนต์แรกที่คุณนิยามไว้ นี่คือ base agent ของคุณ และมี callback context ครับ
ทีนี้ count_agent_returns จะคืนค่าเช่นร้อยครั้ง พันครั้งอะไรทำนองนี้ ถ้าเป็นการบวกหนึ่งทุกครั้ง มันจะสะสมมากกว่าหนึ่งเสมอ ต้องนับมันไปเรื่อยๆ มันจะเพิ่มขึ้นเรื่อยๆ ครับ ตัวที่สอง callback ตัวที่สองรันก่อนที่ model จะถูกเรียก ตรงนี้คุณต้องมี model callback โดย callback context ก็ยังเป็น callback context เหมือนเดิม llm ก็คือ llm request เดิม ทีนี้คุณต้องนับ llm request ซึ่งก็บวกหนึ่งเช่นกันครับ ผมแค่รันอันนี้ ปกติมันไม่กระทบโค้ดของเราเลย พอเสร็จมันจะพิมพ์ว่า example plugin ไม่ทำอะไรเลย เพราะมันไม่ทำอะไร ผมจะกลับมาตรงนี้ คุณสามารถทำตามตัวเลขในไดอะแกรมด้านล่างเพื่อเข้าใจ flow ได้ครับ ไล่ตาม 1 2 แล้ว 3 4 5 ครับ
ขั้นแรกคือหางานวิจัย computing ล่าสุด ตามที่เราใส่ไปใน section ก่อนหน้าผ่านทาง web UI ครับ ตัว runner รันมัน เริ่มทำงาน ไปที่ memory agent ไปที่ agent tool และอื่นๆ ที่ตรงนี้ สิ่งที่เกิดขึ้นคือ count invocation plugin ซึ่งเป็น before agent callback ก่อนหน้านี้ มันไปที่เครื่องมือ research finding ก่อนตัวนั้น count เป็น none ครับ จากนั้นสิ่งที่เกิดขึ้นคือ runner ไปที่ research paper finder เพื่อไปที่โมเดล llm เพื่อหาว่าควรดูหน้าไหนบ้าง ระหว่างกลางมี plugin หนึ่ง นี่คือ before และ after และนี่คือ before model ด้วยเช่นกันครับ ขั้นที่หกคือมันรับกลับมา research agent ส่งต่อให้ runner แล้ว response ก็ออกไปครับ สิ่งที่เกิดขึ้นคือใน count invocation plugin ตัวนี้ถูกเรียกสองครั้ง ที่ขั้นตอนสองมันเรียกก่อนเอเจนต์ เพราะ plugin มี before agent callback ในทำนองเดียวกัน plugin ก็ถูก execute ก่อนการเรียก llm ซึ่งเกิดที่ขั้นตอนสี่ตรงนี้ครับ หวังว่าจะเข้าใจแจ่มชัดแล้วนะครับ
ต่อไปคือ built-in logging plugin ครับ built-in logging plugin คืออะไร ADK มี logging plugin แบบ built-in ซึ่งเก็บกิจกรรมของเอเจนต์โดยอัตโนมัติทั้งหมด เช่น ข้อความของ user และ response ของเอเจนต์ ข้อมูล timing สำหรับวิเคราะห์ประสิทธิภาพ request และ response ของ LLM เพื่อใช้ debug การเรียกใช้ tool และผลลัพธ์ รวมถึง execution trace แบบครบถ้วนครับ เราเคยนิยามเอเจนต์ไปแล้วสำหรับ research paper agent ตรงนี้เราทำคล้ายกันนี้อีกครั้ง โดยรัน research agent พร้อม logging ครับ ทุกอย่างเกือบเหมือนเดิม ตรงนี้ papers ถูกอัปเดตเป็น list ของ string แล้ว ข้อมูลส่วนที่เหลือถูกต้องครับ ต้องคืนค่าทั้งหมด instructions ก็เหมือนเดิมครับ ตรงนี้เราเพิ่ม research agent ด้วย plugin ครับ ผมจะรันตอนนี้เลย มันบอกว่าเอเจนต์ถูกสร้างสำเร็จแล้วครับ
ขั้นที่สามคือการใช้ plugin ใน research agent ด้านบน คลิกเพื่อ import plugin แล้วเพิ่มมันตอน initialize ตัว runner ครับ จาก ADK runners import runner ครับ คุณมี plugin ซึ่งก็คือ log plugin ผมจะรันอันนี้ มันบอกว่า runner ถูก configure แล้ว ใน runner ครับ เสร็จแล้ว ส่วนนี้เพิ่ม plugin เข้าไป มันจัดการ logging แบบ observability มาตรฐานให้กับเอเจนต์ทั้งหมดครับ ตัว runner ถูก configure แล้ว ทีนี้เราจะพิมพ์ statement ต่างๆ แล้วดูว่าได้ผลลัพธ์อะไร เราจะ debug ตอนนี้เลยครับ รันเอเจนต์พร้อม plugin แล้วดู logging output ที่ครอบคลุมครับ
response ตรงนี้คือ user message ได้รับแล้ว มี invocation กำลังใช้ debug ด้วย user ID นี้ มี context ตรงนี้ คือหางานวิจัยล่าสุดเรื่อง quantum computing ครับ แล้ว agent starting อยู่ตรงนี้ มี invocation ID ซึ่งเป็น plugin ID อีกอันหนึ่ง ตรงนี้บอกว่า research paper เริ่มแล้ว ก็มีแบบนี้อีกครับ ทีนี้เธอต้องทำตามขั้นตอนเหล่านี้ ขั้นแรกคือหางานวิจัยในหัวข้อที่ user ให้มาโดยใช้ Google search agent นี่คือ instruction แรกที่เราให้ไว้ใช่ไหมครับ มันบอกว่า tool ที่ใช้ได้คือตัวนี้กับตัวนี้ครับ
ใน LLM response เอเจนต์ research paper finder เรียกใช้ฟังก์ชันนี้ มี token ID มี input มี output เป็น 21 และมี event ID ตรงนี้ ทุก event ที่เกิดขึ้นถูกบันทึกครับ ตอนนี้ tool เริ่มทำงาน มี invocation ID ของ user message นี้ ตอนนี้เริ่ม invocation มีชื่อเอเจนต์ มี invocation ID ตัวนี้อยู่ตรงนี้ครับ ตอนนี้ model เริ่มทำงาน ตอนนี้เธอเป็นเอเจนต์หนึ่ง ชื่อภายในคือ Google search agent คำอธิบาย B ส่วน description เกี่ยวกับการค้นหา ฟิลด์ของ quantum เริ่มเพิ่ม context เข้ามา คุณสามารถไล่ดูได้เลย เรื่องนี้เข้าใจง่ายมาก มันอธิบายตัวเองได้ครับ
ในวิดีโอนี้เราได้ผ่านการ debug ในขั้นพัฒนา observability ระดับ production และ requirement แบบกำหนดเองครับ ในวิดีโอถัดไปซึ่งเป็นส่วนที่สองของ Day 4 เราจะเรียนเรื่อง evaluation คือวิธีประเมินและให้คะแนนคุณภาพคำตอบของเอเจนต์และการใช้ tool ครับ
หมายเหตุการแปล
ความโปร่งใสเกี่ยวกับความไม่แน่นอนในต้นฉบับ
- ไม่มีการใช้สัญลักษณ์ระบุเสียงไม่ชัดเจน (0 จุด) — ทุก segment เข้าใจความหมายได้ครบ
อภิธานศัพท์เทคนิค
คำศัพท์และชื่อผลิตภัณฑ์ที่คงรูปภาษาอังกฤษ
| ศัพท์ | คำแปล / คำอธิบาย |
|---|---|
| agent quality | คุณภาพของเอเจนต์ |
| observability | ความสามารถในการสังเกต/ติดตามการทำงานภายในของระบบ |
| logs | บันทึกเหตุการณ์ — บอกว่าเกิดอะไรขึ้นในช่วงเวลาหนึ่งๆ |
| traces | การติดตามเส้นทาง — แสดงลำดับขั้นตอนทั้งหมดว่าทำไมผลลัพธ์จึงเป็นเช่นนั้น |
| metrics | ตัวชี้วัด — คะแนนว่าเอเจนต์ทำงานได้ดีแค่ไหนโดยรวม |
| white paper | เอกสารทางการเชิงเทคนิค |
| holistic evaluation framework | กรอบการประเมินผลแบบองค์รวม |
| notebook LM / NotebookLM | เครื่องมือสร้างสรุปเนื้อหา/พอดแคสต์จากเอกสารของ Google |
| debug log | บันทึกข้อผิดพลาดใช้หาสาเหตุปัญหา |
| root agent | เอเจนต์หลักที่มอบหมายงานให้เอเจนต์อื่น |
| search agent | เอเจนต์ค้นหาข้อมูล |
| LlmAgent | คลาสเอเจนต์ที่ขับเคลื่อนด้วย LLM ใน ADK |
| count_papers | ชื่อ tool ในตัวอย่าง ใช้นับจำนวนงานวิจัย |
| ADK web UI | หน้าจอเว็บสำหรับรันและ debug เอเจนต์ของ ADK |
| proxy | ตัวกลางส่งต่อคำขอเครือข่าย ใช้เปิด web UI จาก notebook |
| tunneling | การเจาะทางผ่านเครือข่ายเพื่อเข้าถึง service ภายในจากภายนอก |
| invocation | การเรียกใช้งานหนึ่งครั้งของเอเจนต์/โมเดล |
| production | สภาพแวดล้อมระบบจริงที่ใช้งานจริง |
| pipeline | สายการผลิตกระบวนการทำงานอัตโนมัติ |
| plugin | โมดูลโค้ดที่กำหนดเอง รันอัตโนมัติตามช่วงของวงจรเอเจนต์ |
| callback | ฟังก์ชันเรียกกลับที่รันในจุดเวลา specific ของวงจรเอเจนต์ |
| BasePlugin | คลาสหลักสำหรับสร้าง plugin ใน ADK |
| BaseAgent | คลาสหลักของเอเจนต์ใน ADK |
| hook | จุดเกาะสำหรับแทรกโค้ดเข้าไปใน flow การทำงาน |
| built-in logging plugin | plugin บันทึก log สำเร็จรูปที่ ADK ให้มา |
| logging configuration | การตั้งค่าการบันทึก log |
| force flag | ตัวเลือกคำสั่ง (--force) บังคับดำเนินการโดยไม่ถามยืนยัน |
| rm -rf | คำสั่ง shell ลบโฟลเดอร์/ไฟล์แบบ recursive + force |
| case sensitive | sensitive ต่อตัวพิมพ์ใหญ่-เล็ก ต้องพิมพ์ตรงตาม |
| Google AI Studio | เครื่องมือของ Google สำหรับสร้าง/จัดการ API key |
| Kaggle | แพลตฟอร์มการแข่งขันและ notebook วิทยาศาสตร์ข้อมูล |
| Jupyter notebook | สมุดบันทึกโค้ดแบบโต้ตอบ |
| session | เซสชัน — หน่วยบทสนทนาหนึ่งครั้งกับเอเจนต์ |
| event | เหตุการณ์หนึ่งๆ ที่เกิดระหว่างการทำงานของเอเจนต์ |
| token | หน่วยนับข้อความที่โมเดลใช้ |
| evaluation | การประเมินผลการทำงาน |
| data type | ชนิดข้อมูล เช่น string หรือ list |
| string / list | ข้อความ / รายการหลายค่า |
ซับไตเติ้ลภาษาไทย
ดาวน์โหลดหรือดูซับทั้งหมด
1 00:00:00,000 --> 00:00:04,283 สวัสดีทุกคนครับ ยินดีต้อนรับเข้าสู่ assignment 2 00:00:04,283 --> 00:00:08,379 ของ Day 4 ในคอร์ส 5 วันนี้ครับ ใน assignment 3 00:00:08,379 --> 00:00:11,452 นี้เราจะเรียนเรื่อง agent quality 4 00:00:11,452 --> 00:00:13,686 หรือคุณภาพของเอเจนต์ครับ
เปิดดูซับไตเติ้ลทั้งหมด (416 segments)
1 00:00:00,000 --> 00:00:04,283 สวัสดีทุกคนครับ ยินดีต้อนรับเข้าสู่ assignment 2 00:00:04,283 --> 00:00:08,379 ของ Day 4 ในคอร์ส 5 วันนี้ครับ ใน assignment 3 00:00:08,379 --> 00:00:11,452 นี้เราจะเรียนเรื่อง agent quality 4 00:00:11,452 --> 00:00:13,686 หรือคุณภาพของเอเจนต์ครับ 5 00:00:13,686 --> 00:00:17,597 รากฐานพื้นฐานของเรื่องนี้คือ observability 6 00:00:17,597 --> 00:00:21,600 (ความสามารถในการสังเกตการทำงานของระบบ) ครับ 7 00:00:21,600 --> 00:00:26,907 โปรดตรวจสอบให้แน่ใจว่าคุณได้ฟังตอนสรุปพอดแคสต์ที่สร้างโดย 8 00:00:26,907 --> 00:00:30,539 NotebookLM และ white paper เรื่อง agent 9 00:00:30,539 --> 00:00:31,636 quality 10 00:00:31,636 --> 00:00:35,732 ซึ่งเป็นข้อมูลประกอบของพอดแคสต์นี้แล้วนะครับ 11 00:00:35,732 --> 00:00:36,829 white paper 12 00:00:36,829 --> 00:00:41,392 ฉบับนี้จัดการกับความท้าทายในการรับประกันคุณภาพของ 13 00:00:41,392 --> 00:00:45,674 AI agents โดยแนะนำกรอบการประเมินผลแบบ holistic 14 00:00:45,674 --> 00:00:48,375 หรือแบบองค์รวมครับ ใน codelab 15 00:00:48,375 --> 00:00:52,564 พวกนี้เราจะเข้าใจคุณภาพของเอเจนต์อย่างครบถ้วน 16 00:00:52,564 --> 00:00:56,568 codelab แรกเกี่ยวกับวิธีใช้ logs traces และ 17 00:00:56,568 --> 00:00:57,665 metrics 18 00:00:57,665 --> 00:01:01,296 ส่วนอันที่สองคือการประเมินเอเจนต์ของเรา 19 00:01:01,296 --> 00:01:05,300 เพื่อให้คะแนนคุณภาพคำตอบของเอเจนต์และการใช้ 20 00:01:05,300 --> 00:01:09,489 tool ครับ ผมจะคลิกที่ implement ซึ่งจะพาไปที่ 21 00:01:09,489 --> 00:01:13,679 notebook แล้วผมจะแก้ไขสำเนาของผมจากตรงนี้ครับ 22 00:01:13,679 --> 00:01:16,938 ตอนต้นของ notebook ให้สรุปว่า agent 23 00:01:16,938 --> 00:01:20,755 observability คืออะไร agent observability 24 00:01:20,755 --> 00:01:23,921 โดยพื้นฐานคือการเข้าใจ error ต่างๆ 25 00:01:23,921 --> 00:01:27,738 ติดตามทุกขั้นตอน และบันทึกรายละเอียดต่างๆ 26 00:01:27,738 --> 00:01:31,928 เพื่อ debug เมื่อจำเป็นครับ ตัวอย่างเช่น user 27 00:01:31,928 --> 00:01:35,745 สั่งว่าหางานวิจัยเรื่อง quantum computing 28 00:01:35,745 --> 00:01:36,842 ให้หน่อย 29 00:01:36,842 --> 00:01:40,380 แต่เอเจนต์ตอบว่าฉันช่วยเรื่องนี้ไม่ได้ 30 00:01:40,380 --> 00:01:44,291 ตอนนี้เราต้องเข้าใจว่า prompt ผิดตรงไหน มี 31 00:01:44,291 --> 00:01:48,387 tool ตัวไหนขาดหายไปหรือเปล่า หรือมี error ใน 32 00:01:48,387 --> 00:01:52,577 API ครับ ทางแก้ก็คือ agent observability ครับ 33 00:01:52,577 --> 00:01:57,977 มันให้มุมมองแบบครบถ้วนเกี่ยวกับกระบวนการตัดสินใจของเอเจนต์ 34 00:01:57,977 --> 00:02:02,167 คุณจะเห็นชัดเจนว่า prompt อะไรถูกส่งไปที่ LLM 35 00:02:02,167 --> 00:02:05,705 มี tool อะไรให้ใช้บ้าง โมเดลตอบอย่างไร 36 00:02:05,705 --> 00:02:09,988 และความล้มเหลวเกิดขึ้นตรงไหนครับ ตัว debug log 37 00:02:09,988 --> 00:02:13,991 จะแสดงให้เห็นว่า request นี้ไม่มี functions 38 00:02:13,991 --> 00:02:18,088 เลย ซึ่งหมายความว่าเราต้องแทรก Google Search 39 00:02:18,088 --> 00:02:20,508 tool ที่ขาดหายไปตรงนี้ครับ 40 00:02:20,508 --> 00:02:22,650 และนั่นคือวิธีแก้ไขครับ 41 00:02:22,650 --> 00:02:25,257 เพื่ออธิบายให้เห็นภาพชัดขึ้น 42 00:02:25,257 --> 00:02:28,609 มีตัวอย่างหนึ่งครับ เสาหลักของ agent 43 00:02:28,609 --> 00:02:32,891 observability คือ logs traces และ metrics ครับ 44 00:02:32,891 --> 00:02:36,802 logs บอกเราว่าเกิดอะไรขึ้นในช่วงเวลาหนึ่งๆ 45 00:02:36,802 --> 00:02:37,899 traces 46 00:02:37,899 --> 00:02:42,275 แสดงให้เห็นว่าทำไมผลลัพธ์สุดท้ายจึงออกมาแบบนั้น 47 00:02:42,275 --> 00:02:46,185 โดยเปิดเผยลำดับขั้นตอนทั้งหมด ส่วน metrics 48 00:02:46,185 --> 00:02:47,283 คือคะแนน 49 00:02:47,283 --> 00:02:51,379 มันจะบอกว่าเอเจนต์ทำงานได้ดีแค่ไหนโดยรวมครับ 50 00:02:51,379 --> 00:02:57,245 ในตัวอย่างนี้มันแสดงให้เห็นว่าอาหารจานหนึ่งถูกปรุงขึ้นมาอย่างไร 51 00:02:57,245 --> 00:02:59,852 logs ก็เหมือนบันทึกการเตรียม 52 00:02:59,852 --> 00:03:02,924 ที่คุณระบุวัตถุดิบและขั้นตอนต่างๆ 53 00:03:02,924 --> 00:03:08,883 traces คือการที่คุณทำตามขั้นตอนเหล่านั้นเพื่อสร้างสูตรอาหารจริงๆ 54 00:03:08,883 --> 00:03:12,887 ส่วน metrics คือการให้คะแนนอาหารในด้านต่างๆ 55 00:03:12,887 --> 00:03:16,518 เช่น รสชาติ การจัดจาน ความคิดสร้างสรรค์ 56 00:03:16,518 --> 00:03:20,800 แล้วสรุปเป็นคะแนนรวมของจานนั้นครับ ใน notebook 57 00:03:20,800 --> 00:03:24,245 นี้เราจะตั้งค่า logging configuration 58 00:03:24,245 --> 00:03:27,504 สร้างเอเจนต์ที่มีปัญหาที่เราจะแก้ไข 59 00:03:27,504 --> 00:03:31,042 แล้วเรียนรู้วิธี implement logging แบบ 60 00:03:31,042 --> 00:03:35,046 production รวมถึงเรียนรู้ว่าเมื่อไหร่ควรใช้ 61 00:03:35,046 --> 00:03:36,535 built-in logging 62 00:03:36,535 --> 00:03:40,632 เทียบกับโซลูชันที่เขียนเองครับ ในการเริ่มต้น 63 00:03:40,632 --> 00:03:44,822 section แรกเป็นเรื่องตั้งค่า environment เสมอ 64 00:03:44,822 --> 00:03:48,732 ซึ่งเราทำกันมาในทุกวิดีโอแล้ว ผมจะรีบผ่านๆ 65 00:03:48,732 --> 00:03:52,549 ไปเลยนะครับ อย่างแรกคือตั้งค่า Gemini API 66 00:03:52,549 --> 00:03:56,180 วิธีทำคือไปที่ add-ons แล้วเลือก secret 67 00:03:56,180 --> 00:03:59,998 ตอนนี้เรายังไม่มี key ผมจะไปที่ Google AI 68 00:03:59,998 --> 00:04:03,536 Studio คัดลอก key จากตรงนั้น กลับมาที่ 69 00:04:03,536 --> 00:04:07,353 notebook กด add secret ใส่ชื่อ label เป็น 70 00:04:07,353 --> 00:04:08,450 Google API 71 00:04:08,450 --> 00:04:12,733 โปรดตรวจสอบให้แน่ใจว่าใส่ตรงตามนั้นทุกตัวอักษร 72 00:04:12,733 --> 00:04:16,271 เพราะมัน sensitive ต่อตัวพิมพ์ใหญ่เล็ก 73 00:04:16,271 --> 00:04:20,275 ต้องเหมือนกับที่ระบุในโค้ดตรงนี้เป๊ะครับ กด 74 00:04:20,275 --> 00:04:23,719 save แล้วตรวจว่ามันถูกติ๊กแล้วหรือยัง 75 00:04:23,719 --> 00:04:27,444 ติ๊กแล้วครับ ตอนนี้กดรัน เราได้รัน setup 76 00:04:27,444 --> 00:04:28,541 เรียบร้อย 77 00:04:28,541 --> 00:04:32,917 การยืนยันตัวตนและการตั้งค่าเสร็จสมบูรณ์แล้วครับ 78 00:04:32,917 --> 00:04:36,641 ต่อไปเราจะจัดการไฟล์ logging และ cleanup 79 00:04:36,641 --> 00:04:40,738 เราจะตั้งค่ามันกัน import logging และ import 80 00:04:40,738 --> 00:04:44,555 os เพื่อล้าง log เดิมที่เหลือจากครั้งก่อน 81 00:04:44,555 --> 00:04:48,652 รันอันนี้ได้เลย ถ้ามี log file อยู่ใน logger 82 00:04:48,652 --> 00:04:52,376 file ใน web tunnel เราจะเอามันออก โดยใช้ 83 00:04:52,376 --> 00:04:56,659 path.exists ถ้าคุณมี log file ซึ่งก็ไฟล์พวกนี้ 84 00:04:56,659 --> 00:05:00,755 ก็จะลบไฟล์พวกนี้ทิ้ง แล้วพิมพ์ว่า cleaned up 85 00:05:00,755 --> 00:05:05,038 ครับ จากนั้นขั้นต่อไปคือ configure logging แบบ 86 00:05:05,038 --> 00:05:09,042 debug logging โดย basicConfig คือใส่ logger 87 00:05:09,042 --> 00:05:12,766 ตรงนี้ ใช้ level เป็น logging.DEBUG ส่วน 88 00:05:12,766 --> 00:05:16,583 format ประกอบด้วยชื่อไฟล์ เลขบรรทัด ระดับ 89 00:05:16,583 --> 00:05:20,587 และข้อความ พอรันก็บอกว่า logging configured 90 00:05:20,587 --> 00:05:24,683 ครับ ขั้นต่อไปคือตั้งค่า proxy และ tunneling 91 00:05:24,683 --> 00:05:27,197 อันนี้ก็คือ helper function 92 00:05:27,197 --> 00:05:29,990 ที่เราทำกันมาแล้วในวิดีโอก่อนๆ 93 00:05:29,990 --> 00:05:33,715 ถ้าคุณใช้สภาพแวดล้อม notebook ของ Kaggle 94 00:05:33,715 --> 00:05:37,718 คุณต้องทำขั้นตอนนี้ แต่ถ้ารันนอกสภาพแวดล้อม 95 00:05:37,718 --> 00:05:41,815 Kaggle ก็ไม่จำเป็นต้องทำครับ ผมจะรันผ่านๆ ไป 96 00:05:41,815 --> 00:05:46,098 helper function ถูกนิยามแล้วครับ มาถึง section 97 00:05:46,098 --> 00:05:50,287 สองซึ่งเป็นการ debug แบบลงมือจริงด้วย ADK web 98 00:05:50,287 --> 00:05:54,198 UI ครับ อันดับแรกเราจะสร้าง research paper 99 00:05:54,198 --> 00:05:56,991 finder agent เอเจนต์หางานวิจัย 100 00:05:56,991 --> 00:05:59,132 โดยเป้าหมายคือช่วย user 101 00:05:59,132 --> 00:06:02,484 หางานวิจัยวิชาการในหัวข้อใดก็ได้ครับ 102 00:06:02,484 --> 00:06:08,070 ตอนนี้คุณจะสังเกตเห็นว่ามันขึ้นว่าโฟลเดอร์ที่ไม่ว่างอยู่แล้ว 103 00:06:08,070 --> 00:06:12,074 มันถามว่าจะทับโมเดลที่มีอยู่เดิมของเราไหม y 104 00:06:12,074 --> 00:06:14,588 หรือ n คือ yes หรือ no ครับ 105 00:06:14,588 --> 00:06:20,081 เหตุผลที่ผมเจอข้อความนี้เพราะผมเคยทำมาแล้วก่อนถ่ายวิดีโอนี้ 106 00:06:20,081 --> 00:06:22,874 มันเลยบอกว่าโฟลเดอร์มีอยู่แล้ว 107 00:06:22,874 --> 00:06:26,412 ถ้าคุณทำครั้งแรกอาจจะไม่เห็นข้อความนี้ 108 00:06:26,412 --> 00:06:30,695 แต่ถ้าทำรอบที่สองเหมือนผมก็จะเจอข้อความนี้ครับ 109 00:06:30,695 --> 00:06:34,326 ตอนนี้คุณเห็นว่ามันยังคง executing อยู่ 110 00:06:34,326 --> 00:06:37,864 หมายความว่า notebook กำลังรอ input แบบ 111 00:06:37,864 --> 00:06:41,681 interactive แต่เราพิมพ์ y แบบ interactive 112 00:06:41,681 --> 00:06:44,847 ภายใน cell ของ notebook ไม่ได้ครับ 113 00:06:44,847 --> 00:06:48,106 วิธีแก้คือทำให้มันตอบ yes อัตโนมัติ 114 00:06:48,106 --> 00:06:51,457 โดยแก้โค้ดตรงนี้ คือเพิ่ม force flag 115 00:06:51,457 --> 00:06:55,368 เข้าไปในคำสั่ง พิมพ์ขีดกลางสองอันแล้วพิมพ์ 116 00:06:55,368 --> 00:06:58,906 force ก็จะใช้ได้ครับ ปกติวิธีนี้ใช้ได้ 117 00:06:58,906 --> 00:07:00,861 แต่บางครั้งก็ไม่ได้ผล 118 00:07:00,861 --> 00:07:05,051 ในกรณีนั้นเราสามารถลบโฟลเดอร์ด้วยตนเองได้ครับ 119 00:07:05,051 --> 00:07:06,913 ระหว่างที่มันรันอยู่ 120 00:07:06,913 --> 00:07:11,289 ผมจะบอกว่าควรเขียนอะไรไว้ในกรณีที่ใช้ไม่ได้ครับ 121 00:07:11,289 --> 00:07:15,572 ให้เขียนว่าเครื่องหมายอัศเจรีย์ตามด้วย rm ครับ 122 00:07:15,572 --> 00:07:17,899 แล้วขั้นต่อไปคือรันอันนี้ 123 00:07:17,899 --> 00:07:20,506 ขอหยุดอันเดิมก่อนนะครับ โอเค 124 00:07:20,506 --> 00:07:24,417 ให้ผมรันอันนี้ก่อน เสร็จแล้ว ตอนนี้ผมจะเอา 125 00:07:24,417 --> 00:07:27,955 force ออก ขอโทษทีครับ นี่ไงเห็นไหมครับ 126 00:07:27,955 --> 00:07:31,679 สิ่งที่ผมทำตรงนี้ ผมจะอธิบายให้ฟังนะครับ 127 00:07:31,679 --> 00:07:35,217 โค้ดนี้เป็นคำสั่ง shell ที่คุณรันภายใน 128 00:07:35,217 --> 00:07:39,127 notebook ของ Kaggle หรือ Jupyter ถ้ารันนอก 129 00:07:39,127 --> 00:07:42,945 Kaggle ก็ไม่ต้องมีส่วนนี้ครับ rm ย่อมาจาก 130 00:07:42,945 --> 00:07:46,017 remove แล้วก็ recursive กับ force 131 00:07:46,017 --> 00:07:50,300 นี่คือชื่อโฟลเดอร์ที่มีอยู่เดิม ผมสั่งให้มันลบ 132 00:07:50,300 --> 00:07:52,907 directory ของ research agent 133 00:07:52,907 --> 00:07:56,072 ทั้งหมดพร้อมไฟล์ข้างในทั้งหมดทันที 134 00:07:56,072 --> 00:08:00,169 ในสภาพแวดล้อม Kaggle หรือสภาพแวดล้อม Jupyter 135 00:08:00,169 --> 00:08:02,031 โดยไม่ต้องถามอะไรอีก 136 00:08:02,031 --> 00:08:04,452 นี่คือสิ่งที่โค้ดนี้ทำครับ 137 00:08:04,452 --> 00:08:08,362 หลังจากนั้นผมรันโค้ดก่อนหน้านี้ซ้ำอีกครั้ง 138 00:08:08,362 --> 00:08:10,783 มันจึงสร้าง research agent 139 00:08:10,783 --> 00:08:13,111 ใหม่ที่สะอาดเต็มไปหมดครับ 140 00:08:13,111 --> 00:08:16,369 ทีนี้มานิยามเอเจนต์กันที่ตรงนี้ครับ 141 00:08:16,369 --> 00:08:20,000 ถ้าดูส่วนประกอบของ ADK ที่เราเคย import 142 00:08:20,000 --> 00:08:21,769 แยกในอีก cell หนึ่ง 143 00:08:21,769 --> 00:08:25,773 ตอนนี้เรารวมเข้ามาในโค้ดนิยามเอเจนต์เลยครับ 144 00:08:25,773 --> 00:08:29,218 ตรงนี้เรากำลัง configure ตัว LlmAgent 145 00:08:29,218 --> 00:08:33,035 โดยให้ชื่อ คำอธิบาย และ instructions ครับ 146 00:08:33,035 --> 00:08:36,108 ก่อนหน้านั้นขอคุยเรื่องนี้กันก่อน 147 00:08:36,108 --> 00:08:39,832 ในการนิยามเอเจนต์แบบนี้ เรามี root agent 148 00:08:39,832 --> 00:08:43,742 (เอเจนต์หลัก) ที่มอบหมายงานค้นหาให้ search 149 00:08:43,742 --> 00:08:47,001 agent แล้วก็มีอีกเอเจนต์หนึ่งที่ใช้ 150 00:08:47,001 --> 00:08:49,701 count_papers ครับ ส่วน import 151 00:08:49,701 --> 00:08:53,705 ที่เรียกเข้ามาอันดับแรกคือ agent กับ Gemini 152 00:08:53,705 --> 00:08:57,429 แล้วก็ agent tool และ Google Search ครับ 153 00:08:57,429 --> 00:09:01,060 ถ้าคุณรู้จักสิ่งเหล่านี้แล้ว เราก็นิยาม 154 00:09:01,060 --> 00:09:04,412 retry_config ไว้ในโค้ดเดียวกันนี้เลย 155 00:09:04,412 --> 00:09:08,694 แทนที่จะไว้ในส่วน setup ครับ จากนั้นเราจงใจส่ง 156 00:09:08,694 --> 00:09:11,860 data type ที่ผิดพลาด คือส่ง string 157 00:09:11,860 --> 00:09:14,933 แทนที่จะเป็น list ของ string ครับ 158 00:09:14,933 --> 00:09:19,122 แล้วดูกันว่าจะเกิดอะไรขึ้น นิยาม count_papers 159 00:09:19,122 --> 00:09:22,940 โดยรับ papers เป็น string อาร์กิวเมนต์คือ 160 00:09:22,940 --> 00:09:26,664 papers ซึ่งเป็น list ของ string โดยแต่ละ 161 00:09:26,664 --> 00:09:30,854 string คืองานวิจัยหนึ่งชิ้น มันควรคืนค่าจำนวน 162 00:09:30,854 --> 00:09:34,112 paper ใน list นั้น คำสั่งคือ return 163 00:09:34,112 --> 00:09:38,209 len(papers) ครับ ต่อไปเรานิยาม Google search 164 00:09:38,209 --> 00:09:41,468 agent ให้ชื่อ model description และ 165 00:09:41,468 --> 00:09:44,168 instructions ครับ description 166 00:09:44,168 --> 00:09:47,799 คือค้นหาข้อมูลโดยใช้ Google Search ส่วน 167 00:09:47,799 --> 00:09:51,988 instruction คือให้ใช้เครื่องมือ Google Search 168 00:09:51,988 --> 00:09:54,502 ค้นหาข้อมูลในหัวข้อที่กำหนด 169 00:09:54,502 --> 00:09:58,785 แล้วคืนผลลัพธ์การค้นหาแบบดิบๆ ถ้า user ขอ list 170 00:09:58,785 --> 00:10:02,416 ของ paper ให้ส่ง list งานวิจัยที่เจอให้ 171 00:10:02,416 --> 00:10:06,699 ไม่ใช่สรุปย่อครับ เครื่องมือที่เราใช้ตรงนี้คือ 172 00:10:06,699 --> 00:10:09,865 Google Search ครับ ส่วน root agent 173 00:10:09,865 --> 00:10:14,054 จะใช้ตัวนี้กับ count_papers ครับ มีชื่อ model 174 00:10:14,054 --> 00:10:15,916 และ instructions ว่า 175 00:10:15,916 --> 00:10:19,175 ภารกิจของเธอคือหางานวิจัยแล้วนับมัน 176 00:10:19,175 --> 00:10:22,061 เธอต้องทำตามขั้นตอนเหล่านี้เสมอ 177 00:10:22,061 --> 00:10:26,251 ขั้นแรกหางานวิจัยในหัวข้อที่ user ให้มาโดยใช้ 178 00:10:26,251 --> 00:10:28,020 Google search agent 179 00:10:28,020 --> 00:10:32,117 ซึ่งเรานิยามไว้ตรงนี้ในส่วน tools จากนั้นส่ง 180 00:10:32,117 --> 00:10:36,027 papers ที่ได้ไปที่ count_papers ซึ่งก็เป็น 181 00:10:36,027 --> 00:10:39,844 tool ตัวนี้อีกเช่นกัน เพื่อนับจำนวน paper 182 00:10:39,844 --> 00:10:43,755 แล้วคืนค่าทั้ง list งานวิจัยและจำนวน paper 183 00:10:43,755 --> 00:10:47,945 ทั้งหมดครับ มันต้องคืนผลลัพธ์สองอย่างคือ list 184 00:10:47,945 --> 00:10:49,714 กับจำนวน paper ครับ 185 00:10:49,714 --> 00:10:53,996 ผมกำลังสร้างเอเจนต์เหล่านี้ เราได้ทับ research 186 00:10:53,996 --> 00:10:58,093 agent เดิมแล้ว ต่อไปเราจะรันเอเจนต์นี้ใน ADK 187 00:10:58,093 --> 00:11:02,097 web UI ครับ สำหรับขั้นนี้เราต้องสร้าง proxy 188 00:11:02,097 --> 00:11:05,355 ก่อน นี่คือการเข้าถึง URL ของ proxy 189 00:11:05,355 --> 00:11:08,800 โดยต้องรันอันนี้ก่อน พอเห็นว่า server 190 00:11:08,800 --> 00:11:12,245 เริ่มทำงานแล้ว เราก็พร้อมเริ่มต้นครับ 191 00:11:12,245 --> 00:11:15,690 กลับไปที่ section นี้ เปิด ADK web UI 192 00:11:15,690 --> 00:11:19,135 โดยคลิกตรงนี้ เห็นไหมครับ ถ้ากลับไปดู 193 00:11:19,135 --> 00:11:22,766 มันจะให้คำถามอย่างเช่นให้ทำสิ่งนี้ใน UI 194 00:11:22,766 --> 00:11:26,583 คุณต้องเลือก agent ที่ชื่อ research agent 195 00:11:26,583 --> 00:11:30,866 แล้วถามใน interface นี้ครับ เราเลือกไว้แล้วโดย 196 00:11:30,866 --> 00:11:34,497 default ครับ จะถามว่าหางานวิจัย quantum 197 00:11:34,497 --> 00:11:36,452 computing ล่าสุดหน่อย 198 00:11:36,452 --> 00:11:39,153 ซึ่งเป็นคำถามที่ระบุไว้ตรงนี้ 199 00:11:39,153 --> 00:11:43,156 พิมพ์ลงในช่องแชตครับ แล้วเอเจนต์ควรคืน list 200 00:11:43,156 --> 00:11:47,439 งานวิจัยพร้อมจำนวนที่นับได้ครับ เรากลับมาดูกัน 201 00:11:47,439 --> 00:11:51,536 งานวิจัย computing ล่าสุดถูกพบแล้ว ได้ตัวนี้ 202 00:11:51,536 --> 00:11:55,632 ตัวนี้ และตัวนี้มา รวมทั้งหมดเป็น 1690 paper 203 00:11:55,632 --> 00:11:57,680 ซึ่งดูมหาศาลเกินไปครับ 204 00:11:57,680 --> 00:12:01,032 สิ่งที่เราทำคือไปที่ส่วน invocations 205 00:12:01,032 --> 00:12:05,315 ทางซ้ายแล้วขยายออก จะเห็นว่าการนับถูกทำอย่างไร 206 00:12:05,315 --> 00:12:09,412 นี่คือการเรียกใช้ tool ตัว count_papers ครับ 207 00:12:09,412 --> 00:12:13,322 คลิกตรงนี้ มันบอกว่า 1690 ครับ ผู้เขียนคือ 208 00:12:13,322 --> 00:12:17,326 research paper finder คุณจะเห็นการเรียก LLM 209 00:12:17,326 --> 00:12:20,119 ว่ามันรับ parameter อะไรไปบ้าง 210 00:12:20,119 --> 00:12:23,564 ถ้าดูจะเห็นว่ามันรับ text เป็น string 211 00:12:23,564 --> 00:12:26,264 แทนที่จะเป็น list นั่นเองครับ 212 00:12:26,264 --> 00:12:30,081 นี่จึงเป็นเหตุผลที่เราได้ 1690 paper ครับ 213 00:12:30,081 --> 00:12:33,433 ทีนี้เราจะทำอะไรต่อ ต้องหยุด session 214 00:12:33,433 --> 00:12:37,529 ก่อนตรงนี้ครับ มันยังคงพูดเรื่องเดิมอยู่ คือ 215 00:12:37,529 --> 00:12:41,347 root agent ส่ง list ของ paper เป็น string 216 00:12:41,347 --> 00:12:45,350 แทนที่จะเป็น list ของ string และนั่นคือ bug 217 00:12:45,350 --> 00:12:49,447 ที่เราหาเจอครับ สิ่งที่ต้องทำต่อไปคือเปลี่ยน 218 00:12:49,447 --> 00:12:53,637 data type ของอาร์กิวเมนต์ papers ใน tool ชื่อ 219 00:12:53,637 --> 00:12:56,988 count_papers ให้เป็น list ของ string 220 00:12:56,988 --> 00:12:58,385 แล้วรันใหม่ครับ 221 00:12:58,385 --> 00:13:01,551 การจะรันใหม่เราต้องหยุดอันเดิมก่อน 222 00:13:01,551 --> 00:13:04,344 ถ้าไม่หยุดมันจะรันต่อไปเรื่อยๆ 223 00:13:04,344 --> 00:13:08,347 ผมต้องมาตรงนี้แล้วหยุดมันด้วยตนเองครับ โอเค 224 00:13:08,347 --> 00:13:12,537 หยุดแล้ว แล้วรันส่วน debug นี้ เราตรวจสอบ log 225 00:13:12,537 --> 00:13:16,447 ของ web server เพื่อหาเบาะแสการ debug ครับ 226 00:13:16,447 --> 00:13:19,427 ระหว่างนั้นเราจะอัปเดต data type 227 00:13:19,427 --> 00:13:22,965 ของอาร์กิวเมนต์ papers ใน count_papers 228 00:13:22,965 --> 00:13:26,689 ให้เป็นแบบนี้กันด้วย กลับไปตรงนี้ นี่คือ 229 00:13:26,689 --> 00:13:29,855 count_papers ตรงนี้เดิมเป็น string 230 00:13:29,855 --> 00:13:33,300 เราจะเปลี่ยนเป็น list ของ string ครับ 231 00:13:33,300 --> 00:13:35,627 ทีนี้รันอันนี้ ทับของเดิม 232 00:13:35,627 --> 00:13:37,582 เขียนทับเรียบร้อยแล้ว 233 00:13:37,582 --> 00:13:40,003 เรากลับมาแล้วรันส่วนนี้ซ้ำ 234 00:13:40,003 --> 00:13:43,355 แล้วเริ่มอันนี้ขึ้นมาใหม่ web server 235 00:13:43,355 --> 00:13:46,334 ก็เริ่มทำงานครับ คลิกที่ลิงก์นี้ 236 00:13:46,334 --> 00:13:50,338 มันเปิดหน้าเอเจนต์ขึ้นมา สังเกตว่า agent ID 237 00:13:50,338 --> 00:13:53,876 กับ session ID ตรงนี้ไม่เหมือนเดิมแล้ว 238 00:13:53,876 --> 00:13:56,017 อันก่อนหน้านี้ต่างออกไป 239 00:13:56,017 --> 00:13:59,835 เราจึงใช้ตัวใหม่นี้ครับ คัดลอกคำถามเดิมมา 240 00:13:59,835 --> 00:14:04,024 ขอกลับไปเอาคำถามนี้ก่อนนะครับ วางแล้วกด enter 241 00:14:04,024 --> 00:14:08,121 คุณเห็น output ตรงนี้ไหมครับ ได้ข้อมูลมาแล้ว 242 00:14:08,121 --> 00:14:12,124 และอันสุดท้ายคือมี paper รวมทั้งหมด 14 ชิ้น 243 00:14:12,124 --> 00:14:15,569 เทียบกับอันก่อนที่บอก 1690 paper ครับ 244 00:14:15,569 --> 00:14:18,828 และตรงนี้เราก็สามารถเห็นการ execute 245 00:14:18,828 --> 00:14:22,645 ของโค้ดได้อีกเช่นกันครับ ทีนี้คือ section 246 00:14:22,645 --> 00:14:24,787 สามครับ เราสามารถ debug 247 00:14:24,787 --> 00:14:28,697 ความล้มเหลวของเอเจนต์โดยใช้ ADK web UI และ 248 00:14:28,697 --> 00:14:32,049 debug log ได้ ปัญหาแรกคือ production 249 00:14:32,049 --> 00:14:36,052 development ปัญหาที่สองคือระบบอัตโนมัติครับ 250 00:14:36,052 --> 00:14:38,659 มีคนพูดว่า ขอเปิด ADK web UI 251 00:14:38,659 --> 00:14:42,384 เพื่อตรวจสอบว่าทำไมเอเจนต์ถึงล้มเหลว ทีม 252 00:14:42,384 --> 00:14:46,387 DevOps มักจะตอบว่า นี่คือ production server 253 00:14:46,387 --> 00:14:48,715 เข้าถึง web UI ไม่ได้ครับ 254 00:14:48,715 --> 00:14:52,067 ตอนนี้เราอยากเข้าใจว่าจะ debug ปัญหา 255 00:14:52,067 --> 00:14:53,742 production อย่างไร 256 00:14:53,742 --> 00:14:56,536 นี่คือสิ่งที่เราอยากจัดการครับ 257 00:14:56,536 --> 00:14:58,863 อีกเรื่องที่อยากจัดการคือ 258 00:14:58,863 --> 00:15:02,029 เอเจนต์รันวันละพันครั้งใน pipeline 259 00:15:02,029 --> 00:15:03,518 ของเราซึ่งรันช้า 260 00:15:03,518 --> 00:15:06,591 อัตราความสำเร็จของเราเป็นเท่าไหร่ 261 00:15:06,591 --> 00:15:09,012 แล้วคุณคงต้องไปเช็ค web UI 262 00:15:09,012 --> 00:15:11,712 ด้วยตนเองเป็นพันครั้ง ไม่ครับ 263 00:15:11,712 --> 00:15:14,226 ผมว่าเราไม่ควรทำแบบนั้นครับ 264 00:15:14,226 --> 00:15:18,322 ดังนั้นเราต้องมีวิธีเก็บข้อมูล observability 265 00:15:18,322 --> 00:15:20,836 หรือพูดอีกอย่างคือเพิ่ม log 266 00:15:20,836 --> 00:15:22,884 เข้าไปในโค้ดของเราครับ 267 00:15:22,884 --> 00:15:26,329 นั่นแหละสิ่งที่เราทำกันอยู่ใช่ไหมครับ 268 00:15:26,329 --> 00:15:30,612 สำหรับแต่ละ batch เรามี batch run มีข้อมูล job 269 00:15:30,612 --> 00:15:31,709 run ครับ 270 00:15:31,709 --> 00:15:36,085 ในทำนองเดียวกันเราก็จะมีอะไรทำนองนี้เช่นกันครับ 271 00:15:36,085 --> 00:15:39,716 มันบอกว่าในการพัฒนาซอฟต์แวร์แบบดั้งเดิม 272 00:15:39,716 --> 00:15:43,906 เราทำโดยเพิ่ม log statement ในฟังก์ชัน Python 273 00:15:43,906 --> 00:15:47,537 และเอเจนต์ก็ไม่ต่างกัน เราต้องเพิ่ม log 274 00:15:47,537 --> 00:15:50,796 statement เข้าไปในเอเจนต์ของเราครับ 275 00:15:50,796 --> 00:15:54,799 แนวทางที่พบบ่อยคือการเพิ่ม log statement ใน 276 00:15:54,799 --> 00:15:58,617 plugin ครับ จะเพิ่ม log สำหรับ production 277 00:15:58,617 --> 00:16:02,806 observability อย่างไร เราจะทำด้วย plugin ครับ 278 00:16:02,806 --> 00:16:03,904 โดย plugin 279 00:16:03,904 --> 00:16:10,607 คือโมดูลโค้ดที่กำหนดเองซึ่งรันอัตโนมัติในหลายช่วงของวงจรชีวิตเอเจนต์ครับ 280 00:16:10,607 --> 00:16:13,028 แต่ละ plugin จะมี callback 281 00:16:13,028 --> 00:16:16,473 ดังที่เห็นในไดอะแกรมนี้ ซึ่งเป็น hook 282 00:16:16,473 --> 00:16:20,290 สำหรับแทรกตัวเข้าไปใน flow ของเอเจนต์ครับ 283 00:16:20,290 --> 00:16:24,573 ตัวอย่างเช่น workflow ของเอเจนต์เป็นแบบนี้ครับ 284 00:16:24,573 --> 00:16:28,670 user message เข้ามา เอเจนต์คิด เรียกใช้ tool 285 00:16:28,670 --> 00:16:31,928 แล้วตอบกลับครับ เมื่อมี plugin hook 286 00:16:31,928 --> 00:16:35,652 สิ่งที่เกิดขึ้นคือ ก่อนเอเจนต์เริ่มทำงาน 287 00:16:35,652 --> 00:16:38,818 และหลัง tool รัน หรือหลัง response 288 00:16:38,818 --> 00:16:42,449 คุณสามารถวาง hook ได้ทุกจุดเลยครับ แล้ว 289 00:16:42,449 --> 00:16:44,497 callback คืออะไรกันแน่ 290 00:16:44,497 --> 00:16:47,942 มันคือส่วนประกอบย่อยภายใน plugin ครับ 291 00:16:47,942 --> 00:16:51,201 เหมือนมีชิ้นเล็กๆ อยู่ข้างใน plugin 292 00:16:51,201 --> 00:16:54,367 ไดอะแกรมนี้เราเคยเห็นใน Day 3 แล้ว 293 00:16:54,367 --> 00:16:58,649 มันคือฟังก์ชัน Python ที่รันในจุดเวลา specific 294 00:16:58,649 --> 00:17:02,187 ต่างๆ ของวงจรชีวิตเอเจนต์ครับ callback 295 00:17:02,187 --> 00:17:05,912 ถูกรวมกันเป็นกลุ่มเพื่อสร้าง plugin ครับ 296 00:17:05,912 --> 00:17:10,008 เวลาใช้ callback ก็เหมือนที่เราทำเมื่อวานนี้ 297 00:17:10,008 --> 00:17:14,291 มี callback แบบ before กับ after ของเอเจนต์ มี 298 00:17:14,291 --> 00:17:18,481 before กับ after ของ tool มี before กับ after 299 00:17:18,481 --> 00:17:22,671 ของ model และมี callback เมื่อเกิด error ครับ 300 00:17:22,671 --> 00:17:24,719 ทั้งหมดนี้คือ callback 301 00:17:24,719 --> 00:17:26,953 ที่คุณเสียบเข้าไปได้ครับ 302 00:17:26,953 --> 00:17:30,678 เพื่อให้เห็นภาพชัดขึ้น มาดูกันว่า plugin 303 00:17:30,678 --> 00:17:34,029 หน้าตาเป็นอย่างไรครับ นี่คือตัวอย่าง 304 00:17:34,029 --> 00:17:36,916 ในโค้ดนี้มันไม่ได้ทำอะไรจริงจัง 305 00:17:36,916 --> 00:17:40,826 เราแค่ดูว่ามันทำงานอย่างไร ผมรันเพื่อดูว่า 306 00:17:40,826 --> 00:17:42,781 input เป็นอย่างไรครับ 307 00:17:42,781 --> 00:17:46,971 ระหว่างรันผมจะเล่าให้ฟังว่าเกิดอะไรขึ้นตรงนี้ 308 00:17:46,971 --> 00:17:50,788 คุณมี BaseAgent และมี callback context มี 309 00:17:50,788 --> 00:17:54,792 request และมี BasePlugin ครับ จากนั้นคุณใช้ 310 00:17:54,792 --> 00:17:58,795 BasePlugin ตัวนี้ใน count invocation plugin 311 00:17:58,795 --> 00:18:02,240 ที่คุณจะนิยามขึ้นครับ แล้วมี callback 312 00:18:02,240 --> 00:18:05,778 ตัวที่หนึ่ง คุณเขียนว่า self agent คือ 313 00:18:05,778 --> 00:18:09,689 BaseAgent ซึ่งเป็นเอเจนต์แรกที่คุณนิยามไว้ 314 00:18:09,689 --> 00:18:13,320 นี่คือ base agent ของคุณ และมี callback 315 00:18:13,320 --> 00:18:16,858 context ครับ ทีนี้ count_agent_returns 316 00:18:16,858 --> 00:18:20,768 จะคืนค่าเช่นร้อยครั้ง พันครั้งอะไรทำนองนี้ 317 00:18:20,768 --> 00:18:23,189 ถ้าเป็นการบวกหนึ่งทุกครั้ง 318 00:18:23,189 --> 00:18:27,379 มันจะสะสมมากกว่าหนึ่งเสมอ ต้องนับมันไปเรื่อยๆ 319 00:18:27,379 --> 00:18:31,568 มันจะเพิ่มขึ้นเรื่อยๆ ครับ ตัวที่สอง callback 320 00:18:31,568 --> 00:18:34,920 ตัวที่สองรันก่อนที่ model จะถูกเรียก 321 00:18:34,920 --> 00:18:38,924 ตรงนี้คุณต้องมี model callback โดย callback 322 00:18:38,924 --> 00:18:43,114 context ก็ยังเป็น callback context เหมือนเดิม 323 00:18:43,114 --> 00:18:47,396 llm ก็คือ llm request เดิม ทีนี้คุณต้องนับ llm 324 00:18:47,396 --> 00:18:50,469 request ซึ่งก็บวกหนึ่งเช่นกันครับ 325 00:18:50,469 --> 00:18:54,472 ผมแค่รันอันนี้ ปกติมันไม่กระทบโค้ดของเราเลย 326 00:18:54,472 --> 00:18:57,731 พอเสร็จมันจะพิมพ์ว่า example plugin 327 00:18:57,731 --> 00:19:00,524 ไม่ทำอะไรเลย เพราะมันไม่ทำอะไร 328 00:19:00,524 --> 00:19:02,014 ผมจะกลับมาตรงนี้ 329 00:19:02,014 --> 00:19:06,576 คุณสามารถทำตามตัวเลขในไดอะแกรมด้านล่างเพื่อเข้าใจ 330 00:19:06,576 --> 00:19:10,207 flow ได้ครับ ไล่ตาม 1 2 แล้ว 3 4 5 ครับ 331 00:19:10,207 --> 00:19:13,652 ขั้นแรกคือหางานวิจัย computing ล่าสุด 332 00:19:13,652 --> 00:19:17,749 ตามที่เราใส่ไปใน section ก่อนหน้าผ่านทาง web 333 00:19:17,749 --> 00:19:21,659 UI ครับ ตัว runner รันมัน เริ่มทำงาน ไปที่ 334 00:19:21,659 --> 00:19:25,197 memory agent ไปที่ agent tool และอื่นๆ 335 00:19:25,197 --> 00:19:29,387 ที่ตรงนี้ สิ่งที่เกิดขึ้นคือ count invocation 336 00:19:29,387 --> 00:19:32,832 plugin ซึ่งเป็น before agent callback 337 00:19:32,832 --> 00:19:36,463 ก่อนหน้านี้ มันไปที่เครื่องมือ research 338 00:19:36,463 --> 00:19:40,187 finding ก่อนตัวนั้น count เป็น none ครับ 339 00:19:40,187 --> 00:19:43,725 จากนั้นสิ่งที่เกิดขึ้นคือ runner ไปที่ 340 00:19:43,725 --> 00:19:47,542 research paper finder เพื่อไปที่โมเดล llm 341 00:19:47,542 --> 00:19:51,267 เพื่อหาว่าควรดูหน้าไหนบ้าง ระหว่างกลางมี 342 00:19:51,267 --> 00:19:55,549 plugin หนึ่ง นี่คือ before และ after และนี่คือ 343 00:19:55,549 --> 00:19:58,156 before model ด้วยเช่นกันครับ 344 00:19:58,156 --> 00:20:01,787 ขั้นที่หกคือมันรับกลับมา research agent 345 00:20:01,787 --> 00:20:05,698 ส่งต่อให้ runner แล้ว response ก็ออกไปครับ 346 00:20:05,698 --> 00:20:09,794 สิ่งที่เกิดขึ้นคือใน count invocation plugin 347 00:20:09,794 --> 00:20:11,843 ตัวนี้ถูกเรียกสองครั้ง 348 00:20:11,843 --> 00:20:16,033 ที่ขั้นตอนสองมันเรียกก่อนเอเจนต์ เพราะ plugin 349 00:20:16,033 --> 00:20:19,757 มี before agent callback ในทำนองเดียวกัน 350 00:20:19,757 --> 00:20:23,202 plugin ก็ถูก execute ก่อนการเรียก llm 351 00:20:23,202 --> 00:20:26,088 ซึ่งเกิดที่ขั้นตอนสี่ตรงนี้ครับ 352 00:20:26,088 --> 00:20:29,905 หวังว่าจะเข้าใจแจ่มชัดแล้วนะครับ ต่อไปคือ 353 00:20:29,905 --> 00:20:34,095 built-in logging plugin ครับ built-in logging 354 00:20:34,095 --> 00:20:37,819 plugin คืออะไร ADK มี logging plugin แบบ 355 00:20:37,819 --> 00:20:38,916 built-in 356 00:20:38,916 --> 00:20:43,013 ซึ่งเก็บกิจกรรมของเอเจนต์โดยอัตโนมัติทั้งหมด 357 00:20:43,013 --> 00:20:47,110 เช่น ข้อความของ user และ response ของเอเจนต์ 358 00:20:47,110 --> 00:20:50,834 ข้อมูล timing สำหรับวิเคราะห์ประสิทธิภาพ 359 00:20:50,834 --> 00:20:54,837 request และ response ของ LLM เพื่อใช้ debug 360 00:20:54,837 --> 00:20:58,934 การเรียกใช้ tool และผลลัพธ์ รวมถึง execution 361 00:20:58,934 --> 00:21:00,796 trace แบบครบถ้วนครับ 362 00:21:00,796 --> 00:21:04,986 เราเคยนิยามเอเจนต์ไปแล้วสำหรับ research paper 363 00:21:04,986 --> 00:21:08,989 agent ตรงนี้เราทำคล้ายกันนี้อีกครั้ง โดยรัน 364 00:21:08,989 --> 00:21:12,062 research agent พร้อม logging ครับ 365 00:21:12,062 --> 00:21:15,507 ทุกอย่างเกือบเหมือนเดิม ตรงนี้ papers 366 00:21:15,507 --> 00:21:18,672 ถูกอัปเดตเป็น list ของ string แล้ว 367 00:21:18,672 --> 00:21:21,372 ข้อมูลส่วนที่เหลือถูกต้องครับ 368 00:21:21,372 --> 00:21:24,165 ต้องคืนค่าทั้งหมด instructions 369 00:21:24,165 --> 00:21:28,448 ก็เหมือนเดิมครับ ตรงนี้เราเพิ่ม research agent 370 00:21:28,448 --> 00:21:31,521 ด้วย plugin ครับ ผมจะรันตอนนี้เลย 371 00:21:31,521 --> 00:21:35,059 มันบอกว่าเอเจนต์ถูกสร้างสำเร็จแล้วครับ 372 00:21:35,059 --> 00:21:39,155 ขั้นที่สามคือการใช้ plugin ใน research agent 373 00:21:39,155 --> 00:21:43,438 ด้านบน คลิกเพื่อ import plugin แล้วเพิ่มมันตอน 374 00:21:43,438 --> 00:21:47,349 initialize ตัว runner ครับ จาก ADK runners 375 00:21:47,349 --> 00:21:51,538 import runner ครับ คุณมี plugin ซึ่งก็คือ log 376 00:21:51,538 --> 00:21:55,356 plugin ผมจะรันอันนี้ มันบอกว่า runner ถูก 377 00:21:55,356 --> 00:21:58,987 configure แล้ว ใน runner ครับ เสร็จแล้ว 378 00:21:58,987 --> 00:22:03,083 ส่วนนี้เพิ่ม plugin เข้าไป มันจัดการ logging 379 00:22:03,083 --> 00:22:04,666 แบบ observability 380 00:22:04,666 --> 00:22:08,949 มาตรฐานให้กับเอเจนต์ทั้งหมดครับ ตัว runner ถูก 381 00:22:08,949 --> 00:22:13,232 configure แล้ว ทีนี้เราจะพิมพ์ statement ต่างๆ 382 00:22:13,232 --> 00:22:16,491 แล้วดูว่าได้ผลลัพธ์อะไร เราจะ debug 383 00:22:16,491 --> 00:22:20,494 ตอนนี้เลยครับ รันเอเจนต์พร้อม plugin แล้วดู 384 00:22:20,494 --> 00:22:24,125 logging output ที่ครอบคลุมครับ response 385 00:22:24,125 --> 00:22:27,477 ตรงนี้คือ user message ได้รับแล้ว มี 386 00:22:27,477 --> 00:22:31,667 invocation กำลังใช้ debug ด้วย user ID นี้ มี 387 00:22:31,667 --> 00:22:35,391 context ตรงนี้ คือหางานวิจัยล่าสุดเรื่อง 388 00:22:35,391 --> 00:22:39,301 quantum computing ครับ แล้ว agent starting 389 00:22:39,301 --> 00:22:43,584 อยู่ตรงนี้ มี invocation ID ซึ่งเป็น plugin ID 390 00:22:43,584 --> 00:22:47,215 อีกอันหนึ่ง ตรงนี้บอกว่า research paper 391 00:22:47,215 --> 00:22:49,729 เริ่มแล้ว ก็มีแบบนี้อีกครับ 392 00:22:49,729 --> 00:22:52,709 ทีนี้เธอต้องทำตามขั้นตอนเหล่านี้ 393 00:22:52,709 --> 00:22:56,060 ขั้นแรกคือหางานวิจัยในหัวข้อที่ user 394 00:22:56,060 --> 00:22:59,598 ให้มาโดยใช้ Google search agent นี่คือ 395 00:22:59,598 --> 00:23:03,043 instruction แรกที่เราให้ไว้ใช่ไหมครับ 396 00:23:03,043 --> 00:23:07,326 มันบอกว่า tool ที่ใช้ได้คือตัวนี้กับตัวนี้ครับ 397 00:23:07,326 --> 00:23:11,516 ใน LLM response เอเจนต์ research paper finder 398 00:23:11,516 --> 00:23:15,519 เรียกใช้ฟังก์ชันนี้ มี token ID มี input มี 399 00:23:15,519 --> 00:23:19,802 output เป็น 21 และมี event ID ตรงนี้ ทุก event 400 00:23:19,802 --> 00:23:23,154 ที่เกิดขึ้นถูกบันทึกครับ ตอนนี้ tool 401 00:23:23,154 --> 00:23:27,251 เริ่มทำงาน มี invocation ID ของ user message 402 00:23:27,251 --> 00:23:31,254 นี้ ตอนนี้เริ่ม invocation มีชื่อเอเจนต์ มี 403 00:23:31,254 --> 00:23:35,071 invocation ID ตัวนี้อยู่ตรงนี้ครับ ตอนนี้ 404 00:23:35,071 --> 00:23:38,982 model เริ่มทำงาน ตอนนี้เธอเป็นเอเจนต์หนึ่ง 405 00:23:38,982 --> 00:23:42,985 ชื่อภายในคือ Google search agent คำอธิบาย B 406 00:23:42,985 --> 00:23:46,989 ส่วน description เกี่ยวกับการค้นหา ฟิลด์ของ 407 00:23:46,989 --> 00:23:50,061 quantum เริ่มเพิ่ม context เข้ามา 408 00:23:50,061 --> 00:23:54,065 คุณสามารถไล่ดูได้เลย เรื่องนี้เข้าใจง่ายมาก 409 00:23:54,065 --> 00:23:56,113 มันอธิบายตัวเองได้ครับ 410 00:23:56,113 --> 00:24:00,024 ในวิดีโอนี้เราได้ผ่านการ debug ในขั้นพัฒนา 411 00:24:00,024 --> 00:24:04,306 observability ระดับ production และ requirement 412 00:24:04,306 --> 00:24:05,703 แบบกำหนดเองครับ 413 00:24:05,703 --> 00:24:09,427 ในวิดีโอถัดไปซึ่งเป็นส่วนที่สองของ Day 4 414 00:24:09,427 --> 00:24:11,941 เราจะเรียนเรื่อง evaluation 415 00:24:11,941 --> 00:24:17,062 คือวิธีประเมินและให้คะแนนคุณภาพคำตอบของเอเจนต์และการใช้ 416 00:24:17,062 --> 00:24:18,159 tool ครับ