로컬 PostgreSQL(Homebrew)에 pgvector 설치하기
pgvector란?
pgvector는 벡터 유사도 검색을 위한 PostgreSQL 확장입니다. OpenAI의 텍스트 임베딩 모델 등에서 생성한 임베딩을 Postgres에 직접 저장하고, 코사인 유사도, L2 거리, 내적 등으로 쿼리할 수 있습니다.
사전 준비
- Homebrew로 PostgreSQL 설치 (
brew install postgresql@17) - PostgreSQL 서비스 실행 중 (
brew services start postgresql@17)
pgvector 설치
brew install pgvector
확장 활성화
데이터베이스에 접속하여 확장을 생성합니다:
psql -d your_database_name -c "CREATE EXTENSION IF NOT EXISTS vector;"
설치 확인:
psql -d your_database_name -c "SELECT extname, extversion FROM pg_extension WHERE extname = 'vector';"
예상 출력:
extname | extversion
---------+------------
vector | 0.8.0
벡터 컬럼이 있는 테이블 생성
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
content TEXT,
embedding vector(1536)
);
1536 차원은 OpenAI의 text-embedding-3-small 모델에 해당합니다. 사용하는 임베딩 모델에 맞게 조정하세요:
| 모델 | 차원 |
|---|---|
| text-embedding-3-small | 1536 |
| text-embedding-3-large | 3072 |
| text-embedding-ada-002 | 1536 |
벡터 삽입 및 쿼리
임베딩 삽입:
INSERT INTO documents (content, embedding)
VALUES ('Hello world', '[0.1, 0.2, 0.3, ...]'::vector);
랜덤 1536차원 벡터로 테스트 행 삽입:
INSERT INTO documents (content, embedding)
VALUES ('test document', ('[' || array_to_string(ARRAY(SELECT random() FROM generate_series(1, 1536)), ',') || ']')::vector);
코사인 거리로 가장 유사한 문서 5개 찾기:
SELECT id, content, embedding <=> '[0.1, 0.2, 0.3, ...]'::vector AS distance
FROM documents
ORDER BY distance
LIMIT 5;
기존 문서와 유사한 문서 찾기:
SELECT id, content, embedding <=> (SELECT embedding FROM documents WHERE id = 1) AS distance
FROM documents
ORDER BY embedding <=> (SELECT embedding FROM documents WHERE id = 1)
LIMIT 5;
거리 연산자
| 연산자 | 거리 메트릭 |
|---|---|
<-> | L2 (유클리드) |
<=> | 코사인 |
<#> | 내적 (음수) |
성능을 위한 인덱스 추가
대규모 테이블에는 인덱스를 추가하세요. IVFFlat이 대부분의 경우에 적합합니다:
CREATE INDEX ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
더 높은 재현율이 필요하면 HNSW를 사용하세요 (빌드는 느리지만 쿼리가 빠름):
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops);
Python(psycopg2)에서 사용하기
pip install pgvector
import psycopg2
from pgvector.psycopg2 import register_vector
conn = psycopg2.connect(host="localhost", dbname="your_database_name", user="postgres")
register_vector(conn)
cur = conn.cursor()
# 삽입
embedding = [0.1, 0.2, ...] # 임베딩 모델에서 생성한 벡터
cur.execute("INSERT INTO documents (content, embedding) VALUES (%s, %s)", ("hello", embedding))
conn.commit()
# 유사한 문서 쿼리
cur.execute("SELECT id, content FROM documents ORDER BY embedding <=> %s LIMIT 5", (embedding,))
results = cur.fetchall()
Cloud SQL (GCP)
Cloud SQL PostgreSQL 15+에서는 pgvector가 기본 제공됩니다. 별도의 데이터베이스 플래그 설정 없이 바로 사용할 수 있습니다:
CREATE EXTENSION vector;
사용 가능 여부 확인:
SELECT * FROM pg_available_extensions WHERE name = 'vector';
Alembic에서 사용하기
Alembic 마이그레이션에서는 SQLAlchemy가 vector 타입을 네이티브로 지원하지 않으므로 raw SQL을 사용합니다:
def upgrade() -> None:
op.execute("CREATE EXTENSION IF NOT EXISTS vector")
op.execute("""
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
content TEXT,
embedding vector(1536)
)
""")
def downgrade() -> None:
op.drop_table("documents")
op.execute("DROP EXTENSION IF EXISTS vector")
트러블슈팅
확장을 찾을 수 없는 경우
CREATE EXTENSION vector가 실패하면, pgvector가 올바른 PostgreSQL 버전에 설치되었는지 확인하세요:
brew install pgvector
brew services restart postgresql@17
사용 가능한 확장 확인
SELECT * FROM pg_available_extensions WHERE name = 'vector';
표시되지 않으면 pgvector 공유 라이브러리가 PostgreSQL의 확장 디렉토리에 없는 것입니다. brew reinstall pgvector로 재설치하세요.