-
Redis를 활용한 벡터 데이터베이스 구현하기AI 2023. 6. 22. 00:55
2022년 5월 Redis를 벡터 데이터베이스처럼 사용할 수 있는 Vector Similar Search 기능이 새롭게 모습을 나타냈습니다. 아직은 한국에서 도입 사례가 많이 보이지는 않지만 여러 기업에서 Redis를 많이 사용하고 있는 만큼 조만간 기술 블로그 등에서 도입 사례가 점차 올라오지 않을까 조심스레 예상해 봅니다.
인 메모리 NoSQL 방식의 데이터베이스인 Redis에서 벡터 데이터베이스 기능을 지원한다는 것은 기존 백터 데이터베이스가 갖고 있는 특징들과 비교했을 때 조금 차이가 있는 것 같아서 상당히 고무적입니다. 과연 Redis는 어떻게 벡터 데이터베이스 기능을 지원하는 것일까요?
🤔 벡터 데이터베이스란?
AI 필드에서 일하는 경우 다들 벡터(vector)라는 용어를 한 번쯤은 들어보셨을 겁니다. 만약 팀에서 챗봇(NLU) 또는 추천 시스템을 만든다고 한다면 비정형 데이터(텍스트 또는 이미지, 동영상 등)들을 임베딩하여 벡터로 변환하는 작업을 거치는 것이 일반적입니다. 다만, 임베딩은 딥러닝 또는 머신러닝 모델을 통해 일어나게 되는데 운영 및 테스트 환경에 따라 임베딩 속도가 천치만별입니다.
따라서 불필요한 임베딩 과정을 최소화하기 위해 벡터를 어딘가에 저장할 수 있으면 좋은데 일반적인 스칼라 기반 데이터베이스에 벡터를 저장하기에는 벡터의 용량이 너무 크다는 문제점이 있습니다. 반대로 저장해 놓은 벡터를 조회할 때 역시 검색 성능 저하 문제가 일어날 수 있습니다.
그래서 이러한 단점들을 해소시켜 주기 위해 등장한 것이 벡터 데이터베이스입니다. 벡터 데이터베이스란 벡터를 효율적으로 저장 및 검색하기 위한 데이터베이스 입니다. 벡터 데이터베이스를 이용하면 의미론적 정보 검색, 장기 기억 등과 같은 고급 기능을 AI에 탑재하는 등 손쉽게 사용할 수 있게 됩니다.
🔎 벡터 데이터베이스의 특징 및 현황
벡터 데이터베이스의 특징에 대해 좀 더 자세히 살펴보도록 하겠습니다. 시중에 나와있는 벡터 데이터베이스들의 다양한 특징들을 일반화시킬 수는 없겠지만 그래도 일반화를 시켜보자면 저는 다음과 같이 크게 3가지 특징으로 정의할 수 있을 것 같습니다.
- 컬럼 지향 저장(Columnar Storage)
- 임베딩(Embedding)
- 인덱싱(Indexing)
먼저 컬럼 지향 저장(Columnar Storage)이란 전통적인 행(row) 지향 방식과 달리, 열(column) 단위로 데이터를 저장하는 방식입니다. 동일한 열(column)에 속한 값들이 연속적으로 저장되기 때문에 데이터를 압축하여 저장하기 용이합니다. 데이터를 압축하게 되면 그만큼 데이터베이스 공간을 효율적으로 사용할 수 있게 됩니다.
행과 열에 무슨 차이가 있다고 어떤 건 압축이 잘되고 어떤건 압축이 잘 안 되는 건지 의문이 생길 수도 있는데 보통 일반적인 데이터베이스(RDB)를 보면 열(column)에는 속성값이 있습니다. 즉, 데이터의 타입(ex NUMBER, VARCHAR)이 존재합니다. 따라서 압축도 같은 데이터 타입끼리 하게 된다면 훨씬 수월하게 작용합니다.
두 번째 특징으로는 임베딩(Embedding)이 있습니다. 벡터화(Vectorization)라고도 불리는 것 같은데 저는 좀 더 명확히는 둘 사이 용어를 구분해서 임베딩이라고 부르겠습니다. 앞서 잠깐 설명했는데 임베딩이란 비정형 데이터를 벡터로 변형시켜주는 작업입니다. 거의 대부분의 벡터 데이터베이스에서 자체적으로 임베딩 기능을 탑재하여 벡터 변환 기능까지 제공하는 것이 하나의 트렌드로 자리 잡은 것 같습니다.
세 번째 특징으로는 인덱싱(Indexing)이 있습니다. 벡터를 효율적으로 잘 검색하기 위해 데이터베이스를 지속적으로 정렬하고 관리하는 기능입니다. 인덱싱은 워낙 알고리즘도 많고 다양한데 저는 여기서 인덱싱 기능을 제공하고 있다 정도로만 짚고 넘어가도록 하겠습니다.
추가로 지난 1년간 벡터 데이터베이스 제품별 검색 추이를 살펴보았는데요. 아직까지는 크게 검색량이 많지 않아서 제대로 된 비교는 불가능했습니다. 특히 한국에서는 검색량이 거의 없었습니다. 전 세계 기준으로 보았을 때는 그나마 Pinecone과 Milvus가 조금 더 앞장서서 이끌어나가는 분위기로 나타나고 있습니다.
🚀 Redis Vector database는 어떻게 다를까?
Redis의 Vector database는 앞서 소개한 벡터 데이터베이스 특징들과는 사뭇 다른 특징들을 갖고 있습니다. Redis 공식 홈페이지에 소개된 Vector database는 사실상 따로 분리되어 존재하는 것이 아니라 redis 그 자체에 벡터를 저장하여 관리하는 것입니다. 그렇다면 Redis는 어떻게 벡터를 저장하고 조회하는 것일까요? 그 원리는 다음과 같습니다.
왼쪽의 그림과 같이 Redis에서 벡터를 핸들링하기 위해서는 Vector Similarity Search라는 모듈이 필요합니다. Vector Simiilarity Search(VSS)는 2022년 5월에 출시된 검색엔진 모듈로 벡터와 벡터 간 유사도를 검색하여 검색 결과를 반환할 수 있습니다.
RediSearch 2.4 이상 버전에서 사용할 수 있고 Python, Java 등 다양한 프로그래밍 언어를 지원합니다. 만약 Java를 사용한다면 Jedis나 lettuce 등을 통해 사용할 수 있고 Jedis는 현재 공식라이브러리로 채택되어 있습니다.
RediSearch의 VSS 기능 덕분에 이제는 Redis에서 벡터를 효율적으로 저장 및 검색할 수 있게 되었습니다. 다만, 단점으로는 컬럼 지향 방식이 아닌 NoSQL 인메모리 저장 방식이라서 그만큼 메모리 이슈가 있을 수 있고 벡터 임베딩 또한 지원하지 않기 때문에 sentbert나 openAI의 embeddings 등의 AI 모델을 통해 직접 임베딩을 해야 합니다.
🪄 Redis 벡터 데이터베이스를 이용한 파이프라인 구축하기
위에서 얻은 지식들을 바탕으로 실제로 Redis로 어떻게 벡터를 저장하고 꺼내오는지에 대해 데이터 파이프라인을 설계해 보겠습니다. 저는 인사 담당 챗봇을 만든다고 가정하고 데이터를 한번 저장해보겠습니다.
제가 하고 싶은 작업은 Redis를 통해 “급여 지급일은 언제인가요?”와 “월급날 언제야?” 이 두 가지 질문을 챗봇에게 질문했을 때 이 두 질문이 유사하다는 결론을 얻어 같은 답변을 내보내고자 합니다. 따라서 아래와 같이 데이터를 한번 저장해 보도록 하겠습니다.
먼저 사용자의 예상 질문들을 챗봇 DB(redis)에 저장하기 위해 질문 셋을 만들고 각각 임베딩을 시킵니다. 앞서 말했듯이 Redis에서 임베딩 기능을 지원하지 않기 때문에 임베딩 모듈은 Python이나 Java환경에 맞게 각각 라이브러리를 다운로드하셔야 합니다.
만약 Java로 maven환경에서 라이브러리를 내려받는다고 한다면 redisearch 2.4 버전 이상과 transformers 같은 임베딩 라이브러리 두 개를 설치하여야 합니다. Java는 Python에 비해 딥러닝 관련 모듈이 많지 않기 때문에 약간 단점으로 존재하기는 합니다. 그래서 임베딩하는 모듈만 파이썬으로 구현하고 결괏값만 서빙해 오는 방식으로 구현하는 방법도 있습니다.
임베딩을 통해 벡터값을 얻어냈다면 이제 redis에 저장해야 하는데 Vector Similar Search 기능을 사용하면 두 가지 인덱싱 방식 중 하나를 선택할 수 있습니다. 바로 FLAT과 HNSW입니다. FLAT은 Brute-force 알고리즘 방식으로 가능한 모든 벡터를 검색하도록 인덱싱을 합니다.
반면에 HNSW는 Hierarchical Navigable Small World의 약자로 빠른 성능을 위해 대략적인 검색 알고리즘을 지원합니다. 빠르게 대략적으로 검색하기 때문에 그만큼 정확도가 낮아진다는 단점이 존재하긴 합니다. 인덱싱 알고리즘 외에도 추가로 벡터 거리 측정 방법 역시 cosine, internal product, euclidean distance 3가지 중에 옵션을 선택할 수 있는데 여기선 자세한 설명은 생략하도록 하겠습니다.
벡터 데이터베이스에 저장을 완료하면 이번에는 쿼리를 통해 유사값 뽑아낼 수 있는지 확인해봐야 합니다. 초기에 계획했던 “월급날 언제야?” 질문을 챗봇에게 쿼리로 전달해 보겠습니다. 그럼 챗봇은 유사값을 뽑아오기 위해 또다시 벡터 임베딩을 진행합니다. 단 이때 주의할 점은 indexing 할 때 사용한 모델과 동일한 모델을 사용하여 임베딩을 진행해야 합니다.
임베딩을 마치면 rediSearch의 Vector Similar Search 기능을 통해 redis에 저장된 벡터들과 쿼리 벡터 간 유사도 검색을 진행하여 가장 근삿값을 갖고 있는 벡터를 찾아낼 수 있습니다. 즉, "월급날 언제야?"와 가장 유사한 “급여 지급일은 언제인가요?”라는 질문을 찾아낼 수 있습니다.
🌠 회고하기
직접 구현해 본 것은 아니라서 어떻게 작동할지는 사실 잘 모르겠습니다. 원본 문서를 토대로 해석해서 작성해 보았는데 혹시 글에 부족한 점이 있다면 아낌없이 피드백 주시면 감사드리겠습니다.🤗 추후에 국내에서 벡터 데이터베이스에 대한 사용사례가 많아진다면 간단한 딥러닝 챗봇 만들어보기 등을 진행해 보면서 더 좋은 글로 찾아뵙겠습니다.
📖 참고자료
https://redis.com/solutions/use-cases/vector-database/
https://redis.io/docs/stack/search/reference/vectors/
https://redis.com/blog/rediscover-redis-for-vector-similarity-search/
'AI' 카테고리의 다른 글
Cursor IDE 동작원리 및 설치, 사용방법 (16) 2024.06.11