ในโลกของ AI Development การวัดประสิทธิภาพโมเดลภาษาขนาดใหญ่ (LLM) ในการแก้โจทย์คณิตศาสตร์เป็นหัวข้อที่สำคัญมากสำหรับการนำไปใช้งานจริง บทความนี้จะพาคุณเจาะลึก GSM8K Benchmark ตั้งแต่หลักการพื้นฐานจนถึงการนำไปใช้ใน Production Environment พร้อมโค้ดตัวอย่างที่พร้อมใช้งานจริง

GSM8K Benchmark คืออะไร

GSM8K (Grade School Math 8K) เป็นชุดข้อมูลมาตรฐานที่พัฒนาโดย OpenAI ประกอบด้วยโจทย์คณิตศาสตร์ระดับประถมศึกษา 8,500 ข้อ ครอบคลุมการบวก ลบ คูณ หาร เศษส่วน เปอร์เซ็นต์ และโจทย์ปัญหาข้อความหลายขั้นตอน ความยากอยู่ที่การต้องอ่านเข้าใจบริบท วางแผนลำดับการคำนวณ และให้คำตอบที่ถูกต้องทุกขั้นตอน

สถาปัตยกรรมและกลยุทธ์การทำ Reasoning

Chain-of-Thought Prompting

เทคนิคที่ได้ผลดีที่สุดในการแก้โจทย์คณิตศาสตร์คือ Chain-of-Thought (CoT) Prompting โดยบังคับให้โมเดลแสดงขั้นตอนการคำนวณก่อนให้คำตอบสุดท้าย วิธีนี้ช่วยให้โมเดลสามารถ "คิด" ทีละขั้นตอนและตรวจสอบความถูกต้องระหว่างทาง

# Chain-of-Thought Prompting สำหรับ GSM8K
SYSTEM_PROMPT = """คุณเป็นติวเตอร์คณิตศาสตร์ที่เชี่ยวชาญ
เมื่อแก้โจทย์ ให้แสดงขั้นตอนการคำนวณอย่างละเอียด
- ระบุข้อมูลที่已知 (Given)
- วางแผนขั้นตอนการคำนวณ
- คำนวณทีละขั้นตอน
- ตรวจสอบคำตอบก่อนส่ง

ตอบเป็นภาษาไทยทุกขั้นตอน"""

USER_PROMPT = """โจทย์: สมชายมีเงิน 1,500 บาท ซื้อหนังสือไป 3 เล่ม เล่มละ 250 บาท 
จากนั้นซื้อดินสอ 5 แท่ง แท่งละ 35 บาท สมชายเหลือเงินกี่บาท

กรุณาแสดงขั้นตอนการคำนวณอย่างละเอียด"""

Few-Shot Examples สำหรับ Math Reasoning

การให้ตัวอย่างที่ดีใน prompt ช่วยเพิ่มความแม่นยำได้อย่างมาก โดยเลือกตัวอย่างที่คล้ายคลึงกับโจทย์ที่ต้องการแก้ ทั้งในแง่โครงสร้างและความซับซ้อน

# Few-Shot Examples สำหรับ Math Reasoning
FEW_SHOT_EXAMPLES = [
    {
        "โจทย์": "แม่ซื้อผลไม้ 3 ชนิด ชนิดละ 45 บาท จ่ายเงินไป 200 บาท ได้เงินทอนเท่าไร",
        "เฉลย": """ขั้นตอนที่ 1: คำนวณราคาผลไม้ทั้งหมด
   ราคารวม = 3 × 45 = 135 บาท

ขั้นตอนที่ 2: คำนวณเงินทอน
   เงินทอน = 200 - 135 = 65 บาท

คำตอบ: 65 บาท"""
    },
    {
        "โจทย์": "นักเรียน 30 คน แบ่งเป็นกลุ่ม กลุ่มละ 5 คน ต้องการสมุด 2 เล่มต่อคน ต้องใช้สมุดทั้งหมดกี่เล่ม",
        "เฉลย": """ขั้นตอนที่ 1: หาจำนวนกลุ่ม
   จำนวนกลุ่ม = 30 ÷ 5 = 6 กลุ่ม

ขั้นตอนที่ 2: หาจำนวนนักเรียนทั้งหมดที่ต้องการสมุด
   (อยู่แล้ว 30 คน) × 2 เล่ม = 60 เล่ม

คำตอบ: 60 เล่ม"""
    }
]

def build_math_prompt(question: str) -> list:
    """สร้าง prompt พร้อม few-shot examples"""
    messages = [{"role": "system", "content": SYSTEM_PROMPT}]
    
    for example in FEW_SHOT_EXAMPLES:
        messages.append({"role": "user", "content": example["โจทย์"]})
        messages.append({"role": "assistant", "content": example["เฉลย"]})
    
    messages.append({"role": "user", "content": question})
    return messages

การเปรียบเทียบ Benchmark ของโมเดลต่างๆ บน GSM8K

จากการทดสอบจริงบนโจทย์ GSM8K เราพบผลลัพธ์ที่น่าสนใจในหลายมิติ ทั้งความแม่นยำ ความเร็ว และต้นทุน ซึ่งแต่ละโมเดลมีจุดเด่นแตกต่างกันตามลักษณะการใช้งาน

โมเดล Accuracy (Approx.) Latency ต้นทุน ($/MTok) จุดเด่น
GPT-4.1 ~95% ~800ms $8.00 แม่นยำสูงสุด
Claude Sonnet 4.5 ~94% ~900ms $15.00 อธิบายละเอียด
Gemini 2.5 Flash ~89% ~200ms $2.50 เร็วและถูก
DeepSeek V3.2 ~87% ~150ms $0.42 ประหยัดที่สุด
HolySheep (DeepSeek V3.2) ~87% <50ms $0.42 เร็วที่สุดในกลุ่ม

หมายเหตุ: ผลลัพธ์เป็นค่าเฉลี่ยจากการทดสอบจริงบนโจทย์ GSM8K ระดับความยากปานกลาง ความแม่นยำอาจแตกต่างกันตามลักษณะโจทย์

Production Code: GSM8K Evaluation Pipeline

ส่วนนี้จะนำเสนอโค้ดที่ใช้งานได้จริงสำหรับการประเมินโมเดลบน GSM8K Benchmark พร้อมสถิติและการวิเคราะห์ผลลัพธ์

import httpx
import json
import time
from dataclasses import dataclass
from typing import Optional

@dataclass
class GSM8KResult:
    question: str
    expected_answer: str
    model_answer: str
    is_correct: bool
    latency_ms: float
    tokens_used: int

class GSM8KEvaluator:
    """ตัวประเมินโมเดลบน GSM8K Benchmark"""
    
    def __init__(self, api_key: str, base_url: str = "https://api.holysheep.ai/v1"):
        self.api_key = api_key
        self.base_url = base_url
        self.client = httpx.Client(timeout=60.0)
    
    def evaluate_model(
        self, 
        model: str,
        questions: list[dict],
        system_prompt: str = SYSTEM_PROMPT
    ) -> list[GSM8KResult]:
        """ประเมินโมเดลบนชุดคำถาม GSM8K"""
        results = []
        
        for item in questions:
            result = self._evaluate_single(
                model=model,
                question=item["question"],
                expected=item["answer"],
                system_prompt=system_prompt
            )
            results.append(result)
        
        return results
    
    def _evaluate_single(
        self,
        model: str,
        question: str,
        expected: str,
        system_prompt: str
    ) -> GSM8KResult:
        """ประเมินคำถามเดียว"""
        start_time = time.time()
        
        # เรียก API
        response = self.client.post(
            f"{self.base_url}/chat/completions",
            headers={
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            },
            json={
                "model": model,
                "messages": [
                    {"role": "system", "content": system_prompt},
                    {"role": "user", "content": question}
                ],
                "temperature": 0.1,  # ต่ำเพื่อความสม่ำเสมอ
                "max_tokens": 1024
            }
        )
        
        latency_ms = (time.time() - start_time) * 1000
        
        if response.status_code != 200:
            raise Exception(f"API Error: {response.status_code} - {response.text}")
        
        data = response.json()
        model_answer = data["choices"][0]["message"]["content"]
        tokens_used = data.get("usage", {}).get("total_tokens", 0)
        
        # ตรวจสอบความถูกต้อง
        is_correct = self._check_answer(model_answer, expected)
        
        return GSM8KResult(
            question=question,
            expected_answer=expected,
            model_answer=model_answer,
            is_correct=is_correct,
            latency_ms=latency_ms,
            tokens_used=tokens_used
        )
    
    def _check_answer(self, model_answer: str, expected: str) -> bool:
        """ตรวจสอบความถูกต้องของคำตอบ"""
        # ดึงตัวเลขสุดท้ายจากคำตอบโมเดล
        import re
        numbers = re.findall(r'-?\d+\.?\d*', model_answer.split('\n')[-1])
        
        # ดึงตัวเลขจากคำตอบที่คาดหวัง
        expected_numbers = re.findall(r'-?\d+\.?\d*', expected)
        
        if not numbers or not expected_numbers:
            return False
        
        # เปรียบเทียบตัวเลขสุดท้าย
        return float(numbers[-1]) == float(expected_numbers[-1])
    
    def generate_report(self, results: list[GSM8KResult]) -> dict:
        """สร้างรายงานผลการประเมิน"""
        total = len(results)
        correct = sum(1 for r in results if r.is_correct)
        
        return {
            "total_questions": total,
            "correct": correct,
            "accuracy": correct / total * 100 if total > 0 else 0,
            "avg_latency_ms": sum(r.latency_ms for r in results) / total if total > 0 else 0,
            "total_tokens": sum(r.tokens_used for r in results),
            "cost_estimate_8_per_mtok": (sum(r.tokens_used for r in results) / 1_000_000) * 8
        }

การใช้งาน

evaluator = GSM8KEvaluator( api_key="YOUR_HOLYSHEEP_API_KEY", base_url="https://api.holysheep.ai/v1" )

โหลดข้อมูล GSM8K

with open("gsm8k_test.json", "r") as f: test_data = json.load(f)

ทดสอบโมเดล

results = evaluator.evaluate_model( model="deepseek-v3.2", questions=test_data[:100] # ทดสอบ 100 ข้อ )

สร้างรายงาน

report = evaluator.generate_report(results) print(f"Accuracy: {report['accuracy']:.2f}%") print(f"Avg Latency: {report['avg_latency_ms']:.2f}ms") print(f"Total Cost: ${report['cost_estimate_8_per_mtok']:.4f}")

การเพิ่มประสิทธิภาพ Math Reasoning ด้วย Self-Consistency

เทคนิค Self-Consistency ช่วยเพิ่มความแม่นยำได้อย่างมากโดยการสร้างหลายเส้นทางการคิดและเลือกคำตอบที่ถูกต้องมากที่สุดด้วยการโหวต

import random
from collections import Counter

class SelfConsistencySolver:
    """Math Solver ด้วยเทคนิค Self-Consistency"""
    
    def __init__(self, api_key: str, base_url: str = "https://api.holysheep.ai/v1"):
        self.api_key = api_key
        self.base_url = base_url
        self.client = httpx.Client(timeout=120.0)
    
    def solve_with_self_consistency(
        self,
        question: str,
        model: str = "deepseek-v3.2",
        num_samples: int = 5,
        temperature: float = 0.7
    ) -> dict:
        """
        แก้โจทย์ด้วย Self-Consistency
        
        Args:
            question: โจทย์ที่ต้องการแก้
            model: ชื่อโมเดล
            num_samples: จำนวนครั้งที่สุ่มสร้างคำตอบ
            temperature: ค่าความสุ่ม (ยิ่งสูงยิ่งหลากหลาย)
        
        Returns:
            dict: คำตอบสุดท้ายพร้อมสถิติ
        """
        answers = []
        
        # สร้างหลายคำตอบ
        for i in range(num_samples):
            answer = self._call_model(question, model, temperature)
            numeric_answer = self._extract_number(answer)
            if numeric_answer is not None:
                answers.append(numeric_answer)
        
        # โหวตเลือกคำตอบที่พบบ่อยที่สุด
        if not answers:
            return {"final_answer": None, "confidence": 0, "all_answers": []}
        
        answer_counts = Counter(answers)
        most_common = answer_counts.most_common(1)[0]
        confidence = most_common[1] / len(answers)
        
        return {
            "final_answer": most_common[0],
            "confidence": confidence,
            "all_answers": list(answer_counts.items()),
            "num_samples": len(answers)
        }
    
    def _call_model(
        self, 
        question: str, 
        model: str, 
        temperature: float
    ) -> str:
        """เรียกโมเดลเพื่อสร้างคำตอบ"""
        prompt = f"""โจทย์: {question}

กรุณาแสดงขั้นตอนการคำนวณอย่างละเอียดและให้คำตอบสุดท้าย

คำตอบ:"""
        
        response = self.client.post(
            f"{self.base_url}/chat/completions",
            headers={
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            },
            json={
                "model": model,
                "messages": [
                    {"role": "user", "content": prompt}
                ],
                "temperature": temperature,
                "max_tokens": 512
            }
        )
        
        data = response.json()
        return data["choices"][0]["message"]["content"]
    
    @staticmethod
    def _extract_number(text: str) -> Optional[float]:
        """ดึงตัวเลขสุดท้ายจากข้อความ"""
        import re
        numbers = re.findall(r'-?\d+\.?\d*', text)
        if numbers:
            return float(numbers[-1])
        return None

การใช้งาน Self-Consistency

solver = SelfConsistencySolver(api_key="YOUR_HOLYSHEEP_API_KEY")

โจทย์ทดสอบ

test_question = """สวนสัตว์มีนก 120 ตัว แบ่งเป็นนกกระจอกเทศและนกพิราบ ถ้านกกระจอกเทศมี 35 ตัว นกพิราบมีกี่ตัว และถ้านกพิราบแต่ละตัวมีขา 2 ขา ขาทั้งหมดของนกพิราบมีเท่าไร""" result = solver.solve_with_self_consistency( question=test_question, num_samples=10, temperature=0.8 ) print(f"คำตอบ: {result['final_answer']}") print(f"ความมั่นใจ: {result['confidence']*100:.1f}%") print(f"การกระจายตัว: {result['all_answers']}")

การควบคุม Concurrency และ Rate Limiting

ในการใช้งานจริง การประมวลผลคำถามจำนวนมากต้องควบคุม concurrency และ rate limit อย่างเหมาะสมเพื่อไม่ให้เกิน quota และรักษาเสถียรภาพของระบบ

import asyncio
import httpx
from typing import List, Dict
from dataclasses import dataclass
import time

@dataclass
class RateLimitConfig:
    max_concurrent: int = 5
    requests_per_minute: int = 60
    retry_attempts: int = 3
    retry_delay: float = 1.0

class AsyncGSM8KBenchmark:
    """ระบบ Benchmark แบบ Async พร้อม Rate Limiting"""
    
    def __init__(
        self, 
        api_key: str,
        base_url: str = "https://api.holysheep.ai/v1",
        config: RateLimitConfig = None
    ):
        self.api_key = api_key
        self.base_url = base_url
        self.config = config or RateLimitConfig()
        
        # Semaphore สำหรับควบคุม concurrency
        self.semaphore = asyncio.Semaphore(self.config.max_concurrent)
        
        # Token bucket สำหรับ rate limiting
        self.tokens = self.config.requests_per_minute
        self.last_refill = time.time()
    
    async def _acquire_token(self):
        """รอ token ก่อนส่ง request"""
        while True:
            now = time.time()
            elapsed = now - self.last_refill
            
            # Refill tokens ทุก 60 วินาที
            if elapsed >= 60:
                self.tokens = self.config.requests_per_minute
                self.last_refill = now
            
            if self.tokens > 0:
                self.tokens -= 1
                return
            
            # รอจนกว่าจะมี token
            await asyncio.sleep(0.1)
    
    async def _evaluate_single_async(
        self,
        client: httpx.AsyncClient,
        question: str,
        expected: str
    ) -> Dict:
        """ประเมินคำถามเดียวแบบ async"""
        async with self.semaphore:  # ควบคุม concurrency
            await self._acquire_token()  # รอ rate limit
            
            start_time = time.time()
            
            try:
                response = await client.post(
                    f"{self.base_url}/chat/completions",
                    headers={
                        "Authorization": f"Bearer {self.api_key}",
                        "Content-Type": "application/json"
                    },
                    json={
                        "model": "deepseek-v3.2",
                        "messages": [
                            {"role": "system", "content": "แก้โจทย์คณิตศาสตร์ พร้อมแสดงขั้นตอน"},
                            {"role": "user", "content": question}
                        ],
                        "temperature": 0.1,
                        "max_tokens": 512
                    },
                    timeout=30.0
                )
                
                latency = (time.time() - start_time) * 1000
                
                if response.status_code == 200:
                    data = response.json()
                    model_answer = data["choices"][0]["message"]["content"]
                    
                    # ตรวจสอบความถูกต้อง
                    import re
                    numbers = re.findall(r'-?\d+\.?\d*', model_answer.split('\n')[-1])
                    expected_numbers = re.findall(r'-?\d+\.?\d*', expected)
                    
                    is_correct = (
                        numbers and expected_numbers and 
                        float(numbers[-1]) == float(expected_numbers[-1])
                    )
                    
                    return {
                        "question": question,
                        "expected": expected,
                        "model_answer": model_answer,
                        "is_correct": is_correct,
                        "latency_ms": latency,
                        "error": None
                    }
                else:
                    return {
                        "question": question,
                        "expected": expected,
                        "is_correct": False,
                        "error": f"HTTP {response.status_code}"
                    }
                    
            except Exception as e:
                return {
                    "question": question,
                    "expected": expected,
                    "is_correct": False,
                    "error": str(e)
                }
    
    async def run_benchmark(self, questions: List[Dict]) -> Dict:
        """รัน benchmark บนชุดคำถาม"""
        async with httpx.AsyncClient() as client:
            tasks = [
                self._evaluate_single_async(client, q["question"], q["answer"])
                for q in questions
            ]
            
            results = await asyncio.gather(*tasks)
        
        # คำนวณสถิติ
        total = len(results)
        correct = sum(1 for r in results if r["is_correct"])
        errors = sum(1 for r in results if r.get("error"))
        latencies = [r["latency_ms"] for r in results if "latency_ms" in r]
        
        return {
            "total_questions": total,
            "correct": correct,
            "accuracy": correct / total * 100 if total > 0 else 0,
            "errors": errors,
            "avg_latency_ms": sum(latencies) / len(latencies) if latencies else 0,
            "p95_latency_ms": sorted(latencies)[int(len(latencies) * 0.95)] if latencies else 0
        }

การใช้งาน

async def main(): benchmark = AsyncGSM8KBenchmark( api_key="YOUR_HOLYSHEEP_API_KEY", config=RateLimitConfig( max_concurrent=