Skip to main content

OpenThai 2.0 Legal ThaiLLM

ฟรี จนถึง 30 ก.ย. 2026
ตอนนี้: 0 IC — ฟรีพร้อมคีย์ API ของ iApp (ลงทะเบียนฟรี)หลังโปรโมชั่น: 0.01 / 0.02 IC ต่อ 1K โทเค็นอินพุต/เอาต์พุต (เท่ากับ Thanoy Legal AI)
v2.0 ใช้งานอยู่ POST /v3/llm/openthai2p0-legal/chat/completions

OpenThai 2.0 Legal (iapp/openthai2.0-legal-thaillm-nemotron-3-nano-30b-a3b) เป็นโมเดล LLM กฎหมายไทยน้ำหนักเปิด (open-weight) ที่สร้างขึ้นบน NVIDIA Nemotron-3-Nano-30B-A3B โดยทีม OpenThai (AIEAT / บริษัท ไอแอพพ์เทคโนโลยี จำกัด) API ที่โฮสต์อยู่นี้ เชื่อมต่อ RAG มาพร้อมใช้งานทันที: ทุกคำขอจะทำการค้นหาแบบผสมผสาน (hybrid-search) ใน คลังข้อมูลกฎหมายไทย 39 ฉบับ จำนวน 6,300 มาตรา (BM25 + การค้นหาด้วย Qwen3 embedding + reranker) และอ้างอิงคำตอบจากข้อความกฎหมายปัจจุบัน — พร้อมส่งคืนมาตราที่ค้นพบเพื่อให้คุณแสดงผลหรือตรวจสอบได้

ทดลองใช้งาน Demo​

Try OpenThai 2.0 Legal — Live

FREE API · 1 MONTH

Real model, real answers. Free with your iApp API key until 30 Sep 2026.

📚
RAG connected — answers grounded in real statute text

This API retrieves from a 39-law, 6,300-section Thai statute corpus (hybrid BM25 + embedding search + reranker) and grounds every answer in the current law text. The sections it selects are shown below each answer. Switch to Closed-book mode (rag: false in the API) to compare with the bare model.

Full legal analysis in prose, citing มาตรา — grounded in auto-retrieved current statute text.

Try an example:
🧑‍💻 Developer view — the API call behind this demo

This curl command updates live as you change the question, mode and toggles above. Run it in your terminal with your own API key — it is exactly what this page sends.

Request (curl)
curl -s https://api.iapp.co.th/v3/llm/openthai2p0-legal/chat/completions \
  -H "Content-Type: application/json" \
  -H "apikey: YOUR_IAPP_API_KEY" \
  -d '{
  "model": "openthai2.0-legal",
  "rag": true,
  "rag_inject": "system",
  "messages": [
    {
      "role": "system",
      "content": "You are a Thai legal expert. Answer with legal analysis and cite the relevant มาตรา."
    },
    {
      "role": "user",
      "content": "จำเลยขีดฆ่าและฉีกเอกสารหลักฐานแห่งหนี้ แม้ยังอ่านได้ ถือเป็นความผิดสำเร็จหรือเพียงพยายามกระทำผิด"
    }
  ],
  "temperature": 0,
  "top_p": 1,
  "max_tokens": 4096,
  "chat_template_kwargs": {
    "enable_thinking": true
  },
  "stream": true,
  "stream_options": {
    "include_usage": true
  }
}'

Outputs are decision support, not legal advice. Verify every citation against the current law. Free with an iApp API key to 30 Sep 2026; standard pricing afterwards is 0.01/0.02 IC per 1K input/output tokens (same as Thanoy Legal AI).

เริ่มต้นใช้งาน​

  1. สิ่งที่ต้องมี

    • คีย์ API ฟรีของ iApp — ลงทะเบียน → API Keys → Create New API Key
    • คำถามเกี่ยวกับกฎหมายไทย
  2. Endpoint

    Base URLhttps://api.iapp.co.th/v3/llm/openthai2p0-legal
    EndpointPOST /chat/completions (เข้ากันได้กับ OpenAI)
    Modelopenthai2.0-legal
    Authapikey: <key> header หรือ Authorization: Bearer <key> (OpenAI SDK ใช้งานได้ทันที)
    Rate limit30 คำขอ/นาที ต่อ IP (ฟรี)
  3. พารามิเตอร์ RAG (ส่วนเสริมของ API นี้ นอกเหนือจาก schema ของ OpenAI)

    FieldDefaultความหมาย
    ragtrueค้นหาส่วนของกฎหมายไทยบนเซิร์ฟเวอร์และอ้างอิงคำตอบ false = โมเดลเปล่า (closed-book)
    rag_top_k8 (สูงสุด 20)จำนวนส่วนที่ค้นพบที่จะแทรกใน prompt (6 เมื่อ rag_inject: "system")
    rag_inject"user""user" = โครงสร้าง Provided context ที่โมเดลถูกฝึกมา เหมาะสำหรับคำตอบที่มีการอ้างอิง JSON "system" = การอ้างอิงเป็นคำแนะนำใน system prompt เหมาะสำหรับบทความ/การวิเคราะห์แบบยาว
    dekafalseค้นคำพิพากษาศาลฎีกาจริง (133k ฉบับ) มาแนบเป็นแนวเทียบเคียง แนะนำสำหรับความเห็น/บทวิเคราะห์ยาว ปิดสำหรับคำถามอ้างมาตราสั้น ๆ
    unanswerable_mode"replace"เมื่อคำตอบอ้างอิงตัวบทไม่ได้: "replace" = ส่งข้อความปฏิเสธมาตรฐานแทนคำตอบ, "append" = คำตอบ + คำเตือน, "flag" = คำตอบเดิม ติดธงอย่างเดียว ดู Guardrails
    web"auto"ค้นเว็บสำหรับคดี/เหตุการณ์ปัจจุบัน: "auto" = เฉพาะเมื่อคำถามระบุชื่อคดี/บุคคลจริงหรือมีคำแนวข่าว, true = ทุกครั้ง, false = ไม่ค้น
    guardtrueตรวจคำถามก่อนตอบ (กฎหมาย/มาตรา/คดีที่ไม่มีจริง เรื่องสมมติ นอกขอบเขต) false = ปิด (ไม่แนะนำ)

    ทุกการตอบสนองจาก RAG จะมีอาร์เรย์ retrieved_documents ระดับบนสุด — {law, section, text, score} สำหรับแต่ละมาตราที่ใช้ในการตอบสนอง เมื่อใช้งานแบบสตรีมมิ่ง (streaming) จะปรากฏใน SSE chunk แรก

วิธีรับ API Key?

กรุณาไปที่หน้า API Key Management เพื่อดูคีย์ API ที่มีอยู่ของคุณ หรือขอคีย์ใหม่

ตัวอย่างโค้ด​

cURL — RAG ทำงาน (ค่าเริ่มต้น)​

curl -X POST 'https://api.iapp.co.th/v3/llm/openthai2p0-legal/chat/completions' \
-H 'apikey: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"model": "openthai2.0-legal",
"messages": [
{"role": "user", "content": "ลักทรัพย์ในเวลากลางคืน ผิดมาตราใด"}
],
"max_tokens": 1024
}'

ผลลัพธ์ (ตัดทอน)​

{
"id": "chatcmpl-...",
"model": "openthai2.0-legal-thaillm-nemotron-3-nano-30b-a3b",
"choices": [
{"message": {"role": "assistant", "content": "ลักทรัพย์ในเวลากลางคืน เป็นการกระทำความผิดตามมาตรา ๓๓๕ (๑) แห่งประมวลกฎหมายอาญา ..."}}
],
"usage": {"prompt_tokens": 2874, "completion_tokens": 17},
"rag": true,
"retrieved_documents": [
{"law": "ประมวลกฎหมายอาญา", "section": "335", "text": "ผู้ใดลักทรัพย์ (๑) ในเวลากลางคืน ...", "score": 0.9989},
{"law": "ประมวลกฎหมายอาญา", "section": "334", "text": "ผู้ใดเอาทรัพย์ของผู้อื่น ...", "score": 0.9936}
]
}

Python — OpenAI SDK (ใช้งานได้ทันที, Bearer auth)​

from openai import OpenAI

client = OpenAI(
base_url="https://api.iapp.co.th/v3/llm/openthai2p0-legal",
api_key="YOUR_API_KEY",
)

r = client.chat.completions.create(
model="openthai2.0-legal",
messages=[{"role": "user", "content": "ลักทรัพย์ในเวลากลางคืน ผิดมาตราใด"}],
max_tokens=1024,
# extra_body={"rag": False} # โมเดลเปล่า (closed-book)
# extra_body={"rag_inject": "system"} # บทความ / การวิเคราะห์แบบยาว
)
print(r.choices[0].message.content)
print(r.model_extra.get("retrieved_documents")) # มาตรากฎหมายที่คำตอบใช้อ้างอิง

Streaming (SSE) — มาตราที่ค้นพบจะมาใน chunk แรก​

stream = client.chat.completions.create(
model="openthai2.0-legal",
messages=[{"role": "user", "content": "อธิบายความผิดฐานลักทรัพย์โดยละเอียด"}],
max_tokens=2048,
stream=True,
)
for chunk in stream:
docs = chunk.model_extra.get("retrieved_documents")
if docs:
print("Grounded in:", [(d["law"], d["section"]) for d in docs])
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)

ตั้งแต่ 16 ก.ย. 2569 คำตอบจะสตรีม ทีละโทเค็นในทุกค่า unanswerable_mode ก่อนหน้านี้โหมด replace จะกักคำตอบทั้งหมดไว้จนกว่าจะตรวจการอ้างอิงเสร็จ คำตอบจึงมาเป็นก้อนเดียว ตอนนี้ร่างคำตอบจะสตรีมทันที และในกรณีที่ผลตรวจสั่งแทนที่หรือตัดคำตอบ (ประมาณ 1–3 % ของคำตอบ) สตรีมจะต่อด้วยบรรทัดคั่น และข้อความแทนที่ chunk สุดท้ายจะมี content_modified: "replaced" (หรือ "pruned") และ replacement_content เพื่อให้ UI สลับข้อความในกล่องคำตอบ เป็นข้อความแทนที่แทนการแสดงทั้งสองอย่าง ส่ง "hold_until_verdict": true หากต้องการพฤติกรรมเดิม (กักคำตอบไว้จนตรวจเสร็จ)

การจัดการคำตอบที่ถูกแทนที่ระหว่างสตรีม​

สตรีมเป็น SSE แบบ OpenAI ตามปกติ ร่างคำตอบมาเป็น chunk delta.content เมื่อผลตรวจสั่งแทนที่หรือตัดคำตอบ จะมี content chunk อีกหนึ่งชิ้นตามมา เป็น \n\n---\n + ข้อความแทนที่ จากนั้นเป็น chunk finish_reason: "stop" และ chunk สุดท้ายที่ choices: [] ซึ่งมี usage ฟิลด์ผลตรวจ และ replacement_content ไม่มีอะไรตามหลัง data: [DONE]

data: {"choices":[{"delta":{"content":"ไม่"}}], ...}                      ← ร่างคำตอบสตรีมทีละโทเค็น
data: {"choices":[{"delta":{"content":"พบ"}}], ...}
...
data: {"choices":[{"delta":{"content":"\n\n---\nขออภัย ระบบไม่พบตัวบทกฎหมาย … แล้วถามใหม่ให้ชัดเจนขึ้น"}}]} ← มีเฉพาะเมื่อถูกแทนที่/ตัด
data: {"choices":[{"delta":{"content":""},"finish_reason":"stop"}]}
data: {"choices":[], "usage":{...}, "answerable":false, "answerable_reason":"no_relevant_law_found",
"content_modified":"replaced", "replacement_content":"ขออภัย ระบบไม่พบตัวบทกฎหมาย … แล้วถามใหม่ให้ชัดเจนขึ้น", ...}
data: [DONE]

content_modified เป็น null สำหรับคำตอบปกติ (ไม่ต้องทำอะไร), "replaced" (แสดง replacement_content แทนร่างคำตอบ) หรือ "pruned" (ร่างคำตอบที่ตัดบรรทัดซึ่งอ้างมาตราไม่ตรงตัวบทออก: replacement_content คือข้อความที่ตัดแล้วพร้อมหมายเหตุ) ทั้งสองกรณีให้สลับข้อความในกล่องคำตอบ:

# Python (openai SDK): แสดงร่างคำตอบสด ๆ แล้วสลับถ้า chunk สุดท้ายสั่ง
draft, replacement = "", None
with client.chat.completions.create(model="openthai2.0-legal", messages=msgs, max_tokens=2048, stream=True,
extra_body={"rag_inject": "system", "deka": True, "web": "auto"}) as stream:
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
draft += chunk.choices[0].delta.content
ui.set_answer(draft) # แสดงผลทันที
extra = chunk.model_extra or {}
if extra.get("replacement_content") is not None:
replacement = extra["replacement_content"] # chunk สุดท้าย: ผลตรวจแทนที่/ตัดร่างคำตอบ
final_text = replacement if replacement is not None else draft
ui.set_answer(final_text)
// JavaScript (fetch + SSE): ตรรกะเดียวกันในเบราว์เซอร์หรือ Node
let draft = "", replacement = null;
const res = await fetch(url, { method: "POST", headers, body: JSON.stringify({ ...body, stream: true }) });
const reader = res.body.getReader(), dec = new TextDecoder(); let buf = "";
while (true) {
const { value, done } = await reader.read(); if (done) break;
buf += dec.decode(value, { stream: true });
let i; while ((i = buf.indexOf("\n\n")) >= 0) {
const line = buf.slice(0, i).trim(); buf = buf.slice(i + 2);
if (!line.startsWith("data: ") || line === "data: [DONE]") continue;
const o = JSON.parse(line.slice(6));
for (const c of o.choices || []) if (c.delta?.content) { draft += c.delta.content; ui.setAnswer(draft); }
if (o.replacement_content !== undefined && o.replacement_content !== null) replacement = o.replacement_content;
}
}
ui.setAnswer(replacement ?? draft);

ถ้า UI สลับข้อความไม่ได้ ให้ส่ง "hold_until_verdict": true ใน request body คำตอบจะถูกกักไว้จนตรวจเสร็จแล้วส่งเป็น content chunk เดียว (พฤติกรรมก่อน 16 ก.ย.) และจะไม่มี replacement_content

JSON citation contract (โหมด RAG ที่โมเดลถูกฝึกมา)​

สำหรับคำตอบที่เครื่องสามารถอ่านได้ ให้ใช้ system prompt ที่โมเดลถูก RL-trained มา — โดยจะอ้างอิงเฉพาะมาตราที่อยู่ในบริบทที่ค้นพบเท่านั้น:

SYSTEM = (
"You are OpenThaiGPT-Legal, an expert assistant on Thai law. You are given a legal "
"question and the exact statutory sections needed to answer it. Reason step by step in "
"English, then give the final answer in Thai. Cite ONLY sections present in the provided "
"context, using each section's exact law_name and bare section number (e.g. 132, 77/1). "
'Output the final answer as JSON: {"answer": "<Thai answer>", '
'"citations": [{"law": "<law_name>", "section": "<bare id>"}]}.'
)

r = client.chat.completions.create(
model="openthai2.0-legal",
messages=[
{"role": "system", "content": SYSTEM},
{"role": "user", "content": "หมิ่นประมาทโดยการโฆษณา มีความผิดตามมาตราใด"},
],
temperature=0.0, max_tokens=1024,
extra_body={"chat_template_kwargs": {"enable_thinking": False}},
)
# -> {"answer": "...มาตรา 328", "citations": [{"law": "ประมวลกฎหมายอาญา", "section": "328"}]}

Guardrails, การตรวจมาตรา และการค้นเว็บ​

เพิ่มเมื่อ 11 กันยายน 2569 — ใช้งานได้ทันทีบน API ที่ให้บริการ ไม่ต้องแก้ฝั่งผู้เรียก

API จะไม่ตอบคำถามที่อ้างอิงตัวบทไม่ได้อีกต่อไป มี 3 ชั้นทำงานรอบโมเดล

  1. ตรวจคำถามก่อนตอบ (premise guard) — คำถามถูกเทียบกับ corpus, ฐานคำพิพากษาศาลฎีกา และตัวจำแนกขนาดเล็ก ถ้าระบุชื่อกฎหมาย เลขมาตรา หรือเลขคดีที่ไม่มีจริง เป็นเรื่องสมมติ หรือไม่ใช่คำถามกฎหมาย API ตอบข้อความปฏิเสธมาตรฐานทันที (ไม่มีการสร้าง token)
  2. ตรวจมาตราหลังตอบ (citation check) — ทุก มาตรา ในคำตอบถูกเทียบกับตัวบทที่ค้นได้ มาตราที่โมเดลอ้างจากความจำจะถูกเปิดตัวบทจริงจาก corpus แล้วให้ reranker ตรวจว่าประโยคที่อ้างตรงกับตัวบทหรือไม่ ถ้าตรงถือว่าอ้างอิงได้ ถ้าไม่ตรงส่วนนั้นจะถูกตัดออก คำตอบที่ไม่เหลือส่วนที่อ้างอิงได้จะถูกแทนด้วยข้อความปฏิเสธ
  3. ค้นเว็บสำหรับคดีปัจจุบัน — เมื่อคำถามพูดถึงคดีหรือบุคคลจริง (คดีอดีตหลวงพ่อโชติ ผิดอะไร) หรือมีคำแนวข่าว API จะค้นเว็บ อ่านข่าวอันดับต้น ๆ สกัดข้อหาที่ถูกแจ้งจริง ค้นตัวบทของข้อหานั้นแล้วตอบจากตัวบท คดีที่ไม่มีแหล่งข่าว (ไม่นับ social media) รายงานจะถูกปฏิเสธ (case_not_found)

ฟิลด์ในผลลัพธ์​

Fieldความหมาย
answerable / answerable_reasonfalse เมื่อคำตอบถูกปฏิเสธหรือแก้ไข เหตุผล: no_relevant_law_found, ungrounded_citations, model_declined, empty_answer, unknown_law, unknown_section, unknown_case, case_not_found, fictional_premise, not_legal_question
content_modifiednull, "replaced" (ส่งข้อความปฏิเสธแทนคำตอบ), "pruned" (ตัดส่วนที่อ้างอิงไม่ได้ออก), "appended" (ต่อท้ายคำเตือน) ข้อความเดิมอยู่ใน original_content
citations{total, grounded, ungrounded: [{law, section}], lookup: [{law, section, score, ok}]} — lookup คือมาตราที่โมเดลอ้างจากความจำและคะแนนเทียบกับตัวบทจริง
retrieval_confidenceคะแนน reranker สูงสุดของมาตราที่ค้นได้ (0–1)
guard{label: LEGAL / CASE / FICTION / OTHER, findings, deka_missing, deka_found, refused, reason}
web{used, trigger, query, provider, results: [{title, url, snippet, published}], offences, case_evidence, cached} — เมื่อ used เป็น true ควรแสดง results เป็นแหล่งที่มา

แบบสตรีมมิ่ง ฟิลด์เหล่านี้อยู่ใน SSE chunk สุดท้าย (chunk ที่มี usage) ส่วน retrieved_documents ยังอยู่ใน chunk แรก

ตัวอย่าง — คดีที่ไม่มีอยู่จริง​

POST /chat/completions
{"model": "openthai2.0-legal", "messages": [{"role": "user", "content": "คดีหม่ำเท่งโหน่ง ผิดมาตราอะไร"}]}

{
"choices": [{"message": {"role": "assistant",
"content": "ขออภัย ไม่พบข่าวหรือข้อมูลคดีจากแหล่งข่าวที่น่าเชื่อถือเกี่ยวกับ \"หม่ำเท่งโหน่ง\" จึงไม่สามารถวิเคราะห์ทางกฎหมายได้ ..."}}],
"usage": {"prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0},
"answerable": false, "answerable_reason": "case_not_found", "content_modified": "replaced",
"guard": {"label": "CASE", "refused": true, "reason": "case_not_found"},
"web": {"used": false, "trigger": "guard_refused"}
}

ตัวอย่าง — คดีจริงที่กำลังเป็นข่าว​

{"model": "openthai2.0-legal", "messages": [{"role": "user", "content": "คดีอดีตหลวงพ่อโชติ ผิดอะไร"}], "deka": true}

{
"choices": [{"message": {"content": "คดีอดีตหลวงพ่อโชติ ผิดฐานเป็นเจ้าพนักงานเบียดบังทรัพย์และปฏิบัติหน้าที่โดยมิชอบ ตามประมวลกฎหมายอาญา มาตรา 147 และมาตรา 157 และฐานฟอกเงินตามพระราชบัญญัติป้องกันและปราบปรามการฟอกเงิน พ.ศ. 2542 มาตรา 5 และมาตรา 60 ..."}}],
"answerable": true, "answerable_reason": "ok",
"citations": {"total": 4, "grounded": 4, "ungrounded": []},
"guard": {"label": "CASE", "refused": false},
"web": {"used": true, "trigger": "named_case", "provider": "google",
"offences": ["เบียดบังทรัพย์", "ฟอกเงิน", "ปฏิบัติหน้าที่มิชอบ"],
"case_evidence": {"entity": "อดีตหลวงพ่อโชติ", "news_sources": ["thestandard.co", "www.thairath.co.th"], "found": true},
"results": [{"title": "กองปราบฯ คุมตัว 'สมีโชติ' คดีฟอกเงิน-เบียดบังทรัพย์ ...", "url": "https://thestandard.co/...", "published": "2026-09-11T01:22:57+00:00"}]}
}

หมายเหตุ​

  • ข้อความทักทายหรือถามว่า "คุณคือใคร" (สวัสดีครับ, คุณคือใคร, แนะนำตัว, hello, ขอบคุณ) จะได้รับข้อความแนะนำตัวของ OpenThai 2.0 Legal ภาษาไทยแทนการปฏิเสธว่าไม่ใช่คำถามกฎหมาย (ตั้งแต่ 16 ก.ย. 2569; guard.kind = greeting / identity / thanks ไม่เรียกโมเดล) ถ้าทักทายแล้วถามกฎหมายต่อในข้อความเดียวกัน ระบบจะตอบเป็นคำถามกฎหมายตามปกติ
  • ศัพท์กฎหมายที่ตัวบทไม่ได้ใช้คำนั้นตรง ๆ (คดีอุทลุม, ครอบครองปรปักษ์, ทางจำเป็น, นิติกรรมอำพราง, ฟ้องซ้ำ / ฟ้องซ้อน, ประกันตัว, เช็คเด้ง, เลิกจ้างไม่เป็นธรรม, อุ้มหาย …) ระบบมีอภิธานศัพท์ (ตั้งแต่ 17 ก.ย. 2569): มาตราที่นิยามเรื่องนั้นจะถูกใส่ในบริบทเสมอ การค้นตัวบทและฎีกาใช้ถ้อยคำตามตัวบท และ guard.glossary แสดงคำที่พบ คำว่า "คดี" ตามด้วยประเภทคดี (คดีอุทลุม, คดีอนาถา, คดีมโนสาเร่ …) ถือเป็นคำถามกฎหมาย ไม่ใช่ชื่อคดีเฉพาะ
  • คำถามเกี่ยวกับคดีปัจจุบันใช้เวลาเพิ่ม 1–3 วินาที (ค้นเว็บ + อ่านข่าว 2–3 หน้า) ผลค้นและเนื้อหาหน้าเว็บถูก cache 1 ชั่วโมง คำถามซ้ำเรื่องเดิมจึงไม่ช้า
  • โจทย์สมมติแบบข้อสอบ ("นายแดงลักทรัพย์นายดำ …") ไม่ถูกนับเป็นคดีจริง ยังตอบจากตัวบทตามเดิม
  • วัดด้วยชุดทดสอบ guardrail 107 ข้อ (กฎหมาย/มาตรา/คดีที่ไม่มีจริง เรื่องสมมติ นอกขอบเขต พิมพ์ผิด คดีปัจจุบัน คำถามจริงจาก NitiBench): พฤติกรรมถูกต้อง 105/107 ทั้งเปิดและปิด thinking ก่อนอัปเดตนี้ 75/105

คุณสมบัติและความสามารถ​

คุณสมบัติหลัก​

  • RAG ฝั่งเซิร์ฟเวอร์ในตัว — การค้นหาแบบผสมผสาน (hybrid BM25 + embedding) พร้อม reranking บนข้อความปัจจุบันของกฎหมายไทยหลัก 39 ฉบับ (ประมวลกฎหมายอาญา, ป.พ.พ., วิ.แพ่ง, วิ.อาญา, ประมวลรัษฎากร และอีก 34 ฉบับ) รวมกับ พ.ร.บ. พ.ร.ก. พ.ร.ฎ. และกฎกระทรวงอีก 2,026 ฉบับจากฐานสำนักงานคณะกรรมการกฤษฎีกา — รวม 54,215 มาตราที่ยังบังคับใช้; อัตราโทษหลังปี 2560 ได้รับการตรวจสอบแล้ว
  • การอ้างอิงมาตราที่ตรวจสอบได้ — ชื่อกฎหมายที่ถูกต้อง + มาตรา, ทั้งแบบข้อความทั่วไปหรือเป็นสัญญา JSON ที่แน่นอน; retrieved_documents ช่วยให้คุณตรวจสอบทุกคำตอบได้
  • โหมดการใช้เหตุผล — เพิ่ม "chat_template_kwargs": {"enable_thinking": true} เพื่อให้แสดงเหตุผลทางกฎหมายแบบทีละขั้นตอน ส่งกลับแยกใน message.reasoning_content (delta.reasoning_content เมื่อสตรีม) พร้อมจำกัดงบ reasoning อัตโนมัติ
  • น้ำหนักเปิด (Open weights) — สามารถดาวน์โหลดและโฮสต์โมเดลเดียวกันได้เองบน GPU เพียง 24 GB (NVFP4)

กรณีการใช้งาน​

  • แชทบอทและเครื่องมือค้นคว้าทางกฎหมาย — คำตอบที่อ้างอิงพร้อมมาตราที่ผู้ใช้สามารถตรวจสอบได้
  • ผู้ช่วยร่างและทบทวนเอกสาร — สัญญา JSON citation สามารถนำไปใช้กับระบบอัตโนมัติได้โดยตรง
  • ผลิตภัณฑ์ Legal-tech — แสดงแผง retrieved_documents เพื่อแสดง เหตุผล ที่โมเดลตอบเช่นนั้น

การตั้งค่าการสร้างที่แนะนำ​

สำหรับใช้งานจริง (แนะนำ, 14 ก.ย. 2569):

{"temperature": 0.6, "top_p": 0.95, "repetition_penalty": 1.05, "min_p": 0.05, "max_tokens": 2048,
"rag_inject": "system", "deka": true, "deka_top_k": 2, "web": "auto", "unanswerable_mode": "replace"}

วัดจากชุดคำถามที่มักทำให้โมเดลวนซ้ำ (70 คำถาม + 8 คำถาม × 8 seed ต่อการตั้งค่า): ค่าเดิม (temperature 0.7, top_p 0.9 ไม่มี penalty) ทำให้คำตอบวนซ้ำจนชนเพดาน 4,096 โทเค็นประมาณ 1–2 % ของคำตอบ ส่วนค่าที่แนะนำไม่พบการวนซ้ำเลยใน 134 ครั้ง โดยความถูกต้องของการอ้างมาตรา เท่าเดิม (99 % ของมาตราที่อ้างพบในตัวบทที่ค้นได้) และความยาวคำตอบปกติ

  • ถ้าไคลเอนต์ไม่ส่ง repetition_penalty / presence_penalty / frequency_penalty ระบบจะใส่ repetition_penalty 1.05 ให้อัตโนมัติ
  • ตัวป้องกันการวนซ้ำ: ระบบตรวจจับข้อความที่วนซ้ำ (บล็อกเดิมซ้ำ 3 ครั้ง) และตัดออก — แบบสตรีมจะหยุดเครื่องยนต์ ณ จุดนั้น แบบไม่สตรีมจะตัดข้อความ และตอบกลับด้วย content_modified: "loop_cut"
  • max_tokens 2048 เพียงพอสำหรับความเห็นทางกฎหมายฉบับเต็ม (คำตอบเฉลี่ย ≈ 500–650 โทเค็น) และลดเวลารอกรณีเลวร้ายลงครึ่งหนึ่ง
งานtemperaturethinkingrag_inject
ตอบพร้อมอ้างอิง (JSON)0.0ปิดuser (ค่าเริ่มต้น)
บทความ/วิเคราะห์กฎหมาย0.0เปิดsystem
สนทนา / ใช้งานจริง0.6 (+ repetition_penalty 1.05)ปิดsystem

การสนทนาหลายรอบ (multi-turn)​

ส่งบทสนทนาทั้งหมดใน messages (รวมข้อความของ assistant) โมเดลอ่านประวัติอยู่แล้ว และตั้งแต่ 14 ก.ย. ชั้น RAG ก็อ่านด้วย: คำถามต่อเนื่องสั้น ๆ ("แล้วถ้าทำงานมา 3 ปีล่ะ", "การเล่นหมายเลข 5 ถึง 15 ในบัญชี ข. คือ") จะถูกค้นตัวบทร่วมกับคำถามก่อนหน้า (guard.retrieval_query แสดงคำค้นที่รวมแล้ว) ตัวกรองจะจำแนกตามบริบท และข้อความที่มีรูปแบบเป็นคำถามต่อเนื่องในบทสนทนากฎหมายจะไม่ถูกปฏิเสธว่า "ไม่ใช่คำถามกฎหมาย" ส่วนข้อความนอกเรื่องที่จบในตัว ("สูตรทำต้มยำกุ้ง") ยังถูกปฏิเสธเหมือนเดิม

ความยาวบริบท (context length)​

ตั้งแต่ 16 ก.ย. 2569 เอ็นจินหลักรับ prompt ได้สูงสุด 262,144 โทเค็น (เอ็นจินสำรอง 131,072) ข้อความภาษาไทยใช้ประมาณ 1.3–1.8 อักขระต่อโทเค็น ดังนั้น prompt ขนาด 256K เต็ม ≈ 350–450K อักขระไทย

  • ตัดข้อความให้อัตโนมัติ prompt ที่ยาวเกินหน้าต่างของเอ็นจินจะไม่ถูกปฏิเสธ ระบบนับโทเค็นด้วย tokenizer ของเอ็นจินเอง แล้วตัด ส่วนกลาง ของข้อความ user ที่ยาวที่สุดให้ prompt + max_tokens พอดี โดยใส่เครื่องหมายภาษาไทยไว้ตรงจุดที่ตัด response จะมีฟิลด์ truncation: {prompt_tokens_before, prompt_tokens_after, removed_chars, limit} (ใน body แบบไม่ stream และใน chunk แรกของ stream) prompt สั้นจะไม่มีฟิลด์นี้
  • ความแม่นยำไม่คงที่ตลอดหน้าต่าง จากการทดสอบฝังข้อเท็จจริง (needle test) ในตัวบทกฎหมายจริง โมเดลหาเจอทั้งสองจุดที่ 73K และ 92K โทเค็น เจอหนึ่งในสองที่ 115–140K และไม่เจอเลยตั้งแต่ 165K ขึ้นไป เอกสารที่ต้องการคำตอบแม่นยำควรอยู่ต่ำกว่า ประมาณ 90K โทเค็น (≈150K อักขระไทย) ถ้ายาวกว่านั้นให้แบ่งเอกสารหรือถามทีละส่วน
  • ต้นทุน prompt 250K โทเค็นใช้เวลาประมวลผลราว 30–35 วินาที และทำให้คำขออื่นบนเอ็นจินเดียวกันช้าลงระหว่างนั้น ส่วนคำขอสั้น ๆ ไม่ได้รับผลกระทบจากหน้าต่างที่ใหญ่ขึ้น
  • ขนาดคำขอ รับ body ได้ถึง 64 MB (ตั้งแต่ 16 ก.ย. 2569) prompt ภาษาไทย 256K โทเค็นเต็มมีขนาดราว 1.3 MB body ที่ใหญ่กว่า 500 KB จะถูกส่งผ่านเส้นทาง relay แยกไปยังเอ็นจินเดียวกัน จึงมี latency เพิ่มขึ้นไม่กี่ร้อยมิลลิวินาที

การตรวจสอบสถานะระบบ (health check)​

endpoint ที่ไม่ต้องใช้ API key และไม่คิดเครดิต บนโฮสต์เดียวกัน:

curl -s https://api.iapp.co.th/v3/llm/openthai2p0-legal/health/h100     # 200 ขณะที่ H100 reserved stack ปกติ มิฉะนั้น 503
curl -s https://api.iapp.co.th/v3/llm/openthai2p0-legal/health # 200 ขณะที่ API ยังตอบได้ (H100 หรือสำรอง), 503 เมื่อล่มทั้งคู่

/health คืน status: "ok" (H100 ให้บริการ), "degraded" (เหลือแต่ระบบสำรอง) หรือ "down" พร้อมอ็อบเจ็กต์ h100 และ backup ที่มี healthy, probe (ผลและเวลาตอบของการตรวจล่าสุด), load (จำนวนคำขอที่กำลังทำงานและคิวของเอ็นจิน) และ checked_at ส่วน /health/h100, /health/rag (เอ็นจิน embedding + reranker และดัชนี RAG บน H100) และ /health/backup คืนอ็อบเจ็กต์เดียวโดย HTTP status ตรงกับสถานะจริง ระบบเฝ้าระวังจึงดูแค่ status code ได้ หน้าสถานะแบบเดียวกับ status.iapp.co.th (แถบ uptime 90 วัน + เหตุขัดข้องล่าสุด) อยู่ที่ api.iapp.co.th/v3/llm/openthai2p0-legal/status (JSON ที่ …/status/api)

การสนับสนุนการตัดสินใจ, ไม่ใช่คำแนะนำทางกฎหมาย

ผลลัพธ์จะต้องได้รับการตรวจสอบกับกฎหมายปัจจุบันโดยผู้เชี่ยวชาญที่ผ่านการรับรองก่อนนำไปใช้ คุณภาพของการค้นหาเป็นตัวขับเคลื่อนผลลัพธ์ — อาร์เรย์ retrieved_documents มีไว้เพื่อให้สามารถตรวจสอบทุกคำตอบได้