PostgreSQL Vector 사용 – pgvector extension

최근 데이터 기술은 빠르게 발전하고 있으며, 벡터 기반 데이터 표현이 현대 애플리케이션의 핵심 요소로 자리 잡고 있습니다. 텍스트, 이미지, 오디오와 같은 비정형 데이터를 벡터로 표현하면 추천 시스템, 의미적 검색, 이상 탐지와 같은 다양한 작업에서 뛰어난 성능을 발휘할 수 있습니다. 이번 글에서는 PostgreSQL과 pgvector 확장을 활용해 벡터 연산을 구현하는 방법을 살펴 보려고 합니다.
PostgreSQL: 신뢰받는 강력한 관계형 데이터베이스
PostgreSQL은 고성능 오픈소스 관계형 데이터베이스로, 데이터 관리를 위한 강력한 도구로 널리 사용되고 있습니다. 신뢰성, 확장성, 그리고 SQL 표준 준수를 특징으로 하며, 다양한 데이터 타입과 고급 쿼리 기능을 지원합니다. 이러한 유연성 덕분에 PostgreSQL은 벡터 검색과 같은 최신 데이터 처리 기능을 통합하기에 이상적인 선택입니다.
pgvector: PostgreSQL에 벡터 기능 추가
pgvector는 PostgreSQL에 벡터 저장, 관리, 그리고 쿼리 기능을 추가하는 오픈소스 확장입니다. 이를 통해 PostgreSQL의 강력한 인덱싱과 쿼리 메커니즘을 활용해 고차원 벡터를 처리할 수 있습니다. pgvector를 사용하면 다음과 같은 작업이 가능합니다.
  1. 벡터 저장: 벡터를 네이티브 데이터 타입으로 저장.
  2. 벡터 유사도 계산: L2(유클리드 거리) 및 코사인 유사도와 같은 지표를 활용.
  3. 인덱싱 활용: **HNSW(Hierarchical Navigable Small World)**와 같은 인덱스를 사용해 빠른 유사도 검색 구현.

전체 내용:

  1. pgvector 확장 활성화:
    • pgvector extension으로 vector 기능 활성화
  2. NVIDIA 드라이버 설치:
    • Linux Mint에서 NVIDIA 그래픽 드라이버를 설치하고 CUDA와 같은 GPU 가속 워크플로를 위한 준비.
  3. Chrome 설치:
    • 웹브라우저로 Chrome을 apt repository를 이용하여 설치(향후 업그레이드가 용이하게 하기 위해).
  4. Docker 및 Docker Compose 설치:
    • 컨테이너화된 애플리케이션 개발 및 관리를 위한 Docker 설치 방법.
    • Docker Compose를 활용하여 다중 컨테이너 애플리케이션을 설정하는 방법.
  5. Nvidia Docker 설치:
    • GPU를 이용한 머신러닝 학습 시스템 구현을 쉽게 하기 위해 Nvidia Docker 설치.
  6. Visual Studio Code 설치:
    • 인기 있는 코드 편집기 VS Code를 설치하고 플러그인을 설정하는 방법.
    • 프로그래밍 및 프로젝트 관리 환경 구성.
  7. Miniconda 설치:
    • Localhost에서 Python 개발 및 실행환경 구성을 위해 설치.
  8. VirtualBox 설치:
    • Linux Mint 22에 VirtualBox를 설치하는 과정.
    • 가상 머신을 활용하여 다양한 환경에서 작업하는 방법.

* pgvector 확장 활성화

PostgreSQL은 다양한 확장을 통해 기본 기능을 확장할 수 있으며, pgvector는 벡터 데이터를 효율적으로 저장하고 검색할 수 있도록 지원하는 강력한 도구입니다.
pgvector확장 이 설치되어 있는 PostgreSQL을 설치 하는 방법은 이미 작성해 두었으니 필요하면 읽어 보세요. PostgreSQL 설치
pgvector 확장 활성화 방법 : sql 실행
				
					# Create
CREATE EXTENSION vectors;

# Drop
DROP EXTENSION IF EXISTS vectors;
				
			

* vector 타입 테이블 생성

pgvector를 활성화한 후 벡터 데이터를 저장할 테이블을 생성할 수 있습니다. 예를 들어, 3차원 벡터를 저장하는 테이블을 생성하려면 다음 SQL 명령을 실행합니다.
				
					CREATE TABLE items (
    id serial PRIMARY KEY, -- Unique identifier
    embedding vector(3)    -- 3-dimensional vector
);
				
			

* vector 데이터 삽입

테이블 생성 후, 벡터 데이터를 삽입할 수 있습니다. 벡터 데이터는 [숫자1, 숫자2, 숫자3] 형태로 표현된 문자열로 입력 할수 있습니다.
				
					INSERT INTO items (embedding) VALUES
('[1, 2, 3]'),
('[4, 5, 6]'),
('[7, 8, 9]'),
('[1, 0, 0]'),
('[0, 1, 0]'),
('[0, 0, 1]');
				
			
혹은 [숫자1, 숫자2, 숫자3] 형태로 표현된 array로 입력 할수 있습니다.
				
					INSERT INTO items(embedding) VALUES
(ARRAY[1, 2, 3]::real[]),
(ARRAY[4, 5, 6]::real[]),
(ARRAY[7, 8, 9]::real[]),
(ARRAY[1, 0, 0]::real[]),
(ARRAY[0, 1, 0]::real[]),
(ARRAY[0, 0, 1]::real[]);
				
			

* 기본 쿼리 - slicing

기본적인 쿼리는 기존 postgresql과 동일한 sql문을 사용하면 됩니다.
				
					-- Basic Query
SELECT embedding
  FROM items
				
			
column에 저장된 vector를 slicing해서 특정 차원의 값만을 가지고 오는 것은 지원을 하지 않습니다. 하지만 실제 서비스를 만들어 보면 특정 차원의 값만을 가져와야 하는 경우가 많이 있습니다. 먼저 아래에 query는 오류가 발생합니다.
				
					-- Get first dimension
SELECT embedding[1]
  FROM items

-- Result
SQL Error [42804]: ERROR: cannot subscript type vector because it does not support subscripting
				
			
slicing을 지원하기 위해 Query 기반의 함수를 만들어 사용하는 방법이 있습니다. 대용량 데이터의 경우 속도를 생각해야 한다면 차원별로 따로 컬럼을 만들어 저장 하는 것을 권장 하지만, index가 걸려 있는 컬럼으로 조건이 걸리는 간단한 서비스의 경우는 아래와 같은 함수를 만들어 사용하면 됩니다.
				
					-- slice function : return float
CREATE OR REPLACE FUNCTION slice(vec vector, index integer)
RETURNS float AS $$
    SELECT (string_to_array(trim(both '[]' from vec::text), ','))[index]::float
$$ LANGUAGE SQL IMMUTABLE;

-- slice function : return int
CREATE OR REPLACE FUNCTION slice_int(vec vector, index integer)
RETURNS int AS $$
    SELECT (string_to_array(trim(both '[]' from vec::text), ','))[index]::int
$$ LANGUAGE SQL IMMUTABLE;
				
			
직접 만든 slice함수로 쿼리하는 예제
				
					-- Querying the First Dimension
SELECT slice(embedding, 1)
  FROM items

-- Query the first dimension and retrieve it as an integer
SELECT slice_int(embedding, 1)
  FROM items

				
			

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다