การพัฒนา AI Agent ที่ซับซ้อนในยุคปัจจุบันต้องการมากกว่าแค่การเรียก LLM ผ่าน API เพียงอย่างเดียว ทีมพัฒนาต้องออกแบบ flow การตัดสินใจที่ชาญฉลาด จัดการ state ของ conversation ได้อย่างแม่นยำ และ orchestrate API calls หลายตัวพร้อมกัน ในบทความนี้เราจะมาเรียนรู้วิธีใช้ LangGraph เพื่อสร้าง state machine ที่ทรงพลัง พร้อมกรณีศึกษาจริงจากทีมสตาร์ทอัพ AI ในกรุงเทพฯ ที่ปรับปรุงประสิทธิภาพจาก 420ms เหลือ 180ms และประหยัดค่าใช้จ่ายจาก $4,200 เหลือ $680 ต่อเดือน

กรณีศึกษา: ทีมสตาร์ทอัพ AI ในกรุงเทพฯ

ทีมพัฒนา AI สตาร์ทอัพแห่งหนึ่งในกรุงเทพฯ ต้องการสร้าง AI customer service agent ที่สามารถจัดการคำถามลูกค้าหลายประเภท ตั้งแต่การตอบคำถามทั่วไป การประมวลผลออเดอร์ จนถึงการ escalate ปัญหาที่ซับซ้อนไปยังมนุษย์ ระบบเดิมใช้ if-else chain ที่ยาวมากและไม่สามารถจัดการ conversation state ที่ซับซ้อนได้ ทำให้เกิดปัญหา context lost และ response ที่ไม่สอดคล้องกับ conversation flow

จุดเจ็บปวดของระบบเดิมคือความหน่วง (latency) สูงถึง 420ms ต่อการตอบสนองหนึ่งครั้ง เนื่องจากต้องเรียก API หลายรอบอย่าง sequential และค่าใช้จ่ายรายเดือนสูงถึง $4,200 จากการใช้ GPT-4 ผ่าน OpenAI API ทีมงานตัดสินใจย้ายมาใช้ HolySheep AI ซึ่งให้บริการ API ที่เข้ากันได้กับ OpenAI format ใช้งานง่าย ราคาประหยัดกว่า 85% และมี latency เฉลี่ยต่ำกว่า 50ms

ขั้นตอนการย้ายระบบ

การย้ายระบบจาก OpenAI ไปยัง HolySheep AI ทำได้ง่ายมากเพราะ API format เข้ากันได้กัน 100% ทีมงานเพียงแค่เปลี่ยน base_url และ API key ก็สามารถใช้งานได้ทันที นี่คือขั้นตอนที่ทีมใช้:

ตัวชี้วัดหลังการย้าย 30 วัน

หลังจากย้ายระบบมาใช้ HolySheep AI สำเร็จ ตัวชี้วัดหลักของทีมดีขึ้นอย่างเห็นได้ชัด:

พื้นฐาน LangGraph State Machine

LangGraph เป็น library ที่สร้างขึ้นบน LangChain เพื่อให้สามารถสร้าง graph-based workflow ได้ โดยแต่ละ node ใน graph จะรับผิดชอบ task เฉพาะ และ edges จะกำหนด flow การเปลี่ยน state ระหว่าง nodes สิ่งที่ทำให้ LangGraph แตกต่างจาก simple chain คือความสามารถในการ maintain state ข้ามหลาย steps และรองรับ branching, looping และ conditional routing

แนวคิดหลักของ LangGraph State Machine ประกอบด้วย State ที่เป็น dictionary ที่เก็บข้อมูลทุกอย่างที่ agents ต้องการรู้, Nodes ที่เป็น Python functions ที่รับ state และ return state ที่อัพเดต, Edges ที่กำหนดว่าจะไป node ไหนถัดไป, และ Graph ที่รวม nodes และ edges เข้าด้วยกันเพื่อสร้างเป็น workflow สมบูรณ์

การติดตั้งและ Setup

ก่อนเริ่มต้น เราต้องติดตั้ง dependencies ที่จำเป็น คุณสามารถใช้ pip เพื่อติดตั้งได้เลย สำหรับ API endpoint เราจะใช้ HolySheep AI ที่ให้บริการ API ที่เข้ากันได้กับ OpenAI format ใช้งานง่าย และราคาประหยัดมาก

pip install langgraph langchain-core langchain-holysheep openai python-dotenv

สำหรับ environment setup เราจะใช้ไฟล์ .env เพื่อเก็บ API key อย่างปลอดภัย:

HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY
HOLYSHEEP_BASE_URL=https://api.holysheep.ai/v1

การสร้าง AI Agent แบบ State Machine พื้นฐาน

เรามาเริ่มสร้าง AI Agent ที่มี state machine เพื่อจัดการ customer service flow กัน เราจะใช้ HolySheep AI เป็น LLM provider เพราะราคาประหยัดมาก (เริ่มต้นเพียง $0.42 ต่อล้าน tokens สำหรับ DeepSeek V3.2) และ latency ต่ำกว่า 50ms ซึ่งเหมาะมากสำหรับ real-time application

from typing import TypedDict, Annotated, Sequence
from langgraph.graph import StateGraph, END
from langchain_core.messages import BaseMessage, HumanMessage, AIMessage
from openai import OpenAI
import os
from dotenv import load_dotenv

load_dotenv()

Initialize HolySheep AI client

client = OpenAI( api_key=os.getenv("HOLYSHEEP_API_KEY"), base_url="https://api.holysheep.ai/v1" ) class AgentState(TypedDict): """State หลักของ Agent ที่จะถูก pass ผ่านทุก node""" messages: Sequence[BaseMessage] intent: str | None needs_human: bool context: dict def classify_intent(state: AgentState) -> AgentState: """Node แรก: จำแนกประเภทของคำถามลูกค้า""" last_message = state["messages"][-1].content response = client.chat.completions.create( model="gpt-4.1", messages=[ {"role": "system", "content": """จำแนกคำถามลูกค้าเป็นหนึ่งในประเภทต่อไปนี้: - product_inquiry: สอบถามข้อมูลสินค้า - order_status: ติดตามสถานะออเดอร์ - complaint: ร้องเรียนหรือปัญหา - billing: ปัญหาเกี่ยวกับการเงินหรือการชำระเงิน - human_escalation: ต้องการพูดคุยกับมนุษย์ ตอบกลับเฉพาะประเภทเท่านั้น"""}, {"role": "user", "content": last_message} ], temperature=0 ) intent = response.choices[0].message.content.strip().lower() return { **state, "intent": intent, "needs_human": intent == "human_escalation" } def route_based_on_intent(state: AgentState) -> str: """Edge function: ตัดสินใจว่าจะไป node ไหนถัดไป""" intent = state.get("intent", "") if intent == "product_inquiry": return "handle_product" elif intent == "order_status": return "handle_order" elif intent == "complaint": return "handle_complaint" elif intent == "billing": return "handle_billing" elif intent == "human_escalation": return "escalate_to_human" else: return "general_response" def handle_product(state: AgentState) -> AgentState: """จัดการคำถามเกี่ยวกับสินค้า""" last_message = state["messages"][-1].content response = client.chat.completions.create( model="gpt-4.1", messages=[ {"role": "system", "content": "คุณคือ AI ที่ช่วยตอบคำถามเกี่ยวกับสินค้า จงให้ข้อมูลที่เป็นประโยชน์และชัดเจน"}, *state["messages"] ] ) ai_response = response.choices[0].message.content return { **state, "messages": [*state["messages"], AIMessage(content=ai_response)], "context": {**state.get("context", {}), "last_handler": "product"} }

สร้าง Graph

workflow = StateGraph(AgentState)

เพิ่ม nodes

workflow.add_node("classify", classify_intent) workflow.add_node("handle_product", handle_product) workflow.add_node("handle_order", handle_order) workflow.add_node("handle_complaint", handle_complaint) workflow.add_node("handle_billing", handle_billing) workflow.add_node("escalate_to_human", escalate_to_human) workflow.add_node("general_response", general_response)

เพิ่ม edges

workflow.add_edge("classify", END) graph = workflow.compile()

จากตัวอย่างข้างต้น เราได้สร้าง state machine พื้นฐานที่มีหลาย nodes และใช้ conditional routing เพื่อส่ง request ไปยัง handler ที่เหมาะสม สิ่งสำคัญคือ state จะถูก pass ผ่านทุก node ทำให้เราสามารถ maintain context ตลอด conversation ได้

การจัดการ API Call Orchestration

ใน real-world application AI Agent มักจะต้องเรียก API หลายตัวพร้อมกันหรือเรียกตามลำดับ เรามาดูวิธีการ orchestrate API calls อย่างมีประสิทธิภาพ โดยใช้ parallel execution และ async patterns ซึ่งจะช่วยลด latency ได้มาก

import asyncio
from typing import List, Dict, Any
from concurrent.futures import ThreadPoolExecutor

class APICallOrchestrator:
    """จัดการการเรียก API หลายตัวพร้อมกัน"""
    
    def __init__(self):
        self.client = OpenAI(
            api_key=os.getenv("HOLYSHEEP_API_KEY"),
            base_url="https://api.holysheep.ai/v1"
        )
    
    async def fetch_multiple_contexts(
        self, 
        customer_id: str, 
        order_id: str | None = None
    ) -> Dict[str, Any]:
        """เรียก API หลายตัวพร้อมกันเพื่อดึง context"""
        
        async def get_customer_info():
            # Simulate API call to get customer info
            return await asyncio.to_thread(
                self._get_customer_from_db, customer_id
            )
        
        async def get_order_history():
            if not order_id:
                return None
            return await asyncio.to_thread(
                self._get_orders_from_db, customer_id
            )
        
        async def get_product_catalog():
            return await asyncio.to_thread(
                self._get_product_catalog
            )
        
        # Execute all API calls in parallel
        results = await asyncio.gather(
            get_customer_info(),
            get_order_history(),
            get_product_catalog(),
            return_exceptions=True
        )
        
        customer_info, order_history, product_catalog = results
        
        return {
            "customer": customer_info if not isinstance(customer_info, Exception) else None,
            "orders": order_history if not isinstance(order_history, Exception) else [],
            "products": product_catalog if not isinstance(product_catalog, Exception) else []
        }
    
    def generate_response_with_context(
        self, 
        user_message: str, 
        context: Dict[str, Any]
    ) -> str:
        """สร้าง response โดยใช้ context ที่ได้มา"""
        
        context_summary = f"""
        ข้อมูลลูกค้า: {context.get('customer', {})}
        ประวัติการสั่งซื้อ: {context.get('orders', [])}
        แคทตาล็อกสินค้า: {context.get('products', [])}
        """
        
        response = self.client.chat.completions.create(
            model="gpt-4.1",
            messages=[
                {"role": "system", "content": f"""คุณคือ AI customer service agent
                ใช้ข้อมูลต่อไปนี้เพื่อตอบคำถามลูกค้า:
                {context_summary}"""},
                {"role": "user", "content": user_message}
            ],
            temperature=0.7,
            max_tokens=500
        )
        
        return response.choices[0].message.content
    
    # Helper methods (simulated database calls)
    def _get_customer_from_db(self, customer_id: str) -> Dict:
        return {
            "id": customer_id,
            "name": "สมชาย ใจดี",
            "tier": "gold",
            "join_date": "2024-01-15"
        }
    
    def _get_orders_from_db(self, customer_id: str) -> List[Dict]:
        return [
            {"id": "ORD001", "status": "shipped", "total": 2500},
            {"id": "ORD002", "status": "processing", "total": 1800}
        ]
    
    def _get_product_catalog(self) -> List[Dict]:
        return [
            {"id": "P001", "name": "สินค้า A", "price": 500},
            {"id": "P002", "name": "สินค้า B", "price": 1200}
        ]


async def run_agent_flow(user_message: str, customer_id: str):
    """ตัวอย่างการ run agent flow แบบเต็ม"""
    orchestrator = APICallOrchestrator()
    
    # 1. Fetch all contexts in parallel (ลดเวลาจาก 3 API calls เหลือ 1 round trip)
    context = await orchestrator.fetch_multiple_contexts(customer_id)
    
    # 2. Generate response with full context
    response = orchestrator.generate_response_with_context(
        user_message, 
        context
    )
    
    return response


วิธีใช้งาน

result = asyncio.run(run_agent_flow( "สถานะออเดอร์ล่าสุดของฉันเป็นอย่างไร?", "CUST123" ))

ในตัวอย่างนี้เราใช้ asyncio.gather เพื่อเรียก API หลายตัวพร้อมกัน ซึ่งช่วยลดเวลา response ได้อย่างมาก แทนที่จะต้องรอ API call แต่ละตัวตามลำดับ (sequential) ตอนนี้เราสามารถทำทุกอย่างในรอบเดียว (parallel)

Advanced Pattern: Conditional Branching และ Looping

ในบางกรณี AI Agent ต้องมี ability ในการวน loop เพื่อ retry หรือ refine response หรือ branching ตามเงื่อนไขที่ซับซ้อน เรามาดู advanced pattern ที่จะช่วยให้สร้าง logic ที่ยืดหยุ่นได้

def should_retry(state: AgentState) -> bool:
    """ตรวจสอบว่าควรจะ retry หรือไม่"""
    retry_count = state.get("context", {}).get("retry_count", 0)
    last_success = state.get("context", {}).get("last_success", True)
    
    return retry_count < 3 and not last_success


def evaluation_node(state: AgentState) -> AgentState:
    """ประเมินผล response ก่อนที่จะส่งกลับให้ลูกค้า"""
    messages = state.get("messages", [])
    if not messages:
        return {**state, "context": {**state.get("context", {}), "last_success": False}}
    
    last_response = messages[-1]
    response_quality = check_response_quality(last_response.content)
    
    return {
        **state,
        "context": {
            **state.get("context", {}),
            "last_success": response_quality >= 0.7,
            "quality_score": response_quality
        }
    }


def retry_with_feedback(state: AgentState) -> AgentState:
    """Retry โดยให้ feedback จาก response ก่อนหน้า"""
    messages = state.get("messages", [])
    retry_count = state.get("context", {}).get("retry_count", 0)
    last_response = messages[-1].content if messages else ""
    
    response = client.chat.completions.create(
        model="gpt-4.1",
        messages=[
            {"role": "system", "content": """ปรับปรุง response ก่อนหน้าให้ดีขึ้น
            โดยคำนึงถึงปัญหาต่อไปนี้:
            - ความชัดเจนของคำตอบ
            - ความถูกต้องของข้อมูล
            - ความเป็นมิตรในการสื่อสาร"""},
            {"role": "assistant", "content": last_response},
            {"role": "user", "content": "กรุณาปรับปรุงคำตอบนี้ให้ดีขึ้น"}
        ]
    )
    
    new_response = response.choices[0].message.content
    
    return {
        **state,
        "messages": [*messages[:-1], AIMessage(content=new_response)],
        "context": {
            **state.get("context", {}),
            "retry_count": retry_count + 1,
            "improvement_applied": True
        }
    }


def build_advanced_workflow():
    """สร้าง workflow ที่ซับซ้อนขึ้น"""
    workflow = StateGraph(AgentState)
    
    # Nodes
    workflow.add_node("classify", classify_intent)
    workflow.add_node("process", handle_product)
    workflow.add_node("evaluate", evaluation_node)
    workflow.add_node("retry", retry_with_feedback)
    workflow.add_node("escalate", escalate_to_human)
    
    # Edges with conditional logic
    workflow.add_edge("classify", "process")
    workflow.add_edge("process", "evaluate")
    
    # Conditional edge: ถ้า evaluate ว่าไม่ดีพอ ให้ retry
    workflow.add_conditional_edges(
        "evaluate",
        should_retry,
        {
            True: "retry",
            False: END
        }
    )
    
    # Loop back to evaluate after retry
    workflow.add_edge("retry", "evaluate")
    
    return workflow.compile()


วิธีใช้งาน workflow ที่ซับซ้อน

graph = build_advanced_workflow() initial_state = { "messages": [HumanMessage(content="ขอสถานะออเดอร์หมายเลข 12345")], "intent": None, "needs_human": False, "context": {"retry_count": 0} }

Run the graph

final_state = graph.invoke(initial_state) print(final_state["messages"][-1].content)

Pattern นี้มีประโยชน์มากสำหรับการสร้าง AI Agent ที่ต้องการ quality control ในตัว เช่น customer service agent ที่ต้องตรวจสอบว่า response มีคุณภาพเพียงพอก่อนที่จะส่งกลับให้ลูกค้า ถ้าไม่ดีพอก็จะ retry โดยอัตโนมัติจนกว่าจะได้ response ที่acceptable

การ Monitor และ Debug Agent Flow

การ monitor LangGraph workflow สามารถทำได้หลายวิธี วิธีที่ง่ายที่สุดคือใช้ LangSmith หรือสร้าง custom logging system ขึ้นมาเอง เรามาดูวิธีการ trace execution flow เพื่อ debug และ optimize performance

import logging
from datetime import datetime
from typing import Optional

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


class AgentDebugger:
    """Debug และ monitor LangGraph workflow"""
    
    def __init__(self):
        self.execution_history = []
    
    def trace_node_execution(
        self, 
        node_name: str, 
        input_state: dict, 
        output_state: dict
    ):
        """บันทึกการ execute แต่ละ node"""
        execution = {
            "timestamp": datetime.now().isoformat(),
            "node": node_name,
            "input_keys": list(input_state.keys()),
            "output_keys": list(output_state.keys()),
            "state_changes": self._compute_state_diff(input_state, output_state)
        }
        self.execution_history.append(execution)
        logger.info(f"Node '{node_name}' executed - State changes: {execution['state_changes']}")
    
    def _compute_state_diff(self, before: dict, after: dict) -> dict:
        """คำนวณความแตกต่างของ state"""
        diff = {}
        for key in set(before.keys()) | set(after.keys()):
            before_val = before.get(key)
            after_val = after.get(key)
            if before_val != after_val:
                diff[key] = {
                    "before": str(before_val)[:100],  # Truncate for readability
                    "after": str(after_val)[:100]
                }
        return diff
    
    def get_execution_summary(self) -> dict:
        """สรุปการ execute ทั้งหมด"""
        if not self.execution_history:
            return {"total_nodes": 0, "total_time": 0}
        
        return {
            "total_nodes": len(self.execution_history),
            "nodes_executed": [e["node"] for e in self.execution_history],