แปลข้อความเป็นภาษาไทย
เอนด์พอยต์แปลภาษาเปลี่ยนข้อความจากทุกภาษาเป็นภาษาไทยที่เป็นธรรมชาติ ควบคุมระดับภาษา คำทับศัพท์ และศัพท์เฉพาะได้ด้วยอภิธานศัพท์ บริบทเอกสาร และตัวอย่างสไตล์
POST /v1/translate แปลข้อความจากทุกภาษาต้นทางเป็นภาษาไทย ส่งข้อความเดี่ยวหรืออาร์เรย์ของหลายท่อนพร้อมรหัสโมเดล paxa-translation-lite-v1 แล้วรับคำแปลภาษาไทยหนึ่งรายการต่อหนึ่งท่อน พร้อมภาษาต้นทางที่ตรวจพบ เช่นเดียวกับทุกเอนด์พอยต์ ระบบคิดเครดิตก่อนประมวลผลและคืนให้อัตโนมัติเมื่อการประมวลผลล้มเหลว (เครดิต)
# --max-time covers a large request; curl defaults to no limit,
# but most clients and SDKs time out well before a big translation ends.
curl -X POST https://api.paxalabs.com/v1/translate \
--max-time 300 \
-H "Authorization: Bearer $PAXA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Welcome to our store. Free shipping on orders over 500 baht.",
"model": "paxa-translation-lite-v1"
}'const response = await fetch("https://api.paxalabs.com/v1/translate", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PAXA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
text: "Welcome to our store. Free shipping on orders over 500 baht.",
model: "paxa-translation-lite-v1",
formality: "formal",
}),
// A large request can run for minutes; give it room.
signal: AbortSignal.timeout(300_000),
});
if (!response.ok) throw new Error(`Translation failed: ${response.status}`);
const { translations, usage } = await response.json();
console.log(translations[0].text, `${usage.credits} credits`);import os
import requests
response = requests.post(
"https://api.paxalabs.com/v1/translate",
headers={"Authorization": f"Bearer {os.environ['PAXA_API_KEY']}"},
json={
# Send the whole glossary. Terms that do not appear in the text
# are dropped before the request runs, and never billed.
"glossary": [
{"source": "free shipping", "target": "ส่งฟรี"},
{"source": "cash on delivery", "target": "เก็บเงินปลายทาง"},
],
"text": "Welcome to our store. Free shipping on orders over 500 baht.",
"model": "paxa-translation-lite-v1",
},
# A large request can run for minutes; requests defaults to waiting
# forever, but most deployments put a shorter limit in front of it.
timeout=300,
)
response.raise_for_status()
body = response.json()
print(body["translations"][0]["text"])
print(body["usage"]["glossary_terms_sent"], "of", body["usage"]["glossary_terms_available"]){
"translations": [
{
"text": "ยินดีต้อนรับสู่ร้านของเรา ส่งฟรีเมื่อสั่งซื้อครบ 500 บาท",
"detected_source": "en"
}
],
"usage": {
"text_chars": 60,
"reference_chars": 0,
"billable_chars": 60,
"credits": 2,
"glossary_terms_sent": 0,
"glossary_terms_available": 0
}
}การคิดค่าบริการ#
การแปลคิดค่าบริการสองอัตรา ตัวอักษรในฟิลด์ text คือส่วนที่ถูกแปล คิด 25 เครดิตต่อ 1,000 ตัวอักษร ส่วนตัวอักษรใน instructions context examples do_not_translate และ glossary เป็นข้อมูลที่โมเดลอ่านแต่ไม่ได้แปล คิด 8 เครดิตต่อ 1,000 ตัวอักษร โดยนับทั้งสองด้านของทุกคู่ ทั้งสองส่วนรวมกันแล้วปัดขึ้นเป็นหน่วยหนึ่งในร้อยของเครดิตครั้งเดียว ขั้นต่ำ 2 เครดิตต่อคำขอ
ข้อมูลประกอบราคาถูกกว่าเพราะต้นทุนให้บริการต่ำกว่าจริง ส่วนนี้เป็นเพียงข้อมูลเข้าที่โมเดลอ่าน ขณะที่ตัวอักษรที่ถูกแปลยังกำหนดทุกอย่างที่โมเดลเขียนออกมาด้วย จึงควรส่งบริบทให้ครบเท่าที่เนื้อหาต้องการ ไม่ต้องประหยัด ทุกคำตอบรายงานสัดส่วนที่แน่นอนไว้ในฟิลด์ usage ค่าบริการจึงตรวจสอบย้อนกับสิ่งที่ส่งได้เสมอ
เพดานมีสองชั้น ฟิลด์ text รับได้สูงสุด 20,000 ตัวอักษร เพราะเป็นฟิลด์เดียวที่สร้างผลลัพธ์ออกมา และเพดานนี้นับหนึ่งครั้งต่อทุกสำนวนที่ขอ เพราะแต่ละสำนวนสร้างข้อความไทยออกมาเท่ากัน ข้อความที่ยาวกว่านั้นตอบ 400 text_too_long ส่วนทั้งคำขอรับได้สูงสุด 200,000 ตัวอักษรที่คิดค่าบริการรวมทุกฟิลด์ เกินกว่านั้นตอบ 400 request_too_large ทั้งสองกรณีไม่คิดเครดิต เพดานทั้งสองชั้นวัดหลังตัดคำศัพท์ที่ไม่ได้ใช้ออกแล้ว การแนบอภิธานศัพท์ชุดใหญ่จึงไม่ทำให้คำขอเกินเพดาน
ส่งข้อความเป็นชุด#
อาร์เรย์สูงสุด 200 ท่อนแปลในคำขอเดียว ทุกท่อนใช้บริบทเอกสารร่วมกัน สรรพนาม ระดับภาษา และศัพท์เฉพาะจึงสอดคล้องกันทั้งชุด ค่าขั้นต่ำต่อคำขอคิดครั้งเดียวสำหรับทั้งอาร์เรย์ ขอบเขตของแต่ละท่อนคงเดิมตามที่ส่งมา ควรส่งข้อความ UI ซับไตเติล และฟีดสินค้าเป็นชุด
การส่งเป็นชุดยังทำให้ context และ glossary คุ้มค่าขึ้นด้วย ทั้งสองฟิลด์ส่งครั้งเดียวต่อคำขอ บริบทชุดเดิมจึงคิดค่าบริการเท่ากันไม่ว่าจะแนบไปกับข้อความท่อนเดียวหรือ 200 ท่อน เมื่อเฉลี่ยทั้งชุดจะคิดเป็นเพียงเศษเสี้ยวของบิล
// One request, one charge: segments share document context and the
// per-request minimum applies once.
const strings = ["Sign in", "Create account", "Forgot password?"];
const response = await fetch("https://api.paxalabs.com/v1/translate", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PAXA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ text: strings, model: "paxa-translation-lite-v1" }),
});
const { translations } = await response.json();
for (const [index, item] of translations.entries()) {
console.log(`${strings[index]} -> ${item.text}`);
}ท่อนข้อความแบบมีคีย์#
ท่อนข้อความส่งเป็นอ็อบเจกต์แทนสตริงได้ ใส่ id แล้วผลลัพธ์จะส่ง id นั้นกลับมาด้วย จึงจับคู่ผลลัพธ์กับข้อความต้นทางด้วยคีย์ได้ ไม่ต้องอาศัยลำดับ ระบบไม่ตีความ id และไม่บังคับว่าต้องไม่ซ้ำ ลำดับยังคงเดิมทั้งสองแบบ และผสมอ็อบเจกต์กับสตริงธรรมดาในอาร์เรย์เดียวกันได้
อ็อบเจกต์ของท่อนข้อความรับ max_length ได้ด้วย คือความยาวสูงสุดของคำแปลเป็นจำนวนตัวอักษร โมเดลจะย่อให้พอดี ไม่ตัดข้อความทิ้ง การตั้งค่าต่ำกว่าที่ความหมายต้องการจึงแลกมาด้วยความครบถ้วน ผลลัพธ์ที่ยังเกินจะถูกส่งพร้อมการทำเครื่องหมายไว้ เหมาะกับซับไตเติลและข้อความ UI ที่มีพื้นที่จำกัด
// Key the segments and you match results by id, not by position.
// max_length compresses to fit; a result that still exceeds it comes
// back delivered and flagged rather than refused.
const response = await fetch("https://api.paxalabs.com/v1/translate", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PAXA_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "paxa-translation-lite-v1",
text: [
{ id: "cta.save", text: "Save changes", max_length: 24 },
{ id: "cta.cancel", text: "Cancel", max_length: 12 },
"A plain string works alongside them.",
],
do_not_translate: ["Paxa TTS Flash"],
}),
signal: AbortSignal.timeout(300_000),
});
const { translations } = await response.json();
for (const segment of translations) {
if (segment.review) {
console.warn(segment.id, segment.review.reason, segment.review.detail);
}
console.log(segment.id ?? "(unkeyed)", segment.text);
}Markdown และ HTML#
ตั้ง format เป็น "markdown" หรือ "html" แล้วโมเดลจะแปลเฉพาะเนื้อความที่คนอ่าน ปลายทางของลิงก์ โค้ด แท็ก และแอตทริบิวต์กลับมาเหมือนเดิมทุกตัว ภาษาไทยเขียนติดกันโดยไม่เว้นวรรคระหว่างคำ การเลื่อนแท็กในบรรทัดไปเพียงตัวอักษรเดียวจึงเปลี่ยนจุดตัดคำสำหรับผู้อ่านชาวไทย นี่คือเหตุผลที่โหมดเหล่านี้มีอยู่
การทำเครื่องหมายเพื่อตรวจทาน#
ทุกท่อนที่ส่งกลับจะถูกตรวจกับสิ่งที่คำขอระบุไว้ ต้องไม่ว่างเปล่า ต้องไม่หลุดไม่ได้แปล ต้องมีศัพท์เฉพาะและข้อความที่สั่งห้ามแปลครบ ต้องอยู่ในความยาวที่กำหนด และโครงสร้างมาร์กอัปต้องครบถ้วน ท่อนที่ไม่ผ่านการตรวจจะมีอ็อบเจกต์ review ระบุเหตุผลกำกับไว้
การทำเครื่องหมายไม่เคยทำให้คำขอถูกปฏิเสธ ระบบส่งคำแปลและคิดค่าบริการตามปกติทั้งสองกรณี เครื่องหมายหมายถึงท่อนนี้ควรได้รับการตรวจทาน การตรวจที่ปฏิเสธการส่งได้จะกลายเป็นอีกช่องทางหนึ่งที่ทำให้เสียคำขอที่จ่ายเงินไปแล้ว คำตอบที่ทุกท่อนไม่มี review คือคำตอบที่ผ่านการตรวจทั้งหมด
ตัวเลือกของคำขอ#
| ฟิลด์ | ค่า | ผล |
|---|---|---|
| source | auto (ค่าเริ่มต้น), en, zh, ja, ko, ar, fr, de, hi, id, ms, pt, ru, es, vi | กำหนดภาษาต้นทางเอง หรือให้โมเดลตรวจหาต่อท่อน การตรวจหาอัตโนมัติรองรับทุกภาษา รวมถึงข้อความที่ปนหลายภาษา |
| formality | auto, formal, casual | ระดับภาษาไทย: ภาษาเขียนสุภาพพร้อมคำลงท้ายตามธรรมชาติ ภาษาพูดทั่วไป หรืออิงตามน้ำเสียงของต้นฉบับ |
| borrowed_words | auto, transliterate, preserve | การจัดการคำยืม: ใช้คำทับศัพท์ที่ใช้กันแพร่หลาย เขียนทับศัพท์เป็นอักษรไทยทั้งหมด หรือคงศัพท์เทคนิคและชื่อเฉพาะไว้ตามต้นฉบับ |
| format | text, markdown, html | ระบุว่าข้อความเขียนในรูปแบบใด โหมดมาร์กอัปจะรักษาโครงสร้างทุกส่วนไว้ครบและแปลเฉพาะเนื้อความ |
| alternatives | 1 ถึง 5 | จำนวนสำนวนที่ต้องการต่อหนึ่งท่อน เรียงจากดีที่สุด แต่ละสำนวนคือการแปลเต็มรอบหนึ่งครั้งและคิดค่าบริการเท่ากัน |
| do_not_translate | สูงสุด 100 รายการ | ข้อความที่ต้องปรากฏในคำแปลตรงตามตัวอักษรทุกประการ คิดในอัตราข้อมูลประกอบ |
| instructions | สูงสุด 4,000 ตัวอักษร | คำสั่งอิสระที่ตัวเลือกสำเร็จรูปสื่อไม่ได้ เช่น กติกาภายในองค์กร กลุ่มผู้อ่าน หรือคำที่ห้ามใช้ มีผลกับทุกท่อนข้อความ คิดในอัตราข้อมูลประกอบ |
| context | สูงสุด 100,000 ตัวอักษร | ข้อมูลประกอบที่โมเดลอ่านแต่ไม่แปล เช่น เนื้อหาแวดล้อม โดเมน หรือกลุ่มผู้อ่าน คิดในอัตราข้อมูลประกอบ |
| examples | สูงสุด 100 คู่ | สไตล์แบบปรับตาม: คู่ต้นฉบับกับคำแปลที่อยากให้เลียนแบบน้ำเสียงและสำนวน คิดในอัตราข้อมูลประกอบ |
| glossary_mode | matched, all | จะตัดคำศัพท์ที่ไม่ปรากฏในข้อความออกหรือไม่ ค่าเริ่มต้นคือ matched ส่วน all จะส่งและคิดค่าบริการทุกคำที่แนบมา |
| glossary | สูงสุด 5,000 คู่ | ศัพท์บังคับที่ต้องใช้ทุกครั้งที่คำต้นทางปรากฏ คำที่ไม่ปรากฏในข้อความจะถูกตัดออกก่อนเริ่มประมวลผล ไม่ส่งและไม่คิดค่าบริการ ส่วนที่เหลือคิดในอัตราข้อมูลประกอบ |
คำสั่งเพิ่มเติม#
formality และ borrowed_words ครอบคลุมกรณีทั่วไป ส่วน instructions ครอบคลุมที่เหลือ เขียนคำสั่งเป็นภาษาอังกฤษหรือภาษาไทยก็ได้ แล้วคำสั่งนั้นจะมีผลกับทุกท่อนข้อความในคำขอ เช่น ผู้อ่านเป็นใคร ใช้กติกาภายในองค์กรข้อไหน ห้ามใช้คำใด หรือต้องการให้วลีที่ใช้บ่อยออกมาเป็นแบบใด
คำสั่งกำกับเฉพาะสไตล์ ไม่สามารถเปลี่ยนรูปแบบของคำตอบ และไม่สามารถทำให้โมเดลทำตามข้อความที่กำลังแปล ท่อนข้อความที่อ่านแล้วเหมือนคำสั่งจะยังถูกแปลเป็นข้อความตามปกติ ใช้ context สำหรับข้อมูลที่โมเดลควรรู้ และใช้ instructions สำหรับสิ่งที่โมเดลควรทำ
curl -X POST https://api.paxalabs.com/v1/translate \
--max-time 300 \
-H "Authorization: Bearer $PAXA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Your table is ready. Please follow me.",
"model": "paxa-translation-lite-v1",
"instructions": "Hotel front desk speaking to a guest. Warm, never stiff. Keep room and restaurant names in English."
}'อภิธานศัพท์#
ศัพท์ในอภิธานถูกนำไปใช้ตามบริบท โมเดลผันรูป จัดตัวพิมพ์ และวางคำให้ถูกไวยากรณ์ และจับคู่ได้แม้ต้นฉบับใช้รูปแปรของคำนั้น การแทนที่ตรงตัวมักผิดไวยากรณ์ในภาษาไทย อภิธานศัพท์จึงทำงานแบบนี้ หากต้องการให้คำปรากฏตรงตามตัวอักษร เช่น ชื่อสินค้าหรือวลีทางกฎหมาย ให้ระบุไว้ใน context
ส่งอภิธานศัพท์ทั้งชุดได้เลย คำศัพท์ที่ไม่ปรากฏในข้อความย่อมเปลี่ยนคำแปลไม่ได้ ระบบจึงตัดออกก่อนเริ่มประมวลผล ไม่ส่งให้โมเดลและไม่คิดค่าบริการ อภิธานศัพท์ 500 คำที่แนบไปกับข้อความตอบลูกค้าสั้น ๆ จะคิดเท่ากับเฉพาะสองสามคำที่ได้ใช้จริง คำตอบรายงาน glossary_terms_sent และ glossary_terms_available ไว้ให้ตรวจสอบได้เสมอ
การจับคู่ไม่สนใจตัวพิมพ์ใหญ่เล็ก เครื่องหมายเสียง และรูปแบบอะพอสทรอฟี อภิธานศัพท์ที่พิมพ์ว่า customer's จึงยังจับคู่กับเอกสารที่จัดพิมพ์เป็น customer’s ได้ และ hotel จับคู่กับ hôtel ได้ ระบบมองทะลุคำเติมท้ายและคำประสมภาษาเยอรมัน invoice จึงจับคู่กับ invoices และ Rechnung จับคู่กับ Rechnungsnummer และไม่ต้องอาศัยการเว้นวรรคระหว่างคำ จึงทำงานได้เหมือนกันทั้งภาษาจีน ญี่ปุ่น และไทย
สิ่งที่การจับคู่มองไม่ทะลุคือการผันรูปที่เปลี่ยนรากศัพท์ เช่น พหูพจน์ผิดกฎหรือการผันการกในภาษารัสเซีย ให้ตั้ง always: true กับคำนั้นเพื่อส่งไปเสมอ และใช้ค่าเดียวกันนี้กับคำที่กำกับแนวคิดมากกว่าตัวสะกด เช่น ตัวย่อที่ข้อความเขียนเต็ม หากตั้ง glossary_mode เป็น "all" ระบบจะส่งและคิดค่าบริการทุกคำที่แนบมา
ระดับภาษา#
ไวยากรณ์ไทยผูกกับความสุภาพ: คำลงท้าย สรรพนาม และการเลือกคำล้วนเปลี่ยนตามระดับภาษา formality: "formal" ให้ภาษาเขียนสุภาพเหมาะกับประกาศ คำตอบฝ่ายสนับสนุน และเอกสารทางการ "casual" ให้ภาษาพูดของแชตและแคปชันโซเชียล ส่วน "auto" (ค่าเริ่มต้น) อิงตามน้ำเสียงของต้นฉบับ ดูตัวอย่างคู่ระดับภาษาและคำแปลฉบับเต็มได้ที่หน้าการแปลภาษา
คำทับศัพท์#
ภาษาไทยรับคำต่างประเทศเข้ามาเป็นคำทับศัพท์ที่ใช้กันแพร่หลาย เช่น computer อ่านและเขียนว่า คอมพิวเตอร์ "auto" ใช้รูปที่แพร่หลายเมื่อมี และคงคำที่ยังไม่มีรูปทับศัพท์ไว้ตามอักษรเดิม "transliterate" เขียนคำยืมเป็นอักษรไทยทั้งหมด "preserve" คงศัพท์เทคนิคและชื่อเฉพาะตามต้นฉบับ เหมาะกับเอกสารนักพัฒนาและข้อความแบรนด์
curl -X POST https://api.paxalabs.com/v1/translate \
-H "Authorization: Bearer $PAXA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Welcome to our store. Free shipping on orders over 500 baht.",
"model": "paxa-translation-lite-v1",
"source": "en",
"formality": "formal",
"borrowed_words": "auto",
"context": "Homepage banner for an online fashion store.",
"glossary": [{"source": "free shipping", "target": "ส่งฟรี"}]
}'ภาษาต้นทาง#
ทุกรายการในคำตอบรายงาน detected_source เป็นรหัส ISO 639-1 ของภาษาต้นทางท่อนนั้น (หรือ "und" เมื่อระบุไม่ได้) ข้อความปนหลายภาษาถูกจัดการรายท่อน และข้อความที่เป็นไทยอยู่แล้วจะผ่านกลับมาโดยไม่เปลี่ยน ยกเว้นการปรับระดับภาษาตามที่ขอ โดยคิดค่าบริการตามปกติ
ความหน่วงและการส่งซ้ำ#
การแปลเป็นงานประมวลผลเชิงเหตุผล ใช้เวลาระดับวินาที และอาจถึงหลายสิบวินาทีเมื่อใกล้เพดานตัวอักษร ตั้งค่าไทม์เอาต์ของไคลเอนต์ HTTP ไว้อย่างน้อย 300 วินาที ไคลเอนต์และ SDK ส่วนใหญ่ตั้งค่าเริ่มต้นไว้ต่ำกว่าที่คำขอขนาดใหญ่ต้องใช้มาก และการหมดเวลาฝั่งไคลเอนต์จะยกเลิกคำขอที่ถูกคิดเครดิตไปแล้ว แนบ Idempotency-Key เพื่อส่งซ้ำอย่างปลอดภัย โมเดลไม่ได้ให้ผลตายตัว การส่งซ้ำจึงอาจได้สำนวนต่างจากรอบแรก และไม่ถูกคิดเงินซ้ำไม่ว่ากรณีใด
คำขอที่ใช้เวลานานพอจะเขียนส่วนหัวของคำตอบออกไปก่อนที่จะรู้ผลลัพธ์ เพื่อไม่ให้พร็อกซีระหว่างทางตัดการเชื่อมต่อที่ยังทำงานอยู่ คำตอบลักษณะนี้มีสถานะ 200 เสมอ และรายงานความล้มเหลวไว้ในเนื้อคำตอบด้วยเอกสารปัญหาชุดเดียวกับที่คำขอล้มเหลวได้รับ คือมี title และ status แทนที่ตำแหน่งของ translations หากไคลเอนต์ของคุณส่งคำขอใกล้เพดานตัวอักษร ให้ถือว่าเนื้อคำตอบที่มี title คือข้อผิดพลาดตามที่ระบุ ส่วนคำขอที่สั้นกว่านั้นไม่ได้รับผลกระทบ และแจ้งสถานะไว้ที่บรรทัดสถานะเสมอ
หมายเหตุ
เนื้อหาที่ระบบความปลอดภัยต้นทางปฏิเสธจะตอบ 422 content_blocked พร้อมคืนเครดิต การส่งเนื้อหาเดิมซ้ำจะไม่สำเร็จ ให้แก้ไขเนื้อหาก่อน