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 KeysCreate 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 มีไว้เพื่อให้สามารถตรวจสอบทุกคำตอบได้