왜 교차언어 검색은 어려운가

다국어 임베딩 모델은 "여러 언어를 한 벡터 공간에 넣는다"고 하지만, 실제로는 같은 의미의 한국어와 영어 문장이 완전히 겹치지 않는다. 학습 데이터의 언어 편향, 토크나이저의 서브워드 분할 차이, 언어별 문장 길이 분포 차이 때문에 임베딩이 언어 클러스터로 갈라지는 언어 편향(language bias)이 생긴다. 그 결과 한국어 질의로 영어 문서를 찾으면, 의미가 맞아도 같은 언어의 무관한 문서가 상위로 올라오는 현상이 나타난다.

문제를 먼저 측정하라

개선 전에 "얼마나 언어 쪽으로 쏠려 있는가"를 정량화해야 한다. 같은 의미의 다국어 쌍(parallel pairs)으로 코사인 유사도를 재고, 동일 언어 무관 쌍과 비교한다. 교차언어 쌍의 유사도가 동일 언어 무관 쌍보다 낮다면 언어 편향이 검색을 지배하는 상태다.

import numpy as np
from sentence_transformers import SentenceTransformer

model = SentenceTransformer("intfloat/multilingual-e5-base")

ko = ["환불 규정을 알려줘"]
en_same = ["Tell me the refund policy"]        # 의미 동일 (교차언어)
en_diff = ["How do I reset my password?"]      # 의미 무관

emb = model.encode(ko + en_same + en_diff, normalize_embeddings=True)
cos = lambda a, b: float(np.dot(a, b))
print("교차언어 정답 쌍:", cos(emb[0], emb[1]))
print("무관 쌍       :", cos(emb[0], emb[2]))
# 정답 쌍이 확실히 높아야 정상. 역전되면 편향 의심

모델 선택: prefix와 정규화가 절반이다

E5·BGE-M3 계열은 query: / passage: prefix를 강제하고, 벡터를 반드시 L2 정규화해 내적을 코사인으로 쓴다. 이 규칙을 어기면 성능이 수 포인트씩 떨어진다. 언어 커버리지와 임베딩 차원, prefix 요구 여부를 기준으로 고른다.

모델차원prefix특징
multilingual-e5-base768필수가볍고 무난, 100+ 언어
BGE-M31024선택dense+sparse+colbert 하이브리드
LaBSE768없음문장 정렬(bitext)에 강함

하이브리드 검색으로 편향을 완화

순수 dense 검색만으로는 언어 편향을 못 이기는 경우가 많다. 고유명사·제품코드처럼 언어를 넘나드는 토큰은 BM25 같은 어휘 검색이 강하다. dense와 sparse 점수를 RRF(Reciprocal Rank Fusion)로 합치면 한쪽의 실패를 다른 쪽이 보완한다.

-- pgvector + tsvector 하이브리드 예시 (RRF)
WITH dense AS (
  SELECT id, ROW_NUMBER() OVER (ORDER BY embedding <=> :qvec) AS r
  FROM docs ORDER BY embedding <=> :qvec LIMIT 50
),
lexical AS (
  SELECT id, ROW_NUMBER() OVER (
    ORDER BY ts_rank(tsv, plainto_tsquery(:q)) DESC) AS r
  FROM docs WHERE tsv @@ plainto_tsquery(:q) LIMIT 50
)
SELECT COALESCE(d.id, l.id) AS id,
       COALESCE(1.0/(60+d.r),0) + COALESCE(1.0/(60+l.r),0) AS score
FROM dense d FULL OUTER JOIN lexical l USING (id)
ORDER BY score DESC LIMIT 10;

재랭킹으로 상위 결과를 정밀화

1차 검색은 재현율(recall) 확보용으로 넉넉히 50~100건을 뽑고, 교차언어 지원 cross-encoder 재랭커(BGE-reranker-v2-m3 등)로 상위 10건을 다시 채점한다. 재랭커는 질의와 문서를 함께 인코딩하므로 임베딩의 언어 클러스터 문제에 훨씬 덜 휘둘린다. 비용이 크니 후보군에만 적용한다.

운영 시 주의점

  • prefix 일관성: 색인 시 passage:, 질의 시 query:를 섞지 마라. 한쪽만 빠져도 조용히 품질이 무너진다.
  • 정규화 이중 적용 금지: 모델에서 정규화했다면 DB 거리 연산도 코사인/내적으로 통일한다.
  • 모델 교체 = 전체 재색인: 임베딩 공간이 달라지므로 부분 갱신은 무의미하다. 차원·모델 버전을 메타데이터로 남겨라.
  • 회귀 방지: 언어별 평가셋(교차언어 쌍 포함)으로 nDCG@10을 CI에서 추적해, 모델·prefix 변경이 특정 언어만 망가뜨리는지 잡아낸다.

정리하면, 편향을 먼저 측정하고 → prefix·정규화를 지키며 → 하이브리드와 재랭킹을 겹쳐 쓰는 것이 교차언어 검색 품질의 실질적인 지렛대다.