Starlens: OCR และการดึงข้อมูลจากเอกสาร
อ่านใบเสร็จ ใบแจ้งหนี้ และเอกสารอื่นๆ ให้เป็นฟิลด์ที่แอปของคุณต้องการ และจัดการกับสิ่งที่ Starlens อ่านไม่ได้
Starlens อ่านรูปถ่าย PDF เสียง และวิดีโอ ให้เป็นฟิลด์ที่แอปของคุณต้องการ ใช้ได้กับใบเสร็จ ใบแจ้งหนี้ แบบฟอร์ม และเอกสารอื่นๆ
ใช้งานได้ดีเพราะอะไร
Starlens อ่านโครงสร้างของเอกสารไม่ใช่แค่ตัวอักษร โดยจะจัดแถวของตารางให้อยู่ด้วยกัน คืนจำนวนเงินเป็นตัวเลข และแปลงวันที่ให้เป็นรูปแบบมาตรฐาน (รวมถึงวันที่ปี พ.ศ. แบบไทย) อ่านลายมือและหน้าที่มีหลายภาษาได้ คุณเลือกฟิลด์เอง แล้ว Starlens จะคืนค่าตาม schema ของคุณ
ต่างจาก OCR ทั่วไปอย่างไร
OCR ทั่วไปคืนเป็นข้อความ เช่น TOTAL ฿482.00 ส่วน Starlens คืน total: 482 ในใบเสร็จที่มีโครงสร้าง พร้อมร้านค้าและรายการสินค้าที่คุณขอ
| OCR ทั่วไป | Starlens | |
|---|---|---|
| ผลลัพธ์ | ข้อความที่แอปของคุณต้องแยกเอง | ฟิลด์และแถวตาม schema ของคุณ |
| ค่าที่อ่านไม่ออก | แอปของคุณต้องหาเองว่าอะไรขาดไป | null พร้อมเหตุผลใน issues |
| เอกสารผิดประเภท | คืนข้อความทุกอย่างที่มองเห็น | ปฏิเสธการดึงข้อมูลเป็นรูปแบบที่ขอ |
Starlens อ่านได้หลายหน้าและเอกสารหลายภาษา ชื่อที่ดึงมาจะคงอักษรเดิมไว้ Starlens ไม่จับคู่ชื่อที่พิมพ์ในเอกสารกับข้อมูลในแอปของคุณ และไม่สร้างข้อมูลเหล่านั้นให้
ตัวอย่างอินพุตและเอาต์พุต
คำขอตัวอย่างเหล่านี้ใช้รูปแบบอินพุตจริงของ SDK คือ inputs สำหรับไฟล์ instructions สำหรับบริบทของเอกสาร และ Zod schema พร้อมคำอธิบายฟิลด์ เอาต์พุตด้านล่างแสดง output และ issues ส่วน SDK ยังคืน version และ usage ด้วย
อินพุตใบเสร็จ: รูปถ่ายจากโทรศัพท์แสดง ร้านครัวบ้าน, 3 ก.ย. 2569, ข้าวผัด 2 × ฿60 และ รวม ฿120 โดย receiptUrl คือ URL แบบ signed ของไฟล์นั้น:
import { createStarlensClient } from "@stardeck-customer-apps/starlens";
import { z } from "zod";
const starlens = createStarlensClient();
const receipt = await starlens.extract({
version: "v2",
inputs: [{ url: receiptUrl, filename: "receipt.jpg" }],
instructions: "Purchase receipt. Copy printed values; do not calculate totals.",
schema: z.object({
merchant: z.string().nullable().describe("Shop name at the top, not the payment processor"),
date: z
.string()
.nullable()
.describe("Purchase date as YYYY-MM-DD; convert Thai Buddhist years"),
line_items: z.array(
z.object({
description: z.string().nullable().describe("Priced item name, not a barcode-only line"),
quantity: z.number().nullable().describe("Printed quantity"),
amount: z.number().nullable().describe("Printed line amount"),
})
),
total: z
.number()
.nullable()
.describe("Printed amount due / grand total / รวม, not a calculated sum"),
}),
});เอาต์พุต:
{
"output": {
"merchant": "ร้านครัวบ้าน",
"date": "2026-09-03",
"line_items": [{ "description": "ข้าวผัด", "quantity": 2, "amount": 120 }],
"total": 120
},
"issues": []
}อินพุตใบแจ้งหนี้: รูปถ่ายแสดงผู้ขาย Acme Foods และยอดรวม ฿1,250 แต่มีนิ้วโป้งบังเลขประจำตัวผู้เสียภาษี โดย invoiceUrl คือ URL แบบ signed ของไฟล์นั้น คำอธิบายฟิลด์บอก Starlens ว่าป้ายกำกับที่พิมพ์ในเอกสารคืออะไรและแยกแยะอย่างไร:
const invoice = await starlens.extract({
version: "v2",
inputs: [{ url: invoiceUrl, filename: "invoice.jpg" }],
instructions: "Supplier invoice. Copy printed values; do not calculate totals.",
schema: z.object({
supplier: z.string().nullable().describe("Seller's legal entity name, not a brand or logo"),
tax_id: z
.string()
.nullable()
.describe("Printed Tax ID / TIN / VAT no. / เลขประจำตัวผู้เสียภาษี"),
total: z.number().nullable().describe("Printed amount due / grand total / รวมทั้งสิ้น"),
}),
});เอาต์พุต:
{
"output": { "supplier": "Acme Foods", "tax_id": null, "total": 1250 },
"issues": [{ "path": "tax_id", "reason": "A thumb covers the tax ID" }]
}เพิ่มลงในแอปของคุณ
บอก coding agent ของคุณให้สร้างขั้นตอนสแกนและตรวจสอบ agent จะใช้แพ็กเกจ
@stardeck-customer-apps/starlens และ SKILL.md ของแพ็กเกจ หากสร้างบนเบราว์เซอร์ ให้บอก Starcat
Developer ในแท็บ Build ของแอปแทน ตัวอย่างเช่น:
Add supplier bill scanning. Let staff photograph or upload a bill, then use Starlens
to read the supplier, date, line items, tax, and total. Show the image beside an
editable draft. Highlight unreadable fields, and require review before saving.
Reject files that are not supplier bills.แอปของคุณเป็นผู้เรียกใช้ Starlens Settings → Services → Starlens แสดงการทำงานที่ผ่านมา เอาต์พุต issues และค่าใช้จ่าย แต่ไม่ใช่ที่สำหรับเริ่มสแกน ไฟล์ต้นฉบับไม่ถูกเก็บไว้ในประวัติการทำงาน
จัดการผลลัพธ์ที่ไม่แน่ใจ
หาก Starlens อ่านฟิลด์ไม่ได้ จะคืน null และรายการ issues ที่ระบุฟิลด์และเหตุผล ขอรูปที่ชัดขึ้น หรือให้คนแก้ฉบับร่างโดยดูจากต้นฉบับ null ที่ไม่มี issue อาจหมายความว่าเอกสารไม่มีฟิลด์นั้น
issues ที่ว่างเปล่าไม่ได้รับประกันว่ามั่นใจ ตรวจจำนวนเงินและเลขประจำตัวที่สำคัญเทียบกับต้นฉบับก่อนบันทึก หาก Starlens ปฏิเสธทั้งไฟล์ ให้ขอเอกสารที่ถูกต้อง อย่าบันทึกระเบียนที่ว่างเปล่า
ทดสอบด้วย playground
บอก agent ของคุณให้สร้าง playground สำหรับการดึงข้อมูลหรือการประเมินผลในแอป:
Build a Starlens playground for supplier bills. Upload a sample, run the same
schema and version as the real scan flow, and show the source beside the output
and issues. Let me enter correct values and compare them field by field. Do not
save playground results as supplier bills.ลองตัวอย่างที่ชัด เบลอ ถูกบัง หลายหน้า และผิดประเภท ปรับคำอธิบายฟิลด์ใน schema แล้วรันตัวอย่างชุดเดิมอีกครั้งเพื่อดูว่าอะไรเปลี่ยนไป การรันใน playground นับรวมในการใช้งาน AI และขีดจำกัดรายวันของคุณ
ค่าที่รู้อยู่แล้วและ effort (v2)
หากฟิลด์หนึ่งเก็บค่าที่อยู่ในรายการที่คุณมีอยู่แล้ว เช่น ชื่อสินค้าหรือชื่อพนักงาน ให้ส่งรายการนั้นเป็น examples ของฟิลด์ Starlens จะอ่านรายการนี้เป็นค่าที่ฟิลด์น่าจะมี รายการนี้เป็นเพียงคำใบ้ ไม่ใช่ตัวกรอง ค่าที่ไม่ตรงกับรายการใดเลยจะถูกถอดความตามที่เขียนไว้
const sheetSchema = z.object({
rows: z.array(
z.object({
product: z
.string()
.nullable()
.describe("Product name as written")
.meta({ examples: productNames }),
qty: z.number().nullable(),
})
),
});effort: "low" เป็นค่าเริ่มต้นและอ่านเอกสารหนึ่งรอบ effort: "high" อ่านสามรอบและคืนเฉพาะค่าที่ทั้งสามรอบตรงกัน ค่าใช้จ่ายสูงกว่าประมาณสี่เท่าและอาจใช้เวลาถึงห้านาที จึงควรรันจากปุ่ม "Read again carefully" หรือรันเบื้องหลัง โหมด high อ่านจากภาพที่ครอปมา ดังนั้นสำหรับอินพุตที่เป็น PDF เสียง หรือวิดีโอ Starlens จะรันที่ low ตรวจ result.effort ก่อนบอกผู้ใช้ว่าเอกสารถูกอ่านอย่างละเอียดแล้ว
สำหรับนักพัฒนา
เรียก @stardeck-customer-apps/starlens จากโค้ดฝั่งเซิร์ฟเวอร์ โดยระบุเวอร์ชันที่ตรึงไว้ (v2 สำหรับโค้ดใหม่) schema และ signed URL ที่ดึงได้แบบสาธารณะ หรือไบต์ของไฟล์แบบ inline แพลตฟอร์มรับได้สูงสุด 10 อินพุตและรวม 40 MB ต่อคำขอ SDK คืน output และ issues และโยน UnsupportedDocumentError เมื่อเอกสารผิดประเภท ดู API ฉบับเต็มและการจัดการข้อผิดพลาดได้ใน SKILL.md ของแพ็กเกจในแอปของคุณ และ SDK