벡터 모델은 블랙박스와 같습니다. 텍스트를 입력하면 벡터가 출력됩니다. 레이블도, 워터마크도, 출처를 알려주는 메타데이터도 없는 부동 소수점 숫자의 목록일 뿐입니다. 만약 누군가 1024차원 벡터를 건네준다면, 그것이 BGE-M3, jina-embeddings-v5-text-small 또는 Qwen3-Embedding 중 어떤 모델에서 생성되었는지 구분할 수 있을까요? 또한 두 벡터가 동일한 모델에서 생성되었다 하더라도, 그것이 검색(retrieval) 지시어로 생성되었는지 아니면 분류(classification) 지시어로 생성되었는지 알 수 있을까요?
결과적으로 가능합니다. 벡터 모델의 벡터 내 수치 패턴에는 이를 생성한 모델의 놀라울 정도로 강력한 핑거프린트가 담겨 있으며, 심지어 추론 시 사용된 프롬프트 지시어의 특징까지 포함되어 있습니다. 저희는 25개 이상의 벡터 모델에서 추출한 68가지의 모델-태스크 조합을 식별하기 위해 소형 트랜스포머 분류기(파라미터 800K개)를 학습시켰으며, 원시 부동 소수점 숫자만을 읽어 87%의 정확도를 달성했습니다. 라이브 데모를 직접 체험해 보세요. 아무 벡터나 붙여넣으면 분류기가 어떤 모델과 태스크에서 생성된 것인지 판단해 줍니다.
tag토큰화: 숫자를 텍스트처럼 처리하기
1024차원 벡터 모델은 1024개의 부동 소수점 숫자로 이루어진 시퀀스입니다. 이를 분류기에 입력하려면 값의 구조에 대한 어떠한 가정도 하지 않는 표현 방식이 필요합니다.
저희는 과감한 접근 방식을 택했습니다. 각 부동 소수점을 숫자 문자의 문자열로 취급하고 이를 문자 단위로 토큰화하는 것입니다. 이는 더 컴팩트한 대안들에 비해 낭비처럼 보일 수 있지만, 결과적으로 적절한 트레이드오프임이 밝혀졌습니다. -0.1234와 같은 값의 경우, 토큰 시퀀스는 다음과 같습니다.
- 0 . 1 2 3 4각 차원은 [SEP] 토큰으로 구분됩니다. 전체 시퀀스는 [CLS]로 시작합니다. 전체 어휘 사전(vocabulary)은 15개의 토큰으로 구성됩니다.

| 토큰 ID | 의미 |
|---|---|
| 0-9 | 숫자 |
| 10 | 마이너스 부호 |
| 11 | 소수점 |
| 12 | [SEP] |
| 13 | [CLS] |
| 14 | [PAD] |
소수점 4자리 정밀도에서 1024차원 벡터는 약 7,700개의 토큰을 생성합니다. 384차원 벡터는 약 2,900개의 토큰을 생성합니다. 시퀀스 길이는 벡터 모델의 차원에 따라 자연스럽게 달라지며, 차원 간 패딩이나 잘라내기가 필요하지 않습니다. 토크나이저는 학습된 구성 요소가 없는 직접적인 정수 매핑 방식이므로 매우 효율적입니다.
tag모델 아키텍처

분류기는 4개의 레이어, 128차원, RoPE가 적용된 4개의 어텐션 헤드, SwiGLU FFN 및 RMSNorm을 갖춘 소형 인코더 전용 트랜스포머입니다. CLS 토큰은 풀링되어 68개의 클래스 출력 공간으로 투영됩니다. 총 파라미터는 약 800K개입니다.
15개의 토큰으로 구성된 작은 어휘 사전에도 불구하고, 이는 근본적으로 긴 시퀀스를 처리해야 하는 작업입니다. 단일 1024차원 벡터는 일반적인 NLP 입력보다 긴 7,700개의 토큰 시퀀스가 됩니다. 모델은 수천 개의 숫자 토큰을 조사하여 한 모델의 출력을 다른 모델과 구별하는 통계적 패턴을 포착해야 합니다. 따라서 이 정도의 작은 규모에서도 효율적인 어텐션과 위치 인코딩(RoPE)이 필수적입니다.
tag데이터
저희는 10,000개의 다국어 텍스트 샘플을 사용했으며, 각 샘플은 retrieval.query, retrieval.document, classification, clustering과 같은 다양한 태스크 접두사와 함께 25개 이상의 모델에 의해 생성되어 68개의 고유한 클래스를 생성했습니다. 중요한 점은, 68개의 클래스에는 서로 다른 모델뿐만 아니라 동일한 모델에 적용된 서로 다른 프롬프트 지시어도 포함된다는 것입니다. 예를 들어, 검색 지시어가 있는 jina-embeddings-v5-text-small과 분류 지시어가 있는 jina-embeddings-v5-text-small은 별개의 클래스로 취급됩니다. 목표는 원시 출력물만으로 모델의 정체성과 태스크별 동작을 모두 감지하는 것입니다.
각 클래스는 7,000개의 학습 샘플과 3,000개의 검증 샘플로 나뉩니다. 모델은 5가지의 출력 차원에 걸쳐 있습니다.
| 차원 | 클래스 | 예시 모델 |
|---|---|---|
| 384 | 8 | BGE-small, E5-small, MiniLM, GTE-small |
| 512 | 2 | BGE-small-zh |
| 768 | 24 | BGE-base, E5-base, jina-embeddings-v5-text-nano, Nomic, INSTRUCTOR, LaBSE |
| 1024 | 32 | BGE-M3, E5-large, jina-embeddings-v3, jina-embeddings-v5-text-small, Qwen3-0.6B, Snowflake, mxbai |
| 1536 | 2 | GTE-Qwen2-1.5B |
1024차원 그룹 내에서만 태스크 접두사가 다른 동일 계열 모델을 포함하여 32개의 클래스를 구분해야 합니다. 여기서 분류기는 시퀀스 길이에 의존할 수 없으며, 순수하게 수치적 패턴을 학습해야 합니다.
tag학습
학습은 A100 40GB에서 혼합 정밀도(mixed precision), 길이별 버킷 배칭(length-bucketed batching), 코사인 스케줄러가 적용된 AdamW를 사용하여 진행되었으며, 초당 약 340K개의 토큰과 에포크당 23,800단계를 처리했습니다.
tag실험 결과

학습 및 검증 데이터 간의 좁은 격차와 지속적인 성능 향상은 단순 암기가 아닌 일반화 가능한 학습이 이루어지고 있음을 시사합니다. 800K 파라미터에서 모델은 용량 한계에 도달하고 있으며, 더 큰 모델을 사용하면 정확도가 더 높아질 가능성이 큽니다.
tag혼동 행렬 (Confusion Matrix)

전체 정확도는 87.0%로, 무작위 확률인 1.5%보다 59배 더 높습니다. GTE-large, jina-embeddings-v3/jina-embeddings-v5-text-small 분류 변체, LaBSE, Paraphrase MiniLM을 포함한 여러 모델은 완벽하게 분류되었습니다. 가장 까다로운 사례는 동일한 기본 모델의 태스크 접두사 변체들입니다. Qwen3-0.6B는 4가지 태스크 유형 전체에서 계열 내 혼동이 가장 많았던 반면, jina-embeddings-v5-text-small은 5가지 태스크에서 92%의 계열 내 정확도를 달성했습니다. 동일한 모델에서 서로 다른 프롬프트 지시어가 구별 가능한 출력 패턴을 생성한다는 사실 자체가 주목할 만한 발견이며, 이는 기본 가중치가 동일하더라도 태스크 적응이 측정 가능한 수치적 흔적을 남긴다는 것을 시사합니다.
서로 다른 계열의 모델(BGE vs. Jina vs. E5 vs. Nomic)은 동일 모델의 태스크 변체보다 훨씬 더 쉽게 구분됩니다. 핵심 아키텍처와 학습 방법론은 태스크 전용 어댑터보다 더 강력한 시그니처를 남깁니다. 진짜 도전 과제는 시퀀스 길이보다는 순수하게 수치적 패턴에 의존해야 하는 1024차원 그룹(32개 클래스)과 768차원 그룹(24개 클래스)에 있습니다.
tag대안적 접근 방식
tag버킷 토크나이저 (Bucket Tokenizer)
각 차원을 K개의 빈(bin)(예: 256개) 중 하나로 양자화하여 차원당 하나의 토큰을 갖는 길이 D의 컴팩트한 시퀀스를 생성합니다. 이것이 Embedding-Converter(ICLR 2025)에서 사용된 방식입니다. 1024차원 벡터의 경우 7,700개 대신 1,024개의 토큰을 얻게 됩니다.
버킷팅은 값 분포에 대한 사전 확률을 부여합니다. 데이터를 확인하기 전에 빈 경계를 결정해야 합니다. 하지만 모델마다 값을 분산시키는 방식이 근본적으로 다릅니다. 어떤 모델은 0 근처의 좁은 범위에 값을 집중시키고, 다른 모델은 [-1, 1] 전체에 값을 균등하게 퍼뜨리기도 하며, 단일 모델 내에서도 차원마다 분포가 달라집니다. 고정된 버닝(binning) 방식은 값이 밀집된 곳에서는 해상도를 낭비하거나, 값이 퍼져 있는 곳에서는 해상도가 부족해집니다. 모델별 가변 버닝은 모델의 정체성을 미리 알고 있어야 하므로 목적에 어긋납니다.
tag고정 길이 MLP
원시 벡터를 MLP 분류기에 직접 입력합니다. 근본적인 문제는 가변 차원 문제(저희 모델은 384에서 1536차원의 벡터를 생성함) 그 이상입니다. 모든 것을 고정 길이로 패딩하더라도, BGE-M3의 1번 차원이 jina-embeddings-v5-text-small의 1번 차원과 대응된다는 것과 같이 차원 인덱스가 모델 간에 의미론적으로 일치한다고 암묵적으로 가정하는 셈입니다. 이 가정은 틀렸습니다. 아키텍처, 학습 데이터, 학습 목표가 다르면 완전히 다른 내부 표현이 생성됩니다.
두 대안 모두 모델이 해결해야 할 구조적 가정을 부여합니다. 숫자 단위 토큰화는 이러한 모든 문제를 피할 수 있습니다. 이는 저희가 찾은 가장 가정이 없는 표현 방식입니다. 각 숫자의 정확한 자릿수를 순서대로 나열하고 구분 기호로 분리한 뒤, 나머지는 모델이 직접 파악하도록 하는 것입니다.
tag결론
벡터 모델은 의미적으로 유사한 텍스트를 가까운 벡터에 매핑하도록 학습됩니다. 학습 목표에는 벡터를 식별 가능하게 만들거나 모델 시그니처를 인코딩하는 것에 대한 내용이 전혀 없습니다. 그럼에도 불구하고 시그니처는 존재하며, 아주 작은 분류기도 이를 감지할 수 있을 정도로 강력합니다. 벡터 모델의 '스타일', 즉 의미를 표현하기 위해 사용하는 특정 수치 패턴은 필체만큼이나 독특합니다. 심지어 프롬프트 지시어의 선택조차 감지 가능한 흔적을 남깁니다.
이는 소스 모델을 알 수 없는 벡터 데이터베이스를 감사하고, API가 실제로 주장하는 모델을 사용하는지 확인하며, 모델 버전 변경을 감지하는 데 실질적인 가치가 있습니다. 더욱 근본적으로, 이는 벡터 모델이 동일한 차원의 벡터를 생성하더라도 구조적으로 뚜렷하게 다른 방식으로 의미를 인코딩한다는 점을 시사합니다.






