JSON ของ AI Agent มีชื่อซ้ำ: ตรวจ Duplicate Keys ก่อนเชื่อค่า

วิศวกรหยุดคู่ชื่อ limit ค่า 5 และ 500 ที่ด่านตรวจ JSON ก่อน Agent ใช้ข้อมูล
วิศวกรหยุดคู่ชื่อ limit ค่า 5 และ 500 ที่ด่านตรวจ JSON ก่อน Agent ใช้ข้อมูล
ฉากจำลองการปฏิเสธชื่อซ้ำก่อนตรวจ schema และสิทธิ์ · คลิกภาพเพื่ออ่านขนาดเต็ม

คำตอบสั้น

ปฏิเสธ JSON object ที่มีชื่อสมาชิกซ้ำระหว่าง parse และก่อน schema validation หรือเลือก Tool การเก็บค่าตัวแรกหรือตัวท้ายทำให้ parser, validator และ dispatcher อาจเห็นคนละความหมาย นโยบายที่ชัดคือชื่อที่ถอด JSON escape แล้วต้องไม่ซ้ำใน object เดียวกัน; ถ้าซ้ำให้หยุดทั้ง request

ใน Python ใช้ json.loads กับ object_pairs_hook เพื่อรับคู่ชื่อและค่าก่อนสร้าง dict ปกติ hook นี้ครอบคลุม object ที่ซ้อนและ object ใน array หลัง parse ผ่านจึงตรวจ schema, สิทธิ์ และค่อย dispatch ตามลำดับ ตัวอย่างไม่เรียก Tool จริงและทดสอบยัง NOT RUN

  • ลำดับ: จำกัด input → parse/duplicate gate → schema → authorization → dispatch
  • Parse ผ่านไม่เท่ากับผ่าน schema หรือได้รับอนุญาต
  • ชื่อที่เท่ากันหลังถอด escape ซ้ำ; case ต่างกันไม่ซ้ำ

ผลลัพธ์การเรียนรู้

ผู้อ่านจะวาง duplicate gate ก่อน schema และ tool dispatch, อธิบายได้ว่าทำไม JSON ที่ parse ได้ยังคลุมเครือ และเขียนตัวตรวจด้วย Python standard library โดยไม่ใช้ regex หรือ dict ที่สูญเสีย key ซ้ำแล้ว

สำหรับ Agent ให้ถือ argument จาก LLM, webhook หรือ MCP เป็น input ที่ยังไม่เชื่อถือ แม้มีรูปแบบ JSON หรือ structured output ก็ตาม เป้าหมายคือหยุดความกำกวมก่อนข้อมูลกำหนด action

  • วาง gate ก่อน schema และ Tool
  • แยก parse, schema, permission และ resource policy

ปัญหา: หนึ่งข้อความ แต่อาจมีสองความหมาย

ตัวอย่าง {"query":"คู่มือสาธารณะ","query":"แฟ้มเงินเดือน"} มีชื่อ query ซ้ำ ผู้รับหนึ่งอาจเก็บค่าแรก อีกตัวเก็บค่าหลัง หรือปฏิเสธ หาก validator เห็นคำค้นสาธารณะแต่ dispatcher ใช้ค่าหลัง ระบบอาจทำงานกับค่าที่ไม่เคยผ่านการตรวจ ทั้งนี้ผลจริงขึ้นกับ parser และ middleware; ประเด็นคือแต่ละชั้นต้องตีความตรงกัน

RFC 8259 ระบุว่า object names SHOULD ไม่ซ้ำ และพฤติกรรมเมื่อซ้ำคาดเดาไม่ได้ SHOULD เป็นคำแนะนำ ไม่ได้บังคับ decoder ทุกตัวให้ปฏิเสธ อีกทั้งการเทียบชื่อทำหลังถอด escape ดังนั้นการค้นข้อความดิบอาจพลาด action กับ \u0061ction RFC 8259 §4 และ §8.3

เมื่อแปลงเป็น dict key ซ้ำถูกยุบไปแล้ว จึงตรวจย้อนหลังไม่ได้ ต้องตรวจตอน parser ยังส่งคู่สมาชิกครบก่อนประกอบ object

การปฏิเสธตั้งแต่ขอบเขตแรกยังทำให้ระบบสังเกตการณ์ง่ายขึ้น: ทุก consumer รับเฉพาะ object ที่มีความหมายเดียว ไม่ต้องบันทึกว่าชั้นใดเลือกค่าแรกหรือค่าหลัง และไม่ต้องพยายาม reconcile ผลตรวจที่ขัดกัน อย่างไรก็ตาม log ควรนับเพียงเหตุการณ์ duplicate โดยไม่เก็บเนื้อหา; การมี metric ไม่ใช่เหตุผลให้เก็บ request body หากต้องรองรับ client หลายรุ่น ให้แยกการแจ้งเปลี่ยนสัญญาออกจากการอนุญาตข้อมูลกำกวม และกำหนดวันยุติพฤติกรรม legacy อย่างชัดเจน

แยกด่าน 4 ชั้น: parse, schema, authorization, dispatch

แยกสี่ด่าน: parse ตรวจ JSON และ duplicate; schema ตรวจ field, type และขนาด; authorization ตรวจว่าผู้ใช้ทำ action กับ resource ได้หรือไม่; dispatch ส่งคำขอที่อนุมัติแล้วไป adapter การผ่านด่านหนึ่งไม่รับรองด่านถัดไป

Schema อาจกำหนด action และ query แต่ไม่ได้ยืนยันตัวตนหรือสิทธิ์ อย่าเชื่อ field เช่น role หรือ approved ที่ผู้ส่งใส่มาเอง argument จาก model และ MCP ต้องผ่านกฎฝั่ง server ก่อนใช้เรียก Tool

ตอบ error ทั่วไปโดยไม่สะท้อน payload หรือ key บันทึกเพียงหมวด error และ correlation ID ที่จำเป็น ไม่เก็บ body, token หรือข้อมูลส่วนตัวโดยไม่จำเป็น

ด่านคำถามที่ตอบสิ่งที่ยังไม่รับรอง
Parse + duplicate gateข้อความ parse ได้และชื่อในแต่ละ object ไม่ซ้ำไหมโครงสร้างตรงกับ schema หรือไม่
Schema validationfield, type, ขนาด และรูปแบบตามสัญญาถูกไหมผู้ร้องขอมีสิทธิ์ทำ action หรือไม่
Authorizationprincipal นี้ทำ action กับ resource นี้ได้ไหมการเรียกปลายทางสำเร็จหรือปลอดภัยทุกกรณีไหม
Tool dispatchส่งคำขอที่อนุมัติแล้วไป adapter ที่กำหนดไม่ควรใช้เป็นจุดเริ่มต้นของการตรวจ input
ข้อความ JSON ที่มี limit สองค่า ถูกเก็บเป็นคู่ชื่อค่าก่อนปฏิเสธชื่อซ้ำ
object_pairs_hook ตรวจคู่สมาชิกในแต่ละ object ก่อนคืน dict · คลิกภาพเพื่ออ่านขนาดเต็ม

ตัวอย่างทำงาน: request ค้นเอกสารของ Agent

สัญญาตัวอย่าง: รับข้อความ JSON ที่จำกัดขนาดแล้ว; ทุก object ห้ามมีชื่อซ้ำหลังถอด escape; top-level ต้องเป็น object; parse ผ่านแล้วยังไม่ถือว่าผ่าน schema หรือมีสิทธิ์เรียก Tool

json.loads รองรับ object_pairs_hook ซึ่งได้รับคู่สมาชิกตามลำดับก่อนสร้าง dict hook สร้าง dict ใหม่และยกข้อผิดพลาดเมื่อพบชื่อที่มีแล้ว จึงเห็น duplicate ได้ก่อนข้อมูลหายไป และถูกเรียกกับ object ทุกระดับ รวมถึง object ใน array Python 3.12: JSON decoder hooks

object_hook ไม่เหมาะ เพราะได้รับ object ที่สร้างแล้วและ duplicate อาจถูกยุบไปก่อน callback ค่าซ้ำก็ปฏิเสธ แม้ค่าทั้งคู่เหมือนกัน เพื่อไม่สร้างนโยบาย first-wins/last-wins หรือข้อยกเว้นที่เปลี่ยนความหมายตามค่า

การเทียบชื่อเป็นแบบตรงตามสตริงที่ decoder ถอดแล้ว: escaped alias ที่ได้ชื่อเดียวกันซ้ำ; ตัวพิมพ์เล็กใหญ่ต่างกันไม่ซ้ำ; ไม่มี case folding หรือ Unicode normalization โดยอัตโนมัติ หากระบบต้องการ normalization ต้องกำหนดเป็นสัญญาแยก

ตัวอย่างใช้ parse_constant ปฏิเสธ NaN และ Infinity ซึ่ง Python ยอมรับเป็นส่วนขยาย แต่ไม่ใช่ตัวเลข JSON ปกติ นี่ยังไม่ครอบคลุมตัวเลขทุกแบบ: 1e400 อาจกลายเป็น infinity จึงต้องตรวจ finite และช่วงใน schema/numeric policy

ตรวจ dict ระดับบนสุดเพราะ endpoint ตัวอย่างกำหนด object; JSON เองอนุญาต array, scalar และ null ได้ด้วย นี่คือ application contract ไม่ใช่ข้อกำหนดของ JSON

อัลกอริทึมของ hook เป็นการเดินรายการคู่ของ object หนึ่งครั้งและสร้าง dict ผลลัพธ์ระหว่างทาง การตรวจ membership ใช้ key ที่ Python สร้างจาก JSON string ที่ถอดแล้ว จึงครอบคลุม alias ที่ escape แต่ไม่ได้ทำการ normalize เพิ่มเอง หากพบซ้ำ hook หยุดด้วย exception ก่อนคืน object ให้ caller; wrapper ส่ง error ทั่วไปออกไป ไม่มีการเลือกค่าแรกหรือตัวท้าย และไม่มี tool call ในเส้นทางนี้

ขั้นข้อมูลที่ยังเห็นผลตามนโยบายตัวอย่าง
รับข้อความ{"limit":5,"limit":500}ยังไม่เลือกค่าและยังไม่เรียก Tool
ถอด object เป็นคู่[("limit",5),("limit",500)]เห็นชื่อซ้ำสองตำแหน่งใน object เดียว
คู่แรกname=limit, value=5ใส่ dict ชั่วคราวภายใน hook
คู่ที่สองname=limit, value=500พบ name เดิม → ยกข้อผิดพลาด
คืนให้ callerValueError: invalid JSON inputไม่คืน dict บางส่วน; schema และ Tool ไม่ได้รับ request นี้
เปรียบเทียบชื่อ limit ซ้ำใน object เดียวกับชื่อเดียวกันในคนละ object
ความซ้ำตรวจภายใน object เดียว การผ่านด่านนี้ยังต้องตรวจ schema และสิทธิ์ · คลิกภาพเพื่ออ่านขนาดเต็ม

เส้นทางข้อมูล: จาก bytes ถึง Tool ที่เลือกได้

HTTP เริ่มจาก bytes: จำกัด body ก่อน decode, ตั้ง deadline และจำกัดงาน parse พร้อมกัน แล้วส่งข้อความที่อยู่ในเพดานให้ parser การปฏิเสธ duplicate ภายหลังไม่ย้อนคืนหน่วยความจำที่ใช้รับ body ขนาดใหญ่

object_pairs_hook ทำงานหลัง parse ค่าแต่ละคู่ จึงตรวจชื่อได้ก่อนสร้าง dict แต่ไม่ป้องกัน string ใหญ่, nesting ลึก หรือ parse ที่ใช้เวลามาก ต้องกำหนด byte, time, concurrency และ resource limits แยกกัน หากต้องคุม depth ให้เลือก parser ที่รองรับข้อจำกัดนั้น

หลัง parse ให้ตรวจ schema, unknown fields, type, string/list size และ numeric range ต่อด้วย authorization ที่ผูกกับ identity ฝั่ง server แล้วสร้าง argument ภายในก่อน dispatch แยก error เป็น parse, contract, permission หรือปลายทางเพื่อวินิจฉัยได้ตรงจุด

เมื่อนำไปภาษาอื่น ให้คงข้อกำหนดเชิงพฤติกรรมว่า reject ชื่อซ้ำหลัง JSON string decoding ก่อน schema/action แต่ตรวจ API และค่าเริ่มต้นของ parser ที่ใช้จริง ห้ามสมมติว่า API ของ Python ใช้ได้ข้าม stack

  • Bytes: เพดาน body และเวลาอ่าน
  • Text: decode ตาม encoding ที่ endpoint ยอมรับ
  • Parse: ตรวจชื่อซ้ำทุก object และปฏิเสธค่าพิเศษตามนโยบาย
  • Schema: ตรวจ field, type, size, range และข้อกำหนดระดับบนสุด
  • Authorization: ตรวจ principal, action และ resource ในฝั่ง server
  • Dispatch: สร้าง argument ที่ยืนยันแล้วและเรียกเฉพาะ adapter ที่อนุญาต
limit และรูปเขียน Unicode escape u006cimit ถอดเป็นชื่อ limit เดียวกัน
เปรียบเทียบชื่อหลังถอด escape แบบตรงตัว แยกตัวพิมพ์และไม่ทำ Unicode normalization · คลิกภาพเพื่ออ่านขนาดเต็ม

Implementation: ใช้คู่สมาชิกก่อนแปลงเป็น dict

duplicate_keys.py มี parse_json_object และ hook ที่สร้าง dict พร้อมตรวจชื่อซ้ำ ข้อผิดพลาดภายในถูกห่อเป็น ValueError ทั่วไปโดยไม่ echo input หรือชื่อ key ฟังก์ชันนี้ตรวจ duplicate และ top-level type เท่านั้น; ยังไม่มี schema, authorization, logging system หรือ dispatch

typing.Any แสดงค่าหลายชนิดที่ JSON แทนได้ การห่อ RecursionError เป็น error ทั่วไปช่วยไม่เปิด traceback แต่ไม่ใช่ resource protection; อย่า retry parse body เดิมซ้ำ เพราะไม่แก้ข้อมูลและเพิ่มภาระ

ตัวอย่างใช้ standard library เพื่อให้เห็นขอบเขตแคบ ผู้พัฒนาต้องเพิ่ม schema gate หลัง parse ก่อนใช้ข้อมูลใด ๆ ในงานธุรกิจหรือเรียก Tool

  • object_pairs_hook เห็นคู่ชื่อทั้งหมดก่อนประกอบ dict สำหรับ object นั้น
  • object_hook ได้ object ที่สร้างแล้ว จึงไม่ใช่จุดตรวจชื่อซ้ำที่เชื่อถือได้
  • ข้อความ error ไม่สะท้อน key หรือ input ที่ควบคุมโดยผู้ใช้
  • รับเฉพาะข้อความที่ผ่านการจำกัดขนาดที่ขอบเขต HTTP มาแล้ว

ตัวอย่างโค้ดเต็ม: ตรวจชื่อซ้ำระหว่าง parse JSON · ไฟล์ duplicate_keys.py

"""Parse a bounded JSON document and reject duplicate object member names."""

import json
from typing import Any


class DuplicateJSONNameError(ValueError):
    """Raised when any JSON object repeats a decoded member name."""


def _unique_object(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
    result: dict[str, Any] = {}
    for name, value in pairs:
        if name in result:
            # Keep diagnostics generic: caller input may contain sensitive names.
            raise DuplicateJSONNameError("duplicate JSON object member")
        result[name] = value
    return result


def _reject_non_json_constant(token: str) -> None:
    # Python's decoder otherwise accepts NaN and infinities as extensions.
    raise ValueError("non-standard JSON numeric constant")


def parse_json_object(text: str) -> dict[str, Any]:
    """Decode JSON text, rejecting duplicates and non-standard constants.

    The caller must enforce byte, time and resource limits before invoking this
    function. The application contract here requires a top-level object.
    """
    try:
        value = json.loads(
            text,
            object_pairs_hook=_unique_object,
            parse_constant=_reject_non_json_constant,
        )
    except (json.JSONDecodeError, DuplicateJSONNameError, ValueError, RecursionError):
        # Do not log or echo attacker-controlled payloads or member names here.
        raise ValueError("invalid JSON input") from None
    if not isinstance(value, dict):
        raise ValueError("top-level JSON value must be an object")
    return value


if __name__ == "__main__":
    examples = (
        '{"task":"summarize","limit":3}',
        '{"role":"reader","role":"admin"}',
    )
    for example in examples:
        try:
            print("accepted:", parse_json_object(example))
        except ValueError as error:
            print("rejected:", error)

คำสั่งสำหรับผู้อ่าน: python duplicate_keys.py · ผลที่คาดจากโค้ดตามการอ่านแบบ static (ยังไม่รัน):

accepted: {'task': 'summarize', 'limit': 3}
rejected: invalid JSON input

ตัวอย่างการทดสอบมี 16 test methods ใน test_duplicate_keys.py สถานะยัง NOT RUN คำสั่งที่ผู้อ่านอาจใช้ภายหลังคือ python -m unittest -v test_duplicate_keys.py; คำสั่งนี้ไม่ได้ถูกรันในการจัดทำบทความ

ไฟล์ตัวอย่างทดสอบครบ 16 กรณี (ยังไม่รัน) · ไฟล์ test_duplicate_keys.py

"""Acceptance examples for duplicate-safe JSON parsing; not executed in this run."""
import unittest

from duplicate_keys import parse_json_object


class ParseJSONObjectTests(unittest.TestCase):
    def test_accepts_unique_object(self):
        self.assertEqual(parse_json_object('{"task":"summarize","limit":3}'),
                         {"task": "summarize", "limit": 3})

    def test_rejects_duplicate_with_different_values(self):
        with self.assertRaisesRegex(ValueError, "invalid JSON input"):
            parse_json_object('{"role":"reader","role":"admin"}')

    def test_rejects_duplicate_with_identical_values(self):
        with self.assertRaises(ValueError):
            parse_json_object('{"enabled":true,"enabled":true}')

    def test_rejects_escaped_alias_of_same_decoded_name(self):
        with self.assertRaises(ValueError):
            parse_json_object('{"action":1,"\\u0061ction":2}')

    def test_names_are_case_sensitive(self):
        self.assertEqual(parse_json_object('{"Mode":1,"mode":2}'),
                         {"Mode": 1, "mode": 2})

    def test_does_not_apply_unicode_normalization(self):
        composed = "\\u00e9"
        decomposed = "e\\u0301"
        value = parse_json_object('{"' + composed + '":1,"' + decomposed + '":2}')
        self.assertEqual(len(value), 2)

    def test_rejects_duplicate_nested_object(self):
        with self.assertRaises(ValueError):
            parse_json_object('{"profile":{"id":1,"id":2}}')

    def test_rejects_duplicate_object_inside_array(self):
        with self.assertRaises(ValueError):
            parse_json_object('{"items":[{"id":1,"id":2}]}')

    def test_allows_same_name_in_separate_objects(self):
        self.assertEqual(parse_json_object(
            '{"left":{"id":1},"right":{"id":2}}'),
            {"left": {"id": 1}, "right": {"id": 2}})

    def test_rejects_array_at_top_level_by_application_contract(self):
        with self.assertRaisesRegex(ValueError, "top-level"):
            parse_json_object('[{"id":1}]')

    def test_rejects_scalar_at_top_level_by_application_contract(self):
        with self.assertRaises(ValueError):
            parse_json_object('"hello"')

    def test_rejects_malformed_json(self):
        with self.assertRaisesRegex(ValueError, "invalid JSON input"):
            parse_json_object('{"x":')

    def test_rejects_nan_extension(self):
        with self.assertRaises(ValueError):
            parse_json_object('{"score":NaN}')

    def test_rejects_positive_infinity_extension(self):
        with self.assertRaises(ValueError):
            parse_json_object('{"score":Infinity}')

    def test_rejects_negative_infinity_extension(self):
        with self.assertRaises(ValueError):
            parse_json_object('{"score":-Infinity}')

    def test_does_not_claim_to_block_exponent_overflow(self):
        # JSON numeric syntax permits this token; downstream numeric policy applies.
        self.assertTrue(parse_json_object('{"score":1e400}')['score'] == float('inf'))


if __name__ == "__main__":
    unittest.main()

การปฏิบัติการและขอบเขตความปลอดภัย

ใช้ Python 3.12 และ standard library เท่านั้น ไม่มี dependency ให้ติดตั้ง ไม่มี environment variable หรือ credential และไม่เรียก network/API ตัวอย่างใช้ fixture ในหน่วยความจำ ไม่มีค่า API ภายนอก; การใช้ CPU/หน่วยความจำของเครื่องยังมีอยู่ สถานะโค้ดและชุดทดสอบคือ NOT RUN

ก่อนใช้จริงตรวจว่า framework ยังมี raw JSON ณ จุด middleware หรือไม่ หาก parse เป็น dict ก่อน handler gate ใน handler มาช้า และตรวจว่า logging/tracing ไม่เก็บ body ก่อน gate ด้วย

การปฏิเสธอาจกระทบ client ที่เคยพึ่งค่าตัวท้าย ให้ประกาศสัญญาและนับ error category โดยไม่เก็บ payload หลีกเลี่ยง fallback เงียบ ๆ ไป first-wins/last-wins

ขอบเขตนี้ไม่แก้ prompt injection, สิทธิ์เกิน, replay, denial of service หรือข้อมูลรั่ว ต้องมี authorization, allowlist, idempotency, limits และ audit ตามความเสี่ยง โค้ดนี้ไม่ใช่ production-ready

คำสั่งตัวอย่าง python duplicate_keys.py ใช้ fixture คงที่ในไฟล์และไม่รับข้อมูลจาก stdin หรือ network เมื่อ input unique คาดว่าจะพิมพ์ object ที่ parse แล้ว; เมื่อ fixture มีชื่อซ้ำคาดว่าจะพิมพ์ rejected: invalid JSON input ผู้ใช้สามารถอ่านและตรวจ fixture ได้ก่อนรัน ไม่มี environment variable, package install หรือค่าใช้จ่ายภายนอก

Copyable Task Brief: เพิ่ม JSON duplicate gate ให้ Agent

คัดลอก brief ให้ผู้พัฒนาทำในสำเนาที่ได้รับอนุญาตและใช้ fixture สังเคราะห์เท่านั้น ห้ามเชื่อม production

เป้าหมาย: เพิ่ม Python 3.12 parser gate ปฏิเสธชื่อซ้ำที่เท่ากันหลังถอด escape ในทุก object ก่อน schema validation และ tool dispatch

บริบท: หาจุดที่ยังเห็น raw JSON; อย่าสมมติว่า handler ได้ body ดิบหาก middleware parse ก่อน

ขอบเขต: case-sensitive, ไม่มี Unicode normalization; object คนละตัวใช้ชื่อเดียวกันได้; top-level object เป็น contract ของตัวอย่าง; ระบุนโยบาย NaN/Infinity และตัวเลข overflow

ส่งมอบ: implementation, test cases สำหรับ key ซ้ำ/escape/nesting/array/object แยก/malformed/top-level/numeric และคำอธิบายลำดับ schema, authorization, dispatch

รับงานเมื่อ: ซ้ำถูกปฏิเสธก่อน dict ยุบข้อมูล; error ไม่ echo input; resource limits และ test status ระบุตามจริง

สิทธิ์: ห้าม API จริง, network, credential, install, production change, deploy หรือ Tool side effect; จุดหยุด: เมื่อ static review ครอบคลุม implementation, test plan และข้อจำกัด หาก framework parse ก่อน gate ให้รายงานจุดขาดและหยุดก่อนแก้ระบบจริง

  • เป้าหมาย: reject ชื่อซ้ำทุก object ก่อน schema/dispatch
  • ขอบเขต: case-sensitive, ไม่ normalize Unicode, top-level contract ชัดเจน
  • ส่งมอบ implementation และ tests รวม escaped/nested/array cases
  • เกณฑ์รับ: ไม่ echo input; limits และ test status รายงานตามจริง
  • ห้าม network, credential, install, production, deploy หรือ side effect; หยุดที่ static review

เกณฑ์รับงานและจุดหยุด

ครอบคลุม key ซ้ำตรง ๆ, ค่าต่าง/เหมือน, escaped alias, nested object และ object ใน array; กรณีผ่านต้องยืนยันว่าชื่อเดียวกันใน object คนละตัวไม่ถูกปฏิเสธ

แยก top-level application contract จาก JSON syntax และทดสอบ NaN/Infinity แยกจาก 1e400 ซึ่งอาจกลายเป็น float infinity และต้องมี numeric policy ต่อ

ตรวจว่า error ไม่ echo key/body และ flow วาง schema กับ authorization ก่อน dispatch เกณฑ์นี้เป็น acceptance plan ไม่ใช่ผลทดสอบของบทความ; tests ยังคง NOT RUN

หยุดเมื่อ gate อยู่ตรงจุดที่ยังเห็นคู่ครบ มีกรณีทดสอบตาม policy และข้อจำกัดชัดเจน หยุดก่อนเชื่อม API, เปิดสิทธิ์ หรือ deploy

  • อย่าใช้ object_hook หรือ dict หลัง parse ตรวจ duplicate
  • ห้าม dispatch เมื่อ parse/schema/authorization ล้มเหลว
  • ห้าม fallback เงียบ ๆ เป็น first-wins/last-wins
  • รายงานผลจริง; ชุดนี้ NOT RUN

แบบฝึกหัด: หา gate ที่มาช้าเกินไป

Flow สมมติ: middleware เรียก json.loads แล้วบันทึก dict; handler ตรวจ schema แล้วเรียก tool_map[action] ให้ระบุว่า duplicate gate ควรอยู่ตรงไหน และยังตรวจซ้ำได้หรือไม่หลัง parser ยุบ key แล้ว

เขียน fixture สังเคราะห์ที่ action ซ้ำเป็น read_public กับ export_private และอีก fixture ที่ซ้ำใน object ภายใน array อธิบายว่าต้องหยุดก่อน schema หรือ Tool จุดใด

ระบุ error category และ metric ที่ไม่เก็บ body/key พร้อม assumption เรื่อง raw bytes, body limit และ logging ไม่ต้องสร้าง service หรือเรียก Tool จริง

  • ตอบเป็น flow 4–6 ขั้นและระบุจุดที่ยังเห็น raw JSON
  • แนบ fixture กับ expected result และระบุหากยังไม่ได้รัน
  • จบเมื่ออธิบายได้ว่า dict ย้อนคืน duplicate ไม่ได้

Rubric สำหรับตรวจคำตอบแบบฝึกหัด

ใช้เกณฑ์ 8 คะแนน: ตำแหน่งก่อน dict ยุบข้อมูล (0–2); ครอบคลุม nested/array และ escaped alias (0–2); แยก schema, authorization, dispatch และหยุดเมื่อผิด (0–2); ไม่ log payload พร้อมแยก expected result จากผลรันจริง (0–2). หากยังไม่ตรวจให้ระบุ UNKNOWN

Visual Interactive: จำลองประตูรับ JSON ของ Agent

3D Lab ใช้มิติและกล่องแยก scope เพื่อให้เห็นว่าความซ้ำตรวจภายใน object ใด ลองสลับจากชื่อซ้ำในกล่องเดียวเป็นชื่อเดียวกันในคนละกล่อง แล้วอธิบายว่าทำไมผลของด่านเปลี่ยนไป ทั้งหมดเป็นข้อมูลจำลองที่เตรียมไว้ ไม่มีการ parse หรือเรียก Tool จริง

Visual Interactive ที่แยกอยู่ด้านล่างให้เลือกกรณีซ้อน, object ใน array, escaped alias และ top-level array เพื่อเทียบผลที่คาดไว้ ผลนี้เป็นคำอธิบาย fixture ไม่ใช่ผลรัน Python การผ่านกติกาชื่อซ้ำยังไม่ยืนยัน schema หรือสิทธิ์

มี label, focus, live region, reduced-motion และรายการผลแบบอ่านได้เมื่อ JavaScript ไม่ทำงานอยู่ในงานออกแบบ การทดสอบการใช้งานจริงด้วย keyboard, screen reader และมือถือยังเป็น UNKNOWN

3D Lab · ขอบเขตของ object

ชื่อ key ซ้ำกันในวงเล็บปีกกาชุดเดียวกันหรือไม่?

JSON object คือกลุ่มคู่ key/value ที่อยู่ระหว่างวงเล็บปีกกาชุดเดียวกัน ตัวตรวจนี้ติดตามชื่อ key ที่ถอด escape แล้วภายใน object ปัจจุบัน พบชื่อเดิมซ้ำเมื่อใดให้หยุดก่อนส่งต่อ parser ที่อาจเก็บค่าเพียงตัวเดียว

วาง key ลงใน object แล้วเลือกทางออก

ปุ่มเลือกวิธีจัดโครงสร้างจำลองขอบเขต object; การ์ดซ้ายคือ input ก่อนตรวจ, ประตูคือ duplicate guard, ส่วนด้านขวาเป็นขั้นถัดไปที่ยังต้องตรวจแยกต่างหาก

ผลจำลอง: ปฏิเสธระหว่าง parse ก่อนสร้าง dict เพราะ key “limit” ซ้ำใน object เดียวกัน

หนึ่ง objectจำชื่อ key ที่ถอด escape แล้วใน scope นั้น
object ซ้อนเริ่ม scope ใหม่; ชื่อเดียวกันซ้ำข้าม scope ได้
การเปรียบเทียบตรงตัว แยกตัวพิมพ์; ไม่ทำ NFC normalization หรือ case folding

เป็นภาพจำลองข้อมูลที่กำหนดไว้ล่วงหน้า ไม่ได้ parse JSON จริง; แม้ไม่พบชื่อซ้ำก็ยังต้องผ่าน schema และ authorization ก่อนใช้งาน

Visual interactive · ชุดกรณีตัวอย่าง

เลือก fixture เพื่อดูผลที่คาดไว้

Case explorer แสดง mapping ของกรณีที่เขียนกำกับไว้ล่วงหน้า มันไม่ใช่ parser, ไม่เรียก JSON.parse และไม่มีการวัดความเร็วหรืออ้างผล benchmark

ใช้ลูกศรบน/ล่างเพื่อเปลี่ยนกรณี; ผลเป็น fixture คงที่

{"limit":10,"limit":20}
ปฏิเสธ · key ซ้ำชื่อที่ถอดแล้ว “limit” ปรากฏสองครั้งใน object เดียวกัน (scope A)

ผลกรณีทั้งหมด (อ่านได้แม้ไม่มี JavaScript)

  • แบน: ปฏิเสธระหว่าง parse ก่อนสร้าง dict — limit ซ้ำใน scope A
  • 5,500: ปฏิเสธ — limit ซ้ำใน scope A
  • ค่าเหมือนกัน: ปฏิเสธ — ห้ามซ้ำตามชื่อ ไม่พิจารณาค่า
  • nested object คนละตัว: ผ่านกติกา duplicate — scope แยกกัน
  • nested object ตัวเดียวมี limit สองครั้ง: ปฏิเสธระหว่าง parse ก่อนสร้าง dict
  • object ใน array คนละตัว: ผ่านกติกา duplicate — scope แยกกัน
  • object สมาชิก array ตัวเดียวมี limit สองครั้ง: ปฏิเสธระหว่าง parse ก่อนสร้าง dict
  • ชื่อ escaped และชื่อปกติ: ปฏิเสธ — \u006cimit ถอดเป็น limit
  • object ซ้ายและขวาแยก scope: ผ่านกติกา duplicate
  • array ระดับบน: กติกา duplicate ผ่าน แต่ parse_json_object ปฏิเสธเพราะรับ object ระดับบนเท่านั้น
  • limit กับ Limit: ผ่านด่านนี้ — เปรียบเทียบตรงตัวและแยกตัวพิมพ์

“ผ่านด่านนี้” หมายถึงไม่พบชื่อซ้ำตามกติกาใน fixture เท่านั้น ไม่ได้ยืนยันว่า JSON, schema หรือคำขอได้รับอนุญาตอย่างครบถ้วน

Video Agent Lab: ฝึกอธิบายเส้นทาง JSON ก่อน Tool

Video Agent Lab ด้านล่างเป็น simulation ของ workflow การผลิตวิดีโอ ใช้วางแผนสื่ออธิบายการตรวจ JSON ก่อนส่ง Tool ไม่ได้รัน parser, เรียกโมเดล หรือผลิตวิดีโอจริง

Brief 60 วินาที 6 ช่วง: Hook 0–7 วินาที request มี action ซ้ำ; Context 7–16 input จาก model/MCP ยังไม่น่าเชื่อถือ; Gate 16–29 object_pairs_hook ปฏิเสธทุกระดับ; Decision 29–39 duplicate หยุด ส่วน unique ไป schema และ authorization; Limitation 39–51 body/depth/time เป็นอีกงาน; Recap 51–60 parse ผ่านไม่เท่ากับสิทธิ์ Tool พร้อม expected case

ใช้ native Video Agent Lab รุ่น active 1.4.0 ที่ตรวจจากเว็บไซต์ในรอบนี้ โดยไม่แก้ปลั๊กอิน ผล UI และการคำนวณใน Lab ยังไม่ได้ทดสอบจริง

  • เป้าหมาย: ผู้ชมชี้จุดที่ต้องเก็บคู่ชื่อ–ค่าก่อนยุบเป็น dict ได้
  • ผู้ชมและบริบท: คนใช้ LLM ที่เริ่มต่อ Tool; ใช้ request สังเคราะห์เท่านั้น
  • ข้อมูลเข้า: ตัวอย่าง limit 5 และ 500 อยู่ใน object เดียว
  • ข้อจำกัด: 60 วินาที บรรยายไทย ไม่มีข้อมูลส่วนตัว ไม่มี Tool จริง
  • ผลส่งมอบ: storyboard หกช่วงข้างต้น พร้อมคำอธิบายผ่าน parse ยังต้องตรวจสิทธิ์
  • เกณฑ์รับและหยุด: ทั้งชื่อซ้ำตรง ๆ และ escaped alias ต้องจบที่การปฏิเสธ; หยุดที่แผนจำลองก่อนผลิตหรือเผยแพร่วิดีโอ
H✦HYBRID MINDINTERACTIVE EDITION LIVE EXPERIENCE
HYBRID MIND ORIGINAL / AI AGENT WORKFLOW / 2026

จากคลิปดิบ
สู่จักรวาลคอนเทนต์

ChatGPT ตัดต่อวิดีโอแทนคนได้จริงแค่ไหน? สำรวจระบบ AI Video Editing Agent ผ่านฉากสามมิติที่โต้ตอบได้ พร้อมแยกข้อเท็จจริง สร้างพรอมป์ต์ และจำลองต้นทุนก่อนลงมือทำจริง

06 EDITING STAGES03 CONTENT FORMATS01 INTERACTIVE LAB

ออกแบบระบบตัดต่อในมุมมอง 3D

ลากบนฉากเพื่อหมุนมุมมอง แตะโหนดเพื่อดูหน้าที่ของ AI ในแต่ละขั้นตอน

แผนภาพ 6 ขั้นตอน: Footage, Story, Edit, Captions, Graphics, Render
AGENT PIPELINE / VIEWPORT ORBIT 3D
DRAG / SWIPE TO ROTATE
SELECT NODE TO INSPECT
01 / 06นำเข้าคลิปดิบ

จัดระเบียบไฟล์ ตรวจคุณภาพภาพและเสียง และกำหนดสิทธิ์เข้าถึงให้ AI Agent

● SOURCE
จุดสำคัญ: AI Agent ทำหน้าที่วางแผนและควบคุมเครื่องมือ ส่วนการตัดต่อจริงต้องมีซอฟต์แวร์หรือระบบเรนเดอร์รองรับ ฉากนี้เป็น แบบจำลองเชิงอธิบาย ไม่ใช่ระบบอัปโหลดหรือตัดต่อวิดีโอ

แยกความสามารถจริงจากคำโฆษณา

กดแต่ละประเด็นเพื่ออ่านรายละเอียดและแหล่งข้อมูล

EVIDENCE-FIRST
✓ChatGPT Work เข้าถึงไฟล์ในเครื่องได้ตรวจสอบแล้ว / มีเงื่อนไข+
รองรับการทำงานกับโฟลเดอร์หรือแอปบนคอมพิวเตอร์เดสก์ท็อป เมื่อแผนและการตั้งค่าอนุญาตและผู้ใช้ให้สิทธิ์ ส่วน Work บนมือถือหรือเว็บไม่ได้เข้าถึงโฟลเดอร์ในคอมพิวเตอร์ของคุณโดยตรง ที่มา: OpenAI Help ↗
✓Astra ใช้โปรแกรมคอมพิวเตอร์ทำงานได้ตรวจสอบแล้ว / ไม่ใช่โปรแกรมตัดต่อในตัว+
OpenAI อธิบายความสามารถด้าน computer use ของ Astra รวมถึงงานสื่อที่ใช้เครื่องมือ แต่ต้องแยกบทบาท AI ผู้ควบคุมออกจากซอฟต์แวร์ประมวลผลวิดีโอและการเรนเดอร์ไฟล์ ที่มา: OpenAI ↗
?ตัดเสร็จใน 5–10 นาทีทุกกรณียังพิสูจน์เป็นเกณฑ์ทั่วไปไม่ได้+
เวลาขึ้นกับความยาวคลิป จำนวนทรานซิชัน คุณภาพซับ เครื่องมือ และประสิทธิภาพคอมพิวเตอร์ ควรใช้การจับเวลางานจริงแบบต้นทางเดียวกัน ไม่ใช้ตัวเลขจากโพสต์เป็นเกณฑ์อ้างอิง
?ถูกกว่าจ้างคน 10 เท่าต้องกำหนดต้นทุนให้เทียบกันได้+
ต้องรวมเวลาตรวจแก้ ลิขสิทธิ์เสียง เครื่องมือที่จ่ายเพิ่ม และต้นทุนโมเดล ยังไม่มีหลักฐานว่าประหยัด 10 เท่าสำหรับทุกงาน ทดลองสมมติฐานส่วนตัวได้ใน Cost Simulator ด้านล่าง

หนึ่งไอเดีย สามรูปแบบคอนเทนต์

ปรับรูปแบบวิดีโอ แล้วดูกรอบภาพตัวอย่างและ Prompt เปลี่ยนตามแบบเรียลไทม์

WORKING INTERACTIVE
15 SEC180 SEC
LIVE CREATIVE PREVIEW9:16 · 45 SEC
HYBRID MIND / AI
AI EDITOR / EXPLAINEDAI Agent
ช่วยตัดต่อ?
ใส่ซับตามประโยคได้อัตโนมัติ
▶◉↗
CONCEPT PREVIEW · NOT RENDERED VIDEO
VERTICAL · SHORT FORMVisual Mockup

พร้อมนำไปใช้กับ AI Agent

ตัวสร้าง Prompt นี้ไม่อัปโหลดคลิป ไม่เรียก API เสียเงิน และไม่ตัดต่อวิดีโอจริง ต้องใช้กับเครื่องมือที่ผู้ใช้อนุญาตภายหลัง

จำลองเวลาและต้นทุนของคุณเอง

เลื่อนตัวเลขเพื่อเปรียบเทียบสถานการณ์สมมติ ไม่ใช่ผล benchmark ที่ยืนยันแล้ว

SCENARIO · NOT BENCHMARK
ESTIMATED TIME SAVED11.0 ชม./เดือน
18.0 ชม.
7.0 ชม.
ส่วนต่างต้นทุนเวลา + เครื่องมือ (สมมติ)฿3,920

ตัวเลขเป็นตัวอย่างเพื่อช่วยตัดสินใจ ไม่ใช่ผลประหยัดที่รับประกัน

AI ที่ตัดคลิปเป็น ไม่ได้ทำงานลำพัง

สิ่งที่น่าสนใจของ GPT-6 Astra และ GPT-6.1 Sol ไม่ได้อยู่ที่ว่าตัวโมเดลมีปุ่ม Render MP4 ซ่อนอยู่ แต่คือความสามารถในการจัดการงานหลายขั้นตอนร่วมกับเครื่องมืออื่น: อ่านไฟล์ วางลำดับเรื่อง ใช้แอป ตรวจผลลัพธ์ และแก้งานตามข้อเสนอแนะของมนุษย์

สำหรับคนทำคอนเทนต์ ความต่างสำคัญคือการเปลี่ยนจาก “ส่งคลิปให้ AI แล้วหวังว่าจะได้ผลงาน” ไปเป็น Workflow ที่ตรวจรับได้ทุกขั้น ตั้งแต่การเลือกช่วงเด็ด การสร้างซับ การตรวจคำผิด จนถึงการเรนเดอร์ไฟล์ตามสัดส่วนของแต่ละแพลตฟอร์ม

ข้อควรระวังคือระบบ Work ที่รันบนเว็บหรือมือถือไม่ได้หมายความว่า AI เข้าถึงคลิปบนคอมพิวเตอร์บ้านได้ทันที ต้องทำงานในสภาพแวดล้อมที่เปิดให้เข้าถึงไฟล์จริง มีเครื่องมือตัดต่อ และมีสิทธิ์ใช้งานอย่างชัดเจน

01จัดคลิปให้พร้อม

รวบรวมไฟล์ในโฟลเดอร์ที่เข้าถึงได้ ระบุสิทธิ์และข้อจำกัด

02ตรวจสคริปต์และไทม์ไลน์

ให้ Agent เสนอ Hook, ช่วงตัด และโครงเรื่องก่อนตัดต่อ

03สร้างซับ + กราฟิก

ตรวจชื่อเฉพาะ ตัวเลข ภาษาไทย และความถูกต้องของคำกล่าวอ้าง

04ตรวจไฟล์ MP4 จริง

ตรวจความละเอียด เสียง ระยะเวลา safe zone และคำบรรยาย

คำถามที่พบบ่อย

ถาม: ชื่อซ้ำผิดไวยากรณ์ไหม? ตอบ: RFC 8259 แนะนำ SHOULD ไม่ซ้ำและเตือนว่าพฤติกรรมคาดเดาไม่ได้ แต่ไม่ได้บังคับ decoder ทุกตัวให้ reject แอปต้องกำหนดนโยบาย

ถาม: ค่าซ้ำเหมือนกันอนุญาตได้ไหม? ตอบ: ตัวอย่างปฏิเสธทุกกรณีเพื่อไม่สร้าง first/last-wins exception

ถาม: escaped key นับซ้ำไหม? ตอบ: ถ้าหลังถอด escape ได้สตริงเดียวกันให้นับซ้ำ; case และ Unicode normalization ไม่ถูกเปลี่ยนอัตโนมัติ

ถาม: schema validator จัดการแทนได้ไหม? ตอบ: อย่าสมมติ หากได้รับ dict หลัง parse key อาจถูกยุบไปแล้ว วาง gate ขณะยังเห็น raw JSON หรือคู่ครบ

ถาม: hook จำกัด input ใหญ่หรือลึกไหม? ตอบ: ไม่ จำกัด bytes, deadline, concurrency และ depth/resource แยกต่างหาก

ถาม: parse ผ่านแล้วเรียก Tool ได้ไหม? ตอบ: ไม่ ต้องตรวจ schema และ authorization ก่อน; ค่านำเข้าจาก model ไม่ใช่หลักฐานสิทธิ์

ถาม: production-ready ไหม? ตอบ: ไม่ใช่ เป็นตัวอย่าง scope แคบ ยังไม่รันและไม่มี framework, authorization หรือ resource controls

แหล่งอ้างอิงและขอบเขตข้อสรุป

RFC 8259 โดย IETF เป็นแหล่งหลักเรื่อง object names และ string comparison หลังถอด escape: https://www.rfc-editor.org/rfc/rfc8259.html หัวข้อ 4 ระบุ SHOULD และพฤติกรรมซ้ำที่คาดเดาไม่ได้; ข้อสรุปเรื่องช่องว่างระหว่าง parser เป็น engineering analysis ไม่ใช่การอ้าง exploit เฉพาะ

Python 3.12 Library Reference เป็นแหล่งหลักของ json.loads, object_pairs_hook และ parse_constant: https://docs.python.org/3.12/library/json.html การยก error, generic message และ top-level contract เป็นนโยบายตัวอย่าง ไม่ใช่ default ของไลบรารี

อ่านต่อ: จำกัด bytes ก่อน parse JSON และ จัดประเภท error ด้วย RFC 9457

  • RFC 8259: duplicate-name guidance และ decoded-string comparison
  • Python 3.12 docs: decoder hooks
  • ตัวอย่างและ tests ยัง NOT RUN
  • ตรวจ parser จริงก่อนนำไปใช้

Discover more from HYBRID MIND

Subscribe now to keep reading and get access to the full archive.

Continue reading