← Phase 2 Phase 2 • Day 15 Kickoff

Local SE Agent Masterclass

MacBook M3 16GB • Complete Implementation Standard
📍 ส่วนที่ 1: หมุดตั้งโจทย์ & วัตถุประสงค์หลัก (Title Connection)

Chapter 15 — Agent Architecture Blueprint: Dynamic Skills vs. Monolithic Prompts

ทำไมต้องชื่อนี้และเรียนไปเพื่ออะไร?

ใน Phase 1 (Day 1–14) เราสร้าง ReAct Agent ที่ใช้งานเครื่องมือ 2–3 ตัว เช่น read_file หรือ run_maven_test โดยยัดคำสั่ง เครื่องมือ และคู่มือทั้งหมดลงใน DEFAULT_SYSTEM_PROMPT ก้อนเดียว (Monolithic Prompt) ซึ่งใช้งานได้ดีในระดับห้องทดลอง

แต่ใน Phase 2 (Enterprise Software Engineering): เมื่อ Agent ต้องรองรับงานจริงนับสิบประเภท เช่น AST Code Skeleton Parsing, Cross-File Call Hierarchy, Git Worktrees Sandboxing, Security Auditing, และ Test Coverage Analysis...
หายนะจะเกิดขึ้นทันทีหากยังใช้ Monolithic Prompt:
1. Prompt Dilution (คำสั่งเจือจาง): การยัดคำสั่ง 40 หน้าลงใน Prompt ทำให้ Attention Span ของ Local LLM ขนาด 7B–14B ถูกกระจายจนจำกฎสำคัญไม่ได้ และเริ่มละเลยเงื่อนไขความปลอดภัย
2. Tool Selection Confusion: เมื่อมี Tools กองรวมกัน 20–30 ชิ้น โมเดลจะเริ่มส่งพารามิเตอร์สับสน หรือเลือกเครื่องมือผิดตัว
3. Context Budget Explosion: กินพื้นที่ Token เริ่มต้นไปแล้วกว่า 6,000–8,000 Tokens ตั้งแต่ยังไม่ได้เริ่มอ่านโค้ดจริง!

Day 15 เราจึงต้องเปลี่ยนผ่านสถาปัตยกรรมสู่ "Dynamic Skills Architecture (Microkernel & Pluggable Skills)": แยกคู่มือและเครื่องมือเฉพาะทางออกเป็นตลับสกิลอิสระในโฟลเดอร์ skills/ แล้วใช้เทคนิค Two-Stage Progressive Disclosure: เริ่มต้นด้วยสารบัญย่อ (Catalog ~20 tokens/สกิล) และดึงคู่มือตัวเต็มเข้า Working Memory เฉพาะตอนที่ผู้ใช้สั่งงานเรื่องนั้นๆ จริงเท่านั้น!

✓ Phase 1: Core ReAct & Workspace (Day 1-14) Day 15: Dynamic Skills Blueprint 📐 Day 16: SkillRegistry & Lifecycle Engine Day 17: First Enterprise Skill
📂 ส่วนที่ 2: ผังโครงสร้างโปรเจกต์จริง & ตำแหน่งไฟล์ (Project File Structure)

ใน Day 15 เราจะวางรากฐานโฟลเดอร์ใหม่ skills/ และแยกประเภทไฟล์โครงสร้างของแต่ละ Skill Cartridge เพื่อเตรียมพร้อมสำหรับการสร้าง Registry ใน Day 16:

se_agent/
├── config.json                             # Model config & limits
├── se-agent                                # CLI wrapper
├── requirements.txt                       # ollama, chromadb, rich
├── main.py                               # Interactive CLI Cockpit
├── test_dynamic_skills_blueprint.py      # [ไฟล์ใหม่ Day 15] ทดสอบเปรียบเทียบ Token และการจำลองโหลด Skill
├── skills/                                  # [โฟลเดอร์ใหม่ Phase 2] แหล่งเก็บ Pluggable Skill Cartridges
│   ├── __init__.py
│   ├── unit_test_synthesizer/              # ตัวอย่างตลับสกิลที่ 1: สกิลเขียน Unit Test
│   │   ├── metadata.json                   # [Stage 1] ข้อมูลสรุปย่อ (id, triggers, short_description)
│   │   └── instructions.md                 # [Stage 2] คู่มือเชิงลึกกฎเหล็ก (AAA Pattern, Mocking Rules)
│   └── git_release_manager/                 # ตัวอย่างตลับสกิลที่ 2: สกิลจัดการ Git Release
│       ├── metadata.json                   # [Stage 1] ข้อมูลสรุปย่อ
│       └── instructions.md                 # [Stage 2] คู่มือสร้าง Release Note & Semantic Tagging
├── memory/                                # Context & ChromaDB
├── core/                                  # ReAct Engine, Dispatcher, Guardrails, Workspace
└── sample_maven_project/
📍 metadata.json ทำหน้าที่อะไร?

ทำหน้าที่เป็น Stage 1 Discovery Card บรรจุข้อมูลสั้นกระชับ (~25 Tokens) เช่น ID, ชื่องาน, Triggers และ Description เพื่อให้ ReAct Engine รวบรวมทำสารบัญสั้นๆ (Catalog) ใส่ใน System Prompt โดยไม่ทำให้ Context บวม

📍 instructions.md ทำหน้าที่อะไร?

ทำหน้าที่เป็น Stage 2 Deep Operational Manual บรรจุกฎเหล็กทางวิศวกรรมเฉพาะทาง (เช่น AAA Pattern, Mocking Strategy, Edge Cases) ซึ่งจะถูกโหลดเข้าสู่ Working Memory เฉพาะตอนที่ Agent ตรวจพบว่าต้องทำงานที่ตรงกับสกิลนั้นเท่านั้น

🏛️ ส่วนที่ 3: สถาปัตยกรรม Microkernel & Dynamic Skills (Mental Model)
เปรียบเทียบสถาปัตยกรรม: Monolithic Prompt vs. Dynamic Two-Stage Skills
❌ Monolithic System Prompt (Phase 1) Prompt Dilution
System Prompt ขนาดยักษ์ (5,000+ Tokens):
- ReAct Loop Rules (500 tokens)
- Unit Test QA Manual (1,500 tokens)
- Git Release Convention (1,200 tokens)
- AST Parsing Rules (1,800 tokens)
- Tools ทั้งหมด 25 ตัว กองรวมกัน!

ปัญหา: โมเดล 7B–14B สับสน เลือกลำดับ Tool ผิด กฎระเบียบเจือจาง และกินแรมตั้งแต่ยังไม่ได้เริ่มอ่านโค้ดงาน

✅ Dynamic Two-Stage Skills (Phase 2) Microkernel
Stage 1: Core Prompt + สารบัญย่อ (~350 Tokens):
- ReAct Core Loop (300 tokens)
- Skill Catalog: unit_test (~25 tokens)
- Skill Catalog: git_release (~25 tokens)
Stage 2: Expand on Demand:
- โหลด `instructions.md` เฉพาะสกิลที่ Active และคืนแรมเมื่อจบงาน!

ข้อได้เปรียบ: ประหยัด Token เริ่มต้น 90% โมเดลโฟกัสเฉพาะกฎที่กำลังทำอย่างแม่นยำ และต่อยอดได้ไม่จำกัดจำนวนสกิล

วงจรชีวิต 4 จังหวะ: The Dynamic Skill Lifecycle State Machine
1️⃣
DISCOVERED

สแกนเจอโฟลเดอร์ใน skills/ ยังไม่กิน RAM

2️⃣
CATALOGED

ดึง metadata สั้นๆ ใส่ Catalog ใน System Prompt (~25 tokens)

3️⃣
ACTIVE / EXPANDED

ตรวจพบเจตนา ดึง instructions.md เข้า Memory ชั่วคราว

4️⃣
EVICTED / RESET

งานเสร็จสิ้น ปลดคู่มือออกจาก Memory คืนความสดใหม่ให้ Context

💻 ส่วนที่ 4: ซอร์สโค้ดจริง & คำอธิบายทีละบรรทัด (Line-by-Line Implementation)
📄 1. skills/unit_test_synthesizer/metadata.json (Stage 1 Discovery Card) สารบัญย่อสำหรับ System Prompt (~25 tokens)
{
  "id": "unit_test_synthesizer",
  "name": "Enterprise Unit Test Synthesizer",
  "description": "สร้าง Unit Test คุณภาพระดับ Enterprise ตามมาตรฐาน AAA Pattern และครอบคลุมทั้ง Happy, Boundary และ Exception Paths",
  "triggers": ["test", "unit test", "junit", "pytest", "test case", "mock"],
  "version": "1.0.0"
}
📄 2. skills/unit_test_synthesizer/instructions.md (Stage 2 Deep Operational Rules) คู่มือปฏิบัติการตัวเต็ม โหลดเข้าเฉพาะตอนสกิลนี้ Active
# Role: Senior QA Automation & Test Architect
You are operating in specialized 'Unit Test Synthesizer' mode.

## Mandatory Rules:
1. **Strict AAA Structure**: Every test MUST be explicitly divided into:
   - `// Arrange`: Setup mocks, inputs, and expected values.
   - `// Act`: Execute the single target method under test.
   - `// Assert`: Verify return values, exceptions, and verify mock interactions.
2. **Mocking Isolation**: Never call real external databases or network services. Mock all repositories and clients.
3. **Naming Standard**: Test method names must strictly follow `should_[ExpectedBehavior]_When_[StateUnderTest]()`.
4. **Three Critical Paths**: Every tested function must have:
   - Happy Path: Valid inputs, expected successful outcome.
   - Boundary Path: Empty collections, null checks, edge values (0, MAX_INT).
   - Exception Path: Verify expected domain exceptions with `assertThrows`.
📄 3. skills/git_release_manager/metadata.json (ตลับสกิลที่ 2) สารบัญย่อสำหรับสกิลจัดการ Git Release
{
  "id": "git_release_manager",
  "name": "Git Release & Changelog Manager",
  "description": "วิเคราะห์ Git Commits สร้าง Release Notes ตามมาตรฐาน Keep a Changelog และจัดการ Semantic Versioning",
  "triggers": ["git release", "changelog", "release notes", "version bump", "tag"],
  "version": "1.0.0"
}
📄 4. test_dynamic_skills_blueprint.py (สคริปต์พิสูจน์การประหยัด Token และ Stage Disclosure) รันสาธิตเปรียบเทียบขนาด Context ระหว่าง Monolithic vs Two-Stage
import json
from pathlib import Path

SKILLS_DIR = Path("./skills").resolve()

def estimate_tokens(text: str) -> int:
    """ประมาณการจำนวนโทเค็นอย่างปลอดภัย (Heuristic: ~3.5 ตัวอักษรต่อ 1 token)"""
    return int(len(text) / 3.5)

def simulate_monolithic_prompt(skills_root: Path) -> tuple[str, int]:
    """จำลองวิธีแบบเดิม (Monolithic): ยัดทุกคู่มือตัวเต็มของทุกสกิลลง Prompt ก้อนเดียว"""
    monolithic_parts = [
        "You are an Autonomous Software Engineering Agent.\n",
        "--- GENERAL REACT RULES (500 words) ---\n" + ("Rules..." * 50) + "\n"
    ]
    for skill_folder in skills_root.iterdir():
        if skill_folder.is_dir() and (skill_folder / "instructions.md").exists():
            inst = (skill_folder / "instructions.md").read_text(encoding="utf-8")
            monolithic_parts.append(f"\n--- SKILL MANUAL: {skill_folder.name} ---\n{inst}\n")
            
    full_prompt = "".join(monolithic_parts)
    return full_prompt, estimate_tokens(full_prompt)

def simulate_two_stage_skills(skills_root: Path, active_skill_id: str) -> tuple[str, str, int]:
    """จำลองวิธีใหม่ (Two-Stage Progressive Disclosure): ส่งสารบัญย่อ + ขยายเฉพาะสกิลที่ Active"""
    # Stage 1: สร้าง Catalog สารบัญย่อ
    catalog_items = []
    active_instructions = ""

    for skill_folder in skills_root.iterdir():
        if skill_folder.is_dir() and (skill_folder / "metadata.json").exists():
            meta = json.loads((skill_folder / "metadata.json").read_text(encoding="utf-8"))
            catalog_items.append(f"- [{meta['id']}]: {meta['description']}")
            if meta['id'] == active_skill_id and (skill_folder / "instructions.md").exists():
                active_instructions = (skill_folder / "instructions.md").read_text(encoding="utf-8")

    stage_1_prompt = (
        "You are an Autonomous Software Engineering Microkernel Agent.\n\n"
        "AVAILABLE SKILLS CATALOG:\n" + "\n".join(catalog_items) + "\n\n"
        "When a specialized task arrives, the corresponding manual will be dynamically expanded."
    )
    
    total_active_context = stage_1_prompt + "\n\nACTIVE SKILL EXPANSION:\n" + active_instructions
    return stage_1_prompt, total_active_context, estimate_tokens(total_active_context)

def main():
    print("=" * 70)
    print("🚀 Day 15 Lab: Architecture Blueprint — Dynamic Skills vs. Monolithic Prompts")
    print("=" * 70)

    # 1. ทดสอบจำลอง Monolithic
    _, mono_tokens = simulate_monolithic_prompt(SKILLS_DIR)
    print(f"\n❌ [Monolithic Architecture] ขนาด Context ตั้งต้น: ~{mono_tokens} Tokens")
    print("   👉 ข้อเสีย: ยัดทุกคู่มือพร้อมกันทั้งหมด ยิ่งเพิ่มสกิล Token ยิ่งระเบิด โมเดลสับสน!")

    # 2. ทดสอบจำลอง Two-Stage Progressive Disclosure
    stage1_prompt, active_context, dynamic_tokens = simulate_two_stage_skills(SKILLS_DIR, "unit_test_synthesizer")
    print(f"\n✅ [Dynamic Skills Architecture] ข้อมูล Stage 1 Catalog:")
    print("-" * 50)
    print(stage1_prompt)
    print("-" * 50)
    print(f"🎯 ขนาด Context เมื่อขยายเฉพาะสกิล 'unit_test_synthesizer': ~{dynamic_tokens} Tokens")

    saved_percent = ((mono_tokens - dynamic_tokens) / mono_tokens) * 100
    print(f"\n📊 ผลลัพธ์: ประหยัดพื้นที่ Token เริ่มต้นได้กว่า {saved_percent:.1f}%!")
    print("🏆 พิสูจน์แล้วว่าระบบ Microkernel ช่วยให้ Mac M3 ประมวลผลได้เร็วเฉียบคม ไร้ Prompt Dilution 100%!")

if __name__ == "__main__":
    main()
ชำแหละไวยากรณ์สำคัญในสถาปัตยกรรม Dynamic Skills
catalog_items.append(f"- [{meta['id']}]: {meta['description']}")

Stage 1 Low-Footprint Catalog: การส่งเพียง ID และ Description สรุป 1 บรรทัด ช่วยให้ Agent รู้จักทักษะทั้งหมดในระบบ โดยกินพื้นที่เพียง ~20–25 Tokens ต่อสกิลเท่านั้น ทำให้ระบบรองรับการมี 50 สกิลพร้อมกันได้สบายๆ

active_instructions = (skill_folder / "instructions.md").read_text()

Stage 2 On-Demand Expansion: อ่านไฟล์คู่มือตัวเต็มขึ้นมาจากดิสก์เฉพาะเมื่อสกิลนั้นถูกระบุตัวตน (Active) เท่านั้น จึงไม่มีขยะคำสั่งของสกิลอื่นเข้ามาเจือปน Attention

saved_percent = ((mono_tokens - dynamic_tokens) / mono_tokens) * 100

Token Budget Optimization: การประหยัดโทเค็นได้กว่า 80–90% ช่วยปลดล็อกให้โมเดลประมวลผลบน Apple Silicon Unified Memory ได้เร็วขึ้น 3 เท่า และเหลือพื้นที่ Context สำหรับอ่านซอร์สโค้ดจริงได้มากขึ้นมหาศาล

⚡ ส่วนที่ 5: ปฏิบัติการจริงบน Terminal Mac M3 (Step-by-Step Lab)

เปิด Terminal บน MacBook M3 แล้วทำตาม 5 ขั้นตอนนี้เพื่อสร้างโครงสร้าง Pluggable Skills และรันสคริปต์ทดสอบสถาปัตยกรรมทันที:

ขั้นตอนที่ 1: เข้าโฟลเดอร์โปรเจกต์และเปิด Virtual Environment
cd ~/se_agent
source .venv/bin/activate
ขั้นตอนที่ 2: สร้างโฟลเดอร์และไฟล์ใหม่สำหรับ Day 15
mkdir -p skills/unit_test_synthesizer skills/git_release_manager
touch skills/__init__.py
touch skills/unit_test_synthesizer/metadata.json skills/unit_test_synthesizer/instructions.md
touch skills/git_release_manager/metadata.json
touch test_dynamic_skills_blueprint.py
ขั้นตอนที่ 3: วางโค้ดลงในแต่ละไฟล์

- นำโค้ดใน ส่วนที่ 4 (ไฟล์ที่ 1) ไปวางใน skills/unit_test_synthesizer/metadata.json
- นำโค้ดใน ส่วนที่ 4 (ไฟล์ที่ 2) ไปวางใน skills/unit_test_synthesizer/instructions.md
- นำโค้ดใน ส่วนที่ 4 (ไฟล์ที่ 3) ไปวางใน skills/git_release_manager/metadata.json
- นำโค้ดใน ส่วนที่ 4 (ไฟล์ที่ 4) ไปวางใน test_dynamic_skills_blueprint.py

ขั้นตอนที่ 4: สั่งรันสคริปต์ทดสอบพิมพ์เขียวสถาปัตยกรรม
python test_dynamic_skills_blueprint.py

🎉 ผลลัพธ์: คุณจะเห็นหน้าจอ Terminal แสดงการเปรียบเทียบชัดเจนว่าวิธีเดิมกิน Token มหาศาล ในขณะที่วิธี Two-Stage Skills ดึงสารบัญ Catalog มาแสดงอย่างสะอาดตา และประหยัดพื้นที่ Token ได้อย่างน่าทึ่ง!

ขั้นตอนที่ 5 (สังเกตผล): ตรวจดูความพร้อมสำหรับ Day 16

ตอนนี้โฟลเดอร์ skills/ มีโครงสร้างตลับสกิลที่ได้มาตรฐานแล้ว ใน Day 16 เราจะลงมือสร้างคลาส SkillRegistry และ SkillLifecycleManager ใน Python เพื่อสแกนและโหลดสกิลเหล่านี้โดยอัตโนมัติ!

📝 ส่วนที่ 6: ชุดควิซประเมินความรู้เชิงสถาปัตยกรรม 15 ข้อ (ตอบปุ๊บรู้ผลทันที)

ข้อที่ 1: วัตถุประสงค์หลักของ "Day 15: Agent Architecture Blueprint — Dynamic Skills vs. Monolithic Prompts" คืออะไร?

ข้อที่ 2: ปรากฏการณ์ "Prompt Dilution" (ความเจือจางของคำสั่ง) ส่งผลเสียร้ายแรงอย่างไรต่อ Local LLM ขนาด 7B–14B?

ข้อที่ 3: สถาปัตยกรรม "Microkernel" สำหรับ AI Agent หมายถึงการจัดวางระบบอย่างไร?

ข้อที่ 4: กลยุทธ์ "Two-Stage Progressive Disclosure" ในการบริหารจัดการ Context Window มีขั้นตอนอย่างไร?

ข้อที่ 5: องค์ประกอบมาตรฐานของ 1 Skill Cartridge ในโฟลเดอร์ `skills/` ควรมีไฟล์สำคัญใดบ้าง?

ข้อที่ 6: ข้อมูลในไฟล์ `metadata.json` ประจำแต่ละ Skill มีไว้เพื่อให้ส่วนใดนำไปใช้งาน?

ข้อที่ 7: กฎ "One-Active-Skill Policy" ในการบริหาร Working Memory มีจุดประสงค์เพื่ออะไร?

ข้อที่ 8: แนวคิด "Lazy Loading" ในการจัดการ Skill มีความหมายอย่างไร?

ข้อที่ 9: กระบวนการ "Context Eviction" มีความจำเป็นอย่างไรเมื่อ Agent สลับไปทำงานอื่น?

ข้อที่ 10: "Dedicated Tool Isolation" ช่วยลดปัญหาการเลือก Tool ผิดพลาดได้อย่างไร?

ข้อที่ 11: หากระบบมีสกิลรองรับทั้งหมด 30 สกิล การใช้ Dynamic Two-Stage Skills ประหยัด Token ได้ต่างจาก Monolithic อย่างไร?

ข้อที่ 12: อะไรคือความแตกต่างระหว่าง "Core System Prompt" กับ "Skill Instructions"?

ข้อที่ 13: การแยก Skills เป็นโฟลเดอร์โมดูลอิสระส่งผลดีต่อการขยายระบบ (Extensibility) อย่างไร?

ข้อที่ 14: หลังจากที่เราเข้าใจพิมพ์เขียวสถาปัตยกรรมใน Day 15 แล้ว ใน **Day 16** เราจะลงมือสร้างชิ้นส่วนใดต่อไป?

ข้อที่ 15: ในฐานะสถาปนิกซอฟต์แวร์ (Software Architect) เมื่อคุณเข้าใจสถาปัตยกรรม Dynamic Skills ใน Day 15 คุณรู้สึกอย่างไร?

🏁 สรุปหมุดเชื่อมโยง Day 15 (Chapter Wrap-up)

ใน Day 15 — Agent Architecture Blueprint: Dynamic Skills vs. Monolithic Prompts คุณได้วางรากฐานสถาปัตยกรรม Microkernel และเทคนิค Two-Stage Progressive Disclosure ที่พิสูจน์แล้วว่าช่วยประหยัด Token ได้กว่า 85–90% และปกป้องโมเดลบน MacBook M3 16GB ไม่ให้เกิดอาการ Prompt Dilution ตอนนี้พิมพ์เขียวและโฟลเดอร์ skills/ ของเราพร้อมแล้ว พร้อมก้าวเข้าสู่ Day 16: Building the Dynamic Skill Engine (SkillRegistry & Lifecycle Manager in Python) เพื่อลงมือสร้างเครื่องยนต์สแกนและโหลดสกิลจริงแล้วครับ!