Pincone이란?
- AI 어플리케이션을 위한 벡터 데이터를 저장하는 벡터 데이터베이스
- 왜 벡터를 저장해야하는가?
- 다양한 콘텐츠에 대한 내용을 벡터화하여 원본에 대한 정보와 함께 저장
- 나중에 유사한 콘텐츠를 찾기 위해 임베딩으로 DB를 검색할 수 있음
FAISS(Facebook AI Similarity Search) 와의 차이점은?
- FAISS도 벡터 임베딩 검색을 지원하지만 DB의 기능을 가지고 있지 않음
벡터 검색에서 문제점: 필터링
- 검색이나 추천시스템에서는 거의 항상 필터를 적용해야함
- Google은 카테고리(예: 뉴스 또는 쇼핑), 날짜 또는 언어 및 지역별로 검색을 필터링
- Netflix, Amazon 및 Spotify는 유사한 지역의 사용자를 비교하기 위해 필터링을 사용
- 그 외에도 애플리케이션 내에서 특정 부서 내에서만 검색을 하고싶다거나, 특정 날짜 범위로 검색을 제한하고 싶을 수 있음
- 그러나 벡터 검색에 있어
필터링
은 단순해보이지만 해결하기 어려운 문제점임 - 벡터 검색에 필터를 추가하는 두 가지 일반적인 방법
- 사전 필터링
- 사후 필터링
- 이러한 접근 방식에는 일반적으로 벡터 인덱스 와 메타데이터 인덱스 라는두 개의 인덱스가 필요함
🔎 사전 필터링
- 메타데이터 인덱스를 가져와서 조건부 필터링
- 필터링 이후에 남은 데이터에서 벡터 검색
문제점
- 문제는 사전필터링이 ANN의 작동방식을 방해한다는 것
- 벡터 검색은 ANN 알고리즘으로 이루어지는데 이를 위해서는 전체 데이터의 인덱스가 필요하기 때문
- ANN: Approximate Nearest Neighbor 기법
- 정확도를 조금 포기하고 아주 빠른 속도로 주어진 vector의 근접이웃을 찾는 기법
- 정확한 근접 이웃이 아닌 근사적으로 구한 근접이웃이어서 Approximate NN이다.
대안
따라서 위의 문제를 해결하기 위해서는 두 가지 옵션이 있다.
- 모든 필터에 대해 벡터 인덱스를 만들거나
- 필터링 이후의 나머지 벡터에서 kNN 검색을 수행하거나
옵션 (1)은 실용적이지 않다. 필터링은 무수한 조합이 있을 수 있기 때문이다. 옵션 (2)는 남은 모든 벡터 임베딩에 대해 쿼리 임베딩과 비교해야하기 때문에 검색 속도가 크게 느려진다.
그렇다면 사후 필터링은 어떨까?
🔎 사후 필터링
- 벡터 검색을 먼저 수행
- 검색된 데이터에서 조건부 필터링
문제점
- 만약
k=10
으로 10개의 매칭된 데이터를 가져왔을 경우 - 조건을 충족하는 결과가 몇 개 밖에 없거나 아예 없을 수도 있다.
대안
위의 문제를 해결하기 위해 애초에 k
를 높은 숫자로 해서 매칭 데이터를 많이 가져온 후 필터링을 진행하여 너무 적은 결과를 반환하는 위험을 제거할 수는 있다.
그러나 이제 지나치게 높은 k
검색으로 인해 검색 시간이 느려지고 이는 사전 필터링의 느린 검색시간과 상황이 비슷해질 수 있다.
pinecone의 솔루션: 단일 단계 필터링
- 앞서 사전/사후 필터링과 같은 2단계에 거친 과정이 아닌 단일 단계에서 필터링을 수행하고자 하는 방식
- 벡터 및 메타데이터 인덱스를 단일 인덱스로 병합하여 작동
- 실험 결과 사전 필터의 정확도를 유지하면서 검색 속도가 크게 개선된 것을 확인할 수 있음
- 데이터 셋이 커질수록 검색 속도에서 큰 이득을 볼 수 있음
테스트
- SQuAD 데이터셋: 질문 및 답변의 세트가 있음
- 해당 데이터의
language
와title
을 pincone의metadata
태그로 추가하여 인덱스 생성
{
'id': '573387acd058e614000b5cb5en',
'context': 'One of the main driving forces in the growth of the University was its football team, the ... against the New York Giants in New York City.',
'metadata': {
'lang': 'en',
'title': 'University_of_Notre_Dame'
}
}
- 파인콘에서 메타 데이터로 필터링 시 아래와 같은 연산자를 사용할 수 있음
Ex)
- 영어 결과만 반환받기 위해
lang
이en
과 같은지를 기준으로 필터링 수행할 경우
results = index.query(queries=[xq.tolist()], top_k=3, filter={'lang': {'$eq': 'en'}})
lang
필터를 유지하면서 제목이 켄자스 대학교 또는 노틀담 대학교 가 아닌 것을 반환받고자 하는경우
conditions = {
'lang': {'$eq': 'en'},
'title': {'$nin': ['University_of_Kansas', 'University_of_Notre_Dame']}
}
results = index.query(queries=[xq.tolist()], top_k=3, filter=conditions)
%%timeit
index.query(queries=[xq.tolist()], top_k=3, filter=conditions)
>>>
38.3 ms ± 244 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
파인콘의 단일 단계 필터링이 작동 원리에 대해서는 다음 글에서 작성하고자 한다.
'Database' 카테고리의 다른 글
[Redis] redis 클러스터 모드 설치 및 multi command test (2) | 2022.11.05 |
---|