Why I Kept Search Scope Inside a Single Supabase RPC
개요
Supabase RPC를 사용하여 검색 범위를 단일 함수 내로 통합함으로써, 벡터 검색 시스템에서 발생하는 "잘못된 범위의 그럴듯한 이웃"이라는 치명적인 오류 모드를 해결하는 방법에 대한 내용입니다.
주요 내용
* 문제점: 범위 드리프트 (Scope Drift)
* 벡터 검색 시스템에서 올바른 임베딩과 유사도 점수를 반환했지만, 실제로는 잘못된 소스(예: 다른 리포지토리)에서 가져온 정보로 인해 틀린 답을 제공하는 현상이 발생했습니다.
* 이 문제는 임베딩 계산이나 데이터 유효성 문제가 아니라, 검색 로직이 여러 장소에서 결정된 여러 부분을 조합하여 PostgreSQL이 올바른 조합을 추측해야 했기 때문에 발생했습니다.
* 검색 범위를 설정하는 필터, 후보 수, 임베딩이 서로 다른 요청 경계를 넘나들면서 "범위 드리프트"가 발생했습니다.
* 해결책: RPC를 단일 진실 공급원(Single Source of Truth)으로 만들기
* 호출자는 쿼리 임베딩, 후보 수, JSONB 필터를 하나의 단위로 전달하고, Supabase RPC 내부의 SQL 함수는 동일한 값들을 하나의 단위로 받도록 변경했습니다.
* 호출자가 검색 범위를 명시적으로 결정하고, 데이터베이스가 해당 범위를 강제하며, 인덱스는 동일한 범위를 지원하도록 일관성을 유지했습니다.
* search_embeddings RPC 함수는 쿼리 임베딩, match_count, 그리고 JSONB 형식의 filter를 인자로 받아, e.metadata @> filter 조건으로 필터링한 후 코사인 유사도로 순위를 매깁니다.
* JSONB 필터의 중요성
* 메타데이터 필터는 구조화되어 있으며, 여러 조건을 하나의 JSONB 객체로 표현하여 단일한 검색 경계를 정의할 수 있습니다.
* { repo: '...', language: '...' }와 같은 JSONB 객체는 검색 범위를 명확하게 표현하며, RPC 함수는 이 필터를 SQL 내부에서 직접 적용하여 일관성을 보장합니다.
* 필터를 RPC 경계에 명시적으로 두면 디버깅 시 추론하기 쉬워지고, 메타데이터 모델이 확장될 때 RPC 시그니처를 변경할 필요가 없습니다.
* 인덱스와 RPC의 연관성
* HNSW 인덱스는 RPC 함수가 약속하는 접근 경로(cosine distance 기반 검색)를 지원하도록 구축되었습니다.
* 메타데이터 필터가 먼저 작동하여 검색 범위를 좁히고, 벡터 인덱스가 나머지 후보들의 순위를 매기는 방식으로 각 구성 요소의 역할이 명확하게 분리되었습니다.
시사점
검색 요청의 범위를 명시적이고 단일한 객체로 캡슐화하고, 이를 Supabase RPC와 SQL 함수 내에서 일관되게 처리함으로써 벡터 검색 시스템의 정확성과 신뢰성을 크게 향상시킬 수 있습니다. 이는 추후 데이터 수집 과정에도 동일한 원칙을 적용하여 검색 시스템의 무결성을 유지하는 데 중요한 기반이 됩니다.
댓글
GitHub Discussions