2단계
임베딩 — 텍스트를 벡터로
25 분
임베딩 — 텍스트를 벡터로
"가격표" · "영수증" · "리셉트" 를 같은 의미로 묶어 주는 게 임베딩. 단어 · 문장을 고차원 벡터로 바꿔 의미 거리 를 수치화.
1. 임베딩이 답하는 질문
- 단어의 유사도 (
고양이 ↔ 강아지) - 문장의 의미 일치 (
"환불 하고 싶어" ↔ "반품 요청") - 언어 교차 (
"apple" ↔ "사과"· 다국어 모델 한정)
전통적 검색 (BM25 · TF-IDF) 은 정확 일치 위주라 위 3 가지 모두 놓치기 쉬움.
2. 차원과 모델
| 모델 | 차원 | 특징 |
|---|---|---|
| OpenAI text-embedding-3-small | 1536 | 비용 저렴 · 품질 우수 |
| OpenAI text-embedding-3-large | 3072 | 고품질 · 비용 3배 |
| Gemini text-embedding-004 | 768 | Google · 무료 quota 있음 |
| bge-m3 (로컬) | 1024 | 한국어 · 다국어 |
| multilingual-e5-large | 1024 | 공개 모델 · 로컬 가능 |
768 ~ 1024 차원이 품질 · 저장 비용 균형 지점.
3. 코드 — Gemini 무료 API
import google.generativeai as genai
genai.configure(api_key="...")
resp = genai.embed_content(
model="models/text-embedding-004",
content="감사로그 — logAdminAction 패턴",
task_type="retrieval_document",
)
vec = resp["embedding"] # list[float] 768
task_type 을 구분하는 게 중요. retrieval 인덱싱과 질의 임베딩을 다르게 처리.
4. 코사인 유사도
import numpy as np
def cosine(a, b):
a, b = np.array(a), np.array(b)
return float(a @ b / (np.linalg.norm(a) * np.linalg.norm(b)))
cosine(vec_q, vec_doc) # -1 ~ 1, 보통 0.7 이상이면 근접
PostgreSQL 에서는 <=> 연산자가 거리 (1 - cos) 를 반환. 유사도가 아니라 거리이므로 정렬은 ASC.
5. 한국어 품질 체크
같은 의미의 한국어 문장 10 쌍을 준비해 유사도가 평균 0.85+ 가 나오는지 확인. 낮으면 다국어 모델 권장.
"환불 받고 싶어요" ↔ "반품 요청합니다" → 0.89
"로그인 안 돼요" ↔ "로그인 실패" → 0.92
"주문 취소" ↔ "결제 취소 부탁드립니다" → 0.85
6. 자주 걸리는 자리
- 쿼리 · 문서 임베딩 혼동 — task_type 으로 구분
- 너무 긴 텍스트 한 번에 — 토큰 상한 512 ~ 2048. 긴 글은 청킹
- 임베딩 재생성 안 함 — 모델 업그레이드 시 전량 재계산 필요
- 정규화 누락 — HNSW 인덱스는 normalize 된 벡터 가정
하고픈 말
임베딩 품질은 리트리벌 정확도의 60 ~ 70% 를 결정합니다. 모델 선택에 1 시간 쓰는 게 프롬프트 튜닝 하루보다 낫습니다.
Next
- 03-pgvector-hnsw