OCR ภาษาไทยสำหรับคลังความรู้และการนำเอกสารเข้าระบบ
อ่านไฟล์ PDF และไฟล์สแกนภาษาไทยออกมาเป็น Markdown ที่มีโครงสร้าง ระบบดัชนีจึงเก็บหัวข้อและตารางของเอกสารไว้ ไม่ใช่ข้อความยาวติดกันเป็นพืด
ผลลัพธ์ที่ได้กลับมา
# คู่มือพนักงาน
## ๓. การลาพักร้อน
พนักงานที่ทำงานครบหนึ่งปีมีสิทธิลาพักร้อนได้
ปีละหกวันทำการ
### ๓.๑ การยื่นคำขอ
ยื่นล่วงหน้าไม่น้อยกว่าเจ็ดวันheading ข้อกำหนดทางเทคนิค
table 14 rows x 4 columns
paragraph ค่าที่ระบุเป็นค่าที่วัดที่อุณหภูมิห้อง## หน้า 1
# ประกาศ เรื่อง แนวปฏิบัติการเบิกจ่าย
## หน้า 2
๑. ให้ถือปฏิบัติตั้งแต่วันที่ ๑ ตุลาคม ๒๕๖๙
๒. ยกเลิกประกาศฉบับลงวันที่ ๑๕ มีนาคม ๒๕๖๗ผลการอ่านด้านบนเป็นตัวอย่างของรูปแบบผลลัพธ์ ไม่ใช่คำตอบที่บันทึกมาจริง หน้า OCR มีผลการอ่านตัวอย่างจริงของโมเดลพร้อมวันที่บันทึกกำกับไว้
ขั้นตอนการนำเอกสารเข้าระบบ
ระบบค้นคืนจะดีได้เท่าที่สิ่งที่ใส่เข้าดัชนีดีเท่านั้น และในประเทศไทยความรู้ส่วนใหญ่ที่ผู้ช่วยอัจฉริยะต้องใช้อยู่ในไฟล์ PDF ที่มาจากการสแกน ไม่ใช่จากการพิมพ์ การดึงข้อความออกมาเป็นสายเดียวยาว ๆ จากหน้าเหล่านั้นได้สิ่งที่ระบบดัชนีเก็บได้ก็จริง แต่ผู้ช่วยจะหยิบไปตอบได้แย่ เพราะหัวข้อทุกหัวข้อ ตารางทุกตาราง และเส้นแบ่งหน้าทุกเส้นถูกละลายหายไปหมดแล้ว การอ่านที่ช่วยได้จริงคือการอ่านที่คืนโครงสร้างกลับมาครบ
- อ่านครั้งเดียว แล้วทำดัชนีจากข้อความส่งเอกสารแต่ละฉบับเป็นชุดละไม่เกิน 50 หน้า การนำเข้าเป็นค่าใช้จ่ายครั้งเดียวต่อเอกสาร และข้อความที่ได้เป็นของคุณ จะเก็บ จะแบ่งท่อน หรือจะทำ embedding อย่างไรก็ได้ตามที่ระบบของคุณถนัด
- แบ่งท่อนตามโครงสร้าง ไม่ใช่ตามความยาวตัดตามหัวข้อที่การอ่านคืนมา ท่อนขนาดหนึ่งหัวข้อจะเก็บกฎกับข้อยกเว้นของกฎไว้ด้วยกัน ซึ่งการตัดตามจำนวนตัวอักษรจะแยกทั้งสองอย่างออกจากกันไม่ช้าก็เร็ว
- อ้างอิงถึงหน้าเก็บเลขหน้าที่ผลการอ่านคืนมาไว้ด้วย ผู้ช่วยที่บอกได้ว่าตอบจากหน้าไหน คือผู้ช่วยที่ผู้อ่านตรวจสอบย้อนกลับได้
โครงสร้างให้อะไรกับตัวแบ่งข้อความ
ข้อความแบน ...ครบหนึ่งปีมีสิทธิลาพักร้อนได้ปีละหกวันทำการ๓.๑ การยื่นคำขอยื่นล่วงหน้าไม่น้อยกว่าเจ็ดวัน... → ตัดทุก 500 ตัวอักษร กลางประโยค กลางข้อ markdown ## ๓. การลาพักร้อน ### ๓.๑ การยื่นคำขอ → ตัดตามหัวข้อ หนึ่งหัวข้อต่อหนึ่งท่อน
ภาษาไทยเขียนติดกันโดยไม่เว้นวรรคระหว่างคำ การดึงข้อความออกมาแบบแบนจึงไม่เหลืออะไรให้ตัวแบ่งใช้ตัดเลยนอกจากจำนวนตัวอักษร ส่วนหัวข้อและตารางให้เส้นแบ่งที่เป็นของจริง
ค่าใช้จ่ายของการนำเอกสารเข้าระบบหนึ่งรอบ
| ปริมาณงาน | จำนวนหน้า | เครดิต |
|---|---|---|
| คู่มือหนึ่งเล่ม (180 หน้า) | 180 | 1,170 |
| หนึ่งคำขอเต็มเพดาน 50 หน้า | 50 | 325 |
| คลังเอกสาร 500 ฉบับ | 39,000 เครดิต | |
ที่เอกสารละ 12 หน้า และหน้าละ 6.5 เครดิต งบสำหรับการนำเอกสารเข้าระบบคำนวณได้ตั้งแต่ก่อนเขียนโค้ดบรรทัดแรก
การอ้างอิงหน้าตาเป็นอย่างไรหลังจากนั้น
คำถาม ลาพักร้อนได้ปีละกี่วัน
ท่อน คู่มือพนักงาน · ๓. การลาพักร้อน · หน้า 12
คำตอบ หกวันทำการต่อปี สำหรับพนักงาน
ที่ทำงานครบหนึ่งปี
เลขหน้ามาจากผลการอ่าน
ผู้อ่านจึงเปิดหน้า 12 ไปตรวจสอบเองได้ผลลัพธ์ยังแยกตามหน้า เลขหน้าจึงติดเข้าไปในดัชนีและติดออกมาในคำตอบด้วย ผู้ช่วยที่บอกเลขหน้าของตัวเองได้ คือผู้ช่วยที่ผู้อ่านตรวจสอบย้อนกลับได้
สำหรับนักพัฒนา
ใช้ Markdown เมื่อตัวแบ่งข้อความตัดตามหัวข้อ และใช้ผลลัพธ์แบบ structured เมื่อระบบของคุณอยากไล่อ่านบล็อกที่มีชนิดข้อมูลมากกว่ามาแยก Markdown กลับออกมาเอง
# Encode without line wrapping: wrapped base64 breaks the JSON string.
DOC=$(base64 < invoice.pdf | tr -d '\n')
# --max-time covers a multi-page document; curl defaults to no limit.
curl -X POST https://api.paxalabs.com/v1/ocr \
--max-time 300 \
-H "Authorization: Bearer $PAXA_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"document\": \"$DOC\", \"model\": \"paxa-ocr-lite-v1\"}"DOC=$(base64 < invoice.pdf | tr -d '\n')
curl -X POST https://api.paxalabs.com/v1/ocr \
--max-time 300 \
-H "Authorization: Bearer $PAXA_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"document\": \"$DOC\", \"model\": \"paxa-ocr-lite-v1\", \"output\": \"structured\"}"import base64
import os
import requests
with open("invoice.pdf", "rb") as file:
document = base64.b64encode(file.read()).decode()
response = requests.post(
"https://api.paxalabs.com/v1/ocr",
headers={"Authorization": f"Bearer {os.environ['PAXA_API_KEY']}"},
json={"document": document, "model": "paxa-ocr-lite-v1"},
# A multi-page document can run for minutes; give it room.
timeout=300,
)
response.raise_for_status()
body = response.json()
print(body["pages"][0]["markdown"], body["usage"]["credits"], "credits")ภาษาที่ไม่เว้นวรรคระหว่างคำลงโทษการแบ่งท่อนแบบง่าย ๆ
ตัวแบ่งข้อความส่วนใหญ่ถอยไปใช้การนับตัวอักษร ซึ่งในภาษาที่เว้นวรรคระหว่างคำก็มักตัดลงตรงช่องว่างพอดี แต่ภาษาไทยไม่เว้นวรรคระหว่างคำ หน้าต่างขนาดตายตัวจึงตัดลงตรงไหนก็ได้ รวมถึงกลางคำและกลางตัวเลข ทางออกคือโครงสร้าง การอ่านที่คืนหัวข้อ รายการ และตารางกลับมา ให้เส้นแบ่งที่ตัวเอกสารเองวางไว้อยู่แล้ว
คำถามที่พบบ่อย
- ทำการแบ่งท่อนและ embedding ให้ด้วยไหม
- ไม่ ระบบนี้ทำหน้าที่อ่าน ส่วนจะทำดัชนีอะไร แบ่งท่อนอย่างไร และใช้โมเดล embedding ตัวไหน ยังอยู่ในระบบของคุณ ซึ่งเป็นที่ที่ควรอยู่
- ระบบค้นคืนควรใช้ผลลัพธ์แบบไหน
- ใช้ Markdown ถ้าตัวแบ่งข้อความของคุณตัดตามหัวข้อ ซึ่งส่วนใหญ่เป็นแบบนั้น และใช้แบบ structured ถ้าระบบของคุณอยากไล่อ่านบล็อกที่มีชนิดข้อมูล ทั้งหัวข้อ ย่อหน้า รายการ ตาราง และรูปภาพ มากกว่ามาแยก Markdown กลับออกมาเอง
- เอกสารที่เป็นข้อความดิจิทัลอยู่แล้วล่ะ
- ถ้าไฟล์ PDF มีชั้นข้อความที่เชื่อถือได้อยู่แล้ว ให้ดึงออกมาตรง ๆ และประหยัดเครดิตไว้ การอ่านมีไว้สำหรับหน้าที่ไม่มีชั้นข้อความนั้น หรือมีแต่เชื่อถือไม่ได้
- ระบบเดียวกันรองรับเอกสารภาษาอื่นด้วยไหม
- การอ่านทำงานกับหน้าที่ได้รับมา หากคลังเอกสารมีหลายภาษาและผู้อ่านเป็นคนไทย API แปลภาษาคือขั้นตอนถัดไป รองรับภาษาต้นทาง 14 ภาษาแปลเป็นไทย พร้อมส่งบริบทของเอกสารไปด้วยได้
เริ่มต้นด้วยเครดิตฟรี
เข้าสู่ระบบด้วย Google, GitHub หรือ Hugging Face แล้วใช้เครดิตฟรี 100 เครดิตกับข้อความของคุณเอง