본문 바로가기

DB

OpenSearch로 벡터 데이터베이스 구축하기: LLM 어플리케이션의 새로운 가능성

728x90
반응형

OpenSearch로 벡터 데이터베이스 구축하기

최근 벡터 데이터베이스LLM(대형 언어 모델) 어플리케이션에서 중요한 역할을 하고 있습니다. 벡터는 다차원 공간에서 특정 점을 나타내는 수치 집합이며, 문장의 의미를 효과적으로 표현할 수 있는 방식으로 자주 사용됩니다. 이와 같은 벡터 데이터베이스를 사용하면 문장 간 유사성을 비교하거나 의미론적 검색을 구현할 수 있어 자연어 처리(NLP) 및 추천 시스템에 많은 이점을 제공합니다.

이번 블로그에서는 OpenSearch를 활용해 벡터 데이터베이스를 구축하고, 이를 LLM 어플리케이션에 적용하는 방법을 알아보겠습니다. 코드 예시와 설정 파일을 제공하니 쉽게 따라 하실 수 있을 겁니다.

OpenSearch를 벡터 데이터베이스로 사용하는 이유

OpenSearch는 벡터 데이터베이스 기능을 제공하며, 특히 k-NN (k-Nearest Neighbors) 알고리즘을 활용한 의미론적 검색 기능이 강력합니다. 이를 사용하면 텍스트 데이터를 벡터로 변환한 후 유사한 데이터를 빠르게 검색할 수 있습니다. OpenSearch를 벡터 데이터베이스로 사용하면 다음과 같은 장점이 있습니다:

  1. 오픈소스 솔루션: OpenSearch는 AWS에서 제공하는 오픈소스 프로젝트로, 누구나 클러스터를 쉽게 설정하고 사용할 수 있습니다.
  2. 확장성: OpenSearch는 대규모 데이터셋 처리에 적합하며, 수평적 확장이 용이합니다.
  3. k-NN 알고리즘 지원: 내장된 k-NN 플러그인을 통해 고성능의 벡터 검색을 수행할 수 있습니다.
반응형

1. OpenSearch 클러스터 설정하기

먼저, 로컬 환경에서 OpenSearch 클러스터를 실행해야 합니다. 다음과 같은 Docker Compose 파일을 사용하면 두 개의 노드와 대시보드를 설정할 수 있습니다.

version: '3'
services:
  opensearch-node1:
    image: opensearchproject/opensearch:2.1.0
    container_name: opensearch-node1
    environment:
      - cluster.name=opensearch-cluster
      - node.name=opensearch-node1
      - discovery.seed_hosts=opensearch-node1,opensearch-node2
      - cluster.initial_master_nodes=opensearch-node1,opensearch-node2
      - bootstrap.memory_lock=true
      - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65536
        hard: 65536
    volumes:
      - opensearch-data1:/usr/share/opensearch/data
    ports:
      - 9200:9200
      - 9600:9600
    networks:
      - opensearch-net
  opensearch-node2:
    image: opensearchproject/opensearch:2.1.0
    container_name: opensearch-node2
    environment:
      - cluster.name=opensearch-cluster
      - node.name=opensearch-node2
    volumes:
      - opensearch-data2:/usr/share/opensearch/data
    networks:
      - opensearch-net
  opensearch-dashboards:
    image: opensearchproject/opensearch-dashboards:2.1.0
    container_name: opensearch-dashboards
    ports:
      - 5601:5601
    networks:
      - opensearch-net

volumes:
  opensearch-data1:
  opensearch-data2:

networks:
  opensearch-net:

위 YAML 파일을 docker-compose.yml로 저장한 후, 같은 디렉터리에서 아래 명령어로 클러스터를 실행하세요

$ docker-compose up

2. Python으로 데이터 삽입 및 벡터 검색 구현

벡터 데이터베이스를 구축한 후, Python을 이용해 데이터를 삽입하고 k-NN 검색을 실행할 수 있습니다. 필요한 라이브러리를 설치한 후, 영화 데이터셋을 불러와 처리하는 코드를 작성해 보겠습니다.

필수 라이브러리 설치

pip install opensearch-py==2.4.2
pip install sentence-transformers==2.2.2

데이터 로드 및 벡터화

import pandas as pd
from sentence_transformers import SentenceTransformer
from opensearchpy import OpenSearch

# OpenSearch 클라이언트 생성
client = OpenSearch(
    hosts=["https://localhost:9200"],
    http_auth=("admin", "admin"),
    verify_certs=False
)

# 영화 데이터셋 로드
file_path = 'tmdb_5000_movies.csv'
df_movies = pd.read_csv(file_path, usecols=['id', 'original_title', 'overview'])
df_movies = df_movies.dropna()

# SentenceTransformer 모델로 벡터화
model = SentenceTransformer("all-MiniLM-L6-v2")
df_movies['embedding'] = df_movies['overview'].apply(lambda x: model.encode([x])[0])

# OpenSearch에 인덱스 생성
index_body = {
  "settings": {
    "index": {
      "knn": True,
      "knn.algo_param.ef_search": 100
    }
  },
  "mappings": {
    "properties": {
      "embedding": {
        "type": "knn_vector",
        "dimension": 384,  # 모델 차원
        "method": {
          "name": "hnsw",
          "space_type": "l2",
          "engine": "nmslib"
        }
      }
    }
  }
}
client.indices.create(index="movies", body=index_body)

# 데이터 삽입
for i, row in df_movies.iterrows():
    doc = {
        "id": row["id"],
        "title": row["original_title"],
        "plot": row["overview"],
        "embedding": row["embedding"]
    }
    client.index(index="movies", body=doc, id=str(i), refresh=True)

검색 쿼리 실행

user_query = "A spy goes on a mission"
query_embedding = model.encode([user_query])[0]

query_body = {
    "query": {
        "knn": {
            "embedding": {
                "vector": query_embedding,
                "k": 3
            }
        }
    },
    "_source": False,
    "fields": ["id", "title", "plot"]
}

results = client.search(body=query_body, index="movies")
for result in results["hits"]["hits"]:
    title = result["fields"]["title"][0]
    plot = result["fields"]["plot"][0]
    print(f"Title: {title}, Plot: {plot}")
728x90

이처럼 OpenSearch를 활용해 쉽게 벡터 데이터베이스를 구축하고, 대형 언어 모델을 통한 의미론적 검색을 구현할 수 있습니다. 이 방법은 다양한 자연어 처리(NLP) 애플리케이션, 특히 LLM 기반 서비스에서 매우 유용하게 사용될 수 있습니다. OpenSearch의 유연한 확장성과 k-NN 기능을 활용해 더욱 강력한 검색 시스템을 구축해보세요!

참고 : https://medium.com/marvelous-mlops/creating-vector-database-with-opensearch-7562b7451978

728x90
반응형