บทที่ 8 จาก 9 · AI 101 — คู่มือเริ่มต้นสำหรับคนที่จะเอา AI ไปใช้งานจริง
ความปลอดภัย — จุดที่ต้องระวัง
ความเสี่ยงแบ่งเป็นสองกลุ่มที่ต่างกันสิ้นเชิง ตอนโหลดโมเดลซึ่งไฟล์อาจรันโค้ดบนเครื่องคุณ และตอนใช้งานซึ่งโมเดลอาจถูกหลอกหรือทำข้อมูลรั่ว บทนี้ครอบคลุม pickle, trust_remote_code, ข้อจำกัดของสแกนเนอร์ และ checklist ก่อนขึ้นใช้จริง
ความเสี่ยงแบ่งเป็นสองกลุ่มที่ต่างกันสิ้นเชิง คือ ตอนโหลดโมเดล ซึ่งไฟล์อาจรันโค้ดบนเครื่องคุณ และ ตอนใช้งาน ซึ่งโมเดลอาจถูกหลอกหรือทำข้อมูลรั่ว
8.1 ความเสี่ยงตอนโหลด — ไฟล์โมเดลรันโค้ดได้
นี่คือข้อเท็จจริงที่ผู้เริ่มต้นส่วนใหญ่ไม่รู้ การโหลดโมเดล PyTorch รูปแบบดั้งเดิมไม่เหมือนการเปิดไฟล์ภาพ เพราะรูปแบบนั้นใช้ pickle ซึ่งออกแบบมาให้สร้างวัตถุ Python ขึ้นใหม่ และในกระบวนการนั้นมันรันโค้ดได้ ผู้โจมตีจึงฝังคำสั่งไว้ในไฟล์น้ำหนักได้
| รูปแบบ | รันโค้ดตอนโหลดไหม | คำแนะนำ |
|---|---|---|
| safetensors | ไม่ เก็บแค่ตัวเลขและ metadata | บังคับใช้เป็นค่าตั้งต้นของทั้งองค์กร |
.bin / .pt / .pth / .ckpt | ใช่ ผ่าน pickle | หลีกเลี่ยง ถ้าจำเป็นให้โหลดในสภาพแวดล้อมแยกที่ไม่มีเน็ตและไม่มี credential |
.h5 / Keras | ได้ ผ่าน Lambda layer | ระวังเป็นพิเศษเมื่อโหลดผ่าน Keras โดยตรง |
| GGUF | ไม่ โดยการออกแบบ | ค่อนข้างปลอดภัย แต่ยังมีความเสี่ยงจากบั๊กของตัวอ่านไฟล์ อัปเดตตัวรันสม่ำเสมอ |
# ✗ เสี่ยง — โหลดรูปแบบ pickle โดยไม่มีการป้องกัน
model = AutoModelForCausalLM.from_pretrained("some-user/mystery-model")
# ✓ ปลอดภัยกว่ามาก
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen3-8B",
use_safetensors=True, # ล้มเหลวไปเลยถ้าไม่มี safetensors ดีกว่าโหลด pickle เงียบ ๆ
trust_remote_code=False, # ไม่รันโค้ดที่มากับ repo
revision="a1b2c3d4", # ล็อกเวอร์ชัน
)
# ถ้าจำเป็นต้องโหลด checkpoint แบบเก่าจริง ๆ
import torch
state = torch.load("old_model.pt", weights_only=True) # อ่านเฉพาะตัวเลข ไม่สร้างวัตถุ
weights_only=True คือความแตกต่างระหว่าง “อ่านข้อมูล” กับ “รันโปรแกรมของคนอื่น”
8.2 trust_remote_code — พารามิเตอร์ที่อันตรายที่สุดในระบบนิเวศนี้
trust_remote_code=True แปลว่า “ดาวน์โหลดไฟล์ .py จาก repo นั้นแล้วรันบนเครื่องฉัน ด้วยสิทธิ์ของผู้ใช้ฉัน”
มันมีอยู่เพราะโมเดลสถาปัตยกรรมใหม่มักมาก่อนที่ไลบรารีจะรองรับ ผู้พัฒนาจึงใส่โค้ดสถาปัตยกรรมไว้ใน repo เอง ซึ่งเป็นเหตุผลที่ถูกต้อง แต่ผลคือ repo ที่ใครก็อัปโหลดได้ กลายเป็นช่องรันโค้ดบนเครื่องคุณได้
กติกาที่ควรใช้:
- ค่าตั้งต้นคือ
Falseเสมอ - เปิดเป็น
Trueได้เฉพาะกับ repo ของผู้พัฒนาที่ยืนยันตัวตนแล้วเท่านั้น - ถ้าจำเป็นต้องเปิดกับ repo ที่ไม่คุ้นเคย ให้อ่านไฟล์
.pyทั้งหมดก่อน และรันในคอนเทนเนอร์ที่ไม่มีเน็ตและไม่มี credential - ห้ามใช้ในระบบอัตโนมัติที่ชี้ไปยัง repo ซึ่งคนอื่นควบคุมได้ โดยเด็ดขาด
8.3 สแกนก่อนใช้ — และรู้ข้อจำกัดของมัน
uv tool install modelscan
modelscan -p ./models/downloaded-model/
# หรือสแกนเฉพาะไฟล์ pickle
uv tool install picklescan
picklescan -p ./models/downloaded-model/pytorch_model.bin
# ใส่ไว้ใน CI ก่อนที่โมเดลจะเข้า registry ภายใน
modelscan -p ./incoming/ --settings-file ./modelscan-settings.toml || exit 1
สแกนเนอร์ไม่ใช่การรับประกัน
เครื่องมือสแกนตรวจสอบไฟล์แบบไล่อ่านตามลำดับ ขณะที่ตัวถอดรหัสจริงรันคำสั่งไปพร้อมกับที่อ่าน ผู้โจมตีที่วางโค้ดไว้ในตำแหน่งเหมาะสมจึงทำให้โค้ดทำงานก่อนที่สแกนเนอร์จะไปถึงส่วนที่มันเข้าใจได้ มีการยืนยันแล้วว่าเทคนิคนี้ถูกใช้จริงเพื่อหลบเลี่ยงการตรวจ และมีรายงานช่องโหว่ของสแกนเนอร์หลายรายการ ให้ถือว่าการสแกนคือชั้นเสริม ไม่ใช่ใบรับรอง ชั้นหลักคือการใช้ safetensors และเลือกแหล่งที่น่าเชื่อถือ
8.4 รันโมเดลที่ยังไม่ไว้ใจอย่างไร
docker run --rm -it \
--gpus all \
--network none \ # ไม่มีเน็ต = ส่งข้อมูลออกไม่ได้
--read-only \ # ระบบไฟล์อ่านอย่างเดียว
--tmpfs /tmp:rw,size=2g \ # ที่เดียวที่เขียนได้
-v "$PWD/models:/models:ro" \ # โมเดลอ่านอย่างเดียว
-v "$PWD/out:/out:rw" \
--user 1000:1000 \ # ไม่ใช่ root
--cap-drop ALL \
--security-opt no-new-privileges \
--memory 32g --pids-limit 512 \
pytorch/pytorch:latest \
python /out/test_model.py
ลำดับที่ปลอดภัย:
- โหลดในคอนเทนเนอร์นี้ ดูว่ามันพยายามต่อเน็ตหรือเขียนไฟล์แปลก ๆ ไหม
- สแกนด้วย
modelscan - ทดสอบคุณภาพด้วยชุด eval ของคุณ
- ถ้าผ่านทั้งสามข้อ ค่อยย้ายเข้า registry ภายในและใช้จริง
8.5 ความเสี่ยงตอนใช้งานจริง
| ความเสี่ยง | เกิดขึ้นอย่างไร | วิธีลด |
|---|---|---|
| Prompt injection | ข้อความในเอกสาร หน้าเว็บ หรืออีเมลที่โมเดลอ่าน มีคำสั่งฝังอยู่ และโมเดลทำตาม | ถือทุกอย่างที่โมเดลอ่านเป็น “ข้อมูล” ไม่ใช่ “คำสั่ง” จำกัดสิทธิ์ของระบบที่ต่อกับโมเดล และให้มนุษย์ยืนยันก่อนทำสิ่งที่ย้อนกลับไม่ได้ |
| ข้อมูลรั่วผ่าน prompt | ส่งข้อมูลลูกค้าเข้า API สาธารณะโดยไม่มีข้อตกลงรองรับ | ปิดบังข้อมูลส่วนบุคคลก่อนส่ง หรือใช้โมเดลที่รันเองสำหรับข้อมูลอ่อนไหว |
| Secret ในบทสนทนา | วาง log หรือ config ที่มี key เข้าไปให้โมเดลช่วยดู | ปิดบังก่อนวางเสมอ และถ้าเผลอไปแล้วให้ถือว่า key นั้นถูกเปิดเผยแล้ว ต้องหมุนทันที |
| ข้อมูลรั่วผ่าน log | ระบบบันทึก prompt และคำตอบทั้งหมดไว้โดยไม่ปิดบัง | ใส่ตัวกรองปิดบังก่อนเขียน log กำหนดอายุการเก็บ และจำกัดคนที่เข้าถึงได้ |
| โมเดลตอบผิดอย่างมั่นใจ | โมเดลแต่งข้อมูลที่ไม่มีอยู่จริงด้วยน้ำเสียงมั่นใจ | ให้อ้างอิงแหล่งเสมอในงานที่ต้องแม่น ตรวจด้วยกฎหรือโมเดลอื่น และอย่าให้ตัดสินใจสุดท้ายในเรื่องสำคัญ |
| โมเดลถูกเปลี่ยนเงียบ ๆ | ระบบสลับไปใช้โมเดลสำรองหรือเวอร์ชันอื่นโดยไม่มีใครรู้ | บันทึกชื่อและเวอร์ชันโมเดลในทุก log และมี smoke test ที่จับความเปลี่ยนแปลงของพฤติกรรม |
| พึ่งพาผู้ให้บริการรายเดียว | ราคาขึ้น เงื่อนไขเปลี่ยน หรือโมเดลถูกยกเลิก | เรียกผ่าน API มาตรฐาน มีตัวสำรองที่ทดสอบแล้ว และเก็บชุด eval ไว้ตรวจตัวใหม่ได้เร็ว |
8.6 Checklist ก่อนเอาโมเดลขึ้นใช้จริง
ตอนเลือกและโหลด
- มาจากบัญชีผู้พัฒนาที่ยืนยันตัวตน หรือผ่านการตรวจสอบแล้ว
- ใช้ safetensors หรือ GGUF ไม่ใช่
.bin/.pt - ล็อก revision เป็น commit sha ไม่ใช่
main -
trust_remote_code=Falseหรือมีเหตุผลที่บันทึกไว้ถ้าต้องเปิด - สแกนด้วย modelscan แล้ว
- ทดลองโหลดครั้งแรกในคอนเทนเนอร์ที่ไม่มีเน็ต
- อ่านใบอนุญาตจนถึงโมเดลต้นทาง ไม่ใช่แค่ที่ผู้อัปโหลดเขียน
- บันทึก sha256 ของไฟล์ไว้เทียบภายหลัง
ตอนวางระบบ
- คำนวณ VRAM ที่จำนวนผู้ใช้สูงสุด ไม่ใช่ที่หนึ่งคน
- benchmark ด้วย prompt ที่ยาวใกล้เคียงงานจริง
- ผ่านชุด eval ของตัวเองอย่างน้อย 30 เคส
- เรียกผ่าน API มาตรฐาน เพื่อให้เปลี่ยนตัวรันได้
- บันทึกชื่อและเวอร์ชันโมเดลในทุก log
- มีตัวกรองปิดบังข้อมูลอ่อนไหวก่อนเขียน log
- มีแผนสำรองเมื่อโมเดลหรือผู้ให้บริการมีปัญหา
- กำหนดว่าอะไรที่โมเดลตัดสินใจเองไม่ได้ และต้องให้คนยืนยัน
สรุปบทนี้
ไฟล์โมเดลไม่ใช่ไฟล์ข้อมูลเฉย ๆ รูปแบบ pickle รันโค้ดตอนโหลด และ trust_remote_code=True คือการยอมให้ repo รันโปรแกรมบนเครื่องคุณ ใช้ safetensors เป็นค่าตั้งต้น ปิด trust_remote_code ทดลองของใหม่ในคอนเทนเนอร์ที่ตัดเน็ต และถือว่าทุกอย่างที่โมเดลอ่านคือข้อมูล ไม่ใช่คำสั่ง
บทถัดไปเป็นภาคผนวก รวมคำศัพท์ คำสั่งที่ใช้ประจำ และเส้นทางเรียนรู้