เมื่อเดือนที่แล้วผมเจอปัญหาใหญ่กับระบบ AI Agent ที่พัฒนาให้ลูกค้าองค์กรชั้นนำแห่งหนึ่ง ค่าใช้จ่ายด้าน API พุ่งสูงถึง 280% จากเดิมที่คาดการณ์ไว้ สาเหตุหลักคือ Function Calling description ที่ไม่ได้รับการ optimize ทำให้ token consumption สูงเกินจำเป็นอย่างมาก บทความนี้จะแบ่งปันเทคนิคการวิเคราะห์และลดค่าใช้จ่าย token อย่างเป็นระบบ

ปัญหาจริงที่เจอ: Token Budget ระเบิด

ในโปรเจกต์หนึ่งผมสร้าง AI assistant ที่รองรับ 15 functions สำหรับระบบ CRM ซึ่งประกอบด้วย:

หลังจาก deploy ไป 2 สัปดาห์ พบว่า token usage สูงกว่า estimation เดิมถึง 3.5 เท่า สาเหตุหลักคือผมเขียน function descriptions ยาวเกินไปโดยไม่จำเป็น และใช้ JSON schema ที่ซับซ้อนเกินความต้องการจริง

Function Calling Token คิดอย่างไร

ก่อนจะ optimize ต้องเข้าใจก่อนว่า token ใน Function Calling ประกอบด้วยส่วนใดบ้าง:

1. Function Definitions (ส่วนนิยาม)

ส่วนนี้จะถูกส่งใน system prompt ทุกครั้งที่มี function call ซึ่งหมายความว่าถ้าคุณมี 10 functions แต่ละ function มี description 500 tokens คุณจะเสีย 5,000 tokens ในทุก request แม้ว่าจะใช้แค่ 1 function ก็ตาม

// โครงสร้าง function definition ที่ส่งไปใน request
{
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "search_products",
        "description": "ค้นหาสินค้าจากฐานข้อมูล...", // ← นี่คือส่วนที่กิน token มาก
        "parameters": {
          "type": "object",
          "properties": {
            "query": {
              "type": "string",
              "description": "คำค้นหาสินค้า..." // ← รวมทั้ง description ของแต่ละ parameter
            }
          },
          "required": ["query"]
        }
      }
    }
  ]
}

2. Function Call Response

เมื่อ model เรียกใช้ function ผลลัพธ์ที่ส่งกลับมาจะถูกนับรวมใน conversation history ดังนั้นถ้า function return ข้อมูลเยอะมาก ก็จะกิน token ใน messages ถัดไปด้วย

เทคนิคการลด Token ใน Function Definitions

1. ตั้งชื่อ function และ parameter กระชับ

ชื่อ function ควรสื่อความหมายแต่กระชับ ใช้ snake_case หรือ camelCase แล้วแต่ convention ของทีม แต่หลีกเลี่ยงการตั้งชื่อยาวเกินจำเป็น

# ❌ ไม่ดี - ชื่อยาวเกินไป และมี underscore ที่ไม่จำเป็น
{
  "name": "get_customer_order_history_with_date_filtering",
  "description": "ดึงข้อมูลประวัติการสั่งซื้อของลูกค้าพร้อมระบุช่วงวันที่..."
}

✅ ดี - กระชับ ชัดเจน

{ "name": "get_orders", "description": "ดึงประวัติคำสั่งซื้อของลูกค้ารายนั้น" }

2. ใช้ enum แทน string สำหรับค่าที่ตายตัว

ถ้า parameter มีค่าที่เป็นไปได้จำกัด ใช้ enum แทน string จะช่วยลด token ใน description ได้มาก

# ❌ ไม่ดี - ต้องอธิบายค่าที่เป็นไปได้ใน description
{
  "name": "set_order_status",
  "parameters": {
    "properties": {
      "status": {
        "type": "string",
        "description": "สถานะคำสั่งซื้อ ค่าที่เป็นไปได้คือ: pending (รอดำเนินการ), processing (กำลังดำเนินการ), shipped (จัดส่งแล้ว), delivered (ส่งถึงแล้ว), cancelled (ยกเลิก)"
      }
    }
  }
}

✅ ดี - ใช้ enum ชัดเจนกว่า ลด description ยาว

{ "name": "set_order_status", "parameters": { "properties": { "status": { "type": "string", "enum": ["pending", "processing", "shipped", "delivered", "cancelled"], "description": "สถานะคำสั่งซื้อ" } } } }

3. รวม parameters ที่ใช้พร้อมกันเสมอ

ถ้ามี parameters ที่มักจะใช้พร้อมกัน รวมเป็น object หรือใช้ default values จะช่วยลดการส่ง parameters ที่ไม่จำเป็นได้

# ❌ ไม่ดี - แยก parameters ที่มักใช้พร้อมกัน
{
  "name": "create_appointment",
  "parameters": {
    "properties": {
      "year": { "type": "integer" },
      "month": { "type": "integer" },
      "day": { "type": "integer" },
      "hour": { "type": "integer" },
      "minute": { "type": "integer" }
    },
    "required": ["year", "month", "day", "hour", "minute"]
  }
}

✅ ดี - รวมเป็น datetime format

{ "name": "create_appointment", "parameters": { "properties": { "datetime": { "type": "string", "format": "datetime", "description": "วันที่และเวลานัดหมาย (ISO 8601 format)" } }, "required": ["datetime"] } }

4. ใช้ $defs สำหรับ schema ที่ซับซ้อน

ถ้ามี schema ที่ใช้ซ้ำในหลาย functions ควร define ไว้ที่เดียวแล้ว reference อ้าง

{
  "tools": [
    {
      "type": "function", 
      "function": {
        "name": "search_customers",
        "parameters": {
          "type": "object",
          "properties": {
            "filter": {
              "$ref": "#/$defs/CustomerFilter"
            }
          }
        }
      }
    }
  ],
  "$defs": {
    "CustomerFilter": {
      "type": "object",
      "properties": {
        "status": { "type": "string" },
        "min_orders": { "type": "integer" },
        "registered_after": { "type": "string", "format": "date" }
      }
    }
  }
}

Workshop: วัด Token Consumption จริง

มาลองวัด token consumption จริงกันด้วย HolySheep AI ซึ่งมี pricing ที่คุ้มค่ามาก: GPT-4.1 $8/MTok, Claude Sonnet 4.5 $15/MTok, Gemini 2.5 Flash $2.50/MTok และ DeepSeek V3.2 เพียง $0.42/MTok พร้อม latency ต่ำกว่า 50ms รองรับ WeChat/Alipay สำหรับผู้ใช้ในประเทศจีน

import requests
import json

def count_tokens(text):
    """นับ token โดยประมาณ (แบบง่าย)"""
    # สำหรับภาษาไทย + อังกฤษ ใช้อัตราส่วน ~4 ตัวอักษรต่อ 1 token
    return len(text) // 4

def calculate_function_cost(functions, api_cost_per_mtok=8):
    """คำนวณค่าใช้จ่าย token ของ function definitions"""
    functions_json = json.dumps(functions, ensure_ascii=False)
    tokens = count_tokens(functions_json)
    cost = (tokens / 1_000_000) * api_cost_per_mtok
    
    print(f"จำนวน functions: {len(functions)}")
    print(f"Token ทั้งหมด: ~{tokens}")
    print(f"ค่าใช้จ่ายต่อ request (GPT-4.1): ${cost:.6f}")
    print(f"ค่าใช้จ่ายต่อ 1000 requests: ${cost * 1000:.4f}")
    
    return tokens, cost

Example: functions ที่ยังไม่ได้ optimize

unoptimized_functions = [ { "name": "search_products_from_catalog", "description": "ค้นหาสินค้าจากแค็ตตาล็อกสินค้าทั้งหมดที่มีอยู่ในระบบโดยสามารถกรองด้วยหมวดหมู่สินค้า ราคา สถานะสินค้าคงคลัง และคำค้นหาทั่วไปในชื่อสินค้าหรือรายละเอียดสินค้า", "parameters": { "type": "object", "properties": { "category": { "type": "string", "description": "หมวดหมู่สินค้าที่ต้องการค้นหา เช่น electronics, clothing, food เป็นต้น" }, "min_price": { "type": "number", "description": "ราคาขั้นต่ำของสินค้าที่ต้องการค้นหา (หน่วย: บาท)" }, "max_price": { "type": "number", "description": "ราคาสูงสุดของสินค้าที่ต้องการค้นหา (หน่วย: บาท)" }, "in_stock_only": { "type": "boolean", "description": "กรองเฉพาะสินค้าที่ยังมีในสต็อกหรือไม่ ค่า true หมายถึงแสดงเฉพาะสินค้าที่มีในสต็อก ค่า false หมายถึงแสดงทั้งหมด" }, "search_query": { "type": "string", "description": "คำค้นหาสำหรับค้นหาในชื่อสินค้าหรือรายละเอียดสินค้า สามารถใช้คำบางส่วนได้" } } } } ]

Example: functions ที่ optimize แล้ว

optimized_functions = [ { "name": "search_products", "description": "ค้นหาสินค้าในคลัง", "parameters": { "type": "object", "properties": { "category": { "type": "string" }, "min_price": { "type": "number" }, "max_price": { "type": "number" }, "in_stock": { "type": "boolean" }, "q": { "type": "string", "description": "คำค้นหา" } } } } ] print("=== ก่อน optimize ===") before = calculate_function_cost(unoptimized_functions) print("\n=== หลัง optimize ===") after = calculate_function_cost(optimized_functions) print(f"\nปร