12-Factor Agents: รูปแบบสำหรับแอปพลิเคชัน LLM ที่เชื่อถือได้
(github.com/humanlayer)- 12-Factor Agents คือคู่มือแบบเปิดที่รวบรวมหลักการ 12 ข้อสำหรับสร้างซอฟต์แวร์บน LLM ที่น่าเชื่อถือพอจะให้บริการลูกค้าในโปรดักชัน
- มองว่าเอเจนต์ที่ดีไม่ได้มีรูปแบบเป็น “ให้พรอมป์กับชุดเครื่องมือ แล้ววนซ้ำจนบรรลุเป้าหมาย” เท่านั้น แต่ใกล้เคียงกับโครงสร้างที่เป็น ซอฟต์แวร์เชิงกำหนดแน่นอน เป็นหลัก และแทรกขั้นตอน LLM ในจุดที่จำเป็น
- ลูปเอเจนต์ทั่วไปคือ LLM กำหนดขั้นตอนถัดไปเป็น การเรียกใช้เครื่องมือแบบ JSON ที่มีโครงสร้าง จากนั้นโค้ดเชิงกำหนดแน่นอนนำไปประมวลผล แล้วเพิ่มผลลัพธ์เข้าไปใน context window และวนซ้ำจนเสร็จ
- ผู้สร้าง SaaS จำนวนมากเริ่มต้นได้เร็วด้วยเฟรมเวิร์กและไปถึง คุณภาพ 70–80% แต่ยังไม่พอสำหรับฟีเจอร์ที่ลูกค้าใช้งาน จึงต้องย้อนวิศวกรรมเฟรมเวิร์ก พรอมป์ และโฟลว์ หรือไม่ก็เริ่มใหม่ตั้งแต่ต้น
- วิธีที่เร็วที่สุดในการส่งมอบซอฟต์แวร์ AI คุณภาพสูงให้ลูกค้าคือการนำ แนวคิดการสร้างเอเจนต์ ขนาดเล็กและเป็นโมดูลไปผสานกับผลิตภัณฑ์เดิม แทนที่จะรับเอาเฟรมเวิร์กเอเจนต์ทั้งชุดเข้ามา
ประเด็นปัญหาของโปรเจกต์
- 12-Factor Agents เป็นโปรเจกต์เปิดที่พยายามนำแนวคิดของ 12 Factor Apps มาประยุกต์เป็นหลักการสร้างแอปพลิเคชัน LLM
- คำถามหลักคือ “เราจะใช้หลักการอะไรเพื่อสร้างซอฟต์แวร์บน LLM ที่ดีพอจริง ๆ จนฝากไว้กับลูกค้าในโปรดักชันได้”
- โปรเจกต์นี้เริ่มจากประสบการณ์ลองใช้เฟรมเวิร์กเอเจนต์หลายแบบ และพูดคุยกับผู้ก่อตั้งสายเทคนิคทั้งในและนอก YC
- ผู้ก่อตั้งจำนวนมากสร้างสแตกของตนเอง มากกว่าจะใช้เฟรมเวิร์กอย่างหนักในเอเจนต์ที่เป็น customer-facing ในโปรดักชัน
- มองว่าผลิตภัณฑ์จำนวนมากที่ถูกเรียกว่า “AI Agent” ไม่ได้เป็น agentic อย่างสมบูรณ์ แต่เป็นรูปแบบที่ผสมขั้นตอน LLM เข้าไปในโค้ดเชิงกำหนดแน่นอนเป็นหลักอย่างเหมาะสม
มุมมองพื้นฐานต่อเอเจนต์
- เอเจนต์ที่ดีไม่ได้ประกอบขึ้นจากแพตเทิร์น “พรอมป์ ชุดเครื่องมือ และวนซ้ำจนบรรลุเป้าหมาย” เพียงอย่างเดียว
- ซอฟต์แวร์สามารถมองเป็นกราฟมีทิศทาง (DG) ได้ และนี่ก็เป็นเหตุผลที่โปรแกรมในอดีตมักถูกอธิบายด้วยผังงาน
- ตั้งแต่ราว 20 ปีก่อน DAG orchestrator เริ่มถูกใช้อย่างแพร่หลาย
- คำสัญญาของเอเจนต์คือ แทนที่วิศวกรจะต้องเขียนโค้ดทุกขั้นตอนและทุกข้อยกเว้น ก็ให้แค่เป้าหมายกับการเปลี่ยนผ่าน แล้วให้ LLM ตัดสินเส้นทางแบบเรียลไทม์
- วิธีนี้คาดหวังว่าจะเขียนโค้ดน้อยลง ฟื้นตัวจากข้อผิดพลาดได้ และให้ LLM ค้นหาวิธีแก้ใหม่ ๆ ได้
- แต่ในทางปฏิบัติ มองว่าแนวทางนี้ไม่ได้ทำงานได้ดีเท่าที่คาดหวัง
โมเดลการทำงานของลูปเอเจนต์
- ลูปเอเจนต์พื้นฐานประกอบด้วย การตัดสินของ LLM → การรันเครื่องมือ → เพิ่มผลลัพธ์เข้า context → วนซ้ำ
- โฟลว์เป็นดังนี้
- context เริ่มต้นคืออีเวนต์เริ่มต้น เช่น ข้อความผู้ใช้, การรัน cron, webhook
- LLM ตัดสินขั้นตอนถัดไปหรือว่าควรสิ้นสุดหรือไม่
- ขั้นตอนถัดไปถูกส่งออกเป็นการเรียกใช้เครื่องมือในรูปแบบ JSON ที่มีโครงสร้าง
- โค้ดเชิงกำหนดแน่นอนเรียกใช้เครื่องมือนั้น
- ผลลัพธ์การรันถูกเพิ่มเข้าไปใน context window
- หากขั้นตอนถัดไปคือ
doneก็ส่งคืนคำตอบสุดท้าย
- ตัวอย่างใน README แสดงลูปที่กำหนดขั้นตอนถัดไปด้วย
llm.determine_next_step(context)รันด้วยexecute_step(next_step)แล้วแนบผลลัพธ์กลับเข้า context
ทำไมจึงต้องมีหลักการ 12 ข้อ
- ระหว่างสร้าง HumanLayer ได้พูดคุยกับผู้สร้าง SaaS อย่างน้อย 100 คน ซึ่งส่วนใหญ่เป็นผู้ก่อตั้งสายเทคนิคที่ต้องการทำให้ผลิตภัณฑ์เดิมมีความเป็น agentic มากขึ้น
- เส้นทางทั่วไปเป็นดังนี้
- ตัดสินใจสร้างเอเจนต์
- ออกแบบผลิตภัณฑ์ ทำแผนที่ UX และกำหนดปัญหาที่จะแก้
- เลือก เฟรมเวิร์ก บางตัวเพื่อให้เดินหน้าได้เร็ว
- ไปถึงระดับคุณภาพ 70–80%
- ตระหนักว่าคุณภาพ 80% ไม่เพียงพอสำหรับฟีเจอร์ส่วนใหญ่ที่ลูกค้าใช้งาน
- หากต้องการเกิน 80% จำเป็นต้องย้อนวิศวกรรมเฟรมเวิร์ก พรอมป์ โฟลว์ ฯลฯ
- สุดท้ายเริ่มใหม่ตั้งแต่ต้น
- ข้อวิจารณ์นี้ไม่ได้มีเจตนาโจมตีเฟรมเวิร์กหรือผู้สร้างเฟรมเวิร์ก และระบุว่าเฟรมเวิร์กช่วยเร่งระบบนิเวศ AI
- ไม่ครอบคลุม MCP และตัวอย่างส่วนใหญ่ใช้ TypeScript แต่ระบุว่าสามารถนำไปใช้กับ Python หรือภาษาอื่นได้เช่นกัน
12 ปัจจัย
- แม้ LLM จะทรงพลังขึ้นเรื่อย ๆ แต่เทคนิควิศวกรรมหลักที่ทำให้ซอฟต์แวร์บน LLM เชื่อถือได้มากขึ้น ขยายได้มากขึ้น และดูแลรักษาง่ายขึ้นจะยังคงอยู่
- 12 ปัจจัยมีดังนี้
- Factor 1: Natural Language to Tool Calls: แปลงภาษาธรรมชาติเป็นการเรียกใช้เครื่องมือ
- Factor 2: Own your prompts: เป็นเจ้าของพรอมป์ของคุณเอง
- Factor 3: Own your context window: เป็นเจ้าของ context window ของคุณเอง
- Factor 4: Tools are just structured outputs: เครื่องมือเป็นเพียงเอาต์พุตที่มีโครงสร้าง
- Factor 5: Unify execution state and business state: รวมสถานะการรันกับสถานะธุรกิจเข้าด้วยกัน
- Factor 6: Launch/Pause/Resume with simple APIs: เริ่ม/หยุดชั่วคราว/ทำต่อด้วย API ที่เรียบง่าย
- Factor 7: Contact humans with tool calls: ติดต่อมนุษย์ด้วยการเรียกใช้เครื่องมือ
- Factor 8: Own your control flow: เป็นเจ้าของ control flow ของคุณเอง
- Factor 9: Compact Errors into Context Window: บีบอัดข้อผิดพลาดเข้าไปใน context window
- Factor 10: Small, Focused Agents: เอเจนต์ขนาดเล็กและมีโฟกัส
- Factor 11: Trigger from anywhere, meet users where they are: ทริกเกอร์ได้จากทุกที่ และพบผู้ใช้ในที่ที่พวกเขาอยู่
- Factor 12: Make your agent a stateless reducer: ทำให้เอเจนต์เป็น reducer แบบไร้สถานะ
- มีคำแนะนำเพิ่มเติมคือ Factor 13: Pre-fetch all the context you might need
วิธีนำไปใช้และเอกสารที่เกี่ยวข้อง
- มองว่าการรับเฟรมเวิร์กทั้งชุดมาใช้จนแทบกลายเป็นการเขียนใหม่แบบ greenfield อาจให้ผลตรงข้าม
- หลักการสำคัญที่ทำให้เอเจนต์ดีขึ้นอาจได้มาส่วนใหญ่จากการนำเฟรมเวิร์กมาใช้ แต่หนทางที่เร็วกว่าในการส่งมอบซอฟต์แวร์ AI คุณภาพสูงให้ลูกค้าคือการผสานแนวคิดที่เล็กกว่าและเป็นโมดูลกว่าเข้ากับผลิตภัณฑ์เดิม
- ระบุว่าแนวคิดแบบโมดูลนี้สามารถนิยามและนำไปใช้ได้แม้โดยวิศวกรซอฟต์แวร์ที่มีประสบการณ์แต่ไม่มีพื้นฐานด้าน AI
- เอกสารที่เกี่ยวข้องเชื่อมไปยัง Building Effective Agents ของ Anthropic, Prompts are Functions, Library patterns: Why frameworks are evil, The Wrong Abstraction เป็นต้น
- เนื้อหาและรูปภาพเผยแพร่ภายใต้ไลเซนส์ CC BY-SA 4.0 ส่วนโค้ดเผยแพร่ภายใต้ไลเซนส์ Apache 2.0
1 ความคิดเห็น
ความคิดเห็นใน Hacker News
ประเด็นในบทความนี้ยอดเยี่ยมมาก ผมมีรายการบทเรียนที่ได้จากการลองทำเองมาหลายปีด้วย: https://mg.dev/lessons-learned-building-ai-agents/
ถ้าเป็นตอนนี้ สิ่งที่อยากเพิ่มมากที่สุดคือให้เป็นเจ้าของ ลูปการวางแผนระดับต่ำสุด ด้วยตัวเอง การวางแผนแบบไดนามิกนั้นโอเค แต่ควรมีลูปสังเกต-ประเมิน-ตัดสินใจ-ลงมือทำ (OODA) ของตัวเอง และมี heuristic (เช่น การให้คะแนน) เพื่อ判断ว่ากำลังลู่เข้าไปหาคำตอบหรือไม่ หรือมีเงื่อนไขสำหรับออกจากลูป (เช่น จำนวนรอบสูงสุด)
อีกอย่างที่ควรพิจารณาคือการใส่ workflow engine แทนที่จะให้โมเดลคงและเดินหน้า workflow โดยนัยข้ามหลาย turn ควรให้โมเดลสร้างสเปก workflow ที่จะถูกรันในเอนจินนั้น แล้วค่อยเรียกโมเดลอีกครั้งในแต่ละขั้นเมื่อจำเป็นจะดีกว่า
สงสัยว่าไลบรารีอย่าง DSPY เข้ากับ factor-2 อย่างไร: https://dspy.ai/, https://github.com/humanlayer/12-factor-agents/blob/main/con...
อ่านไปแล้วเห็นว่ามีการพูดถึงการสร้างพรอมป์ด้วย BAML โดยส่วนตัวแล้ว การเขียนพรอมป์ด้วยมือเพื่อดึงข้อมูลเชิงโครงสร้างจากข้อมูลที่ไม่มีโครงสร้างไม่ใช่เรื่องง่าย และจนถึงตอนนี้มีประสบการณ์กับ DSPY ค่อนข้างดี
ถ้าใช้พรอมป์ดิบของ BAML อยากรู้ว่ามองวิธีใช้พรอมป์ดิบของ DSPY อย่างไร: https://dspy.ai/tutorials/observability/#using-inspect_histo...
https://www.chrismdp.com/beyond-prompting/ ผมไม่ได้เห็นด้วยทั้งหมดกับบทความนี้ แต่การเปรียบเทียบ punch card → assembly → C → ภาษา high-level มีประโยชน์มากในบริบทนี้
ตอนนี้ยังไม่รู้ว่า abstraction ที่เหมาะสมจะออกมาเมื่อไร และผมยังไม่คิดว่า LangChain หรือ DSPY เป็น “ภาษาโปรแกรม C” ของ AI อาจจะเป็นได้สักวันหนึ่ง
ตอนนี้ผมจะใช้ โต๊ะทำงานระดับ low-level ที่ตรวจสอบโทเคนได้ สลับลำดับโทเคนพิเศษอย่าง system/user/JSON ได้ และปรับตัวให้เข้ากับลักษณะเฉพาะของโมเดลใหม่ ๆ ได้อย่างรวดเร็ว โดยไม่ถูกผูกมัดระหว่างรอการรองรับจากไลบรารี
บทความเก่าที่ไม่ค่อยเป็นที่รู้จักเกี่ยวกับรูปแบบของ framework ชิ้นหนึ่งโดนใจผมมาตลอดอาชีพ และคิดว่านำมาใช้กับเรื่องนี้ได้ด้วย: https://tomasp.net/blog/2015/library-frameworks/
ด้วยเหตุผลที่บทความอธิบายและมากกว่านั้น โดยเฉพาะในช่วงที่ทุกอย่างเปลี่ยนเร็วแบบตอนนี้ LLM ควรถูกใช้เหมือน library มากกว่า framework อย่างไรก็ตาม framework ดูเซ็กซี่กว่า ขายง่ายกว่า และนำไปสู่ lock-in กับบริการเสริม จึงถูกโปรโมตมากกว่า
ได้สร้าง “AI agent framework” ของตัวเองชื่อ SecAI โดยอิง actor model, state machine และ aspect-oriented programming และเพิ่งเปิดเผยสู่สาธารณะ: https://github.com/pancsta/secai
ชอบข้อ 5 “รวมสถานะการรันกับสถานะธุรกิจเข้าด้วยกัน” และข้อ 8 “เป็นเจ้าของ control flow ด้วยตัวเอง” เป็นพิเศษ แกนหลักของ SecAI คือไลบรารีควบคุม flow แบบกราฟ ใช้ multigraph ไม่ใช่ DAG และการเรียก LLM ถูกฝังอยู่ใน node ของกราฟ
flow ถูกเสริมด้วยการเจรจา การยกเลิก และความสัมพันธ์ที่มีสถานะ ทำให้ทำงานได้เป็นธรรมชาติมากขึ้น นอกจากนี้ยังมีเครื่องมือพัฒนาเฉพาะทาง (dbg, repl, svg) ที่ framework อื่นมักไม่มี, การเขียนโปรแกรมโดยสมมติว่า failure จะเกิดขึ้น, ความสามารถในการตรวจสอบทุกขั้นอย่างละเอียด, การส่งออกข้อมูลอัตโนมัติ (metrics·traces·logs·SQL) และการผสานรวมแบบเรียบง่าย (bash)
ได้เผยแพร่เดโมทางเทคนิคแรกด้วย โดยเป็น reference implementation ของ deepresearch ที่พอร์ตมาจาก AtomicAgents เพื่อแสดงเครื่องมือพัฒนา: https://youtu.be/0VJzO1S-gV0
ปุ่ม Send/Stop แทบจะเป็น “Factor 6. เริ่ม/หยุดชั่วคราว/ทำต่อด้วย API ที่เรียบง่าย” และยังมี network transparency จึงขยายได้
ถ้าจะเพิ่มอีกอย่าง ควรวางแผนเรื่อง ต้นทุนเมื่อสเกลใหญ่ขึ้น ด้วย
ระบบแบบนี้เมื่อสเกลแล้วไม่ถูก ดังนั้นถ้างานใดสามารถจัดการด้วยคอมโพเนนต์ที่กำหนดผลได้แน่นอน ก็ควรลองทางนั้นก่อน ไม่เพียงช่วยลด hallucination และ latency แต่ยังสร้างความแตกต่างอย่างมากต่อกำไรสุดท้ายได้ด้วย
เพื่อให้ติดตามแต่ละหลักการได้ง่ายขึ้น น่าจะมี เรื่องเล่าที่สอดคล้องกัน พาดผ่านหลาย factor ถ้าใช้ตัวอย่างระบบที่ใกล้เคียงของจริงต่อเนื่องไปเรื่อย ๆ น่าจะเข้าใจง่ายขึ้น
อยากพัฒนาต่อแบบเปิดเผยร่วมกับชุมชน
ยอดเยี่ยมมาก 80% ผมได้เรียนรู้มาแบบลำบากแล้ว ส่วนอีก 20% ก็น่าจะคุ้มค่าที่จะอ่าน
ส่วนตัวผมเคยประสบความสำเร็จกับชุด LangGraph + pydantic schema อยากรู้เหมือนกันว่าเครื่องมืออื่น ๆ ที่คนอื่นใช้แล้วมีประโยชน์มีอะไรบ้าง
เป็นบทความที่ออกมาตรงเวลาที่ต้องการพอดี
ผมกำลังทดลองไอเดียแซนด์บ็อกซ์ภาพและเสียงอยู่ คล้าย ๆ vvvv แต่เรียบง่ายกว่ามากและมีแค่ฟังก์ชันขั้นต่ำ: https://kfs.mkj.lt/#audiovisllm, https://vvvv.org/
ไอเดียคือแทรก “โหนด” ที่เป็น LM หรือโครงข่ายประสาทโลคอลแบบง่าย ๆ ซึ่งรับหน้าที่เฉพาะและมีเอาต์พุตจำกัดมาก ดังนั้นตัวอย่างแบบ “question -> answer: float” จึงน่าสนใจมาก สำหรับผม บางคำถามอาจค่อนข้างเป็นนามธรรม แต่ ไปป์ไลน์หลายขั้นตอน ก็น่าสนใจเช่นกัน
ยังไม่ได้อ่านละเอียด แต่ผมอยากใช้ โค้ดแบบกำหนดผลได้แน่นอน ให้มากที่สุดเท่าที่ทำได้ และใช้ LLM ให้น้อยที่สุด
เพราะคิดว่านั่นนำไปสู่ผลลัพธ์ที่คาดการณ์ได้ ต้นทุนดำเนินงานต่ำ และเป็นสัญญาณว่าคนอื่นจะลอกแอปเดียวกันได้อย่างรวดเร็วได้ยาก ผมมักจะสร้างเครื่องมือเอง มากกว่าจะใช้กาวเชื่อมแบบ buzzword ตามกระแสเพื่อต่อ LLM เข้ากับระบบอื่น
ถ้าเงื่อนไขเหล่านี้ไม่เป็นจริงหรือไม่จำเป็น ผมคิดว่าใครสักคนก็สามารถ vibe coding วิธีแก้แบบเดียวกันขึ้นมาได้ในพริบตา ต้องรักษาการควบคุมไว้ ผมยืนกรานว่าจะตายบนเนินแห่งการควบคุมนี้ แต่ไม่ได้หมายความว่าไม่ทึ่งกับ LLM นะ ตรงกันข้ามเลย