시맨틱 검색 및 RAG의 이해
시맨틱 검색은 키워드 매칭이 아닌 단어나 구문의 ‘의미’를 기반으로 정보를 탐색하는 방식입니다. 이는 주로 신경망에 의해 생성되는 임베딩(Embedding)을 활용하며, 대규모 언어 모델(LLM)의 핵심 구성 요소입니다. RAG는 시맨틱 검색으로 관련성 높은 콘텐츠를 찾아(Retrieval) 이를 기반으로 LLM이 답변을 합성(Generation)하는 기술입니다.
임베딩(Embeddings)과 벡터(Vectors)
- 개념: 임베딩은 단어나 문장을 숫자 벡터로 변환한 것으로, 기계가 단어의 의미를 이해하고 처리할 수 있게 합니다. 의미가 유사한 단어들은 벡터 공간에서 서로 가깝게 위치합니다.
- 차원: 고차원 벡터(예: 1024차원)는 복잡한 의미 관계를 표현할 수 있습니다.
- 유사도 측정: 벡터 간의 거리를 측정하는 데 유클리드 거리(Euclidean distance)보다 코사인 유사도(Cosine similarity)가 더 일반적으로 사용됩니다. 코사인 유사도는 두 벡터 간의 각도를 측정하여 방향의 유사성을 판단합니다.
임베딩 생성 및 저장
- 생성 도구: Ruby에서 직접 임베딩을 생성하기보다는 OpenAI, Anthropic 또는 로컬에서 실행 가능한 Ollama와 같은 API를 활용합니다. Ollama는
brew install
로 쉽게 설치할 수 있으며,mxb-ai-embed-large
와 같은 임베딩 모델을 로컬에서 실행할 수 있습니다. - Ruby 연동:
ollama
Ruby Gem을 사용하여 Ollama API와 통신할 수 있습니다. 텍스트를 임베딩 모델에 전달하기 전에 특정 접두사(prefix)를 붙이는 것이 모델의 성능을 향상시킬 수 있습니다. - 문맥 길이 및 청킹: 각 임베딩 모델은 고유한 문맥 길이(Context Length)를 가지므로, 긴 텍스트는 네트워크가 처리할 수 있는 크기로 분할(Chunking)해야 합니다.
- 저장: 생성된 임베딩은 효율적인 검색을 위해 벡터 데이터베이스에 저장하는 것이 좋습니다. SQLite VSS(Ruby Gem), PGVector, MeiliSearch 등이 활용될 수 있습니다. 본 발표에서는 SQLite VSS를 사용하여 Reddit 게시물의 제목과 내용을 임베딩으로 변환하여 저장하는 예시를 보여줍니다.
임베딩 검색 및 RAG 구현
- 검색 과정: 검색 쿼리 텍스트를 임베딩으로 변환한 후, 벡터 데이터베이스에서 가장 가까운(유사한) 벡터들을 찾아 관련 게시물을 검색합니다. 이를 통해 키워드가 직접 포함되지 않아도 의미적으로 유사한 결과를 얻을 수 있습니다.
- RAG를 통한 응답 생성: 시맨틱 검색으로 찾아낸 관련 콘텐츠(예: Reddit 게시물의 댓글)를 LLM에 문맥(Context)으로 제공하고, LLM(예: Llama 3.1)에게 이를 요약하거나 질문에 대한 답변을 생성하도록 요청합니다.
- 프롬프트 엔지니어링: LLM으로부터 원하는 응답을 얻기 위해서는 효과적인 프롬프트 엔지니어링이 필수적입니다.
클러스터링(Clustering)
- 개념: 고차원 벡터 공간에서 유사한 임베딩들을 그룹화(클러스터링)하여 특정 주제나 패턴을 발견할 수 있습니다. K-평균 클러스터링(K-means clustering)이 대표적인 방법입니다.
- 도구: Facebook의 Faiss 라이브러리는 고차원 벡터의 효율적인 클러스터링 및 유사도 검색을 지원합니다.
- 고려 사항: 클러스터의 개수를 결정하는 것이 중요하며, 유클리드 거리와 코사인 유사도 간의 차이를 이해해야 합니다.