인공지능 - 텍스트 임베딩과 유사도 검색의 원리를 이해하기 - 간단한 FAISS 실습
🛠 텍스트 임베딩과 유사도 검색의 원리를 이해하기 - 간단한 FAISS 실습
생성형 AI를 다루다 보면 이런 시스템을 자주 듣게 됩니다:
“문서에서 질문에 맞는 내용을 검색해서 답변하는 시스템(RAG, Retrieval Augmented Generation)”
이걸 제대로 이해하려면, 먼저 다음 과정을 알아야 합니다:
- 텍스트를 임베딩(embedding) 한다
- 벡터 기반으로 의미상 유사도를 계산한다
- FAISS 같은 검색 엔진을 통해 가장 가까운 문장을 찾는다
오늘 소개하는 코드는 바로 이 과정을 직접 눈으로 보고 체험할 수 있게 설계되었습니다.
즉, 텍스트 임베딩과 의미 기반 검색의 기본 원리를 이해하는 것이 목표입니다.
🧠 이 코드가 설명하는 핵심 원리
단계 | 설명 | 예시 |
---|---|---|
1 | 텍스트를 조각(청크)으로 나눈다 | “Tom and Becky went to the cave” → 청크 |
2 | 각 청크를 벡터(embedding)로 변환한다 | [0.023, -0.055, …, 0.078] (1536차원) |
3 | 질문을 벡터로 변환한다 | “등장 인물은 누구야?” → 벡터 |
4 | 질문 벡터와 문서 벡터 간 유사도를 계산한다 | 코사인 유사도, L2 거리 기반 |
5 | 가장 비슷한 문서를 찾아낸다 | 가장 의미가 가까운 문장들 반환 |
📄 전체 코드 흐름
1. PDF 파일에서 텍스트 추출 + 청크 분할
import fitz # PyMuPDF
text_chunks = []
chunk_size = 500
with fitz.open("pdf/The_Adventures_of_Tom_Sawyer.pdf") as doc:
for page_num, page in enumerate(doc, 1):
text = page.get_text()
chunks = [text[i:i+chunk_size] for i in range(0, len(text), chunk_size)]
text_chunks.extend(chunks)
- 긴 텍스트를 500자 단위로 잘게 나눕니다.
- 이렇게 해야 LLM이나 임베딩 모델이 잘 처리할 수 있습니다.
2. 청크 → 임베딩 변환
from openai import OpenAI
def get_embedding(text):
response = client.embeddings.create(input=text, model="text-embedding-ada-002")
emb = np.array(response.data[0].embedding, dtype=np.float32)
return emb
- 각 청크를 OpenAI API를 사용해 1536차원 벡터로 변환합니다.
- 텍스트의 의미를 숫자로 표현하는 과정입니다.
3. FAISS 인덱스에 저장
import faiss
import numpy as np
embeddings_matrix = np.vstack([emb for _, emb in chunk_embedding_pairs])
index = faiss.IndexFlatL2(embeddings_matrix.shape[1])
index.add(embeddings_matrix)
- 모든 임베딩을 하나의 거대한 행렬로 묶습니다.
- FAISS에 저장해서 빠른 유사도 검색이 가능하게 합니다.
4. 질문 → 임베딩 변환 후 검색
question = "등장 인물에 대해 알려줄래?"
q_emb = get_embedding(question).reshape(1, -1)
_, top_index = index.search(q_emb, k=5)
- 질문도 벡터화합니다.
- 문서 청크 벡터들과 거리 비교를 해서 가장 가까운 5개를 찾습니다.
5. 결과 출력
for i in top_index[0]:
chunk, emb = chunk_embedding_pairs[i]
print(f"텍스트 미리보기: {chunk[:200]}...")
print(f"임베딩 일부: {emb[:5]}...")
- 유사한 문장들을 실제로 출력해서 확인합니다.
- “이 질문에는 이 문장이 제일 비슷하구나” 를 직접 볼 수 있습니다.
🎯 정리: 이 코드가 알려주는 것
주제 | 설명 |
---|---|
토크나이징 | 문장을 조각(청크)으로 나눈다 |
임베딩 | 텍스트를 고차원 숫자 벡터로 변환한다 |
의미 비교 | 임베딩 벡터끼리 거리를 계산해서 의미 유사도를 판단한다 |
유사 문서 검색 | 가장 가까운 청크를 검색한다 |
벡터 DB | 검색을 빠르게 하기 위해 FAISS 인덱스를 사용한다 |
🧩 추가 심화 개념
- 임베딩 모델:
text-embedding-ada-002
를 사용하여 문장의 의미를 벡터로 변환 - L2 거리: 두 벡터 간 “유클리드 거리”를 계산하여 가장 가까운 것을 선택
- 코사인 유사도: 각도를 계산해 유사성을 판단하는 방법도 있다
- RAG 시스템: 위 과정을 GPT 같은 LLM과 결합하면 “내 문서에서 답변하는 AI”가 완성된다
📝 마무리
정리하자면,
텍스트를 벡터로 변환해 의미를 비교하고, 빠르게 유사한 문장을 찾는 원리
이 과정을 실제로 체험하고 이해하는 것이 이 코드의 핵심 목표입니다.
생성형 AI 시대에,
임베딩 → 검색 → 답변 흐름은 모든 AI 서비스의 기본 뼈대가 되고 있습니다. 🚀
🚀 다음 글 예고
다음에는
👉 “FAISS 인덱스를 파일로 저장하고 다시 불러오는 방법”
👉 “검색된 문서를 기반으로 GPT가 답변 생성하는 방법(RAG 완성)”
도 함께 다뤄보겠습니다!
댓글남기기