OpenThai 2.0 Legal
在 OpenThai 2.0 Legal 上进行对话补全,依据其检索索引中 2,065 部泰国法律的条文作答,并返回所依据的条文,答案在送达前经过检查;OpenAI 兼容。
/v3/llm/openthai2p0-legal/chat/completions试一试- 价格0.01 / 0.02 IC每 1k 词元,输入 / 输出
- 实测0.772
- 累计调用55.5K次
- v2.0
- 运行中
- 基准报告 (PDF)
输入
- model
- openthai2.0-legal
- messages
- role: user content: ลักทรัพย์ในเวลากลางคืน ผิดมาตราใด
- max_tokens
- 1024
输出POST /v3/llm/openthai2p0-legal/chat/completions
- id
- chatcmpl-...
- model
- openthai2.0-legal-thaillm-nemotron-3-nano-30b-a3b
- choices
- message: { role, content }
- usage
- prompt_tokens: 2874 completion_tokens: 17
- rag
- true
- retrieved_documents
- 2 × law: ประมวลกฎหมายอาญา section: 335 text: ผู้ใดลักทรัพย์ (๑) ในเวลากลางคืน ... score: 0.9989
- answerable
- true
- answerable_reason
- ok
- content_modified
- —
- citations
- total: 1 grounded: 1 ungrounded: []
请求
JSON,采用 OpenAI 聊天补全的格式;OpenAI SDK 只需将 base URL 设为 https://api.iapp.co.th/v3/llm/openthai2p0-legal,密钥以 apikey 或 Authorization: Bearer 传入即可。本 API 特有的字段用于控制检索以及答案前后的检查。
请求头
apikeystring必填请求体
modelstring必填openthai2.0-legal。messagesarray必填role 与 content 的对象。请发送完整历史,包括 assistant 回合;简短的追问会与上一个问题一起检索。ragbooleantrue:先检索法条,再据此作答。false 为不查资料的裸模型。rag_top_kintegerrag_inject 为 system 时为 6。rag_injectstringuser(默认)把条文放入模型训练时的框架,最适合 JSON 引用式回答;system 把条文作为参考放入系统提示,最适合长篇分析。dekabooleanfalse。true 时还会检索最高法院判决(共 133,000 份),并将最相近的判决作为类比裁判注入提示;数量由 deka_top_k 设定。用于长篇分析;简短的引用式回答请保持关闭。webstringauto(默认)仅在问题指名真实案件或人物、或含新闻用语时搜索;true 总是搜索;false 从不搜索。unanswerable_modestringreplace(默认)改为返回标准拒答;append 保留答案并附加警告;flag 原样保留答案,只设置判定字段。guardbooleantrue:在模型运行前检查问题是否指名不存在的法律、条款或案件,是否基于虚构,是否属于法律问题,以及问题中是否夹带意在推翻或泄露您系统提示的指令。false 关闭该检查,不建议使用。hold_until_verdictbooleanstream 使用:扣留答案直至检查完成,再作为一个块发送,适用于无法替换已显示答案的界面。chat_template_kwargsobject{"enable_thinking": true} 开启逐步法律推理,推理内容与答案分开,在 message.reasoning_content 中返回(流式输出时为 delta.reasoning_content)。temperaturefloatseedintegerrepetition_penaltyfloatmax_tokensintegerstreambooleantrue 时以 server-sent events 逐词元返回。检索到的条文随第一块到达,判定字段随最后一块到达。价格
每次调用按每 1K 输入词元 0.01 IC、每 1K 输出词元 0.02 IC 计费。
对话设置
{"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"}
在一组为诱发循环而挑选的问题上共运行 134 次,这组设置没有出现重复循环,引用的依据比例不变:99% 的引用条文出现在检索文本中。旧默认值(temperature 0.7、top_p 0.9,不加惩罚)有 1 至 2% 的答案陷入循环,直至 4,096 词元的上限。若仍出现循环,会在其起始处截断,响应中标明 content_modified: "loop_cut"。JSON 引用式回答请使用 temperature 0.0、关闭推理、rag_inject 设为 user;文章或分析请使用 temperature 0.0、开启推理、rag_inject 设为 system。
响应
OpenAI 聊天补全对象,如右侧面板所示,另加本 API 特有的字段:检索到的内容,以及检查的判定。
choices[0]choices[0].messagechoices[0].message.contentretrieved_documentsarray答案所依据的条文,每条含 law、section、text 与 score
retrieved_documents.lawstringretrieved_documents.sectionstringretrieved_documents.textstringretrieved_documents.scorenumberanswerablebooleanfalseanswerable_reasonstringok,或无法回答的原因:no_relevant_law_found、ungrounded_citations、model_declined、empty_answer、unknown_law、unknown_section、unknown_case、case_not_found、fictional_premise、not_legal_question, instruction_override_detectedcontent_modifiedstringnull;否则为 replaced(以拒答替换答案)、pruned(删除无依据的行)、appended(附加警告)或 loop_cut。改动前的文本在 original_content 中。replacement_contentstringcontent_modified 为 replaced 或 pruned,用于代替草稿显示的文本citationsobjecttotal、grounded、ungrounded(无依据的条文),以及 lookup:模型凭记忆引用的条文及其与法条原文比对的得分retrieval_confidencenumberguardobjectlabel(LEGAL、CASE、FICTION、INJECTION 或 OTHER)、refused、reason,以及 glossary,即解析出的法律术语webobjectused),以及搜索结果 results,每项含 title 与 url;请将其作为来源展示truncationobjectprompt_tokens_before、prompt_tokens_after、removed_chars、limitragbooleanusageobjectidstringmodelstringchoicesarray同 OpenAI 格式
choices.messageobjectrole 与 content需要机器可读的答案时,使用模型训练所用的系统提示(与 JSON 约定一起发布在模型页面);模型将只引用检索上下文中存在的条文。
流式输出
草稿逐词元流式输出。当检查替换或裁剪草稿时(占答案的 1 至 3%),随后还会到达一个内容块,其中是分隔符 \n\n---\n 与替换文本;最后一块为 choices: [],其中带有 usage、判定字段与 replacement_content。data: [DONE] 之后不再有任何内容。replacement_content 有值时,请用它代替草稿显示:
- Python
- JavaScript
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) # live
extra = chunk.model_extra or {}
if extra.get("replacement_content") is not None:
replacement = extra["replacement_content"] # last chunk: the check replaced or pruned the draft
ui.set_answer(replacement if replacement is not None else draft)
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 != null) replacement = o.replacement_content;
}
}
ui.setAnswer(replacement ?? draft);
若界面无法替换已显示的内容,请发送 "hold_until_verdict": true;答案将在检查完成后作为一个块到达。
详情
实测
2026 年 10 月 28 日在生产环境测得,使用公开的 NitiBench 基准:仅发送问题,开启检索,以模型页面的系统提示词要求以 JSON 返回引用,temperature 为 0。引用 F1 衡量答案所引法律条文与正确条文的吻合程度,取值 0 到 1,多引条文会拉低分数;它只检查所引条文,不评判法律结论是否正确。
| 指标 | 结果 |
|---|---|
| 引用 F1,NitiBench-CCL,200 道民商、金融与公司法题目 | 0.772(95% CI 0.721–0.820) |
| 引用 F1,NitiBench-Tax,50 份泰国税务厅裁定 | 0.444(0.348–0.547) |
| 引用 F1,38 份未用于训练的较新税务裁定 | 0.218(0.119–0.332) |
| 检索到全部正确条文的问题占比:CCL / Tax / 未训练裁定 | 95.0% / 46.0% / 21.1% |
| 在提示中给出正确条文时的引用 F1:CCL / Tax | 1.000 / 0.848 |
| 经 API 的每次回答中位耗时,100 道题 | 1.43 秒;第 90 百分位 3.21 秒 |
模型的微调数据取自 NitiBench-CCL 来源数据集的训练部分,已剔除测试题;2021 年起的税务裁定也用于后期训练,因此 38 份未训练裁定才代表模型面对未见问题的表现。结果主要取决于检索:依据多个条文的税务裁定最难,依赖答案前请核对 retrieved_documents。由程序读取引用时请要求 JSON 输出;以普通聊天消息发送时,200 道 CCL 题中有 43 个答案未引用任何条文。方法与局限:基准测试报告 (PDF)。
答案前后的检查
- 模型运行前,将问题与法律语料库及最高法院判决比对。若问题指名不存在的法律、条款或案号,以虚构为前提,或不属于法律问题,会立即得到标准的泰文拒答,不生成任何词元。问候语会得到简短的自我介绍;问候后紧接问题的消息按问题作答。
- 问题中夹带的指令,例如“忽略之前的指令”、要求打印系统提示,或冒充管理员命令的文字,会在模型运行前被拒绝:
answerable为false,answerable_reason为instruction_override_detected,不生成任何词元。若答案复述了您系统提示的开头,在任何unanswerable_mode下都会被替换,您的系统提示不会被返回。在 2026 年 9 月 20 日至 10 月 20 日的 9,005 次调用中,该检查触发 13 次,全部是有意的攻击测试。 - 模型生成后,答案中的每个 มาตรา 都与检索到的条文比对;凭记 忆引用的条文会被查出,引用它的句子再与法条原文比对。无法找到依据的内容会被删除;若答案中已没有任何有依据的引用,则整个答案被替换为拒答。
- 对于真实的当前案件,API 阅读排名靠前的新闻报道,提取其中指明的罪名,检索这些罪名对应的法条并据此作答。指名的案件若没有任何新闻来源报道,则以
case_not_found拒答。这会增加 1 至 3 秒;搜索结果缓存一小时。考试式的假设题按法条作答,不进行搜索。
在一组 107 题的测试集上(涵盖不存在的法律、条款与案件、虚构内容、离题问题、错别字、当前案件以及真实考试题),无论是否开启推理,API 都在 105 题上表现正确;加入这些检查之前,105 题中有 75 题正确。法条中没有逐字写出的法律术语,例如 คดีอุทลุม、ครอบครองปรปักษ์ 或 ทางจำเป็น,会通过术语表解析到定义它们的条文。
长提示
提示最长可达 262,144 词元,约 350,000 至 450,000 个泰文字符;由备用引擎应答时为 131,072 词元。更长的提示不会被拒绝:服务会截去最长一条 user 消息的中间部分,使提示与 max_tokens 能够放入窗口,并以泰文标记注明截断位置,响应中带有 truncation。准确率在整个窗口内并不均匀。在使用真实法条文本的测试中,模型在 73K 和 92K 词元处找到了全部两个植入事实,在 115K 至 140K 处只找到其中一个,从 165K 起一个也找不到;因此需要精确回答的文本请控制在约 90K 词元(150,000 个泰文字符)以内。250K 词元的提示需要 30 至 35 秒读入。请求体 最大可达 64 MB;超过 500 KB 的请求体经由中继路径传输,会增加几百毫秒。
健康检查
GET https://api.iapp.co.th/v3/llm/openthai2p0-legal/health 无需密钥,也不计费:API 能够应答时返回 200,无法应答时返回 503,响应中的 status 为 ok、degraded(仅由备用引擎应答)或 down。状态页显示过去 90 天的可用率与近期事件。
限制
- 每个 IP 每分钟 30 次请求。
- 仅为决策支持,不是法律建议:任何答案在被依赖之前,须由合格专业人士对照现行法律核实。
- 答案的质量取决于检索到的条文;可通过
retrieved_documents审核每个答案。
数据处理
提示与补全在内存中处理,响应返回后不保留。依 PDPA 与 GDPR 取得同意并告知当事人,由作为数据控制者的您负责。权重在 Hugging Face,可在单张 24 GB GPU 上运行;教程可在您自己的机器上搭建同样的检索。