# API (Gateway) แบบ OpenAI — คู่มือใช้งาน Gateway รับคำขอแบบ OpenAI แล้วส่งไปยังเครื่อง (เช่น PGX) ที่มีโมเดลนั้น โหลดโมเดลให้ตามต้องการ และปล่อยหน่วยความจำเมื่อว่าง - Base URL: `https://api.wxch.org/v1` (ต้องเพิ่ม DNS A record `api` → IP ของ VPS ก่อน) - เส้นทางที่รองรับ: `GET /v1/models`, `POST /v1/chat/completions` (รองรับ stream), `POST /v1/completions`, `POST /v1/embeddings` - ยืนยันตัวตนด้วย `Authorization: Bearer ` สร้าง/ปิด/ลบ key ได้ที่แท็บ **API** ใน control.wxch.org (key แสดงครั้งเดียวตอนสร้าง; server เก็บเฉพาะค่าแฮช) ``` curl https://api.wxch.org/v1/chat/completions \ -H "Authorization: Bearer " -H "Content-Type: application/json" \ -d '{"model":"qwen2.5:0.5b","messages":[{"role":"user","content":"hi"}]}' ``` ใช้กับ AIBIO หรือโปรแกรมที่รองรับ OpenAI API ได้โดยตั้ง Base URL และ API key ## ชื่อโมเดลตาม runtime ใส่ชื่อตามที่เห็นใน `GET /v1/models`: Ollama ใช้แท็ก (`qwen3:14b`, ไม่ใส่ `:latest` ได้ถ้าติดตั้งเป็น latest), LM Studio ใช้ key (`qwen3-0.6b`), vLLM ใช้ Hugging Face id (`nvidia/Qwen3.8-27B-NVFP4`) ระบบจับคู่กับรายการที่ติดตั้งจริงและส่งชื่อที่ตรงไปยัง runtime ## การทำงาน 1. **เลือกเครื่อง** เฉพาะเครื่องที่ออนไลน์และมีโมเดลนั้นติดตั้ง ชอบเครื่องที่โหลดโมเดลอยู่แล้ว รองลงมาคือเครื่องที่ยุ่งน้อยสุด 2. **Model Pool บนเครื่อง** (agent) - โมเดลที่โหลดอยู่และยังมีคนใช้ จะค้างไว้ (ค้างไว้นานถึง 24 ชั่วโมงหลังใช้ครั้งสุดท้าย `OLLAMA_KEEP_ALIVE=24h` และปล่อยก่อนเมื่อหน่วยความจำไม่พอ (ตัวที่ไม่ได้ใช้นานที่สุดก่อน)) - ขอโมเดลที่ยังไม่โหลดและหน่วยความจำไม่พอ: ปล่อยโมเดลที่ว่างอยู่ก่อน (ใช้ล่าสุดนานสุดก่อน) **ไม่ตัดงานที่กำลังทำ**; ถ้ายังไม่พอ รอได้สูงสุด ~90 วินาที แล้วตอบ 503 - โมเดลที่เพิ่งโหลดจะอยู่ขั้นต่ำ 60 วินาทีก่อนถูกปล่อยเพราะโมเดลอื่น (กันโหลดสลับไปมา) - เก็บหน่วยความจำไว้ให้เจ้าของเครื่อง `reserve_gb` (ค่าเริ่มต้น 8 GB ตั้งได้ใน `/etc/wxch/node.json`) 3. **วัดการใช้งาน**: นับโทเค็นเข้า/ออกต่อ key (จากฟิลด์ `usage` ของโมเดล; ถ้าเป็น stream ระบบเพิ่ม `stream_options.include_usage` ให้เอง) และเก็บประวัติคำขอล่าสุด 200 รายการ (เวลา, key, โมเดล, เครื่อง, สถานะ, โทเค็น, เวลาตอบโทเค็นแรก, เวลารวม) ## ข้อจำกัด/รหัสผิดพลาด | สถานะ | ความหมาย | |---|---| | 401 | key ผิด ถูกปิด หรือไม่ได้ส่ง | | 404 `model_not_found` | ไม่มีเครื่องที่ออนไลน์ติดตั้งโมเดลนี้ (`qwen2.5` หมายถึง `qwen2.5:latest`) | | 429 | เกินเพดานต่อ key: 60 คำขอ/นาที และ 4 คำขอพร้อมกัน | | 503 `no_machine_online` | ไม่มีเครื่องออนไลน์ | | 503 `owner_mode` | เครื่องที่มีโมเดลนี้เจ้าของใช้อยู่หรือหยุดแชร์ (มี `Retry-After`) | | 503 (อื่นๆ) | หน่วยความจำไม่พอสำหรับโหลดโมเดลตอนนี้ (ลองใหม่) | | 504 | เครื่องไม่เริ่มตอบ: 180 วินาทีถ้าโมเดลอยู่ในหน่วยความจำแล้ว, 25 นาทีถ้าต้องโหลดโมเดลก่อน (vLLM โหลดหลายนาที) | - ขนาดคำขอสูงสุด 4 MB - ยังไม่มี: สิทธิ์ราย key ต่อโมเดล, โควตา/เครดิต, คะแนนบริการ - **ความเป็นส่วนตัว:** prompt ผ่านเครื่องที่ให้บริการ เจ้าของเครื่องนั้นมองเห็นได้ (ดู DESIGN-TH.md หัวข้อ 11) - Ollama เลือกขนาด context เองตามหน่วยความจำ (บน PGX วัดได้ 32768 สำหรับ qwen2.5:0.5b) ควรตรวจกับโมเดลใหญ่ที่ใช้จริง ## สถานะการทดสอบ (2026-10-03) - เทสต์อัตโนมัติ: Model Pool 10 กรณี (ปล่อยตัวว่าง/ไม่ตัดตัวที่ยุ่ง/รอแล้วสำเร็จ/503/ป้องกันโหลดซ้อนจนเกินหน่วยความจำ ฯลฯ), การแยก usage, และชุดครบวงจร (server+agent จริง, Ollama จำลอง) 18 ข้อ - ทดสอบบน PGX จริง: `/v1/models`, chat ปกติ + stream, นับโทเค็นจริง, 429, 404, ตอบกลับหลังรีสตาร์ท server ภายใน ~3 วินาที - **ยังไม่ได้ทดสอบบนเครื่องจริง:** การปล่อยโมเดลเพื่อสลับโมเดลตอนหน่วยความจำเต็ม (ทดสอบเฉพาะด้วยเทสต์จำลอง เพราะ PGX มี RAM เหลือมาก), หลายเครื่องพร้อมกัน, ผ่าน `api.wxch.org` จริงผ่าน HTTPS ## Owner Guard (เจ้าของเครื่องมาก่อน) agent ตรวจทุก 5 วินาที เจอสัญญาณเจ้าของเมื่อ: แตะคีย์บอร์ด/เมาส์ภายใน 30 วินาที (GNOME idle monitor), มีโปรเซสอื่นกิน GPU (ไม่ใช่ Ollama), หรือกดปุ่ม **หยุดแชร์** (แท็บ "สถานะเครื่อง") / รัน `wxch-agent -pause` บนเครื่อง เมื่อเจอ: หยุดรับงานใหม่ → ให้งานที่กำลังทำจบภายใน 30 วินาที (เกินแล้วยกเลิก) → ปล่อยโมเดลทั้งหมดจากหน่วยความจำ → API ตอบ 503 `owner_mode` สำหรับโมเดลที่มีแต่เครื่องนี้ กลับมารับงานเมื่อเจ้าของว่างต่อเนื่อง 5 นาที (ถ้าไม่รู้เวลาว่าง เช่น ไม่มีหน้าจอ จะถือว่าเจ้าของไม่อยู่) ปรับค่าได้ใน `/etc/wxch/node.json`: `owner_guard_off` (true = ปิดการตรวจอัตโนมัติ ยังหยุดแชร์เองได้), `owner_active_idle_s` (30), `owner_return_idle_s` (300), `owner_grace_s` (30) ต้อง restart agent หลังแก้ ข้อจำกัด: ยังไม่ตรวจภาระ CPU ของเจ้าของ (เช่นคอมไพล์ใหญ่) และคนที่ใช้เครื่องผ่านเว็บ terminal ไม่นับเป็นเจ้าของ ให้กด "หยุดแชร์" เอง ## หน้าแชต chat.wxch.org หน้าแชตแบบ ChatGPT ที่ใช้โมเดลได้ทุก runtime (Ollama, LM Studio, vLLM) เพราะคุยผ่าน Gateway เดียวกัน: ล็อกอินด้วยรหัสผ่านเว็บ, เลือกโมเดล (จัดกลุ่มตาม runtime, ● = อยู่ในหน่วยความจำแล้ว), ตอบแบบทยอยทีละคำ, ปุ่มหยุด/คัดลอก/สร้างใหม่, Markdown + code block, แสดงส่วน "ความคิดของโมเดล" แยกสำหรับโมเดลแบบ reasoning (ฟิลด์ `reasoning` ของ Ollama หรือ `reasoning_content` ของ LM Studio/vLLM), หลายแชต (เก็บในเบราว์เซอร์เท่านั้น), System prompt/Temperature/Max tokens, แสดง runtime/เครื่อง/เวลาตอบแรก/tok/s ต่อข้อความ - โมเดลแบบคิดอาจใช้โทเค็นไปกับการคิดจนชน Max tokens ก่อนตอบ หน้าแชตจะแจ้งให้เพิ่มค่า (ค่าเริ่มต้น 4096) - โมเดลที่ vLLM ต้องโหลดก่อน (หลายนาที) จะแสดงตัวนับเวลา "กำลังรอเครื่องตอบ / โหลดโมเดล…" - ทดสอบแล้ว: Ollama และ LM Studio บน PGX จริง (ผ่าน chat.wxch.org) และหน้าเว็บด้วยข้อมูลจำลองรูปแบบเดียวกัน; vLLM ยังไม่ได้ทดสอบเพราะรอติดตั้ง