Ternlight, 브라우저(WASM)에서 실행되는 7MB 임베딩 모델
(ternlight-demo.vercel.app)- Ternlight는 서버 호출 없이 브라우저 안에서 텍스트 임베딩과 유사도 검색을 수행해, 작은 클라이언트 측 의미 검색을 빠르게 구성할 수 있게 함
- 기본 패키지는 엔진과 가중치를 합쳐 7MB, mini 변형은 5MB이며 GPU 없이 CPU에서 동작함
@ternlight/base를 설치한 뒤embed,similar를 가져오면 3줄 수준으로 의미 기반 검색 흐름을 만들 수 있음- 예시 호출은 레시피 목록에서 상위 3개 결과를 정렬하며, 약 5ms와 네트워크 호출 없음이 강조됨
- React 문서 검색 데모는 사용자가 질문을 입력하면 브라우저에서 검색을 수행하고, 5MB 티어인 @ternlight/mini가 이를 구동함
브라우저 안에서 끝나는 임베딩
- Ternlight는 “7MB 임베딩 모델”을 내세우며, 텍스트를 밀리초 단위로 임베딩하고 서버를 호출하지 않음
-
실행 특성
- API 호출 없음
- 엔진 + 가중치: 7MB
- mini 변형: 5MB
- 빠른 임베딩: 약 5ms
- CPU 전용, GPU 없음
설치와 사용 예시
- npm 패키지 하나로 제공되며, 별도 모델 다운로드 단계나 서버 없이 사용할 수 있음
- 설치 명령은 다음과 같음
npm install @ternlight/base
@ternlight/base에서embed,similar를 가져와 의미 기반 검색을 실행함
import { embed, similar } from '@ternlight/base';
similar('easy weeknight dinner ideas', recipes, { topK: 3 });
// → ranked matches · ~5 ms · zero network
- React 문서 검색 데모는 사용자가 질문을 입력하면 브라우저에서 검색을 수행하며, @ternlight/mini 5MB 티어로 구동됨
댓글과 토론
Hacker News 의견들
-
취미 프로젝트로 브라우저에서 유용한 모델을 돌려보고 싶어서 MiniLM에서 작은 문장 인코더를 증류하고, ternary 양자화 인식 학습을 적용함
추론 엔진도 직접 작성해서 Rust → WASM SIMD로 배포함
LLM이 아니라 임베딩 모델이라 텍스트를 넣으면 384차원 벡터가 나오고, 두 벡터의 코사인 유사도로 텍스트 관련성을 판단함. 예를 들어 "reset my password"와 "I forgot my password"가 0.88처럼 나옴
의미 기반 검색, FAQ/의도 매칭, 군집화에 쓸 수 있고, 기기 내 실행이라 API 의존 없이 입력 즉시 의미 검색이 빠르게 가능함
데모는 React 문서 2천 개를 완전히 기기 내에서 검색함: https://ternlight-demo.vercel.app
npm에는 @ternlight/base(7MB, 임베딩당 약 5ms, 더 성능 좋은 임베딩)와 @ternlight/mini(전송 5MB, 임베딩당 약 2.5ms) 두 단계가 있고, Node와 브라우저용으로 번들링됨
저장소에는 기술 세부사항과 MIT 라이선스, 학습 파이프라인이 포함됨: https://github.com/soycaporal/ternlight
기기 내 임베딩이 실제로 유용한지, 어떤 사용 사례가 있는지 궁금함- OpenStreetMap 태그로 단어를 매핑하는 사전이 있는데, https://codeberg.org/cartes/web/src/branch/master/components...처럼 되어 있음
사용자가 "pancake"를 입력했을 때 명시적으로 "pancake = crêpe" 사전 항목을 쓰지 않아도 crêpe를 찾게 만드는 데 도움이 될지 궁금함
이해한 게 맞다면 라이브러리가 처음에 5MB를 한 번 다운로드하고, 이후에는 지금 Fuse.js를 쓰는 것처럼 쓰는 구조인지도 궁금함
영어 외 언어를 얼마나 잘 처리하는지, OpenStreetMap 태그 위키로 학습시킬 수 있는지도 알고 싶음 - 단순 의미 기반 검색을 네이티브 데스크톱 앱에 넣는 데 정말 관심이 감
다른 초소형 임베딩 모델과 비교가 있는지 궁금함. MiniLM-L6에서 시작한 이유가 같은 급에서 특히 좋은 모델이라서인지 판단하기 어려운데, 제공된 지표가 "Retrieval (SciFact NDCG@10)"뿐임
다만 주장한 성능과는 꽤 차이가 나서, i5-4570의 Firefox에서는 초당 400개가 아니라 초당 35개 임베딩만 나옴. SIMD가 아닌 경로로 떨어지는 문제가 있는지 의심되고, 네이티브 Rust 바이너리도 시도해볼 예정임 - django 문서 전체와 사내 지식 베이스를 방금 임베딩해서 두 소스를 즉시 검색할 수 있게 됨
- OpenStreetMap 태그로 단어를 매핑하는 사전이 있는데, https://codeberg.org/cartes/web/src/branch/master/components...처럼 되어 있음
-
멋지지만, 랜딩 페이지에 데모를 시작하는 버튼을 두면 좋겠음. 웹페이지를 여는 순간 팬이 미친 듯이 도는 소리가 나서 꽤 놀람
- 동의함. 동시에 컴퓨터 소리만 들어도 지금 무슨 일이 벌어지는지 친밀하게 알 수 있던 시절이 떠올라 반갑기도 함
- 팬이 돌기 시작해서 놀랐음. 다만 토스터도 종종 나를 놀라게 하긴 함
- CPU 사이클 극한 활용이라니, GPU만 특별하다고 누가 그랬나 싶음
-
Astro나 범용 메타 프레임워크 플러그인으로 만들어서 생성된 모든 HTML 파일을 자동 파싱하고 작은 임베딩 데이터베이스를 만들면 좋겠음
프런트엔드에서는 이를 지연 로딩할 수 있고, HNSW도 청크 단위로 저장해서 검색 질의에 필요한 부분만 불러올 수 있을지도 모름
예를 들면 https://pagefind.app/와 비슷하지만, 완전 정적 벡터 검색을 제공하는 형태임- 우리 정적 사이트 생성기에는 sqlite-vec를 쓰고 싶었지만, 마지막으로 확인했을 때는 HNSW가 구현되어 있지 않았거나 브라우저 내 벡터 검색 지원이 좋지 않았음. 아마 여전히 전체 테이블 스캔을 하고 있었던 것 같음
몇 달, 몇 년이 지났는데도 그 상태라면 프로젝트를 제대로 완수할 역량이 부족한 신호처럼 보여 꽤 실망했음. 심지어 내가 지원한 보조금에서 그 프로젝트를 괜찮은 후보로 추천했는데, 그쪽은 선정되고 나는 떨어졌음
이 영역에서 좋은 해법을 아는 사람이 있거나, SQLite-vec에 대해 내가 틀렸다면 알려줬으면 함. 우리 SSG에서는 일단 다른 인프라를 몇 달 작업해보고, 그때도 완성되지 않았으면 직접 만들기로 거의 정했음
- 우리 정적 사이트 생성기에는 sqlite-vec를 쓰고 싶었지만, 마지막으로 확인했을 때는 HNSW가 구현되어 있지 않았거나 브라우저 내 벡터 검색 지원이 좋지 않았음. 아마 여전히 전체 테이블 스캔을 하고 있었던 것 같음
-
예전에 여기서 본 DuckDB HNSW 검색 프로젝트에 꽤 멋진 추가 기능이 될 수 있겠음: https://github.com/jasonjmcghee/portable-hnsw
정적으로 호스팅된 Parquet 파일을 대상으로 HTTP 범위 요청을 써서 검색이 일어나는 점이 정말 흥미로움
이런 것들이 대기업이 통제하지 않는 비교적 개방적이고 분산된 검색 생태계로 커질 수 있다고 봄- 비슷한 아이디어로, 정적 호스트의 SQLite DB를 HTTP 범위 요청과 WASM으로 사용하는 방식도 흥미로울 수 있음
https://news.ycombinator.com/item?id=27016630 - 멋진 아이디어임. 범위 요청과 정적 호스팅에서 클라이언트가 탐색할 수 있는 형식을 정말 좋아함
- 비슷한 아이디어로, 정적 호스트의 SQLite DB를 HTTP 범위 요청과 WASM으로 사용하는 방식도 흥미로울 수 있음
-
이건 정말 멋지고, 예전에 만들고 싶었던 것의 빠진 조각일 수 있겠음
https://github.com/npiesco/absurder-sql을 쓰면 원본 말뭉치 전체를 브라우저 안에 IndexedDB/SQLite로 영속 저장할 수 있음
그다음 https://weaviate.io/blog/chunking-strategies-for-rag처럼 모든 것을 미리 색인하지 않고, Ternlight로 필요할 때 임베딩 생성과 캐시를 할 수 있음
그러면 네이티브 SQLite의 FTS5/BM25와 Ternlight의 의미 검색을 합치는 Reciprocal Rank Fusion, 즉 하이브리드 검색도 가능해짐 -
잘 만들었음
7MB로 홍보되어 있지만 5MB mini 버전도 있음
mini는 내부적으로 384가 아니라 256요소 벡터를 써서 공간을 줄이고, 마지막에 호환성을 위해 384로 투영하는 것으로 보임
크기는 3분의 1 줄지만 손실은 선형적이지 않아서, 더 작은 데이터 경로를 쓰더라도 정보 손실은 3분의 1보다 적어 보임 -
멋진 프로젝트임
예전에 비슷한 것을 시도했음: http://sol.quipu-strands.com/
브라우저 안에서 임베딩 모델을 불러와 텍스트를 의미적으로 정렬하고 싶었음
HuggingFace에서 ONNX 가중치(MPNet, MiniLM)를 가져오고, Transformers.js로 임베딩을 만든 뒤, 페이지 안에서 pyodide로 실행되는 scikit-learn의 군집화기를 사용했음. 전부 클라이언트 측에서 돌아갔고, 이게 완벽히 동작해서 놀랐음 -
데모가 꽤 이상하게 동작함. 예를 들어 "how to use typescript with createContext"를 검색하면 상위 결과가 typescript 항목뿐이라 유사도 검색이 실패한 것처럼 보임
-
고마움. 로컬 모델은 언젠가 프라이버시를 가져올 것이고, 이런 작은 임베딩 모델에 딱 맞는 훌륭한 사용 사례도 이미 알고 있음. 제품 데이터베이스에서 저렴하고 빠른 검색을 하는 용도임
내 경우에는 CPU에 의존한다는 점도 장점임- 좋음. 지원할 방법이 있거나 로드맵에서 다뤄야 할 구체적인 사용 사례가 있으면 알려주면 좋겠음
-
30초 걸리는 임베딩 생성을 미리 해두고 브라우저로 보낼 수 있나?
그다음 추론은 빠르고 좋음- 가능함. 서버 쪽에서 한 번만 색인을 돌리고, 임베딩만 프런트엔드로 보내면 됨