- Để giảm bớt các hạn chế của
sqlite-vsshiện có,sqlite-vecđang được phát triển như một phần mở rộng tìm kiếm vector nhúng dựa trên C thuần, nhắm tới toàn bộ các môi trường nơi SQLite có thể chạy - Luồng sử dụng SQL được đơn giản hóa xoay quanh
CREATE VIRTUAL TABLE,INSERT INTO,SELECT, đồng thời hỗ trợ tìm kiếm kiểu KNN và đầu vào vector dạng JSON/binary compact - Loại bỏ phụ thuộc vào Faiss, nhắm tới không chỉ Linux, macOS mà cả Windows, WebAssembly, di động và Raspberry Pi; kích thước binary cũng được kỳ vọng ở mức vài trăm KB, nhỏ hơn mức 3MB~5MB hiện tại
- Lưu vector theo đơn vị chunk trong shadow table để giảm nhu cầu đưa toàn bộ lên RAM, và có thể dùng
PRAGMA mmap_sizeđể tăng tốc tìm kiếm dựa trên bộ nhớ - Phiên bản ban đầu chỉ cung cấp exhaustive full-scan, chưa có ANN; bản phát hành
v0.1.0dự kiến sẽ có sau khi hoàn tất 246 TODO trongsqlite-vec.c
Tìm kiếm vector SQLite mà sqlite-vec muốn thay đổi
sqlite-veclà một phần mở rộng SQLite mới được viết bằng C thuần, là dự án nhằm thay thếsqlite-vssđã được công bố vào tháng 2/2023- Phạm vi mục tiêu bao gồm các hàm SQL do người dùng định nghĩa để tìm kiếm vector nhanh, bảng ảo (virtual table), cũng như công cụ và tiện ích cho thao tác vector
- Lượng tử hóa
- Chuyển đổi JSON/BLOB/numpy
- Số học vector
- Người dùng có thể tạo và tìm kiếm kho vector chỉ bằng SQL thuần
- Tạo bảng ảo cho vector bằng
CREATE VIRTUAL TABLE - Chèn vector bằng
INSERT INTO - Tìm kiếm kiểu KNN theo dạng
SELECT ... WHERE sample_embedding MATCH ... ORDER BY distance LIMIT ...
- Tạo bảng ảo cho vector bằng
- Đầu vào vector có thể dùng chuỗi JSON hoặc định dạng binary compact
C thuần và không phụ thuộc mở ra các môi trường chạy
sqlite-vechướng tới một phần mở rộng C thuần không phụ thuộc, và lựa chọn này là điều kiện cốt lõi để mở rộng nền tảng được hỗ trợsqlite-vsshiện có, do phụ thuộc C++, chỉ hoạt động ổn định trên Linux và macOS, còn kích thước binary nằm trong khoảng 3MB~5MB- Phần mở rộng mới đặt mục tiêu chạy trong các môi trường sau
- Linux
- macOS
- Windows
- WebAssembly trong trình duyệt
- Thiết bị di động
- Thiết bị nhỏ như Raspberry Pi
- Kích thước binary dự kiến nằm trong khoảng vài trăm KB
Điều chỉnh mức dùng bộ nhớ và tốc độ tìm kiếm
sqlite-veckiểm soát mức dùng bộ nhớ bằng cách chia vector để lưu vào các chunk bên trong shadow table- Khi tìm kiếm KNN, không đưa tất cả vector lên RAM cùng lúc mà đọc theo từng chunk
- Không cần giữ toàn bộ vector thường trú trong bộ nhớ
- Nếu cần tốc độ dựa trên bộ nhớ, có thể dùng
PRAGMA mmap_sizecủa SQLite để làm tìm kiếm KNN nhanh hơn
Tính năng vector mới và giới hạn ban đầu
sqlite-vecmuốn hỗ trợ tốt hơn các tính năng sau, phản ánh dòng chảy của công cụ và nghiên cứu tìm kiếm vector gần đây- Embedding có độ dài thích ứng, tức Matryoshka embeddings
- Vector
int8vàbit - Binary and scalar quantization
- Những tính năng này là nền tảng để điều chỉnh tinh tế hơn tốc độ, độ chính xác và dung lượng đĩa của vector
sqlite-vecban đầu chỉ hỗ trợ tìm kiếm vector exhaustive full-scan- Ban đầu không có tùy chọn “approximate nearest neighbors”
- IVF và HNSW là các tính năng hy vọng sẽ bổ sung trong tương lai
Cấu hình demo trên trình duyệt
- Demo sử dụng
sqlite-vecchạy trong trình duyệt - Cấu hình có thể kiểm tra trong công cụ dành cho nhà phát triển như sau
sqlite3.wasm5.9MB chưa được tối ưu hóa- Bản build SQLite WASM chính thức đã biên dịch
sqlite-vec - Cơ sở dữ liệu SQLite
movies.bit.dbcó kích thước 2.6MB
- Trong
movies.bit.db, bảngarticleschứa overview của 4.800 bộ phim dựa trên metadata phim TMDB - Bảng ảo riêng
vec_movieslà chỉ mục vector của các embedding overview đó- Embedding dùng Nomic 1.5 embeddings model
- Vector được lượng tử hóa thành binary vector
Dữ liệu demo và luồng tìm kiếm KNN
- Bảng
articlescó các cột nhưtitle,release_date,overview - Cột
overviewchứa cốt truyện phim dưới dạng câu ngắn, và là đối tượng được embedding trong demo - Bảng ảo
vec_movieslưu embedding củaarticles.overviewtrong cộtoverview_embeddings- Vector là binary vector 768 chiều
- Kích thước lưu trữ là
768 / 8 = 96, tức 96 byte
- Khi người dùng chọn phim bằng nút radio, ID phim được chọn sẽ được điền vào tham số
:selected_moviecủa truy vấn SQL KNN - Kết quả tìm kiếm là 10 bộ phim gần nhất với phim đã chọn
- Vì là binary vector, phép tính khoảng cách dùng hamming distance
- Kết quả gần nhất luôn là chính bộ phim đó và khoảng cách là 0
- Kết quả embedding các cốt truyện một câu ngắn và tập dữ liệu phim nhỏ không có chất lượng cao nhất; binary quantization cũng hy sinh thêm chất lượng, nhưng trọng tâm là cho thấy tìm kiếm vector nhanh và “đủ tốt” ngay trong trình duyệt
- Để kiểm tra hoạt động bên trong, chỉ cần thêm
EXPLAIN QUERY PLANtrướcSELECT; có thể thấy “index”0:knnmàvec_moviessử dụng
Hạn chế của sqlite-vss và phụ thuộc Faiss
- Việc phát triển và áp dụng
sqlite-vssgặp nhiều trở ngại- Chỉ hoạt động trên Linux và macOS, không hỗ trợ Windows, WASM, thiết bị di động, v.v.
- Lưu toàn bộ vector trong bộ nhớ
- Có lỗi và vấn đề liên quan đến transaction
- Biên dịch rất khó và mất nhiều thời gian
- Thiếu các thao tác vector phổ biến như scalar/binary quantization
- Gần như hầu hết các vấn đề này bắt nguồn từ phụ thuộc vào
Faiss - Một số vấn đề có thể giải quyết nếu đầu tư nhiều thời gian và công sức, nhưng không ít vấn đề có thể bị chặn bởi Faiss
- Một giải pháp cấp thấp không phụ thuộc trở thành lựa chọn hấp dẫn, và
sqlite-vecđược bắt đầu từ nhận định rằng bản thân tìm kiếm vector không quá phức tạp
Trạng thái phát hành và lời kêu gọi tài trợ
- Các chức năng cốt lõi của
sqlite-vecđã hoạt động, nhưng xử lý lỗi và kiểm thử vẫn còn rất thiếu - Trong tệp
sqlite-vec.ccòn 246 TODO- 191
todo_assert() - 41 chú thích
// TODO - 14
todo panic - Tiến độ tổng thể được hiển thị là 0/246, 0% theo
sqlite-vec v0
- 191
- Khi hoàn tất 246 TODO, bản phát hành
v0.1.0đầu tiên dự kiến sẽ ra mắt- Tài liệu
- Demo
- Binding
- Các thành phần khác sẽ được cung cấp cùng
- Mục tiêu thời gian là khoảng một tháng, nhưng không phải lịch trình đã được xác định chắc chắn
- Đang tìm kiếm tài trợ từ các công ty quan tâm đến thành công của
sqlite-vec; có thể liên hệ qua email
1 bình luận
Ý kiến trên Hacker News
Tôi là tác giả — nếu có câu hỏi thì tôi sẽ trả lời. Đây mang tính chất “đang làm một dự án mới” hơn là một bản phát hành chính thức, và bản thân extension cũng vẫn đang được phát triển. Link dự án là https://github.com/asg017/sqlite-vec
Tôi đã có hình dung khá cụ thể về v0.1.0 của extension này sẽ trông như thế nào, nhưng có lẽ sẽ cần thêm vài tuần nữa để tới đó. Bài viết này chủ yếu nhằm báo cho người dùng sqlite-vss, extension tìm kiếm vector cho SQLite mà tôi từng làm trước đây, biết điều gì sẽ đến tiếp theo; khi sẵn sàng sẽ có một bản phát hành lớn hơn
Nhìn chung tôi rất hào hứng vì sẽ có một phương án tìm kiếm vector dễ nhúng. Điều đặc biệt hay là nó chạy được trên mọi hệ điều hành, WASM, thiết bị di động, Raspberry Pi, v.v.; cá nhân tôi đang thử chạy một ứng dụng tìm kiếm ngữ nghĩa nhỏ trên Beepy nên thấy khá thú vị
[0] https://beepy.sqfmi.com/
Tôi cũng muốn biết hiệu năng so với sqlite-vss. Tôi tò mò các số liệu profiling cả về tốc độ truy vấn lẫn mức dùng bộ nhớ
Nhìn chung trông thật sự tuyệt vời, và tôi thích hướng đi này
Cách tiếp cận ban đầu là sqlite-vec chỉ hỗ trợ tìm kiếm vector bằng quét toàn bộ vét cạn, chưa có tùy chọn láng giềng gần đúng gần nhất (ANN), nhưng sau này muốn thêm IVF và HNSW — tôi thấy đúng 1000%. Tôi thích việc không làm nó phức tạp quá mức ngay từ đầu
Tôi từng ra mắt tìm kiếm vector trên thiết bị, và với tổ hợp vector nhị phân 128-bit cùng khoảng cách Hamming, nó đủ nhanh để chạy tìm kiếm khoảng cách hoàn toàn brute-force trên hơn 200.000 mục trong cơ sở dữ liệu cho từng khung hình camera. Trên điện thoại giá rẻ vẫn đạt hơn 10fps, còn trên điện thoại tốt thì rất mượt. Có rất nhiều trường hợp đáng ngạc nhiên là brute-force đã đủ
Tuy vậy, khi triển khai các thuật toán ANN như HNSW, sẽ rất hay nếu có thể xử lý theo mô hình chỉ mục bảng. Khi đó việc chuyển từ tìm kiếm brute-force sang ANN sẽ đơn giản như tạo một chỉ mục trên bảng, và việc thử nghiệm nhiều thuật toán ANN cùng tham số cũng có thể thực hiện bằng cách điều chỉnh tham số tạo chỉ mục. Có thể bạn đã đi theo hướng đó rồi, nhưng tôi vẫn nhắc tới phòng khi hữu ích
Tôi cũng tò mò liệu nó có được build cùng sqlite-httpvfs không. Có vẻ rất hợp với dự án này: https://github.com/phiresky/sql.js-httpvfs
Tôi cũng tò mò liệu bạn đã cân nhắc làm cho nó tương thích cú pháp với pgvector để có một DSL vector SQL chung chưa. Tôi đoán nhược điểm có lẽ không nhỏ hơn ưu điểm nhiều lắm, nhưng vẫn muốn biết có khả thi không
https://observablehq.com/@asg017/introducing-sqlite-loadable...
sqlite-vss hiện đã được dùng tốt trong một số dự án
Tôi thấy khó hiểu đoạn “vector nhị phân 768 chiều nên chiếm 96 byte (768 / 8 = 96)”. Vấn đề mà hầu hết vector store gặp phải là lời nguyền chiều không gian, và tôi nghĩ đây là vấn đề trước cả lập chỉ mục
Ban đầu tôi tưởng có lẽ ý là 768 chiều * 8 byte (f64), tức 6144 byte. Thông thường người ta chấp nhận một chút mất mát để giảm xuống f32 hoặc f16, hoặc biểu diễn nhỏ hơn nữa
Nếu có cách đưa 768 chiều vào 96 byte bằng nén hay kiểu phân bổ khấu hao giống trie, tôi muốn nghe thêm trong một bài riêng. Nếu coi mỗi chiều là 1 bit thì tôi hiểu, nhưng khi đó tôi vẫn còn thắc mắc về chất lượng tìm kiếm
Một số mô hình embedding như nomic v1.5[0] hay mô hình mới của mixedbread[1] được huấn luyện đặc biệt để vẫn giữ chất lượng sau lượng tử hóa nhị phân. Không phải mô hình nào cũng như vậy, nên kết quả có thể khác nhau. Nói chung với các vector rất lớn, như mô hình embedding lớn 3072 chiều của OpenAI, dường như nó vẫn hoạt động ở mức nào đó dù không được huấn luyện riêng cho việc này
[0] https://twitter.com/nomic_ai/status/1769837800793243687
[1] https://www.mixedbread.ai/blog/binary-mrl
Nếu dùng chỉ mục FAISS cho dữ liệu và áp dụng Product Quantization, với đặc trưng nhị phân bạn có thể thử vector nhị phân theo kiểu PQ768x1, và cũng có thể so sánh các cách như lượng tử hóa mỗi cặp vector thành một trong bốn giá trị: https://github.com/facebookresearch/faiss/wiki/The-index-fac...
Thông thường trong cơ sở dữ liệu vector, dữ liệu được nén hoặc chiếu xuống không gian có số chiều thấp hơn trước khi lưu, nên tình huống này thực ra được cải thiện
Nhờ sqlite-vss, tôi đã học được cách RAG hoạt động và có thể triển khai nó trong một dự án đồ chơi. Việc debug hơi khó, nhưng khi cấu hình đúng thì nó chạy hoàn hảo trên Ubuntu, và tôi vẫn đang dùng đến giờ
Thật vui khi có người làm một phiên bản mới tốt hơn mà không có các phụ thuộc hạn chế
Tôi tò mò liệu dự định chỉ dùng SQLite API công khai, hay hình dung theo kiểu gắn vào SQLite amalgamation
Tôi chắc chắn quan tâm đến tính năng kiểu này, nhưng cần suy nghĩ xem sẽ phân phối nó riêng với SQLite như thế nào trong binding Go dựa trên Wasm. Cho đến nay, cách làm của tôi là đóng gói toàn bộ mã C để phân phối, vì đơn giản hơn nhiều so với “liên kết động” trong Wasm
Ngoài ra, bạn có nhắc đến I/O BLOB tăng dần; chắc bạn đã biết, nhưng cần lưu ý rằng vì BLOB lớn được lưu dưới dạng danh sách liên kết các trang, I/O BLOB tuyệt đối không phải là truy cập ngẫu nhiên
Tôi rất thích binding SQLite của wazero. Thực tế tôi dự định cung cấp 1) binding CGO cho sqlite-vec và 2) một bản build sqlite-vec WASI tùy chỉnh có thể dùng trực tiếp trong go-sqlite3. Ban đầu tôi định dùng script build của repo đó để tạo file sqlite3.wasm. Nếu muốn hỗ trợ trực tiếp trong dự án, có lẽ chỉ cần đưa các file sqlite-vec.c/h vào go-sqlite3/sqlite3 là được
I/O BLOB tăng dần là thứ tôi đã học được theo cách khá vất vả. Nó rõ ràng là yếu tố giới hạn tốc độ truy vấn của sqlite-vec. Giữ kích thước chunk tương đối nhỏ, ở mức vài MB thấp, và tăng page_size thì đạt được cân bằng khá ổn, nhưng đặc biệt page_size có các tác dụng phụ. PRAGMA mmap_size cũng giúp rất nhiều, vì dường như giữ các trang trong bộ nhớ và làm cho việc tra cứu overflow nhanh hơn, nhưng dĩ nhiên mức dùng bộ nhớ tăng lên nhiều. Đây là một sự cân bằng khó
Hôm nay DuckDB đã công bố extension “Vector Similarity Search in DuckDB”
https://duckdb.org/2024/05/03/vector-similarity-search-vss.h...
Với DuckDB VSS, có vẻ có thể embedding rồi lưu ở định dạng DuckDB, sau đó chạy SQL ngay trong CDN
Tôi thích những dự án kiểu này. Thích vì đây là một dự án mã nguồn mở nhắm vào một vấn đề rất cụ thể
Tôi vẫn tiếp tục nghĩ xem liệu trong hệ sinh thái TypeScript/Next.js/React có thể tạo ra thứ gì đó rất hữu ích cho một ngách kỹ thuật hay không, nhưng vẫn chưa nảy ra cảm hứng
Trong ứng dụng AI RAG https://github.com/rnadigital/agentcloud, chúng tôi đã dùng Qdrant vector DB cho tự động hóa end-to-end, nên tôi rất mong chờ phần tiếp theo. Tôi muốn biết khi nào nó sẵn sàng để dùng và có hướng dẫn quick start hay không
Tôi cũng có thể giúp viết blog
Có một package pip
sqlite-vecchưa được ghi tài liệu, nên nếu muốn gọi trực tiếp từ “Agent Backend” trong Python thì có lẽ hiện giờ bạn cũng có thể thửCái này khá giống với những gì tôi tưởng tượng về “phát triển dựa trên README”. Tôi tò mò liệu tác giả có bắt đầu từ tài liệu hay không
Tuy nhiên hiện đang ở trạng thái “tạo ra 80% bằng 20% công sức”, nên 20% còn lại gồm xử lý lỗi, fuzz testing, kiểm thử độ chính xác có lẽ sẽ chiếm 80% thời gian. Dù vậy, mọi người đã hỏi về tình trạng hiện tại của
sqlite-vss, nên tôi nghĩ bài blog “đang làm” này có thể trả lời một vài câu hỏiTôi cũng thích ý tưởng bắt đầu từ tài liệu. Đặc biệt với extension SQLite, SQL API trông như thế nào, tức là scalar function và virtual table, v.v., thật sự rất quan trọng. Trước khi viết phần lớn code, tôi đã phác thảo khá nhiều về phần SQL của sqlite-vec nên trông như thế nào
[0] https://github.com/asg017/sqlite-vec/blob/main/sqlite-vec.c
Có vẻ đây gần như là câu trả lời cho một GitHub issue tôi đã mở trên SQLite-vss vài tháng trước. Nói chính xác thì không phải là phản hồi cho issue đó, nhưng
https://github.com/asg017/sqlite-vss/issues/124
Thực ra khi đọc ticket đó lần đầu, tôi đã rơi vào một hố thỏ kiểu “làm sao để cải thiện sqlite-vss”, và cuối cùng dẫn đến “mình nên tạo sqlite-vec”. Cảm ơn vì đã giúp tôi đi theo hướng này
Với lượng tử hóa nhị phân tích hợp của sqlite-vec, bạn có thể làm đại khái như sau:
CREATE VIRTUAL TABLE vec_files USING vec0 ( contents_embedding bit[1536] );INSERT INTO vec_files(rowid,contents_embedding) VALUES ((1, vec_quantize_binary( /* 1536-dimension float vector here*/)))Tôi thắc mắc liệu khi chạy trong trình duyệt, sqlite-vec có thể lưu bền vững dữ liệu vào IndexedDB native của trình duyệt hay không. Hay tôi muốn biết phần này người dùng phải tự xử lý
Dù câu trả lời là chưa nghĩ đến, nếu có thể chia sẻ suy nghĩ theo hướng đó thì tôi rất cảm ơn
Tôi không chắc IndexedDB có được hỗ trợ cụ thể hay không, nhưng có thể dùng localStorage/OPFS VFS
[0] https://sqlite.org/wasm/doc/trunk/persistence.md#kvvfs