콘텐츠로 이동

임베딩과 재순위화

생성 모델은 프롬프트에 답하고 검색 시스템은 생성 모델이 어떤 정보를 볼지 결정합니다. 실제 검색 증강 시스템은 이 결정을 보통 두 단계의 모델 서빙으로 나눕니다.

  1. 임베딩 모델이 질의와 문서를 벡터로 바꾸어 큰 문서 집합을 저렴하게 검색합니다.
  2. 재순위화 모델이 작은 후보 목록에 더 많은 계산을 사용하여 관련도 순서를 정밀하게 고칩니다.

두 단계는 서로 보완합니다. 임베딩 인덱스는 규모와 재현율을, 재순위화 모델은 정밀도를 제공합니다. mlxcel은 오프라인 명령, 전용 서버 작업자, 밀집·다중 벡터 임베딩, 지원 모델의 텍스트·이미지 입력, 교차 인코더·생성형 재순위화를 모두 지원합니다.

검색 후 재순위화 절차

flowchart TB
    subgraph 오프라인 인덱싱
        A[문서] --> B[분할과 접두문 적용]
        B --> C[문서 인코더]
        C --> D[(벡터 인덱스)]
    end
    subgraph 온라인 요청
        Q[질의] --> E[질의 인코더]
        E --> F[근사 검색 또는 최대 유사도 검색]
        D --> F --> G[상위 K개 후보]
        Q --> H[재순위화 모델]
        G --> H --> I[상위 N개 근거]
        I --> J[생성 모델 또는 응용 프로그램]
    end

오프라인에서는 문서나 구절을 조각으로 나누고 체크포인트의 형식에 맞춘 뒤 인코딩하여 텍스트, 안정적인 식별자, 메타데이터, 인코더 버전과 함께 인덱스에 기록합니다. 온라인에서는 질의 인코더가 벡터 하나 또는 토큰 벡터 행렬을 만듭니다. 근사 최근접 이웃 검색이나 후기 상호작용 검색이 상위 K개 후보를 가져오고 재순위화 모델이 각 질의-문서 쌍을 평가합니다. 응용 프로그램은 보통 N < K인 상위 N개를 사용합니다.

검색 품질에는 상한이 있습니다. 관련 문서가 첫 단계 후보에 없으면 재순위화 모델이 복구할 수 없습니다. 임베딩 단계는 Recall@K를, 재순위화 단계는 최종 순서 품질을 목표로 조정하십시오.

mlxcel이 제공하는 기능

mlxcel은 생성, 임베딩, 재순위화를 서로 다른 모델 종류로 구분합니다. -m에 지정한 임베딩 체크포인트나 레이블 하나짜리 시퀀스 분류 체크포인트는 일반 생성 로더보다 먼저 감지됩니다. 생성 명령은 임베딩 체크포인트의 은닉 상태를 임의로 로그잇처럼 사용하지 않고 mlxcel embed 또는 /v1/embeddings를 사용하라는 오류를 냅니다.

사용 경로 용도
mlxcel embed 서버와 같은 로더, 풀링, 정규화, 배칭을 사용하여 오프라인에서 임베딩과 유사도를 확인합니다.
mlxcel rerank 서버와 같은 쌍 구성과 배칭으로 오프라인 관련도와 순위를 확인합니다.
POST /v1/embeddings OpenAI 호환 임베딩 요청과 응답입니다.
POST /embedding, POST /embeddings llama-server 고유 임베딩 요청과 응답입니다. OpenAI 응답 형식의 별칭이 아닙니다.
POST /v1/rerank, /v1/reranking, /rerank, /reranking 요청 필드에 따라 Jina/Cohere 또는 TEI 호환 형식으로 응답하는 재순위화 경로입니다.
GET /v1/models 불러온 대화, 임베딩, 재순위화 모델을 나열합니다.

정확한 전송 형식과 오류 코드는 임베딩 및 재순위화 API를 참고하십시오.

밀집 임베딩

밀집 이중 인코더는 질의와 문서를 독립적으로 처리합니다.

e_q = f_q(q)    e_d = f_d(d)

문서 벡터 e_d는 현재 질의와 무관하므로 한 번만 계산해 둘 수 있습니다. 검색할 때는 내적, 코사인 유사도, 거리와 근사 최근접 이웃 자료 구조를 사용하여 질의 벡터를 저장된 문서 벡터와 비교합니다.

풀링

많은 인코더가 [배치, 토큰, 은닉 차원]을 출력합니다. 풀링은 각 시퀀스를 벡터 하나로 줄입니다.

방식 mlxcel 동작
cls 첫 번째 유효 토큰을 선택합니다.
mean 패딩을 제외한 유효 토큰만 평균냅니다.
max 유효 토큰에서 차원별 최댓값을 구합니다.
lasttoken 왼쪽·오른쪽 패딩 모두에서 마지막 유효 토큰을 선택합니다.

결정 순서는 명시적인 --pooling 지정, 체크포인트의 1_Pooling/config.json, 모델 계열 기본값입니다. 명령행 값을 지정하지 않았을 때 MLXCEL_EMBEDDING_POOLING을 진단용 덮어쓰기로 사용할 수도 있습니다. llama-server 방식의 --pooling last는 lasttoken으로 이어지고 rank는 풀링 커널이 아니라 재순위화 모드를 선택합니다. none은 풀링이 끝난 뒤 토큰 벡터를 되살릴 수 없으므로 거부됩니다.

풀링 방식을 감으로 고르지 마십시오. 잘못된 풀링을 사용해도 겉보기에 정상인 벡터가 나오지만 검색 품질은 크게 떨어질 수 있습니다.

정규화와 Matryoshka 차원 축소

널리 쓰는 유사도 함수는 다음과 같습니다.

dot(q, d)    = e_q dot e_d
cosine(q, d) = (e_q dot e_d) / (norm(e_q) * norm(e_d))

두 벡터를 L2 정규화하면 코사인 유사도 순위와 내적 순위가 같습니다. mlxcel은 기본적으로 체크포인트의 정규화 규칙을 따르며 llama-server 호환 --embd-normalize 값을 지원합니다.

값 연산
-1 정규화하지 않음
0 절댓값 최댓값을 기준으로 int16 범위에 맞춤
1 L1 정규화
2 L2 정규화
p > 2 p-노름 정규화

요청마다 embd_normalize를 지정할 수도 있습니다. 영 벡터는 NaN이 되지 않고 그대로 영 벡터로 남습니다.

OpenAI 요청의 dimensions와 mlxcel embed --dimensions는 앞쪽 차원만 남긴 뒤 정규화가 켜져 있으면 다시 정규화합니다. 모델이 Matryoshka 차원 축소를 학습했을 때만 품질을 보존하는 기능입니다. 임의의 폭을 고르면 JSON 모양은 맞아도 검색 품질이 나빠질 수 있습니다.

길이, 패딩, 배칭

실제 최대 길이는 sentence_bert_config.json, tokenizer_config.json, 절대 위치 임베딩 표, 명령행 상한, mlxcel의 8192 하드 상한 가운데 적용되는 가장 작은 값입니다. 텍스트는 특수 토큰을 붙인 뒤 오른쪽에서 자르되 [SEP] 같은 마지막 특수 토큰을 보존합니다. 사용자가 직접 넣은 토큰 ID는 그대로 오른쪽에서 자릅니다.

텍스트 입력은 토큰 길이로 정렬하고 작은 배치로 나누며 그 배치의 최장 길이에만 맞춰 오른쪽을 패딩한 뒤 요청 순서로 되돌립니다. --embedding-batch-size의 기본값은 16입니다. 지원되는 이미지 입력은 시각 자료마다 크기가 다르므로 한 번에 하나씩 처리합니다. bf16 체크포인트는 누산 배열 모양의 영향으로 같은 문장을 혼자 처리했을 때와 큰 배치에서 처리했을 때 코사인 유사도가 약 0.9999일 수 있습니다. 부동소수점의 비트 단위 일치보다 검색 허용 오차로 검증하십시오.

밀집, 멀티모달, 다중 벡터 모델 계열

인코더 및 디코더 백본 임베딩 모델

계열 일반적인 규칙 예시와 참고 사항
BERT / MiniLM 평균 또는 체크포인트 지정 풀링, 밀집 텍스트 sentence-transformers/all-MiniLM-L6-v2; multilingual E5는 query:와 passage:가 필요합니다.
XLM-RoBERTa 체크포인트 지정 풀링, 다국어 밀집 텍스트 BAAI/bge-m3; 절대 위치 길이를 검증합니다.
ModernBERT 긴 문맥의 밀집 텍스트 nomic-ai/modernbert-embed-base는 search_query:와 search_document:가 필요합니다.
SigLIP 텍스트 타워 고정 64토큰 입력, 마지막 위치 사용 이 계열에서는 텍스트 타워만 제공하고 비전 타워는 제공하지 않습니다.
EmbeddingGemma 양방향 Gemma 3, 평균 풀링, 학습된 밀집 사영 과제별 질의·문서 프롬프트도 모델 계약에 포함됩니다.
Qwen3-Embedding 인과적 디코더 백본, 마지막 토큰 풀링 instruction으로 질의를 꾸미고 문서는 원문 그대로 보냅니다.
양방향 Llama / LLM2Vec 양방향 Llama, 평균 풀링 학습할 때 사용한 질의·문서 규칙을 호출자가 적용합니다.
Nemotron-3-Embed / Ministral 3 양방향 Ministral 3, 평균 풀링 체크포인트가 요구하면 query: 또는 passage:를 호출자가 붙입니다.
LFM2.5-Embedding 양방향 어텐션과 비인과적 짧은 합성곱, CLS 풀링 query:와 document:를 사용합니다.

멀티모달 임베딩 모델

계열 입력 출력
Qwen3-VL-Embedding 텍스트 또는 이미지가 든 형식 지정 항목 입력마다 풀링된 벡터 하나
Llama-Nemotron-VL-Embed 텍스트 또는 SigLIP 타일링 경로를 거치는 이미지 입력마다 풀링된 벡터 하나
EmbeddingGemma 2 (embedding_gemma2, embedding_gemma2_text) 텍스트, 그리고 체크포인트에 비전 타워가 있으면 이미지. embedding_gemma2_text 변형은 텍스트 전용 양방향 Gemma 4, 모델 내부의 512에서 768로의 사영, 평균 풀링, L2 정규화를 거친 입력별 768차원 벡터 하나. Matryoshka 폭 512, 256, 128을 지원합니다. bf16 가중치는 로드할 때 bf16을 유지하며, 검증된 변환본은 mlx-community/embeddinggemma-2-bf16입니다.

이미지는 supports_images() 계약이 참인 모델 계열에서만 받을 수 있습니다. image_url.url에는 데이터 URI, file:// URL, HTTP(S) URL, 로컬 경로를 쓸 수 있으며 공통 이미지 제한을 적용합니다. 서비스는 벡터를 만들 뿐 벡터 데이터베이스, 메타데이터 필터, 이미지 검색 인덱스를 제공하지 않습니다.

후기 상호작용

ColIdefics3와 ColQwen2.5는 시퀀스 벡터 하나 대신 유효 토큰마다 정규화한 벡터를 반환합니다. 보통 토큰 벡터 하나는 128차원입니다. 실수형 응답 모양은 [토큰 수, 차원 수]이고 base64 응답에는 shape 필드가 따로 붙습니다.

mlxcel은 다음 최대 유사도 합산 방식으로 두 행렬을 비교합니다.

MaxSim(q, d) = sum_i max_j dot(q_i, d_j)

각 질의 토큰에 가장 가까운 문서 토큰을 찾고 그 유사도를 모두 더합니다. 단일 벡터 코사인보다 표현력이 높고 완전 교차 인코더보다 저렴하지만 다중 벡터를 이해하는 인덱스가 필요합니다. 점수는 비대칭이며 질의 토큰 수에 따라 커지므로 서로 관계없는 질의 사이의 절댓값을 직접 비교하면 안 됩니다.

프롬프트와 접두문 계약

mlxcel은 일반적으로 과제 접두문을 임의로 붙이지 않습니다. 문서 집합을 임베딩할 때 사용한 바이트열은 모델 학습 규칙과 맞아야 합니다.

체크포인트 유형 질의 문서
Multilingual E5 query: ... passage: ...
Nomic ModernBERT search_query: ... search_document: ...
Llama/Nemotron 검색형 query: ... passage: ...
LFM2.5 query: ... document: ...
EmbeddingGemma 모델 카드의 과제별 프롬프트 모델 카드의 과제별 프롬프트
EmbeddingGemma 2 모델 카드 프롬프트(예: task: search result \| query: ...) 모델 카드 프롬프트(예: title: none \| text: ...)
Qwen3-Embedding instruction과 질의 문서 원문

접두문, 지시문, 토크나이저 리비전, 풀링, 정규화, 출력 차원, 잘림 길이는 모두 인덱스 버전의 일부입니다. 하나라도 바뀌면 길이가 우연히 같다는 이유로 벡터를 섞지 말고 문서 집합을 다시 임베딩하십시오.

재순위화 모델

재순위화 모델은 질의-문서 쌍마다 관련도 점수를 계산합니다.

r_i = g(q, d_i)

결합 어텐션은 독립된 밀집 벡터를 비교하는 것보다 표현력이 높지만 문서 계산 전체를 미리 해 둘 수 없습니다. 후보 K개를 재순위화하려면 대략 K개의 쌍을 평가해야 하므로 저렴한 첫 검색 뒤에 배치해야 합니다.

지원하는 점수 계산 방식

종류 감지 또는 선택 방법 점수 대표 체크포인트
BERT 교차 인코더 레이블 하나짜리 ForSequenceClassification sigmoid(logit) cross-encoder/ms-marco-MiniLM-L6-v2
XLM-R 교차 인코더 레이블 하나짜리 ForSequenceClassification sigmoid(logit) BAAI/bge-reranker-v2-m3
ModernBERT 교차 인코더 레이블 하나짜리 ForSequenceClassification sigmoid(logit) Alibaba-NLP/gte-reranker-modernbert-base
Qwen3 생성형 명시적인 --reranker-model sigmoid(logit("yes") - logit("no")) Qwen/Qwen3-Reranker-0.6B 및 MLX 양자화본
Qwen3-VL 생성형 명시적인 --reranker-model 텍스트와 이미지 내용에서 같은 예·아니요 점수 Qwen/Qwen3-VL-Reranker-2B

교차 인코더는 체크포인트에서 식별할 수 있으므로 -m만으로 제공할 수 있습니다. 생성형 재순위화 모델은 일반 인과적 체크포인트 또는 VLM처럼 보이므로 재순위화 로더를 선택하려면 --reranker-model이 필요합니다. 출력 레이블이 둘 이상인 분류기는 점수의 의미가 모호하므로 거부합니다.

시퀀스 분류기는 체크포인트의 쌍 템플릿과 긴 쪽부터 자르는 규칙을 사용하며 특수 토큰을 보존합니다. Qwen3 재순위화 모델은 시스템 지시문과 답 점수를 읽는 보조 구조를 보존한 채 질의·문서 내용만 자릅니다. 기본 지시문은 웹 구절 검색을 설명하며 사용자가 바꿀 수 있습니다. Qwen3-VL은 체크포인트의 reranker.jinja를 렌더링하고 텍스트나 이미지가 든 객체를 받으며 이미지가 든 행은 따로 평가합니다. 비디오 재순위화는 지원하지 않습니다.

점수 범위는 [0, 1]이지만 주된 의미는 한 질의의 후보 집합 안에서의 상대 순서입니다. mlxcel은 점수가 높은 순으로 정렬하고 점수가 정확히 같으면 원래 인덱스가 작은 항목을 먼저 둔 다음 top_n을 적용합니다.

오프라인 실행

임베딩

mlxcel embed -m nomic-ai/modernbert-embed-base \
  -p "search_query: 벡터 검색이란 무엇인가?" \
  -p "search_document: 벡터 검색은 가까운 임베딩을 찾는다." \
  -p "search_document: 컴파일러는 소스 코드를 번역한다."

텍스트는 -p, 지원하는 멀티모달 입력의 이미지는 --image를 반복해 지정합니다. 비어 있거나 공백만 있는 -p는 mlxcel rerank가 그런 -d를 거부하는 것과 마찬가지로 거부됩니다. --instruction, --dimensions, --pooling, --embd-normalize, --max-length, --batch-size, --models-dir, --json으로 서버와 같은 주요 선택을 제어할 수 있습니다. 입력이 여럿이면 밀집 벡터에는 코사인 유사도, 다중 벡터에는 최대 유사도 합산 행렬을 출력합니다.

재순위화

mlxcel rerank -m BAAI/bge-reranker-v2-m3 \
  -q "벡터 검색이란 무엇인가?" \
  -d "벡터 검색은 가까운 임베딩을 찾는다." \
  -d "컴파일러는 소스 코드를 번역한다." \
  --top-n 1

지원되는 멀티모달 재순위화 모델에는 --query-image와 반복 가능한 --image로 시각 입력을 추가합니다. --instruction, --max-length, --batch-size, --models-dir, --json도 사용할 수 있습니다.

한 가지 또는 세 가지 모델을 함께 서빙하기

# 임베딩 전용
mlxcel-server -m sentence-transformers/all-MiniLM-L6-v2 --port 8080

# 교차 인코더 재순위화 전용
mlxcel-server -m BAAI/bge-reranker-v2-m3 --port 8080

# 한 프로세스에서 대화, 임베딩, 재순위화 제공
mlxcel-server \
  -m mlx-community/Qwen3-4B-4bit \
  --embedding-model Qwen/Qwen3-Embedding-0.6B \
  --reranker-model mlx-community/Qwen3-Reranker-0.6B-4bit \
  --port 8080

# 생성형 재순위화 전용: 두 옵션이 의도적으로 같은 모델을 가리킨다
mlxcel-server \
  -m mlx-community/Qwen3-Reranker-0.6B-4bit \
  --reranker-model mlx-community/Qwen3-Reranker-0.6B-4bit

임베딩 제공자와 재순위화 제공자는 각각 전용 스레드에서 모델, 토크나이저, MLX 배열을 소유합니다. 대화 작업자와 같은 스트림을 공유하지 않고 나란히 실행할 수 있습니다. 프로세스 하나에는 임베딩 모델 하나와 재순위화 모델 하나까지만 불러올 수 있습니다. --embedding/--embeddings 및 --rerank/--reranking은 llama-server 호환 제한 모드를 선택하며 해당 제공자가 반드시 있어야 합니다.

주요 처리 용량 설정은 다음과 같습니다.

옵션 기본값 효과
--embedding-batch-size 16 임베딩 순전파 한 번에 넣는 텍스트 수
--embedding-max-length 자동 결정 체크포인트에서 구한 길이 상한을 더 낮춤
--embedding-queue-depth 8 각 임베딩·재순위화 작업자 명령 큐의 상한
--embedding-request-timeout-secs 120 두 작업자 유형이 공유하는 응답 제한 시간
--rerank-batch-size 0 모델 종류의 기본값 사용: 텍스트 8, 멀티모달 2

인덱스 설계는 모델 계약의 일부

최소한 다음을 기록하십시오.

  • 모델 저장소와 변경되지 않는 리비전
  • 토크나이저, 접두문·지시문, 풀링, 정규화, 최대 길이, 출력 차원
  • 밀집 또는 다중 벡터 모양, 자료형, 유사도 함수
  • 문서 분할기 버전, 겹침, 텍스트 정규화, 상위 문서 연결
  • 근사 검색 또는 후기 상호작용 인덱스 알고리즘과 매개변수
  • 메타데이터 필터 의미, 삭제 세대, 테넌트 경계

매우 큰 조각은 관련 문장을 희석하고 재순위화 모델의 토큰 예산을 소모합니다. 지나치게 작은 조각은 문맥을 잃고 인덱스 항목을 늘립니다. 의미 있는 경계에서 나누고 적당한 겹침을 두며 안정적인 문서·구역 식별자를 보존하고 검색 뒤 같은 상위 문서에 속한 결과를 합치십시오.

mlxcel의 책임은 모델 추론에서 끝납니다. 벡터 저장, 근사 최근접 이웃 인덱스 구축, 희소 검색, 메타데이터 결합은 제공하지 않습니다. 임베딩 체크포인트의 어댑터 병합·적용과 한 프로세스에서 같은 종류의 임베딩 또는 재순위화 모델을 둘 이상 불러오는 것도 현재 범위 밖입니다.

평가와 처리 용량 계획

지표 단계 해석
Recall@K 최초 검색 재순위화 모델이 볼 수 있는 관련 항목의 비율
MRR 검색 또는 최종 순위 첫 관련 항목 순위의 역수
nDCG@K 최종 순위 관련도가 높은 항목을 앞에 둘수록 높은 값
MAP 최종 순위 관련 항목의 위치와 질의에 걸쳐 평균한 정밀도
초당 질의 수와 p50/p95 지연 서빙 목표 동시성에서 처리 용량과 사용자 지연

검색과 재순위화를 따로 측정한 뒤 전체도 측정하십시오. 재현율이 포화될 때까지 K를 늘려 보고 각 후보 목록을 재순위화하십시오. 요구 품질을 만족하면서 꼬리 지연 여유를 남기는 가장 작은 K를 고릅니다. N은 재순위화 모델의 최대치가 아니라 후속 문맥 또는 화면 표시 예산에서 결정합니다.

오프라인 문서 집합 인코딩은 큰 배치와 재시도 가능한 작업에 유리하고 온라인 질의 인코딩은 작은 동적 배치와 낮은 꼬리 지연이 중요합니다. 재순위화에는 질의-문서 쌍이라는 배치 차원이 하나 더 생깁니다. 대량 재인덱싱 작업이 대화형 질의용 가속기를 독점하지 않도록 처리 용량을 분리하십시오.

보안과 격리

  • 후보를 반환하기 전에 테넌트와 권한 필터를 적용합니다. 벡터 유사도는 접근 제어가 아닙니다.
  • 정책이 허용하지 않으면 민감한 텍스트나 벡터를 기록하지 않습니다. 임베딩은 속성을 드러낼 수 있으며 익명 식별자가 아닙니다.
  • 문서 길이와 후보 수를 제한하여 요청 하나가 작업자를 독점하지 못하게 합니다.
  • 원격·로컬 이미지 참조를 단순 문자열이 아니라 자원 접근으로 다룹니다. 신뢰할 수 있는 호출자, 외부 통신, 파일 시스템 공개 범위를 제한하십시오.
  • 검색한 신뢰할 수 없는 내용을 생성 모델에 넣을 때 시스템 지시문과 분리합니다.
  • 삭제와 재인덱싱에 버전을 붙여 제거된 문서가 벡터, 메타데이터, 문서 저장소에서 함께 사라지게 합니다.

생성 모델 내부의 임베딩과는 다르다

생성 모델도 토큰 ID를 은닉 벡터로 바꾸고 이미지·오디오·비디오 특징을 언어 모델 시퀀스로 사영합니다. 이러한 텐서는 토큰 단위이고 풀링되지 않았으며 위치에 종속되거나 특정 생성 아키텍처 내부에서만 의미가 있을 수 있습니다. 새 공개 임베딩 기능은 이와 다릅니다. 체크포인트 종류 감지, 어텐션 마스크, 풀링 또는 다중 벡터 사영, 정규화, 배칭, 길이 제한, 토큰 사용량 계산, 안정적인 API 계약을 명시적으로 수행합니다. 둘 다 “임베딩”이라는 이름을 쓴다는 이유로 생성 모델의 내부 은닉 상태를 검색 모델 대신 사용하면 안 됩니다.

더 읽을거리