https://www.elastic.co/kr/blog/text-similarity-search-with-vectors-in-elasticsearch
기존 정보 검색에서는 텍스트를 숫자 벡터로 나타낼 때 어휘의 각 단어에 하나의 차원을 지정하는 것이 일반적입니다.
그리고 텍스트 한 부분의 벡터는 어휘의 각 용어가 나타나는 횟수를 기반으로 합니다. 이러한 텍스트 표현 방식은 흔히 “BOW(Bag of Words)”라고 불리는데, 이는 문장 구조와 관계없이 단어 빈도수만 계산하기 때문입니다.
텍스트 임베딩은 다음과 같은 몇 가지 중요한 측면에서 기존 벡터 표현과 다릅니다.
인코딩된 벡터는 밀도가 높고 차원은 상대적으로 낮습니다(주로 100개에서 1,000개 차원)
반면, BOW 벡터는 밀도가 낮고 차원이 상대적으로 높습니다 (50,000개 이상의 차원으로 구성될 수 있습니다)
문장 임베딩에서는 벡터 표현을 결정할 때 단어 순서를 고려할 수 있습니다. 예를 들어 “tuin in”이라는 구문은 “in tune”과는 매우 다른 벡터로 매핑될 수 있습니다.
실제로 문장 임베딩이 텍스트의 긴 구절을 일반화하는 경우는 드뭅니다. 일반적으로 짧은 단락 수준을 넘는 길이의 텍스트를 나타내는 데는 사용되지 않습니다.
방대한 양의 질문과 답변 모음이 있다고 가정해 보겠습니다. 사용자가 질문하면, 우리는 사용자가 답을 찾을 수 있도록 이 모음에서 가장 유사한 질문을 검색하고자 합니다.
텍스트 임베딩을 사용하여 유사한 질문을 검색할 수 있습니다.
indexing 하는 동안, 각 질문들은→ [M: 문장 임베딩 모델] → vector 생성
사용자가 query 입력 → [M: 문장 임베딩 모델] → vector 생성
사용자의 query에 맞는 응답의 순위를 매기기 위해, 쿼리와 응답사이의 코사인 유사도를 사용
"zipping up files"는 "Compressing / Decompressing Folders & Files"를 반환
"determine if something is an IP"는 "How do you tell whether a string is an IP or a hostname"을 반환
"translate bytes to doubles"는 "Convert Bytes to Floating Point Numbers in Python"을 반환
색인하는 동안 각 질문은 문장 임베딩 모델을 통해 실행되어 숫자 벡터를 생성합니다.
사용자가 쿼리를 입력하면 동일한 문장 임베딩 모델을 통해 실행되어 벡터를 생성합니다. 응답의 순위를 매기기 위해 각 질문과 쿼리 벡터 사이의 벡터 유사도를 계산하게 됩니다. 임베딩 벡터를 비교할 때는 코사인 유사도를 사용하는 것이 일반적입니다.
이 리포지토리는 Elasticsearch에서 이를 구현하는 방법을 간단한 예시를 통해 보여줍니다. 기본 스크립트는 StackOverflow 데이터 세트의 질문을 최대 20,000개까지 색인한 다음 사용자가 데이터 세트에 대한 자유 텍스트 쿼리를 입력할 수 있게 합니다.
이 스크립트의 각 부분을 자세히 짚어보기 전에 몇 가지 예시 결과를 살펴보겠습니다. 대부분의 경우 이 메서드를 사용하면 쿼리와 색인된 질문 사이에 많은 단어가 겹치지 않더라도 유사도를 포착할 수 있습니다.
"zipping up files"는 "Compressing / Decompressing Folders & Files"를 반환
"determine if something is an IP"는 "How do you tell whether a string is an IP or a hostname"을 반환
"translate bytes to doubles"는 "Convert Bytes to Floating Point Numbers in Python"을 반환