Cơ sở dữ liệu vector là một lớp trừu tượng sai lầm
(timescale.com)- Thông điệp ám ảnh các nhóm kỹ thuật đang cố xây dựng ứng dụng AI: "embedding không còn được đồng bộ lại"
- Việc triển khai tìm kiếm vector đơn giản dần biến thành một dàn nhạc phức tạp của giám sát, đồng bộ hóa và xử lý sự cố
- Sau khi trao đổi với các nhóm kỹ thuật xây dựng hệ thống AI bằng cơ sở dữ liệu vector, tác giả nhận ra lớp trừu tượng sai lầm của cơ sở dữ liệu vector và những khiếm khuyết trong cách chúng được dùng hiện nay
"Trường hợp phổ biến khi xây dựng hệ thống RAG"
- Dùng Pinecone làm cơ sở dữ liệu vector để lưu trữ và truy xuất embedding
- Vì dữ liệu văn bản không phù hợp với metadata của Pinecone, DynamoDB được dùng để xử lý blob và dữ liệu ứng dụng
- Cần thêm OpenSearch cho tìm kiếm từ vựng
- Giờ đây việc nối và đồng bộ 3 hệ thống trở thành cơn ác mộng
Khi xóa tài liệu nguồn, bạn phải làm như sau:
- Chạy boto3 để xóa bản ghi khỏi DynamoDB
- Cập nhật Pinecone để bảo đảm embedding đã bị xóa
- Cần một yêu cầu POST để cập nhật chỉ mục tìm kiếm từ vựng
- Phải làm như vậy với mọi lần cập nhật, thêm mới hoặc xóa tài liệu nguồn
- Quản lý cấu hình không chỉ lộn xộn mà còn đầy rủi ro
- Có đội ngũ phải trả $2.000 mỗi tháng cho một chỉ mục đáng lẽ phải xóa từ 4 tháng trước
- Có nguy cơ trả về dữ liệu sai hoặc đã cũ cho người dùng
Cơ sở dữ liệu vector được xây trên một lớp trừu tượng sai lầm
- Cơ sở dữ liệu vector coi embedding là dữ liệu độc lập thay vì dữ liệu phái sinh
- Việc coi embedding là dữ liệu độc lập tạo ra độ phức tạp không cần thiết
Cách tốt hơn: lớp trừu tượng "Vectorizer"
- Đề xuất lớp trừu tượng "vectorizer", trong đó embedding được đối xử như một chỉ mục cơ sở dữ liệu
- Cách tiếp cận này tự động đồng bộ embedding với dữ liệu nguồn, loại bỏ chi phí bảo trì
- Vectorizer tương ứng với lệnh
CREATE INDEXnhư sau:
SELECT ai.create_vectorizer(
'public.blogs'::regclass,
embedding => ai.embedding_openai('text-embedding-3-small', 1536),
chunking => ai.chunking_recursive_character_text_splitter('content')
);
- Lệnh này tạo embedding cho mọi mục trong bảng blog và tiếp tục cập nhật embedding khi dữ liệu trong bảng thay đổi
Vấn đề của cơ sở dữ liệu vector (và kiểu dữ liệu vector)
- Cơ sở dữ liệu vector được phát triển để xử lý khối lượng lớn vector embedding cho dữ liệu văn bản, hình ảnh và đa phương thức
- Các cơ sở dữ liệu đa dụng như PostgreSQL, MySQL, MongoDB, Oracle cũng đã bổ sung hỗ trợ tìm kiếm vector
- Tuy nhiên, lớp trừu tượng của các hệ thống độc lập hoặc tính năng tìm kiếm vector được thêm vào cơ sở dữ liệu hiện có có một khiếm khuyết chí mạng
- Một khi embedding được chèn vào cơ sở dữ liệu, kết nối giữa dữ liệu phi cấu trúc được embedding và bản thân vector embedding bị cắt đứt
- Khi không có kết nối này, embedding bị đối xử sai như những nguyên tử dữ liệu độc lập mà lập trình viên phải tự quản lý, thay vì dữ liệu phái sinh
- Khi tái khái niệm embedding như dữ liệu phái sinh, sự phi lý của lớp trừu tượng cơ sở dữ liệu vector hiện nay — nơi embedding không gắn với dữ liệu nguồn — trở nên rõ ràng
Các nhóm phát triển phải quản lý:
-
Pipeline ETL (extract-load-transform) phức tạp
-
Cơ sở dữ liệu vector cho embedding, một cơ sở dữ liệu khác cho metadata và dữ liệu ứng dụng, cùng chỉ mục tìm kiếm từ vựng
-
Dịch vụ đồng bộ dữ liệu
-
Hệ thống hàng đợi cho cập nhật và đồng bộ
-
Công cụ giám sát để phát hiện data drift và xử lý các giới hạn tốc độ của dịch vụ embedding
-
Hệ thống cảnh báo khi truy vấn trả về kết quả cũ
-
Các bước xác minh trên mọi hệ thống
-
Muốn nâng cấp sang mô hình embedding mới hoặc thử phương pháp chunking khác, bạn phải viết mã tùy chỉnh và điều phối thay đổi trên nhiều dịch vụ dữ liệu và cơ sở dữ liệu
-
Những công việc này đặt gánh nặng lên nhóm phát triển trong việc bảo đảm embedding được tạo ra kịp thời khi dữ liệu nguồn thay đổi
-
Nếu không, embedding rất dễ trở nên lỗi thời và mang lại trải nghiệm ứng dụng tệ hơn cho người dùng
Cách tốt hơn: để cơ sở dữ liệu xử lý độ phức tạp
- Khi tái định nghĩa embedding là dữ liệu phái sinh, có thể giao trách nhiệm tạo và cập nhật embedding theo các thay đổi của dữ liệu nền cho hệ quản trị cơ sở dữ liệu
- Sự thay đổi này giải phóng lập trình viên khỏi gánh nặng phải tự tay giữ embedding luôn đồng bộ với dữ liệu nguồn
- Sự phân biệt này có thể không quan trọng với các ứng dụng đơn giản chỉ nhập dữ liệu một lần cho RAG
- Nhưng trong phần lớn ứng dụng thực tế, dữ liệu thay đổi liên tục
- Hãy nghĩ đến nền tảng thương mại điện tử dùng tìm kiếm ngữ nghĩa dựa trên embedding, hoặc ứng dụng RAG làm trợ lý sản phẩm phải luôn cập nhật thông tin sản phẩm mới nhất
- Việc tự theo dõi các thay đổi này và tái tạo embedding không chỉ tốn công và dễ lỗi mà còn khiến nhà phát triển mất tập trung khỏi mục tiêu kinh doanh cốt lõi
- Tại sao phải lãng phí thời gian phát triển khi hệ thống cơ sở dữ liệu có thể tự động xử lý?
Vectorizer: vector embedding như một chỉ mục
- Một lớp trừu tượng hiệu quả hơn là coi vector embedding như một chỉ mục đặc biệt cho dữ liệu được embedding, thay vì một bảng hay kiểu dữ liệu độc lập
- Vector embedding không phải chỉ mục theo nghĩa truyền thống
- Thay vào đó, vector embedding hoạt động như một cơ chế lập chỉ mục để truy xuất những phần dữ liệu liên quan nhất dựa trên embedding
- Có thể gọi lớp trừu tượng mới giống chỉ mục này là "vectorizer"
Các lợi ích chính của lớp trừu tượng vectorizer:
Tự động đồng bộ
- Một trong các lợi ích lớn của lập chỉ mục trong cơ sở dữ liệu là tự động giữ chỉ mục đồng bộ với dữ liệu nền
- Khi dữ liệu trong cột thay đổi, chỉ mục sẽ được cập nhật tương ứng
- Bằng cách coi vector embedding như một dạng lập chỉ mục, ta có thể tận dụng cơ chế tự động đồng bộ tương tự
- Hệ thống bảo đảm vector embedding luôn được cập nhật theo dữ liệu mới nhất, loại bỏ nhu cầu cập nhật thủ công và giảm nguy cơ lỗi
Tăng cường mối quan hệ giữa dữ liệu và embedding
- Khi vector được lưu độc lập, rất dễ đánh mất mối liên hệ với dữ liệu gốc
- Vector này được tạo từ bản cập nhật gần đây của dữ liệu, hay là vector cũ từ một mô hình embedding trước đó?
- Đây là những câu hỏi quan trọng, và nếu nhầm lẫn ở đây có thể gây ra lỗi nghiêm trọng
- Bằng cách gắn trực tiếp vector embedding với dữ liệu như một chỉ mục, mối quan hệ trở nên rõ ràng và được duy trì tự động
Đơn giản hóa quản lý dữ liệu
- Lập trình viên thường gặp khó khăn khi phải tự quản lý đồng bộ dữ liệu
- Ví dụ, khi dữ liệu nền bị xóa mà quên xóa dữ liệu từ mô hình embedding cũ, sự không nhất quán có thể xảy ra
- Lớp trừu tượng vectorizer biến việc quản lý các mối quan hệ này thành trách nhiệm của hệ thống, giảm tải nhận thức cho lập trình viên và hạn chế tối đa sai sót
Vectorizer là sự tiến hóa tự nhiên của lời hứa cốt lõi từ DBMS
- Khái niệm vectorizer là sự tiến hóa tự nhiên của các năng lực hiện đại trong hệ quản trị cơ sở dữ liệu (DBMS)
- DBMS ngày nay vốn đã rất giỏi trong việc quản lý biến đổi và đồng bộ dữ liệu thông qua các cấu trúc khai báo như index, trigger và materialized view
- Lớp trừu tượng vectorizer rất phù hợp với mô hình này khi cung cấp một công cụ mới để xử lý tác vụ ngày càng quan trọng là quản lý vector embedding
- Bằng cách tích hợp trực tiếp khả năng này vào DBMS, chúng ta tiến gần hơn đến việc hiện thực hóa lời hứa tối hậu của hệ thống cơ sở dữ liệu
- Đó là quản lý dữ liệu theo cách trừu tượng hóa độ phức tạp, để người dùng có thể tập trung vào việc họ làm tốt nhất: xây dựng ứng dụng, phân tích dữ liệu và thúc đẩy đổi mới
Triển khai vectorizer cho PostgreSQL: pgai Vectorizer
- Với động lực giảm gánh nặng cho lập trình viên, nhóm kỹ sư AI của Timescale đã triển khai vectorizer cho PostgreSQL
- Nó có tên là pgai Vectorizer và hiện đang ở giai đoạn Early Access
- Đây là một phần của dự án PGAI nhằm làm cho PostgreSQL phù hợp hơn với hệ thống AI và giúp việc phát triển AI dễ dàng hơn cho các lập trình viên quen thuộc với PostgreSQL
- Nếu muốn xem cách pgai Vectorizer tự động tạo và cập nhật vector embedding cho dữ liệu trong PostgreSQL, hãy xem video demo
Cách pgai Vectorizer hoạt động
- Vectorizer được định nghĩa và tạo bằng SQL
- Truy vấn sau tạo một vectorizer và chỉ định bảng mà nó tác động, cột sẽ được vector hóa, mô hình embedding sẽ dùng và định dạng bổ sung cho các thông tin khác cần đưa vào dữ liệu nguồn được embedding
-- Tạo vectorizer tự động embedding dữ liệu trong bảng blogs
SELECT ai.create_vectorizer(
'public.blogs'::regclass
-- Sử dụng mô hình OpenAI text-embedding-3-small
, embedding=>ai.embedding_openai('text-embedding-3-small', 1536, api_key_name=>'OPENAI_API_KEY')
-- Tự động tạo chỉ mục StreamingDiskANN khi bảng có 100k hàng
, indexing => ai.indexing_diskann(min_rows => 100000, storage_layout => 'memory_optimized'),
-- Áp dụng chunking đệ quy lên cột content
, chunking=>ai.chunking_recursive_character_text_splitter('content')
-- Thêm metadata từ các cột khác vào embedding để cải thiện truy xuất
, formatting=>ai.formatting_python_template('Blog title: $title url: $url blog chunk: $chunk')
);
-- Vectorizer cập nhật embedding khi bảng nguồn thay đổi
-- Không cần thao tác nào khác từ người dùng
- Ngoài ra, do văn bản dài cần được chia thành nhiều chunk nhỏ hơn để phù hợp với giới hạn token của mô hình embedding, hệ thống định nghĩa sẵn các hàm chunking mặc định
Theo dõi thay đổi dữ liệu nguồn
- pgai Vectorizer nội bộ sẽ kiểm tra các sửa đổi (insert, update, delete) trên bảng nguồn và tạo/cập nhật vector embedding một cách bất đồng bộ
- pgai Vectorizer được xây dựng cho hai kiểu triển khai: tự lưu trữ và được quản lý hoàn toàn trên Timescale Cloud
- Trong triển khai được lưu trữ trên đám mây của pgai Vectorizer, việc tạo embedding sử dụng các khả năng cloud của nền tảng Timescale Cloud
- Trong phiên bản mã nguồn mở của pgai Vectorizer, embedding được tạo bằng cách chạy một worker bên ngoài
- pgai Vectorizer lưu cấu hình và thông tin catalog bên trong cơ sở dữ liệu cùng với dữ liệu sổ sách nội bộ quan trọng
Embedding thực sự được tạo ở đâu?
- Quá trình embedding thực tế diễn ra trong một tiến trình bên ngoài, nằm ngoài cơ sở dữ liệu
- Điều này giúp giảm tải cho máy chủ cơ sở dữ liệu và bảo đảm vectorizer không ảnh hưởng đến khả năng xử lý truy vấn ứng dụng của cơ sở dữ liệu
- Nó cũng cho phép mở rộng tác vụ embedding dễ dàng, độc lập với các tác vụ cơ sở dữ liệu khác
- Quy trình này trước tiên đọc cơ sở dữ liệu để kiểm tra có công việc nào cần thực hiện hay không
- Nếu có, nó đọc dữ liệu từ cơ sở dữ liệu, thực hiện chunking và formatting, gọi nhà cung cấp mô hình embedding như OpenAI để tạo embedding, rồi ghi kết quả trở lại cơ sở dữ liệu
Tùy chỉnh quy trình
- pgai Vectorizer rất linh hoạt: bạn có thể chỉ định quy tắc chunking và formatting dùng để tạo embedding
- Cụ thể, có thể cấu hình các cột trong bảng nguồn sẽ được vector hóa, cũng như các quy tắc chunking và formatting để dữ liệu nguồn vừa với giới hạn token của embedding và bảo đảm dữ liệu liên quan được đưa vào mỗi embedding
- Trong bản phát hành Early Access của pgai Vectorizer, người dùng có thể tùy chỉnh lựa chọn mô hình embedding OpenAI, chiến lược chunking để chia văn bản thành các phần nhỏ hơn, tùy chọn formatting để chèn thêm ngữ cảnh vào từng chunk, cùng cấu hình indexing tùy chỉnh cho việc tự động tạo chỉ mục và tinh chỉnh hiệu năng
- Sắp tới, nhóm phát triển dự định tăng thêm độ linh hoạt bằng cách cho phép người dùng gửi mã Python của riêng mình để tùy biến hoàn toàn chunking, embedding và formatting
Ví dụ, dưới đây là một vectorizer được cấu hình để chia đệ quy các tệp nguồn HTML và tạo OpenAI embedding từ dữ liệu nguồn. Có thể cấu hình chunking và formatting để phù hợp với dữ liệu ứng dụng như code, tài liệu, markdown, v.v.
-- Cấu hình vectorizer nâng cao
SELECT ai.create_vectorizer(
'public.blogs'::regclass,
destination => 'blogs_embedding_recursive',
embedding => ai.embedding_openai('text-embedding-3-small', 1536),
-- Áp dụng recursive chunking với cấu hình chỉ định cho nội dung HTML
chunking => ai.chunking_recursive_character_text_splitter(
'content',
chunk_size => 800,
chunk_overlap => 400,
-- Dấu phân tách nhận biết HTML, sắp xếp từ ưu tiên cao nhất đến thấp nhất
separator => array[
E'
', -- Tách ở các phần tài liệu chính
E'
', -- Tách ở ranh giới div
E'
',
E'
', -- Tách ở đoạn văn
E'
', -- Tách ở chỗ xuống dòng
E'
', -- Tách ở mục danh sách
E'. ', -- Dự phòng theo ranh giới câu
' ' -- Phương án cuối cùng: tách theo khoảng trắng
]
),
formatting => ai.formatting_python_template('title: $title url: $url $chunk')
);
Ý kiến của GN⁺
- pgai Vectorizer có vẻ là một công cụ mạnh mẽ và đổi mới, có thể đơn giản hóa đáng kể việc quản lý embedding. Lớp trừu tượng vectorizer giúp giảm gánh nặng phải quản lý embedding thủ công cho lập trình viên và bảo đảm embedding được đồng bộ với dữ liệu nguồn.
- Đặc biệt, nó có vẻ rất hữu ích khi áp dụng các thay đổi như nâng cấp mô hình embedding hoặc thay đổi chiến lược chunking. Với cơ sở dữ liệu vector truyền thống, những thay đổi như vậy có thể dẫn tới một quy trình phức tạp đòi hỏi viết mã tùy chỉnh và điều phối trên nhiều hệ thống, nhưng với pgai Vectorizer thì chỉ cần cập nhật cấu hình vectorizer.
- Ngoài ra, việc quản lý embedding trong một cơ sở dữ liệu đa dụng như PostgreSQL có thể tránh được bài toán phải điều phối nhiều hệ thống chuyên biệt. Điều này có thể giúp đơn giản hóa mạnh việc phát triển ứng dụng.
- Một điểm cần cân nhắc là embedding thực tế được tạo trong một tiến trình Python bên ngoài. Đây là lựa chọn thiết kế tốt để tránh ảnh hưởng đến hiệu năng cơ sở dữ liệu, nhưng cũng có nghĩa là quá trình tạo embedding cần được giám sát và quản lý riêng.
- Cuối cùng, pgai Vectorizer là một bước tiến đáng kể trong cách quản lý embedding cho ứng dụng AI. Khi ngày càng nhiều đội ngũ áp dụng và phản hồi, công cụ mạnh mẽ này được kỳ vọng sẽ tiếp tục phát triển hơn nữa. Việc tích hợp quản lý embedding vào một công cụ quen thuộc như Postgres sẽ giúp nhiều lập trình viên hơn tận dụng được các khả năng AI tiên tiến.
1 bình luận
Ý kiến trên Hacker News
Đang đánh giá quá cao overhead của việc đồng bộ dữ liệu, và hầu hết các workflow dựa trên embedding không có nhiều cập nhật hay xóa. Ngay cả với các tập dữ liệu nhỏ cũng khó nhận ra vấn đề về tính nhất quán. Tuy vậy, việc không phải lo đồng bộ dữ liệu vẫn rất tuyệt
Với tư cách là nhân viên Elastic, có nhắc tới việc Elasticsearch gần đây đã thêm kiểu dữ liệu
semantic_text. Kiểu này tự động chia văn bản thành các chunk rồi tính toán và lưu embedding. Truy vấn cũng được đơn giản hóa, giúp giảm I/O và làm mã phía client đơn giản hơnGiới thiệu một công cụ cho PostgreSQL, tái hình dung vector embedding như một chỉ mục cơ sở dữ liệu. Hiện tại chỉ hỗ trợ OpenAI, nhưng có kế hoạch sớm hỗ trợ các mô hình cục bộ và OSS. Đang mong chờ phản hồi và ý kiến từ mọi người
Nêu nghi vấn về việc dùng FAISS như một cơ sở dữ liệu duy nhất. Nó giống như sqlite cho vector embedding, và có thể lưu metadata cùng vector để duy trì các mối quan hệ
Tỏ ra tích cực về việc dùng vector trong Postgres, đồng thời nêu câu hỏi về thứ tự filtering khi đưa tìm kiếm vector và logic vào truy vấn SQL. Thích DX của
pg_vector, nhưng filtering sau tìm kiếm vector có thể làm chậm tốc độCó ý kiến rằng việc lưu raw embedding trong cơ sở dữ liệu vector cũng giống như lưu các n-gram thô của văn bản trong cơ sở dữ liệu. Lưu tài liệu sẽ hợp lý hơn
Có nhắc tới việc đang dùng sqlite-vec và FTS5 trong SQLite, và thấy chúng rất hữu ích
Đã xây dựng một ORM PostgreSQL trong Node.js để có thể viết code bao gồm cả trường vector. Cách này cho phép truy vấn dữ liệu hoặc nội dung embedding, đồng thời có thể định nghĩa cách lưu các trường của model dưới dạng embedding
Có nhắc rằng Materialized Views rất tốt
Có ý kiến rằng các ứng dụng AI dùng chunk dựa trên ký tự vẫn chưa vượt qua giai đoạn PoC