GN⁺: 벡터 데이터베이스는 잘못된 추상화임
(timescale.com)- AI 애플리케이션을 구축하려는 엔지니어링 팀을 괴롭히는 메시지 : "임베딩이 다시 동기화되지 않았습니다"
- 간단한 벡터 검색 구현은 모니터링, 동기화 및 문제 해결의 복잡한 오케스트라로 발전함
- 벡터 데이터베이스로 AI 시스템을 구축하는 엔지니어링 팀과 이야기를 나눈 결과, 벡터 데이터베이스의 잘못된 추상화와 오늘날 사용 방식의 결함을 발견함
"RAG 시스템을 구축하는 공통적인 사례"
- Pinecone을 벡터 데이터베이스로 사용하여 임베딩을 저장하고 검색함
- 텍스트 데이터가 Pinecone의 메타데이터에 잘 맞지 않아 DynamoDB로 블롭과 애플리케이션 데이터를 처리함
- 어휘 검색을 위해 OpenSearch가 필요했음
- 이제 3개의 시스템을 연결하고 동기화하는 것이 악몽임
소스 문서를 삭제할 때 다음을 수행해야 함:
- boto3를 실행하여 DynamoDB에서 레코드 제거
- Pinecone을 업데이트하여 임베딩이 삭제되었는지 확인
- 어휘 검색 인덱스를 업데이트하기 위해 POST 요청 필요
- 모든 소스 문서 업데이트, 추가 또는 삭제에 대해 이를 수행해야 함
- 구성 관리는 지저분할 뿐만 아니라 위험함
- 4개월 전에 삭제했어야 할 인덱스에 대해 한 달에 $2,000를 지불한 팀도 있음
- 잘못되거나 오래된 데이터를 사용자에게 반환할 위험이 있음
벡터 데이터베이스는 잘못된 추상화에 구축됨
- 벡터 데이터베이스는 임베딩을 파생 데이터가 아닌 독립적인 데이터로 취급함
- 임베딩을 독립적인 데이터로 취급함으로써 불필요한 복잡성을 만듦
더 나은 방법: "Vectorizer" 추상화
- 임베딩을 데이터베이스 인덱스와 같이 취급하는 "벡터라이저" 추상화를 제안함
- 이 접근 방식은 임베딩을 소스 데이터와 자동으로 동기화하여 유지 관리 비용을 제거함
-
CREATE INDEX
명령에 해당하는 벡터라이저는 다음과 같음:
SELECT ai.create_vectorizer(
'public.blogs'::regclass,
embedding => ai.embedding_openai('text-embedding-3-small', 1536),
chunking => ai.chunking_recursive_character_text_splitter('content')
);
- 이 명령은 블로그 테이블의 모든 항목에 대한 임베딩을 생성하고 테이블의 데이터가 변경될 때 임베딩을 계속 업데이트함
벡터 데이터베이스(및 벡터 데이터 유형)의 문제점
- 벡터 데이터베이스는 텍스트, 이미지 및 멀티모달 데이터에 대한 대량의 벡터 임베딩을 처리하기 위해 개발됨
- PostgreSQL, MySQL, MongoDB, Oracle과 같은 범용 데이터베이스도 벡터 검색 지원을 추가함
- 그러나 독립형 시스템 또는 기존 데이터베이스에 추가된 벡터 검색 기능의 추상화에는 치명적인 결함이 있음
- 임베딩이 데이터베이스에 삽입되면 임베딩되는 비정형 데이터와 벡터 임베딩 자체 간의 연결이 끊어짐
- 이 연결이 없으면 임베딩은 파생 데이터가 아닌 개발자가 관리해야 하는 독립적인 데이터 원자로 잘못 취급됨
- 임베딩을 파생 데이터로 재구성하면 임베딩이 소스 데이터와 연결되지 않은 현재 벡터 데이터베이스 추상화의 부조리함이 분명해짐
개발 팀은 다음을 관리해야 함:
-
복잡한 ETL(추출-로드-변환) 파이프라인
-
임베딩용 벡터 데이터베이스, 메타데이터 및 앱 데이터용 다른 데이터베이스, 어휘 검색 인덱스
-
데이터 동기화 서비스
-
업데이트 및 동기화를 위한 큐잉 시스템
-
데이터 드리프트를 잡고 임베딩 서비스의 속도 제한 등을 처리하는 모니터링 도구
-
검색이 오래된 결과를 반환할 때 알림 시스템
-
모든 시스템에 대한 검증 확인
-
새로운 임베딩 모델로 업그레이드하거나 다른 청킹 방법을 시도하려면 사용자 정의 코드를 작성하고 여러 데이터 서비스 및 데이터베이스에서 변경 사항을 조정해야 함
-
이러한 작업은 개발 팀에게 임베딩이 소스 데이터가 변경됨에 따라 시기적절하게 생성되도록 보장하는 부담을 줌
-
그렇지 않으면 임베딩이 자주 오래되어 사용자에게 더 나쁜 애플리케이션 경험을 제공할 위험이 있음
더 나은 방법: 데이터베이스가 복잡성을 처리하도록 하기
- 임베딩을 파생 데이터로 재구성하면 기본 데이터가 변경됨에 따라 임베딩을 생성하고 업데이트할 책임을 데이터베이스 관리 시스템에 맡길 수 있음
- 이 변경으로 개발자는 수동으로 임베딩을 소스 데이터와 동기화된 상태로 유지해야 하는 부담에서 벗어남
- 이 구분은 RAG에 대해 일회성 데이터 가져오기를 수행하는 간단한 애플리케이션에는 중요하지 않을 수 있음
- 그러나 대부분의 실제 애플리케이션에서 데이터는 지속적으로 변경됨
- 임베딩 기반 의미론적 검색을 사용하는 전자상거래 플랫폼이나 최신 제품 정보로 최신 상태를 유지해야 하는 제품 어시스턴트 RAG 앱을 고려하십시오.
- 이러한 변경 사항을 수동으로 추적하고 임베딩을 다시 생성하는 것은 노동 집약적이고 오류가 발생하기 쉬울 뿐만 아니라 개발자가 핵심 비즈니스 목표에 집중하는 것을 방해함
- 데이터베이스 시스템이 자동으로 처리할 수 있는데 왜 개발 시간을 낭비하는가?
벡터라이저: 인덱스로서의 벡터 임베딩
- 벡터 임베딩을 독립적인 테이블이나 데이터 유형이 아닌 임베딩된 데이터에 대한 특수한 인덱스로 개념화하는 것이 더 효과적인 추상화임
- 벡터 임베딩은 전통적인 의미에서 인덱스가 아님
- 대신에 벡터 임베딩은 임베딩에 기반하여 데이터의 가장 관련성 있는 부분을 검색하는 인덱싱 메커니즘으로 작동함
- 우리는 이 새로운 인덱스와 유사한 추상화를 "벡터라이저"라고 부를 수 있음
벡터라이저 추상화의 주요 이점:
자동 동기화
- 데이터베이스의 인덱싱의 주요 이점 중 하나는 기본 데이터와 인덱스를 자동으로 동기화된 상태로 유지하는 것
- 열의 데이터가 변경되면 인덱스가 그에 따라 업데이트됨
- 벡터 임베딩을 인덱싱의 한 형태로 취급함으로써 이와 동일한 자동 동기화를 활용할 수 있음
- 시스템은 벡터 임베딩이 항상 최신 데이터로 최신 상태를 유지하도록 보장하여 수동 업데이트의 필요성을 제거하고 오류 위험을 줄임
강화된 데이터-임베딩 관계
- 벡터가 독립적으로 저장되면 원래 데이터와의 관계를 잃어버리기 쉬움
- 이 벡터는 데이터의 최근 업데이트에서 생성되었는가? 아니면 이전 임베딩 모델의 오래된 벡터인가?
- 이러한 질문은 중요하며 여기서 혼동되면 심각한 오류가 발생할 수 있음
- 벡터 임베딩을 인덱스로 데이터에 직접 연결함으로써 관계가 명확해지고 자동으로 유지됨
단순화된 데이터 관리
- 개발자는 종종 데이터 동기화를 수동으로 관리할 때 어려움에 직면함
- 예를 들어, 기본 데이터가 삭제될 때 이전 임베딩 모델의 데이터를 삭제하는 것을 잊으면 불일치가 발생할 수 있음
- 벡터라이저 추상화는 이러한 관계를 관리하는 것을 시스템의 책임으로 만들어 개발자의 인지 부하를 줄이고 실수 가능성을 최소화함
벡터라이저는 핵심 DBMS 약속의 자연스러운 진화
- 벡터라이저 개념은 현대 데이터베이스 관리 시스템(DBMS) 기능의 자연스러운 진화임
- 오늘날의 DBMS는 인덱스, 트리거, 물질화된 뷰와 같은 선언적 구조를 통해 데이터 변환 및 동기화를 관리하는 데 이미 능숙함
- 벡터라이저 추상화는 벡터 임베딩 관리의 점점 더 중요해지는 작업을 처리하기 위한 새로운 도구를 제공하여 이 패러다임에 잘 맞음
- 이 기능을 DBMS에 직접 포함함으로써 데이터베이스 시스템의 궁극적인 약속을 실현하는 데 더 가까워짐
- 사용자가 애플리케이션 구축, 데이터 분석 및 혁신 주도에 가장 잘하는 일에 집중할 수 있도록 복잡성을 추상화하는 방식으로 데이터를 관리함
PostgreSQL용 벡터라이저 구현: pgai Vectorizer
- 개발자의 부담을 가볍게 하겠다는 약속에 동기를 부여받아 Timescale의 AI 엔지니어링 팀은 PostgreSQL용 벡터라이저를 구현했음
- pgai Vectorizer라고 하며 현재 Early Access에 있음
- PGAI 프로젝트의 일부로 PostgreSQL을 AI 시스템에 더 적합하게 만들고 PostgreSQL에 익숙한 개발자에게 AI 개발을 쉽게 하기 위한 프로젝트임
- pgai Vectorizer가 PostgreSQL의 데이터에 대한 벡터 임베딩을 자동으로 생성하고 업데이트하는 방법을 보려면 데모 비디오를 확인하세요
pgai Vectorizer 작동 방식
- SQL에서 벡터라이저를 정의하고 생성함
- 다음 쿼리는 벡터라이저를 생성하고 작용하는 테이블,벡터화할 열, 사용할 임베딩 모델, 임베딩할 소스 데이터에 포함할 다른 정보에 대한 추가 서식을 지정함
-- blogs 테이블의 데이터를 자동으로 임베드하는 벡터라이저 생성
SELECT ai.create_vectorizer(
'public.blogs'::regclass
-- OpenAI text-embedding-3-small 모델 사용
, embedding=>ai.embedding_openai('text-embedding-3-small', 1536, api_key_name=>'OPENAI_API_KEY')
-- 테이블에 100k 행이 있을 때 StreamingDiskANN 인덱스 자동 생성
, indexing => ai.indexing_diskann(min_rows => 100000, storage_layout => 'memory_optimized'),
-- content 열에 재귀적 청킹 적용
, chunking=>ai.chunking_recursive_character_text_splitter('content')
-- 더 나은 검색을 위해 다른 열의 메타데이터를 임베딩에 추가
, formatting=>ai.formatting_python_template('Blog title: $title url: $url blog chunk: $chunk')
);
-- 벡터라이저는 소스 테이블이 변경될 때 임베딩을 업데이트함
-- 다른 사용자 작업은 필요하지 않음
- 또한 긴 텍스트를 임베딩 모델 토큰 제한에 맞는 여러 개의 작은 청크로 분할해야 하므로 기본 청킹 함수를 정의함
소스 데이터 변경 사항 추적
- pgai Vectorizer는 내부적으로 소스 테이블의 수정(삽입, 업데이트, 삭제)을 확인하고 벡터 임베딩을 비동기식으로 생성하고 업데이트함
- 자체 호스팅 및 Timescale Cloud에서 완전 관리형의 두 가지 배포 유형에 대해 pgai Vectorizer를 구축함
- pgai Vectorizer의 클라우드 호스팅 구현에서는 Timescale Cloud 플랫폼의 클라우드 기능을 사용하여 임베딩 생성
- pgai Vectorizer의 오픈 소스 버전에서는 외부 작업자를 실행하여 임베딩 생성
- pgai Vectorizer는 구성 및 카탈로그 정보를 데이터베이스 내부의 주요 내부 부기 데이터와 함께 저장함
임베딩을 실제로 생성하는 곳은?
- 실제 임베딩 프로세스는 데이터베이스 외부의 외부 프로세스에서 발생함
- 이는 데이터베이스 서버의 부하를 줄이고 벡터라이저가 애플리케이션 쿼리를 처리하는 데이터베이스의 기능에 영향을 미치지 않음을 의미함
- 또한 다른 데이터베이스 작업과 독립적으로 임베딩 작업을 쉽게 확장할 수 있음
- 이 프로세스는 먼저 데이터베이스를 읽어 수행해야 할 작업이 있는지 확인
- 있는 경우 데이터베이스에서 데이터를 읽고, 청킹 및 포맷팅을 수행하고, OpenAI와 같은 임베딩 모델 제공업체에 호출하여 임베딩을 생성하고, 결과를 다시 데이터베이스에 씀
프로세스 사용자 정의
- pgai Vectorizer는 유연함: 임베딩을 만드는 데 사용되는 청킹 및 포맷 규칙을 지정할 수 있음
- 특히 벡터화할 소스 테이블의 열과 소스 데이터가 임베딩 토큰 제한 내에 맞고 관련 데이터가 각 임베딩에 포함되도록 하는 청킹 및 포맷팅 규칙을 구성할 수 있음
- pgai Vectorizer의 Early Access 릴리스에서는 OpenAI 임베딩 모델 선택, 텍스트를 더 작은 청크로 분할하는 청킹 전략, 각 청크에 추가 컨텍스트를 주입하는 포맷팅 옵션, 자동 인덱스 생성 및 성능 튜닝을 위한 사용자 정의 인덱싱 구성을 사용자 정의할 수 있음
- 곧 사용자가 자신의 Python 코드를 제출하여 청킹, 임베딩 및 포맷팅을 완전히 사용자 정의할 수 있도록 하여 이를 더욱 유연하게 만들 계획
예를 들어 다음은 HTML 소스 파일을 재귀적으로 분할하고 소스 데이터에서 OpenAI 임베딩을 만들도록 구성된 벡터라이저임. 코드, 문서, 마크다운 등 애플리케이션 데이터에 맞게 청킹과 포맷팅을 구성할 수 있음
-- 고급 벡터라이저 구성
SELECT ai.create_vectorizer(
'public.blogs'::regclass,
destination => 'blogs_embedding_recursive',
embedding => ai.embedding_openai('text-embedding-3-small', 1536),
-- HTML 콘텐츠에 대해 지정된 설정으로 재귀 청킹 적용
chunking => ai.chunking_recursive_character_text_splitter(
'content',
chunk_size => 800,
chunk_overlap => 400,
-- HTML 인식 구분 기호, 우선 순위가 가장 높은 것부터 가장 낮은 순서로 정렬
separator => array[
E'</article>', -- 주요 문서 섹션에서 분할
E'</div>', -- div 경계에서 분할
E'</section>',
E'</p>', -- 단락에서 분할
E'<br>', -- 줄 바꿈에서 분할
E'</li>', -- 목록 항목에서 분할
E'. ', -- 문장 경계로 대체
' ' -- 최후의 수단: 공백에서 분할
]
),
formatting => ai.formatting_python_template('title: $title url: $url $chunk')
);
GN⁺의 의견
- pgai Vectorizer는 임베딩 관리를 크게 단순화할 수 있는 강력하고 혁신적인 도구로 보임. 벡터라이저 추상화는 개발자가 임베딩을 수동으로 관리해야 하는 부담을 덜어주고 임베딩이 소스 데이터와 동기화되도록 보장.
- 특히 임베딩 모델 업그레이드 또는 청킹 전략 변경과 같은 변경 사항을 적용할 때 매우 유용할 것 같음. 기존의 벡터 데이터베이스에서는 이러한 변경으로 인해 여러 시스템에서 사용자 정의 코드를 작성하고 조정해야 하는 복잡한 프로세스가 발생할 수 있지만, pgai Vectorizer를 사용하면 벡터라이저 구성만 업데이트하면 됨.
- 또한 PostgreSQL과 같은 범용 데이터베이스에서 임베딩을 관리하면 여러 전문 시스템을 오케스트레이션해야 하는 문제를 피할 수 있음. 이는 애플리케이션 개발을 크게 단순화할 수 있음.
- 한 가지 고려해야 할 점은 외부 Python 프로세스에서 실제 임베딩이 생성된다는 것. 이는 데이터베이스 성능에 영향을 미치지 않도록 하는 좋은 설계 선택이지만, 임베딩 생성 프로세스를 별도로 모니터링하고 관리해야 함을 의미함.
- 궁극적으로 pgai Vectorizer는 AI 애플리케이션을 위한 임베딩 관리 방식에 상당한 발전을 나타냄. 더 많은 팀이 이를 도입하고 피드백을 제공함에 따라 이 강력한 도구가 더욱 발전할 것으로 기대됨. Postgres와 같은 친숙한 도구에 임베딩 관리를 통합하면 더 많은 개발자가 첨단 AI 기능을 활용할 수 있게 될 것임.
Hacker News 의견
-
데이터 동기화의 오버헤드를 과대평가하고 있으며, 대부분의 임베딩 기반 워크플로우는 업데이트나 삭제가 많지 않음. 작은 데이터 집합에서도 일관성 문제를 인식하기 어려움. 하지만 데이터 동기화 걱정이 필요 없다는 점은 여전히 멋짐
- Postgres 데이터베이스에 임베딩을 저장할 때 가장 큰 단점은 워크로드가 매우 다르다는 것임. HNSW 인덱스는 많은 리소스를 소모하며, 리소스 경쟁 문제를 일으킬 수 있음. 데이터베이스를 이동시키면 일관성 문제가 다시 발생함
- 필터링과의 상호작용에 대한 질문이 있음. 부분 인덱스를 활용할 수 있는지, pgvector의 HNSW 구현의 제한 사항이 여전히 존재하는지 궁금함
-
Elastic 직원으로서, Elasticsearch가 최근에 semantic_text라는 데이터 타입을 추가했음을 언급함. 이는 텍스트를 자동으로 청크로 나누고 임베딩을 계산하여 저장함. 쿼리도 간소화되어 I/O가 줄어들고 클라이언트 코드가 간단해짐
-
PostgreSQL 도구를 소개하며, 벡터 임베딩을 데이터베이스 인덱스로 재구상함. 현재 OpenAI만 지원하지만, 곧 로컬 및 OSS 모델 지원을 계획 중임. 피드백과 반응을 기대함
-
FAISS를 단일 데이터베이스로 사용하는 것에 대한 의문을 제기함. 이는 벡터 임베딩을 위한 sqlite와 같으며, 메타데이터와 벡터를 함께 저장하여 관계를 유지할 수 있음
-
Postgres에 벡터를 사용하는 것에 대해 긍정적이며, SQL 쿼리에서 벡터 검색과 논리를 포함할 때 필터링 순서에 대한 의문을 제기함. pg_vector의 DX를 좋아하지만, 벡터 검색 후 필터링이 속도를 저하시킬 수 있음
-
원시 임베딩을 벡터 데이터베이스에 저장하는 것은 텍스트의 원시 n-그램을 데이터베이스에 저장하는 것과 같다고 언급함. 문서를 저장하는 것이 더 합리적임
-
sqlite-vec과 FTS5를 SQLite에서 사용 중이며, 매우 유용하다고 언급함
-
PostgreSQL ORM을 Node.js에서 구축하여 벡터 필드를 포함한 코드를 작성할 수 있게 함. 이는 데이터나 임베딩 콘텐츠를 쿼리할 수 있으며, 모델의 필드를 임베딩으로 저장하는 방법을 정의할 수 있음
-
Materialized Views가 좋다고 언급함
-
캐릭터 기반 청크를 사용하는 AI 앱은 PoC 단계를 넘지 않았다고 언급함