ในฐานะ Data Engineer ที่ทำงานมากว่า 5 ปี ผมเคยเจอปัญหาเดิมซ้ำแล้วซ้ำเล่า — การเขียน ETL pipelines ที่ต้องรับมือกับข้อมูลที่มีโครงสร้างไม่ตรงตาม schema, การ transform ข้อมูลที่ซับซ้อน, และการ validate ผลลัพธ์ จนกระทั่งผมเริ่มใช้ LLM เข้ามาช่วยในปี 2024 และทุกอย่างเปลี่ยนไป วันนี้ผมจะมาแชร์วิธีการที่ใช้งานได้จริงใน production

ทำไมต้องใช้ LLM กับ ETL?

ข้อดีหลักๆ ที่ผมพบเจอจากการใช้งานจริง:

เปรียบเทียบต้นทุน LLM APIs ปี 2026

ก่อนจะเริ่ม มาดูต้นทุนที่ตรวจสอบแล้วสำหรับปี 2026 กัน:

ModelOutput Price ($/MTok)10M Tokens/เดือน
GPT-4.1$8.00$80.00
Claude Sonnet 4.5$15.00$150.00
Gemini 2.5 Flash$2.50$25.00
DeepSeek V3.2$0.42$4.20

สำหรับ ETL pipelines ที่ต้อง process ข้อมูลจำนวนมาก DeepSeek V3.2 ที่ $0.42/MTok เป็นตัวเลือกที่คุ้มค่าที่สุด โดยเฉพาะเมื่อใช้กับ HolySheep AI ที่อัตราแลกเปลี่ยน ¥1=$1 ประหยัดได้ถึง 85%+ พร้อม latency ต่ำกว่า 50ms

Architecture Overview

ระบบ ETL ที่ใช้ LLM ของผมประกอบด้วย 4 ส่วนหลัก:

  1. Ingestion Layer — ดึงข้อมูลจากแหล่งต่างๆ (SQL, NoSQL, APIs, Files)
  2. LLM Processing Layer — ใช้ LLM วิเคราะห์และ transform ข้อมูล
  3. Validation Layer — ตรวจสอบคุณภาพผลลัพธ์
  4. Output Layer — เขียนข้อมูลไปยัง destination

ตัวอย่างโค้ด: ETL Pipeline พื้นฐาน

1. Setup และ LLM Client

import requests
import json
from typing import Dict, List, Any, Optional
from dataclasses import dataclass
from enum import Enum

class LLMProvider(Enum):
    DEEPSEEK = "deepseek"
    GPT4 = "gpt-4.1"
    CLAUDE = "claude-sonnet-4.5"
    GEMINI = "gemini-2.5-flash"

@dataclass
class LLMConfig:
    model: LLMProvider
    api_key: str
    base_url: str = "https://api.holysheep.ai/v1"  # HolySheep Unified API
    temperature: float = 0.1
    max_tokens: int = 2048

class LLMETLClient:
    """Client สำหรับใช้ LLM ในการทำ ETL"""
    
    def __init__(self, config: LLMConfig):
        self.config = config
        self.session = requests.Session()
        self.session.headers.update({
            "Authorization": f"Bearer {config.api_key}",
            "Content-Type": "application/json"
        })
    
    def _get_endpoint(self) -> str:
        """Map model ไปยัง endpoint ที่ถูกต้อง"""
        endpoints = {
            LLMProvider.DEEPSEEK: "/chat/completions",
            LLMProvider.GPT4: "/chat/completions", 
            LLMProvider.CLAUDE: "/chat/completions",
            LLMProvider.GEMINI: "/chat/completions"
        }
        return f"{self.config.base_url}{endpoints[self.config.model]}"
    
    def call_llm(self, system_prompt: str, user_message: str) -> str:
        """เรียก LLM ผ่าน HolySheep API"""
        payload = {
            "model": self.config.model.value,
            "messages": [
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": user_message}
            ],
            "temperature": self.config.temperature,
            "max_tokens": self.config.max_tokens
        }
        
        response = self.session.post(self._get_endpoint(), json=payload)
        response.raise_for_status()
        
        result = response.json()
        return result["choices"][0]["message"]["content"]

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

config = LLMConfig( model=LLMProvider.DEEPSEEK, api_key="YOUR_HOLYSHEEP_API_KEY" # ใส่ API key จาก HolySheep ) client = LLMETLClient(config) print("✅ LLM ETL Client initialized successfully!")

2. Schema Inference Pipeline

import pandas as pd
from typing import Dict, Any
import json

class SchemaInferencePipeline:
    """Pipeline สำหรับ inference schema จากข้อมูลดิบ"""
    
    SYSTEM_PROMPT = """คุณเป็น Data Engineer ผู้เชี่ยวชาญ วิเคราะห์ข้อมูล JSON ที่ให้มา 
และสร้าง JSON Schema ที่สมบูรณ์ ระบุ:
- data types ที่ถูกต้อง (string, number, integer, boolean, date, datetime)
- required fields
- format patterns สำหรับ dates/times
- enum values ถ้ามี
- descriptions สำหรับแต่ละ field

ตอบเฉพาะ JSON Schema เท่านั้น ไม่ต้องอธิบาย"""

    def __init__(self, llm_client: LLMETLClient):
        self.llm = llm_client
    
    def infer_schema(self, sample_data: List[Dict], 
                     target_schema: Optional[Dict] = None) -> Dict[str, Any]:
        """Infer schema จาก sample data"""
        
        # สุ่ม sample ถ้าข้อมูลเยอะเกินไป
        sample = sample_data[:50] if len(sample_data) > 50 else sample_data
        
        user_message = f"""ข้อมูลตัวอย่าง (จำนวน {len(sample)} records):
{json.dumps(sample, ensure_ascii=False, indent=2)}

{target_schema if target_schema else 'ไม่มี target schema กำหนดไว้'}"""
        
        result = self.llm.call_llm(self.SYSTEM_PROMPT, user_message)
        
        # Parse JSON result
        try:
            return json.loads(result)
        except json.JSONDecodeError:
            # ถ้า LLM ตอบมาไม่เป็น JSON ล้วงเอา JSON ออกมา
            import re
            json_match = re.search(r'\{.*\}', result, re.DOTALL)
            if json_match:
                return json.loads(json_match.group())
            raise ValueError(f"Cannot parse LLM response: {result}")

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

sample_data = [ {"name": "สมชาย", "age": 30, "join_date": "2024-01-15"}, {"name": "สมหญิง", "age": 25, "join_date": "2024-02-20"}, {"name": "วิชัย", "age": 35, "join_date": "2024-03-10"} ] schema_pipeline = SchemaInferencePipeline(client) inferred_schema = schema_pipeline.infer_schema(sample_data) print(f"✅ Inferred Schema: {json.dumps(inferred_schema, indent=2, ensure_ascii=False)}")

3. Data Transformation Pipeline

from typing import Dict, Any, List, Callable
from dataclasses import dataclass
import pandas as pd

@dataclass
class TransformRule:
    source_field: str
    target_field: str
    transform_type: str  # 'direct', 'derived', 'aggregate', 'custom'
    transform_fn: Optional[Callable] = None

class DataTransformationPipeline:
    """Pipeline สำหรับ transform ข้อมูลด้วย LLM"""
    
    SYSTEM_PROMPT = """คุณเป็น Data Transformation Engine วิเคราะห์ transformation rules 
ที่ต้องการ และ generate Python code ที่รันได้

Rules:
1. รองรับ field mapping ตรง (direct copy)
2. รองรับ derived fields (computed from existing fields)
3. รองรับ conditional logic
4. รองรับ string/number/date manipulations
5. รองรับ data type conversions

ตอบเป็น Python function ที่รับ dict และ return dict เท่านั้น
ชื่อ function: transform_record"""

    def __init__(self, llm_client: LLMETLClient):
        self.llm = llm_client
        self.transform_fn: Optional[Callable] = None
    
    def learn_transform_rules(self, 
                               input_samples: List[Dict], 
                               output_samples: List[Dict]) -> None:
        """เรียนรู้ transformation rules จาก input-output pairs"""
        
        user_message = f"""Input samples ({len(input_samples)} records):
{json.dumps(input_samples[:10], ensure_ascii=False, indent=2)}

Expected Output samples ({len(output_samples)} records):
{json.dumps(output_samples[:10], ensure_ascii=False, indent=2)}"""
        
        code = self.llm.call_llm(self.SYSTEM_PROMPT, user_message)
        
        # Execute generated code
        local_vars = {}
        exec(code, {}, local_vars)
        self.transform_fn = local_vars.get('transform_record')
        
        if not self.transform_fn:
            raise ValueError("Generated code does not contain transform_record function")
    
    def transform(self, records: List[Dict]) -> List[Dict]:
        """Apply transformation ไปยัง records"""
        if not self.transform_fn:
            raise ValueError("Must call learn_transform_rules first")
        
        return [self.transform_fn(record) for record in records]

ตัวอย่าง: เรียนรู้การ normalize ชื่อ

input_samples = [ {"customer_name": "นาย สมชาย ใจดี", "amount": "1,500.00", "date": "15/01/2024"}, {"customer_name": "Mrs. Jane Smith", "amount": "$2,500.00", "date": "2024-02-20"} ] output_samples = [ {"name": "สมชาย ใจดี", "amount": 1500.00, "date": "2024-01-15", "prefix": "นาย"}, {"name": "Jane Smith", "amount": 2500.00, "date": "2024-02-20", "prefix": "Mrs."} ] transform_pipeline = DataTransformationPipeline(client) transform_pipeline.learn_transform_rules(input_samples, output_samples) test_record = {"customer_name": "ดร. วิชัย มหาชน", "amount": "3,000.50", "date": "31/03/2024"} result = transform_pipeline.transform([test_record])[0] print(f"✅ Transformed: {json.dumps(result, ensure_ascii=False, indent=2)}")

4. Data Validation Pipeline

from typing import Dict, List, Any, Tuple
from dataclasses import field, dataclass
from datetime import datetime
import jsonschema

@dataclass
class ValidationResult:
    is_valid: bool
    errors: List[str] = field(default_factory=list)
    warnings: List[str] = field(default_factory=list)
    suggestions: List[str] = field(default_factory=list)

class DataValidationPipeline:
    """Pipeline สำหรับ validate คุณภาพข้อมูลด้วย LLM"""
    
    def __init__(self, llm_client: LLMETLClient):
        self.llm = llm_client
    
    def validate_with_schema(self, record: Dict, schema: Dict) -> ValidationResult:
        """Validate ด้วย JSON Schema"""
        errors = []
        try:
            jsonschema.validate(instance=record, schema=schema)
            return ValidationResult(is_valid=True)
        except jsonschema.ValidationError as e:
            errors.append(f"Schema validation failed: {e.message}")
        except jsonschema.SchemaError as e:
            errors.append(f"Invalid schema: {e.message}")
        return ValidationResult(is_valid=False, errors=errors)
    
    def validate_data_quality(self, records: List[Dict], 
                              context: str) -> Tuple[List[Dict], List[Dict]]:
        """Validate data quality ด้วย LLM"""
        
        SYSTEM_PROMPT = """คุณเป็น Data Quality Analyst ตรวจสอบ records และจำแนกว่า:
- valid: ข้อมูลถูกต้อง พร้อมใช้งาน
- invalid: ข้อมูลมีปัญหาที่ต้องแก้ไข

ปัญหาที่ควรตรวจสอบ:
1. Missing required fields
2. Invalid data types
3. Outlier values
4. Inconsistent formats
5. Business logic violations
6. Duplicates
7. Sanity check failures

ตอบเป็น JSON ดังนี้:
{{"valid_records": [indices of valid records], "invalid_records": [{{"index": N, "reason": "..."}}]}}"""

        user_message = f"""Context: {context}

Records to validate ({len(records)} records):
{json.dumps(records, ensure_ascii=False, indent=2)[:4000]}"""  # Limit size
        
        try:
            result_str = self.llm.call_llm(SYSTEM_PROMPT, user_message)
            result = json.loads(result_str)
            
            valid_indices = set(result.get("valid_records", []))
            invalid_info = {item["index"]: item["reason"] for item in result.get("invalid_records", [])}
            
            valid_records = [records[i] for i in range(len(records)) if i in valid_indices]
            invalid_records = [
                {**records[i], "_invalid_reason": invalid_info.get(i, "Unknown")}
                for i in range(len(records)) if i in invalid_info
            ]
            
            return valid_records, invalid_records
            
        except Exception as e:
            print(f"⚠️ LLM validation failed: {e}, returning all as valid")
            return records, []

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

validation_pipeline = DataValidationPipeline(client) test_records = [ {"id": 1, "name": "สมชาย", "email": "[email protected]", "age": 30}, {"id": 2, "name": "สมหญิง", "email": "invalid-email", "age": 25}, {"id": 3, "name": "", "email": "[email protected]", "age": 150} # Empty name + outlier age ] valid, invalid = validation_pipeline.validate_data_quality(test_records, context="Customer database for e-commerce platform") print(f"✅ Valid: {len(valid)}, Invalid: {len(invalid)}")

ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข

1. ข้อผิดพลาด: "Connection timeout หรือ API rate limit"

# ❌ วิธีที่ผิด: เรียก API ตรงๆ โดยไม่มี retry logic
response = requests.post(url, json=payload)  # จะ fail ถ้า API ตอบช้า

✅ วิธีที่ถูก: ใช้ retry พร้อม exponential backoff

from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry import time