- Ternlight ช่วยให้ทำ text embedding และการค้นหาความคล้ายกันภายในเบราว์เซอร์ได้โดยไม่ต้องเรียกเซิร์ฟเวอร์ ทำให้สร้าง semantic search ฝั่งไคลเอนต์ขนาดเล็กได้อย่างรวดเร็ว
- แพ็กเกจพื้นฐานมีขนาด 7MB เมื่อรวมเอนจินและน้ำหนักโมเดล ส่วนรุ่น mini มีขนาด 5MB และทำงานบน CPU โดยไม่ต้องใช้ GPU
- หลังติดตั้ง
@ternlight/base แล้ว สามารถนำเข้า embed และ similar เพื่อสร้างโฟลว์การค้นหาเชิงความหมายได้ด้วยโค้ดเพียงประมาณ 3 บรรทัด
- ตัวอย่างการเรียกใช้งานจะจัดอันดับผลลัพธ์ 3 อันดับแรกจากรายการสูตรอาหาร โดยเน้นความเร็วราว 5ms และไม่มีการเรียกเครือข่าย
- เดโมค้นหาเอกสาร React จะค้นหาภายในเบราว์เซอร์เมื่อผู้ใช้ป้อนคำถาม และขับเคลื่อนด้วย @ternlight/mini ระดับ 5MB
embedding ที่จบในเบราว์เซอร์
- Ternlight ชูจุดเด่นว่าเป็น “โมเดล embedding ขนาด 7MB” โดยทำ embedding ข้อความได้ในระดับมิลลิวินาทีและไม่เรียกเซิร์ฟเวอร์
-
คุณลักษณะการทำงาน
- ไม่มีการเรียก API
- เอนจิน + น้ำหนักโมเดล: 7MB
- รุ่น mini: 5MB
- embedding เร็ว: ประมาณ 5ms
- ใช้ CPU เท่านั้น ไม่มี GPU
ตัวอย่างการติดตั้งและใช้งาน
- ให้มาในรูปแบบ npm package เดียว และใช้งานได้โดยไม่ต้องมีขั้นตอนดาวน์โหลดโมเดลแยกหรือมีเซิร์ฟเวอร์
- คำสั่งติดตั้งมีดังนี้
npm install @ternlight/base
- นำเข้า
embed, similar จาก @ternlight/base เพื่อรันการค้นหาเชิงความหมาย
import { embed, similar } from '@ternlight/base';
similar('easy weeknight dinner ideas', recipes, { topK: 3 });
// → ranked matches · ~5 ms · zero network
- เดโมค้นหาเอกสาร React จะค้นหาภายในเบราว์เซอร์เมื่อผู้ใช้ป้อนคำถาม และทำงานด้วย @ternlight/mini ระดับ 5MB
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
อยากลองรัน โมเดลที่ใช้งานได้จริงในเบราว์เซอร์ เป็นโปรเจกต์งานอดิเรก เลย distill ตัวเข้ารหัสประโยคขนาดเล็กจาก MiniLM และใช้การฝึกแบบรับรู้การ quantization แบบ ternary
เขียน inference engine เองด้วย แล้วปล่อยเป็น Rust → WASM SIMD
มันไม่ใช่ LLM แต่เป็นโมเดล embedding ดังนั้นเมื่อใส่ข้อความเข้าไปจะได้เวกเตอร์ 384 มิติ และใช้ cosine similarity ของเวกเตอร์สองตัวเพื่อตัดสินความเกี่ยวข้องของข้อความ ตัวอย่างเช่น "reset my password" กับ "I forgot my password" จะได้ประมาณ 0.88
ใช้ได้กับการค้นหาเชิงความหมาย การจับคู่ FAQ/intent และการจัดกลุ่ม และเพราะรันในอุปกรณ์ จึงค้นหาเชิงความหมายได้เร็วทันทีหลังป้อนข้อมูลโดยไม่ต้องพึ่ง API
เดโมค้นหาเอกสาร React 2,000 รายการทั้งหมดในอุปกรณ์: https://ternlight-demo.vercel.app
บน npm มี 2 ระดับคือ @ternlight/base (7MB, ประมาณ 5ms ต่อ embedding, embedding คุณภาพดีกว่า) และ @ternlight/mini (ขนาดส่งผ่าน 5MB, ประมาณ 2.5ms ต่อ embedding) และ bundle ไว้สำหรับ Node กับเบราว์เซอร์
repo มีรายละเอียดทางเทคนิค ไลเซนส์ MIT และ pipeline การฝึก: https://github.com/soycaporal/ternlight
อยากรู้ว่า embedding ในอุปกรณ์มีประโยชน์จริงไหม และมี use case แบบไหนบ้าง
อยากรู้ว่าจะช่วยให้ผู้ใช้พิมพ์ "pancake" แล้วหา crêpe เจอได้ไหม โดยไม่ต้องเขียนรายการพจนานุกรมแบบชัดเจนว่า "pancake = crêpe"
ถ้าเข้าใจถูก โครงสร้างคือไลบรารีจะดาวน์โหลด 5MB หนึ่งครั้งตอนแรก แล้วหลังจากนั้นก็ใช้งานเหมือนตอนนี้ที่ใช้ Fuse.js ใช่ไหม
อยากรู้ด้วยว่าจัดการภาษาที่ไม่ใช่อังกฤษได้ดีแค่ไหน และเอาไปฝึกด้วย OpenStreetMap tag wiki ได้ไหม
อยากรู้ว่ามีการเทียบกับโมเดล embedding ขนาดจิ๋วตัวอื่นไหม ยากจะตัดสินว่าเหตุผลที่เริ่มจาก MiniLM-L6 เป็นเพราะมันเป็นโมเดลที่ดีเป็นพิเศษในระดับเดียวกันหรือไม่ เพราะตัวชี้วัดที่ให้มามีแค่ "Retrieval (SciFact NDCG@10)"
แต่ก็ยังต่างจากประสิทธิภาพที่อ้างไว้พอสมควร บน Firefox ของ i5-4570 ได้แค่ 35 embeddings ต่อวินาที ไม่ใช่ 400 ต่อวินาที สงสัยว่าอาจตกไปใช้ path ที่ไม่ใช่ SIMD และตั้งใจจะลอง native Rust binary ด้วย
เจ๋งดี แต่ถ้ามีปุ่มเริ่มเดโมบน landing page น่าจะดีมาก เปิดเว็บปุ๊บได้ยิน เสียงพัดลมหมุนอย่างบ้าคลั่ง เลยค่อนข้างตกใจ
น่าจะทำเป็นปลั๊กอินสำหรับ Astro หรือ meta-framework ทั่วไป ให้ parse ไฟล์ HTML ที่สร้างทั้งหมดโดยอัตโนมัติแล้วสร้าง ฐานข้อมูล embedding ขนาดเล็ก
ฝั่ง frontend สามารถ lazy-load สิ่งนี้ได้ และอาจเก็บ HNSW เป็น chunk เพื่อโหลดเฉพาะส่วนที่จำเป็นต่อ query การค้นหา
ตัวอย่างเช่นคล้าย https://pagefind.app/ แต่เป็นรูปแบบที่ให้ static vector search แบบเต็มตัว
ผ่านมาหลายเดือน หลายปีแล้ว ถ้ายังเป็นแบบนั้นก็ถือว่าค่อนข้างน่าผิดหวัง เพราะดูเหมือนเป็นสัญญาณว่าขาดความสามารถในการทำโปรเจกต์ให้เสร็จจริง ๆ ถึงขั้นที่ผมเคยเสนอโปรเจกต์นั้นเป็นผู้สมัครที่ดีสำหรับทุนที่ผมสมัคร แต่ฝั่งนั้นได้ทุน ส่วนผมไม่ผ่าน
ถ้าใครรู้วิธีแก้ดี ๆ ในพื้นที่นี้ หรือถ้าผมเข้าใจ SQLite-vec ผิด ช่วยบอกที สำหรับ SSG ของเรา ตอนนี้เกือบตัดสินใจแล้วว่าจะไปทำโครงสร้างพื้นฐานอื่นสักสองสามเดือนก่อน แล้วถ้ายังไม่เสร็จก็จะทำเอง
น่าจะเป็นฟีเจอร์เสริมที่เจ๋งมากสำหรับโปรเจกต์ค้นหา DuckDB HNSW ที่เคยเห็นที่นี่: https://github.com/jasonjmcghee/portable-hnsw
จุดที่น่าสนใจมากคือการค้นหาเกิดขึ้นกับไฟล์ Parquet ที่โฮสต์แบบ static โดยใช้ HTTP range requests
มองว่าสิ่งเหล่านี้อาจเติบโตเป็นระบบนิเวศการค้นหาที่ค่อนข้างเปิดและกระจายศูนย์ ซึ่งไม่ได้ถูกควบคุมโดยบริษัทใหญ่
https://news.ycombinator.com/item?id=27016630
อันนี้เจ๋งจริง และอาจเป็นชิ้นส่วนที่ขาดไปของสิ่งที่เคยอยากสร้าง
ถ้าใช้ https://github.com/npiesco/absurder-sql จะสามารถ persist corpus ต้นฉบับทั้งหมดไว้ใน IndexedDB/SQLite ภายในเบราว์เซอร์ได้
จากนั้นก็ใช้ Ternlight ทำ การสร้าง embedding และ cache ตามต้องการ โดยไม่ต้อง index ทุกอย่างล่วงหน้า เหมือน https://weaviate.io/blog/chunking-strategies-for-rag
แบบนั้นก็จะทำ hybrid search ได้ด้วย Reciprocal Rank Fusion ที่รวม FTS5/BM25 ของ SQLite แบบ native กับ semantic search ของ Ternlight
ทำได้ดีมาก
โปรโมตว่า 7MB แต่ก็มีเวอร์ชัน mini 5MB ด้วย
ดูเหมือน mini จะใช้ เวกเตอร์ 256 องค์ประกอบ ภายในแทน 384 เพื่อลดพื้นที่ แล้วค่อย project กลับเป็น 384 ตอนท้ายเพื่อความเข้ากันได้
ขนาดลดลงหนึ่งในสาม แต่ loss ไม่ได้เป็นเส้นตรง ดังนั้นแม้ใช้ data path ที่เล็กกว่า ก็ดูเหมือนสูญเสียข้อมูลน้อยกว่าหนึ่งในสาม
โปรเจกต์เจ๋งมาก
เคยลองทำสิ่งคล้ายกันมาก่อน: http://sol.quipu-strands.com/
อยากโหลดโมเดล embedding ในเบราว์เซอร์ แล้วจัดเรียงข้อความตามความหมาย
ดึง ONNX weights (MPNet, MiniLM) จาก HuggingFace ใช้ Transformers.js ทำ embedding แล้วใช้ตัวจัดกลุ่มของ scikit-learn ที่รันผ่าน pyodide ในหน้าเว็บ ทั้งหมดทำงานฝั่ง client และแปลกใจที่มันทำงานได้สมบูรณ์แบบ
เดโมทำงานค่อนข้างแปลก ตัวอย่างเช่นถ้าค้นหา "how to use typescript with createContext" ผลลัพธ์อันดับต้น ๆ มีแต่ รายการ typescript เลยดูเหมือน similarity search ล้มเหลว
ขอบคุณ โมเดล local จะนำ ความเป็นส่วนตัว มาให้ในสักวัน และผมก็รู้ use case ที่ยอดเยี่ยมซึ่งเหมาะกับโมเดล embedding เล็ก ๆ แบบนี้อยู่แล้ว คือการค้นหาราคาถูกและรวดเร็วในฐานข้อมูลสินค้า
ในกรณีของผม การพึ่ง CPU ก็เป็นข้อดีด้วย
สามารถทำ การสร้าง embedding ที่ใช้เวลา 30 วินาทีไว้ล่วงหน้าแล้วส่งไปยังเบราว์เซอร์ได้ไหม
หลังจากนั้น inference ก็เร็วและดี