scalalang2

벡터 데이터베이스 소개 | 음악 검색 기능은 어떻게 만드는 걸까?

벡터 임베딩(Vector Embedding)은 머신 러닝의 핵심 요소로 이미지, 음성, 단백질 분자 구조 등의 비정형 데이터를 벡터로 표현하는 방법이다. 비정형 데이터를 일단, 벡터로 표현하고 나면 이를 수로 취급할 수 있어서 벡터 간의 유사도를 계산할 수 있다.

딥러닝을 사용해서 비정형 데이터를 벡터로 임베딩 한다.

딥러닝 모델에게 입력으로 데이터를 주면, 출력으로 나온 벡터에는 해당 데이터의 특징들이 수치화 되서 표현된다. 아래 그림은 벡터 임베딩 결과를 후려쳐서 표기하였는데, 아마 딥러닝 괴물들이 보면 이게 무슨 말이냐며 오열할지도 모르겠지만 일단 내가 이해한 수준은 이정도이다. 이미지에서 특징을 추출하는 일은 VGG나 ResNet 오픈소스를 이용하면 쉽게 개발할 수 있다.

고양이와 사자 이미지의 벡터 임베딩 결과

우리는 정형 데이터를 관리할 때 주로 관계형 데이터베이스(RDBMS)에 저장하고 질의문(SQL)을 이용해 원하는 결과를 찾는데 이용한다. 벡터 또한 (1) 저장하고 (2) 벡터를 찾는 질의를 할 수 있는 데이터베이스가 있으면 어떨까? ‘고양이 이미지를 모두 찾아줘’ 라는 질의를 전송하면 고양이와 유사한 벡터를 찾아주거나 혹은 네이버의 음악검색 서비스를 직접 구현할 수도 있다.

출처 : https://m.blog.naver.com/naver_search/221167578156

오늘은 벡터의, 벡터에 의한, 벡터만을 위한 데이터베이스 Milvus 논문에 대해 다룬다[1]. Milvus는 2021년 SIGMOD 에서 발표된 논문으로 현재 오픈소스[2]로 공개되어 있으며 Zilliz 라는 회사에서 클라우드 서비스로 운영하고 있다. 글의 내용은 벡터 데이터베이스에 대한 전반적인 소개가 아닌, Milvus가 1. 어떤 목적을 가지고 개발되었는지 2. 어떻게 개발되었는지 내부 구조를 자세히 뜯어보고 3. 응용 사례가 무엇인지 중심으로 다루고자 한다.

목차

벡터 데이터베이스

벡터 데이터베이스는 고차원(high-dimensional) 벡터를 관리하는 시스템이다. 여기서 관리란 저장, 갱신, 삭제, 검색 등을 포함하여 기능을 제공한다는 의미이고 우리가 사용하는 DBMS의 기능이 벡터에 대해 적용된다고 생각하면 된다. 우리는 데이터의 형태와 목적에 따라 다양한 종류의 데이터베이스를 이용한다.

데이터베이스 종류에 따른 분류

텍스트 검색을 위해 검색 엔진 시스템에 데이터를 적재하는 것처럼 유사한 벡터를 찾기 위해 벡터 데이터베이스를 이용할 수 있다. 아래는 대표적인 응용방법이다.

이를 실제 상용 레벨에서 사용할 수 있으려면 (1) 대규모 벡터 데이터에 대해 빠른 쿼리가 가능해야 하며, (2) 벡터 데이터를 삽입/삭제/변경이 용이해야 한다. 유튜브는 1분에 500시간 분량의 영상이 업로드 되고 이를 실시간으로 다른 유저에게 추천해줄 수 있어야 하기 때문에 대규모 데이터 셋에 대한 응답속도가 합리적이어야 하고 (3) 단순 유사도 검색만으로는 모든 기능을 구현하기엔 부족할 수 있다. 속성 필터링, 멀티 벡터 쿼리 등의 고급 쿼리를 지원하면 유연하게 기능을 구현하는데 도움이 된다. 지금부터 소개할 Milvus는 이 세가지 미덕을 모두 갖추고 있다.

Milvus 탄생 배경

Milvus 이전에 벡터 데이터베이스가 없던 것은 아니었다. 기존에 있던 제품들은 크게 세 가지 분류 나눌 수 있는데 모두 사용하기에 아쉬운 점이 있었다.

Milvus와 기존 시스템의 성능 비교

Milvus는 벡터를 일급 시민으로 취급하는 특수 목적 데이터베이스이며 데이터 과학 및 AI 애플리케이션을 위한 대규모 벡터 검색을 수행할 수 있다. 언급한 많은 아쉬운점을 해결했다

  1. 개발자 친화적 : Python/Java/Go/C++로 구현된 SDK과 RESTful API 지원으로 개발자 친화적으로 접근했다
  2. 고급 쿼리 지원 : 속성 필터링 및 멀티 벡터 쿼리를 지원한다. 속성 필터링은 Vector 유사도 검색과 더불어서 일부 속성에 대한 검색을 지원하는 기능이다. (e.g. 유사한 상품을 찾지만 가격이 $1,000 미만인 제품만 보겠다), 멀티 벡터 쿼리는 다수의 벡터를 입력값으로 주는 방식이다. (1) 색상에 대한 벡터, (2) 사물의 위치에 대한 벡터 를 동시에 주면 이 두가지를 만족하는 데이터를 찾는 식이다
  3. 인덱스 : 벡터 검색을 빠르게 수행하기 위해 여타 DBMS와 마찬가지로 인덱싱이 필요하다. 현재, 벡터를 인덱싱 하는 방법은 다양한데, Milvus는 유명한 인덱스는 기본 지원하고 새로운 인덱스를 추가할 수 있도록 확장 가능하게 설계되었다
  4. 동적 데이터 : LSM 기반의 구조를 채용해 벡터를 동적으로 관리한다. 즉, 삽입 삭제가 가능하도록 했으며 스냅샷 격리(e.g. MVCC)를 지원해 일관성 있는 실시간 검색을 가능하게 했다

Milvus는 페이스북의 Faiss를 메인으로 하여 개발되었지만, Faiss를 상당히 의미있는 수치만큼 성능을 높였으며 DBMS의 면모를 갖추기 위해 기능을 개발하였다. 현재 Milvus는 전 세계에서 이미지 프로세싱, 자연어 처리, 음성 인식, 추천 시스템 등 다양한 영역에서 활용되고 있다

시스템 디자인

Milvus 데이터베이스의 시스템 디자인

Milvus의 시스템은 쿼리 엔진, GPU 엔진, 저장소 이렇게 크게 3가지로 구분되며 세부적으로는 그림 내의 점선으로 표기된 역할을 수행한다.

const data = Array.from({ length: 2000 }, (v,k) => ({
“book_id”: k,
“word_count”: k+10000,\

"book_intro": Array.from({ length: 2 }, () => Math.random()),
}));

출처 : Pinecome : Nearest Neighbor Indexes for Similarity Search

필자 주 — 아파치 파케이
컬럼 기반 저장 포맷으로 대량의 데이터를 압축하여 저장하는게 용이하고, 특정 그룹마다 최솟값, 최댓값과 같은 정보를 저장하고 있어서 데이터의 풀 스캔을 피하면서 point-query를 가능하게 하는 포맷이다. 재밌는 한 예로, Grafana Labs의 Tempo가 대규모 트레이싱 정보를 파케이 포맷으로 저장하고 오브젝트 스토리지(e.g. Amazon S3)를 메인 저장소로 사용하고 있어서 Elasticsearch, Cassandra를 주요 스토리지로 사용하는 Jaeger보다 운영 비용이 매우 저렴하다. 대신 쿼리는 좀 느린편

CPU/GPU를 이용한 고성능 쿼리 구현

위에서는 Milvus의 특징에 대해 소개했다면, 여기서는 CPU/GPU를 이용하여 Milvus가 어떻게 쿼리 성능을 높였는지에 대해 소개한다. CPU/GPU/FPGA 등 서로 다른 종류의 프로세서가 동시에 탑재된 것을 ‘이종 컴퓨팅(Heterogeneous Computing)’이라고 부른다.

이 부분을 이해하려면 먼저, 벡터 데이터를 어떻게 인덱싱을 수행하여 저장하는지 그리고 쿼리는 어떻게 동작하는지에 대해 알고 있어야 한다. Milvus는 페이스북의 Faiss[4] 오픈소스를 사용하여 개발되었기 때문에 해당 오픈소스에 구현된 인덱스를 그대로 이용했다. 지금 부터 가장 사용하기 쉽고 합리적인 성능을 갖추었다고 알려진 IVF인덱스에 대해 간략히 소개하고자 하며 자료 [5], [6]을 참고했다.

① IVF 인덱스

IVF(Inverted File Index)는 유사한 벡터 데이터를 찾기 위한 인덱스 자료구조이다. IVF은 양자화(Quantization) 알고리즘 이라고도 불리는데, 여기서 양자화란 컴퓨터에서 처리하기 어려운 거대한 데이터를 압축 표현하여 성능을 높이는 방법을 말한다. 예를 들어 float32 데이터 타입을 int8 로 압축할 수 있다면, 크기가 4배로 줄어드는 효과가 있다.

Inverted File Index (IVF) Flat 의 대략적인 동작 과정

위 그림은 IVF_FLAT 인덱스의 대략적인 동작 과정을 보여준다. 먼저, 벡터를 일정한 개수(M)로 나누고 K-means clustering을 수행하여 검색의 범위를 축소시킨다. 결과로 나온 인코딩된 벡터는 모든 벡터에 대해서 동일한 크기를 가지게 된다. 이 때 어떤 방식으로 인코딩 할지에 따라서, 다시 말하자면 어떻게 양자화 할지에 따라서 IVF_FLAT, IVF_SQ8, IVF_PQ 등 이 종류가 나뉘게 된다.

이러한 컨셉은 보로노이 다이어그램(Voronoi Diagram)의 컨셉으로 설명할 수 있는데 아래 그림이 보로노이 다이어그램이다. 검은색 점을 K-means clustering으로 군집화된 그룹들의 중앙점(centroid)라고 본다면 임의의 정점 사이에 동일한 거리를 가지도록 선을 그으면 아래 그림이 완성된다.

출처 : 보로노이 다이어그램 | Wikipedia

이제 우리가 입력값으로 주어진 벡터(Query Vector)가 어느 그룹에 속하는지만 효율적으로 찾을 수 있다면 인덱스가 완성된다. 단, 다이어그램에 애매하게 걸친 벡터가 존재할 수 있는데 이를 Edge Problem 이라고 부른다.

IVF 인덱스에서 Edge Problem을 나타내는 그림

위 그림과 같이 A,B,C,D 로 군집화된 벡터들 사이에 쿼리 벡터를 입력으로 주어지면 이 친구는 동시에 A에 속할수도 있고, D에 속할수도 있다. 그림이 2차원 평면으로 그려져있기 때문에 별 일 아니라고 느껴지긴 하지만 실제 세상에서 우리가 군집화 하는 차원은 훨씬 더 고차원이기 때문에 위와 같은 상황이 발생할 가능성이 크다. 그래서 IVF Index에서는 최대 몇개의 그룹을 탐색할건지 결정하는 nprobe 값을 파라미터로 결정해야 한다. nprobe값을 결정하는데에 성능(Performance)과 정확도(Accuracy) 사이의 트레이드 오프가 존재한다. 높은 값을 쓸 수록 정확도는 올라가지만 성능을 희생해야 한다.

② Cache-aware Optimization

이런 IVF 계열의 인덱스를 사용하여 쿼리를 수행할 때 주어진 M개의 쿼리를 어떻게 효율적으로 처리할 것인지가 문제가 된다. 실제 애플리케이션에서는 유저가 한개의 쿼리만 수행하는 것이 아니라 동시에 m개의 배치 쿼리를 던질 수 있기 때문에 아주 빠르게 처리가 되어야 한다. Milvus논문에서는 페이스북 Faiss의 쿼리 성능 문제를 대량의 캐시 미스가 발생하여 성능 비효율이 보인다고 진단했다.

Faiss는 멀티 쓰레드로 각각의 쿼리를 병렬로 처리하는 디자인은 사용한다. 각 스레드는 하나의 쿼리를 담당하여 처리하며, 쿼리에 대한 수행이 끝나면 스레드 자은 반환된다. 이거 마치 톰캣에서 Servlet이 하는 역할과 비슷하지 않은가? 이게 뭐가 문제지 라고 하면서 논문을 읽으면 이런 이야기가 나온다. (1) 각 스레드마다 쿼리를 수행하기 위한 대량의 데이터가 CPU 캐시로 스트림되며 다음 쿼리에서 재사용되기 어렵다. t를 필요한 전체 스레드의 개수, m을 쿼리의 개수라고 볼 때 m/t 시간 만큼 데이터 접근이 필요하다. (2) 쿼리의 개수 m이 매우 작을 때 가용 가능한 모든 스레드를 사용하지 않는다.

(1)의 문제를 자세히 이해하기 위해서 이 글[7]을 참고했다. CPU가 고성능이 되는 것과 별개로 메모리의 성능은 크게 향상을 하지 못했다. 즉, CPU에서 메인 메모리(L4)로 접근하는 비용이 비싸기 때문에 CPU에 가까이 있는 캐시 메모리(SRAM)을 이용하는데 메인 메모리 보다는 용량이 적기 때문에 IVF 인덱스를 수행하는데 필요한 정보를 저장하기 어렵기 때문에 캐시 미스가 자주 발생하는 것으로 해석된다.

Milvus 에서 각 스레드는 일정한 크기 b=n/t 만큼의 데이터 벡터를 할당 받고 각각의 쿼리는 L3 CPU Cach에 알맞도록 s 그룹으로 파티셔닝하여 병렬로 처리한다. 아래 그림은 Milvus 구조의 모습을 보여준다.

Cache-aware design in Milvus

위 구조에서 top-k 유사도 탐색은 각 쿼리 블록 마다 병렬로 이루어지며, 결과를 동기화 하기 위한 오버헤드를 줄이기 위해 결과를 힙(Heap)에 저장한다. 힙은 스레드 마다 할당되며 각 쿼리의 결과가 스레드의 각 힙에 전파되며 나중에 병합하여 top-k 유사도 결과를 도출한다. 이런 구조를 사용하면 m/(s*t) 만큼만 전체 데이터 접근에 필요하므로 1.5x 에서 2.7x까지 성능을 향상할 수 있다.

L3 캐시가 증가함에 따라 성능 향상이 있는지 확인한 실험 결과

③ SIMD-aware Optimization

SIMD는 CPU 내에서 하나의 명령어로 다수의 데이터를 처리하는 것을 말한다. 특히 이게 벡터 연산을 할 때 매우 효율적인데 쉽게 생각하면 두 벡터의 합은 벡터 내의 모든 원소를 더하는 것이다. 원소의 개수가 N개라면 N만큼의 합 명령어가 필요하지만, SIMD를 사용하면 하나의 명령어로 벡터의 합을 병렬로 처리하도록 CPU 자체적으로 지원한다.

Faiss 에서도 SIMD를 이용하여 벡터 유사도 탐색의 속도를 높이고 있었는데, Milvus에서는 AVX512 지원을 추가로 구현하였고 자동 SIMD 명령어 선택 알고리즘을 사용하여 성능으 한쳬라 더 높였다. AVX는 고급 벡터 확장(Advanced Vector eXtensions) 이란 의미로 벡터 연산에 최적화된 명령어 셋이며, 현재 장비에서 지원되는 SIMD명령어가 상이한경우 자동으로 사용할 수 있는 SIMD명령어를 선택하여 처리하는 것이 구현되었다.

④ GPU-oriented Optimization

Faiss는 공유 메모리 크기의 한계로 유사도 탐색의 결과가 1024개로 제한되어 있었는데, 영상 탐색이나 추천 시스템에서는 데이터의 검증이나 랭킹을 다시 매기는 요구 등에 의하여 1024개 이상의 데이터를 처리할 필요가 있었다. Milvus에서는 16384개 이상의 결과를 낼 수 있도록 수정되었다. 메모리 크기가 늘어난 건 아니어서 같은 쿼리를 다수의 라운드에 걸쳐서 누적하여 처리하는 방법으로 알고리즘이 수정되었다.

일반적으로 GPU 메모리는 대량의 데이터를 저장하기에 용량이 충분하지 않아서 Faiss에서는 벡터 데이터를 IVF_SQ8 포맷으로 한 번 더 압축하여 CPU 메모리에서 GPU 메모리로 전송(via PICe bus)하여 사용한다. 논문의 저자들은 이러한 방식이 PICe 버스의 대역폭이 낮아서 오히려 오버헤드가 커서 GPU를 이용한다고 쿼리 성능이 항상 빠르지 않다는 걸 관측했다.

쿼리의 배치 사이즈가 커야 대량의 데이터를 전송하는 오버헤드를 감수할 만 하다는 실험결과를 토대로, 특정 임계값 이상의 쿼리가 들어올 때는 쿼리 전체를 GPU에 넘겨서 처리한다. IVF 계열의 인덱스에서는 1. nprobe 만큼의 데이터 버킷을 찾는 것과 2. (1)의 결과로 주어진 주어진 버킷을 탐색하는 것 이 두가지 연산을 거치는데 1.은 GPU에서 처리하고 2.는 CPU에서 처리하는 것으로 구현되었다.

성능 최적화 평가(Evaluation)

Milvus의 이런 접근법이 실제 성능향상이 있었는지 평가하기 위해 징동(중국의 쿠팡이며 LCS 리그의 그 징동이 맞다)에서 개발한 Vearch와 마이크로소프트 SPTAG와 상업 문제로 익명 처리를 한 상용 서비스 A, B, C를 비교하였다. 평가 방식은 1000만개의 벡터 데이터를 저장하고, 1만개의 랜덤 쿼리를 발생시켜서 recall이 1에 근사할 때 까지 수행하여 쿼리 성능을 관측했다.

recall(재현율)
벡터의 유사도 탐색이라 함은, 말 그대로 유사한 벡터를 찾는 것이다. 실제 데이터의 정답은 ground-truth라고 이 데이터의 집합을 S, 쿼리의 집합 S’라고 할때 S와 S’의 교집합이 몇개냐에 따라 recall을 계산한다.

Milvus와 경쟁 제품간의 성능 비교

위 그림은 IVF 계열 인덱스에 대해서 성능 결과를 비교한 것으로, 확실히 타사 제품에 비해 높은 성능을 보여주었다. 아래는 각 제품들 간의 정확한 수치와 몇 가지 추가 정보를 나열했다.

본 포스팅에서는 단순히 IVF 인덱스 계열에 대한 평가 결과만 소개하였지만, 논문에서는 그래프 계열의 인덱스인 HNSW에 대해서도 평가한 내용이 있으며, 속성 필터링 및 멀티 벡터 쿼리의 성능 또한 비교한 자료가 있다. 아무래도 Milvus가 최신 논문이며 본인들이 원하는 환경에서 실험을 진행했기 때문에 높은 성능을 보일 수 밖에 없긴 하다. 더 자세한 내용을 원한다면 논문 [1]을 참고 하면 된다.

고급 쿼리 프로세싱

위에서는 IVF 인덱스를 이용해서 벡터의 유사도 탐색을 어떻게 수행하였고, 어떤 방식으로 성능을 올렸는지에 대해 설명했다. 고급 쿼리 프로세싱 장에서는 속성 필터링(Attribute Filtering)멀티 벡터 쿼리(Multi-vector query)가 Milvus에서 어떻게 구현되었는지 설명한다.

① 속성 필터링 (Attribute Filtering)

Milvus 데이터베이스의 데이터 단위인 엔티티는 벡터 데이터와 키-밸류로 구성된 속성 정보의 조합으로 이루어져있다. 속성 필터링은 벡터 유사도 탐색을 수행하면서 동시에 일부 속성을 만족하는 데이터를 탐색하는 것을 말한다. 예를 들어 T셔츠와 유사한 옷을 찾되, 가격은 $10 이상 & $100 이하의 조건을 찾고 싶을 수 있다.

속성 필터링 쿼리 구현 전략

위 그림에서 전략이 A~D까지는 기존에 연구된 사례이며, 전략 E가 Milvus에서 새롭게 구현된 내용이다. [A] 속성을 검색하고 벡터는 풀스캔을 치는 방식이며 정확도가 가장 높다. [B] 속성을 만족하는 벡터를 찾은뒤 인덱스를 타서 유사도 검색을 하는 방식이다. [C] 벡터를 먼저 찾고 속성을 필터링 하는 방식이다. 여기서 A, B, C는 쿼리의 개수, 탐색해야하는 데이터 크기 등에 따라 성능이 제각각 다르다. [D] 는 상황에 따라 A, B, C를 적절히 선택하겠다는 전략을 의미한다.

마지막으로 Milvus에서 구현된 [E]는 자주 사용되는 쿼리 속성에 대해 데이터를 파티셔닝 한 뒤, 특정 파티션에 대해서 전략 [D]를 취한다. 예를 들어 가격에 대해서 쿼리가 빈번한 경우 모든 데이터를 P1=[0100], P2=[100200], P3[200~300],… 등으로 파티셔닝 한다. 그리고 쿼리 p의 범위가 p ≥ $50 & p ≤ $150 이라면 파티션 그룹 P1, P2 에 대해서만 수행하여 결과를 반환한다.

② 멀티 벡터 쿼리 (Multi-vector Query)

많은 애플리케이션에서 하나의 데이터는 다수의 벡터로 표현될 수 있다. 레시피를 저장할 때는 이미지 정보와 텍스트 정보를 함께 저장할 수 있고, 영상 정보를 벡터로 저장할 때는 front-face vector, side-face vector 그리고 카메라에 담긴 포즈에 대한 값을 함께 저장할 수 있다.

멀티 벡터 쿼리란 하나의 엔티티가 다수의 벡터 { v0, v1, … , vn } 개를 저장하고 있을 때에도 유사도 검색을 지원하는 것을 말한다. 본 포스팅의 앞부분에서는 하나의 벡터에 대해서만 유사도 검색을 수행하는 과정을 소개했었다. 이를 다수의 벡터로 확장한다는 개념이다. 이를 가장 쉽게 구현하는 방식은 각각의 벡터에 대해서 합산하지 않고, 각 벡터마다 top-k개의 결과를 가지고 추려내는 것이다. 구현은 단순하지만 결과값의 정확도가 떨어진다.

score 계산 방식

그래서 두 벡터의 유사도를 평가하는 함수 f에 대해 모두 집계하는 함수 g를 계산하여 가장 점수가 높은 벡터를 찾는 것으로 문제를 정의할 수 있다. 이제는 점수를 매기는 함수 g 결과값에 퀄리티가 의존한다 .엔티티 X, Y가 있을 때 각각의 점수는 위와 같이 계산된다. 이 때, g는 일반적으로 weighted-sum, average/median과 같은 모노토닉 연산을 사용하여 합산한다.

Milvus에서는 멀티 벡터 쿼리를 처리하기 위해 두 가지 접근법을 상황에 따라 적용한다. (1) Vector fusion 은 단순하게 엔티티 내의 벡터 들을 모두 이어붙여서(concatenation) 하나의 벡터로 저장하고 함수 g를 적용하는 방식이다. 함수 g가 벡터의 내적(inner product)처럼 분해할 수 있는 형태면 이런 방식을 취해도 결과가 동일함이 증명된다. (2) 만약 유클리드 거리처럼 분해할 수 없는(not decomposable) 형태의 함수를 스코어 함수 g로 이용한다면 NRA (no random accesss) 알고리즘을 조금 변형한 형태를 이용해서 top-k 연산을 처리한다.

NRA(no random access) 알고리즘은 N개 이상의 정렬된 집합을 입력으로 받고 스코어 함수 g를 순차적(sequential)으로 처리하는 알고리즘이다. 이름에서 알 수 있듯이 random access을 줄여서 성능을 높이는 기법이라는 걸 알 수 있는데 자세한 동작 과정은 해당 논문 [8]의 섹션 3.2를 참고하면 된다. 아무래도 2001년에 나온 기법이다 보니까 현대 시대에는 맞지 않는게 있을 수 있다. 우선, 랜덤 엑세스는 더 이상 심한 오버헤드를 발생시키지 않는다는 것이 있다. NVMe SSD가 흔한 시대로 넘어와서는 데이터를 CPU에서 정렬시키는 비용보다 그냥 SSD에서 랜덤 엑세스로 접근하는게 빠르다. 이건 필자의 개인적인 의견을 덧붙여 보았고, Milvus에서는 NRA의 입력값이 전체 데이터의 정렬된 셋이라는 문제점 때문에 집합 선정을 점차 늘려나가면서 휴리스틱하게 K개를 찾는 방식을 사용하고 있다.

Iterative merging : Milvus의 멀티 쿼리 구현 방식

알고리즘을 보면 k개를 선정할 수있을 때 까지 NRA의 입력으로 주어지는 집합 R을 키워나가는 것을 볼 수 있다.

응용 사례

논문에서는 저자들이 이미지 검색, 영상 검색, 분자 구조 분석, COVID-19 데이터셋 탐색, 개인화 추천, 생물학적 다중 인증, 질문 답변, 이미지-텍스트 탐색, 보행자 탐색, 음식 레시피 검색 등 이렇게 10가지 분야에 대해 Milvus에 적용했다고 말했고, 실제로 이 곳 깃허브에 들어가보면 코드도 같이 소개되어있다.

Milvus를 이용한 이미지 탐색

여기서는 데모가 아닌, 실전에서 Milvus가 어떻게 쓰이고 있는지 소개해보려고 한다. 먼저, 이미지 탐색은 VGG와 ResNet 딥러닝 모델을 쓰면 이미지를 벡터로 변환할 수 있다는게 잘 알려져 있는 응용 사례였고 Milvus를 이용하면 간단하게 이미지 검색 기능을 구현할 수 있다. 중국에서는 Qichacha와 Beike Zhafang 회사가 Milvus를 이용해 이미지 검색을 지원하고 있다. 각각 중국 회사의 신용정보을 검색할 수 있는 서비스와 직방과 같은 온라인 부동산 중계 서비스이며 모두 중국 내에서 유니콘에 해당하는 스타트업이다.

비고라이브(BIGO)로 알려진 BIGO Technology 에서는 자사의 숏폼 플랫폼 Likee에서 중복 동영상을 제거하기 위해 Milvus를 이용하고 있다[9]. 그리고 중국 제약회사인 Apptech 에서는 신약 개발에 도움을 얻기 위해서, 분자 구조를 탐색용도로 Milvus를 채택하였다. 아무래도 Milvus 가 중국에서 먼저 유즈케이스를 만들면서 성장하다보니까 중국 및 아시아 위주로 유즈 케이스가 소개되었다.

마무리

벡터 데이터베이스의 분야에서 이용되는 Milvus에 대해 소개하였다. 마지막으로 유즈케이스 설명에서 아무래도 중국에 기반한 회사다 보니까 중국 위주의 사례가 많이 보고되었다. 미국에서는 Head of AWS AI Labs 였던 Edo Liberty가 창립한 Pinecone이 주로 채용되고 있는 것으로 보인다. 대표적인 유즈 케이스로는 Shopify나 Zapier등이 있다. Milvus 논문에서는 pinecome에 대한 언급은 없었는데, 두 회사의 창립일이 비슷한 것으로 보아 아마 서로의 존재를 모르고 있던게 아닐까 싶다.

Pinecone이 미국 빅테크 출신이 개발했다는 타이틀은 있지만 공개된 코드가 없다. 이 회사가 Datadog 수준으로 이 분야에서 독보적인 서비스를 제공한다면 경쟁력이 있을 수도 있지만, 요즘 오픈소스는 쿠버네티스에 배포부터 쉽게 하라고 Helm chart까지 작성되어 나오는게 기본 소양인지라 운영 부담은 많이 하락한 상황이다. Milvus가 비슷한 수준의 퍼포먼스만 낸다면 이 또한 좋은 선택지가 아닐까 싶다.

마지막으로, 중국 IT 기술이 나날이 발전하고 있는게 피부로 느껴진다. 논문을 탐색해보면 중국인 유학생 또는 중국 대학에서 작성한게 많이 보이고, 무엇보다 나의 인생 갓겜 원신을 만든 호요버스의 기술력은 한국에서는 흉내내기도 어렵다. 저잣거리에 나도는 소문에 따르면 유니티 개발자들조차 호요버스 개발자를 초청해 유니티에 대해서 배움을 얻을 정도라고 하니 이제는 중국한테서 기술을 배워야 하지 않을까

레퍼런스