kiom-embedding-bge-m3: Korean Medicine Embedding Model

한의학(Korean Medicine) 도메인 특화 임베딩 모델입니다. BAAI/bge-m3를 기반으로 한의학 온톨로지 및 용어 데이터를 활용하여 LoRA 파인튜닝하였습니다.

Highlights

  • MRR@10 0.9002 (3포맷 평균) — 베이스 모델(0.7285) 대비 +23.6% 향상
  • 13개 SOTA 모델 대비 1위 (OpenAI, Gemini, Qwen3, E5 등 포함)
  • Sim_Gap 0.5221 — 베이스 모델(0.1719) 대비 3배 향상, 정답/오답 분리 능력 대폭 개선
  • 한글, 한자, 한글+한자 3가지 포맷 모두에서 최고 성능

Model Details

항목
Base Model BAAI/bge-m3
Method LoRA (PEFT)
LoRA Rank 16
LoRA Alpha 32
Target Modules query, key, value
Output Dim 1024
Max Seq Length 256 tokens
Training Data 302,676 samples (한의학 온톨로지 10종, 3포맷)
Loss MultipleNegativesRankingLoss
Epochs 35 (effective, multi-epoch sweep)
Batch Size 64
Learning Rate 2e-5
Hard Negatives 3 per query
Adapter Size ~9MB

Usage

Installation

pip install -U sentence-transformers peft

Inference

from sentence_transformers import SentenceTransformer

# 모델 로드
model = SentenceTransformer("kmkeum/kiom-embedding-bge-m3")

# 문장 인코딩
sentences = [
    "두통(頭痛)",
    "머리가 아픈 증상",
    "복통(腹痛)",
]
embeddings = model.encode(sentences)

# 유사도 계산
similarities = model.similarity(embeddings, embeddings)
print(similarities)
# 두통-머리가 아픈 증상: 높은 유사도
# 두통-복통: 낮은 유사도

With PEFT (Low-level)

from transformers import AutoModel, AutoTokenizer
from peft import PeftModel

base_model = AutoModel.from_pretrained("BAAI/bge-m3")
model = PeftModel.from_pretrained(base_model, "kmkeum/kiom-embedding-bge-m3")
tokenizer = AutoTokenizer.from_pretrained("kmkeum/kiom-embedding-bge-m3")

Evaluation Results

13개 SOTA 임베딩 모델과 전체 테스트셋(25,223건 × 3포맷)으로 비교 평가하였습니다.

Average (3포맷 평균)

Rank Model MRR@10 Recall@10 NDCG@10 Sim_Gap
1 kiom-embedding-bge-m3 (Ours) 0.9002 0.9952 0.9230 0.5221
2 Octen-Embedding-8B 0.7887 0.9897 0.8365 0.2352
3 BGE-m3 (Base) 0.7285 0.9757 0.7864 0.1719
4 OpenAI text-embedding-3-large 0.7258 0.9806 0.7859 0.1955
5 Gemini Embedding 0.8023 0.9890 0.8464 0.1329
6 KaLM-Gemma3-12B 0.7526 0.9847 0.8073 0.1237
7 Qwen3-Embedding-4B 0.7121 0.9815 0.7758 0.1531
8 Qwen3-Embedding-8B 0.7067 0.9831 0.7720 0.1454
9 E5-large-instruct 0.6930 0.9787 0.7601 0.0348
10 Qwen3-Embedding-0.6B 0.6844 0.9775 0.7535 0.1415
11 NVIDIA Nemotron-8B 0.6622 0.9761 0.7360 0.1024
12 KLUE-SBERT (Huffon) 0.5980 0.9697 0.6848 0.1744
13 KLUE-SBERT 0.5562 0.9647 0.6515 0.1416
14 KoSimCSE-RoBERTa 0.5427 0.9629 0.6405 0.1372

Both (한글+한자 병기)

Model MRR@10 Recall@1 Recall@10 NDCG@10 Sim_Gap
Ours 0.9135 0.8747 0.9960 0.9333 0.5517
BGE-m3 0.7579 0.6779 0.9776 0.8092 0.1728
OpenAI 0.7660 0.6759 0.9844 0.8177 0.2140

Korean (한글만)

Model MRR@10 Recall@1 Recall@10 NDCG@10 Sim_Gap
Ours 0.8801 0.8269 0.9943 0.9075 0.4693
BGE-m3 0.6648 0.5551 0.9688 0.7358 0.1490
OpenAI 0.6416 0.5173 0.9718 0.7191 0.1422

Chinese (한자만)

Model MRR@10 Recall@1 Recall@10 NDCG@10 Sim_Gap
Ours 0.9070 0.8656 0.9954 0.9282 0.5453
BGE-m3 0.7629 0.6774 0.9808 0.8142 0.1940
OpenAI 0.7697 0.6811 0.9856 0.8208 0.2302

Training Data

Overview

한국한의학연구원(KIOM)의 한의학 온톨로지 및 용어 데이터(JSON 15개 + Excel 3개)에서 10가지 유형의 positive pair를 생성하고, 온톨로지 기반 하드 네거티브를 추가한 뒤, 3가지 텍스트 포맷으로 변환하여 학습 데이터를 구축하였습니다.

Raw Data Sources

카테고리 파일 건수 주요 필드
동유의어 (Excel) 동유의어.xlsx 4,869건 동의어 그룹 ID, 한글명, 한자명
표준한의학용어집 (Excel) 표준한의학용어집.xlsx 9,074건 한글, 한자, 정의설명, 동의어(마침표 구분)
일반인용어사전 (Excel) 일반인용어사전.xlsx 20,379건 한글, 한자, 설명
병증 (JSON × 5) 간계/비계/신계/심계/폐계 내과학병증 각 ~127건 한글명, 한자명, 증상, 맥, 설, 치법, 처방
처방 (JSON × 5) 간계/비계/신계/심계/폐계 내과학처방 각 ~425건 한글명, 한자명, 주치, 구성약재
참고서 (JSON × 3) 동의방제와처방해설, 방약합편, 방제학 다수 처방과 동일 구조
약재 (JSON × 1) 약재.json 4,400건 한글명, 한자명, 성, 미, 귀경, 효능, 주치
병리 (JSON × 1) 한방병리학.json 393건 한글명, 한자명, 증후개념/분석, 주/차증상, 치법, 처방, 상용약물

Step 1: Positive Pair Generation (10 Types)

# 유형 소스 건수 생성 방법
1 동의어 쌍 동유의어.xlsx 20,004 같은 그룹 내 모든 용어의 양방향 조합 (A↔B)
2 표준용어 동의어 쌍 표준한의학용어집.xlsx 56,650 주용어 + 마침표 구분 동의어 간 전체 양방향 조합
3 용어-정의 쌍 일반인용어사전.xlsx 20,378 용어 → 일반인용 설명 (단방향)
4 표준용어-정의 쌍 표준한의학용어집.xlsx 9,074 용어 → 정의설명 (단방향)
5 질환-증상 쌍 병증 JSON 5개 5,495 질환 → 개별 증상/맥/설 (이름: 설명 형태)
6 질환-치법 쌍 병증 JSON 5개 902 질환 → 치법 (이름: 설명 형태)
7 처방-주치 쌍 처방+참고서 JSON 8개 5,227 처방 → 주치 목록 결합 텍스트
8 처방-구성약재 쌍 처방+참고서 JSON 8개 5,590 처방 → 구성약재 리스트 (쉼표 결합)
9 약재-효능/주치 쌍 약재.json 1,706 약재 → 효능/주치/성미귀경 (3종 각각)
10 병리패턴 쌍 한방병리학.json 1,089 패턴 → 증후개념/분석/주증상/차증상/치법 (5종 각각)
합계 126,115
Positive Pair 생성 예시 (클릭하여 펼치기)

유형 1 (동의어):

{"query": "자락법(刺絡法)", "pos": ["자락(刺絡)"]}
{"query": "자락(刺絡)", "pos": ["자락법(刺絡法)"]}

유형 3 (용어-정의):

{"query": "고열번갈(高熱煩渴)", "pos": ["열이 높고 갈증이 심한 증상"]}

유형 5 (질환-증상):

{"query": "열독황달(熱毒黃疸)", "pos": ["두훈목현(頭暈目眩): 머리가 어지럽고 눈앞이 아찔한 것"]}

유형 7 (처방-주치):

{"query": "청온패독음(淸瘟敗毒飮)", "pos": ["대열갈음: 열이 많이 나고 갈증이 나서 물을 많이 마시는 것. 두통여벽: 머리가 쪼개질 듯이 아픈 것. ..."]}

유형 8 (처방-구성약재):

{"query": "해독정기탕(解毒正氣湯)", "pos": ["창출(蒼朮) 7.5g, 갈근(葛根) 7.5g, ..."]}

유형 9 (약재-성미귀경):

{"query": "한채(蔊菜)", "pos": ["성: 平. 미: 苦, 辛. 귀경: 肝, 肺"]}

Step 2: Hard Negative Mining (Ontology-aware)

단순 랜덤 네거티브가 아닌, 통합 온톨로지 그래프를 구축하여 의미적으로 관련된 텍스트를 배제한 뒤 하드 네거티브를 선택합니다.

2-1. 통합 온톨로지 그래프 구축

모든 원본 데이터를 하나의 지식 그래프로 통합합니다:

Ontology Graph:
  entity_texts:      엔티티 → {관련 텍스트들}     (질환→증상, 처방→주치 등)
  entity_links:      엔티티 → {연결된 엔티티들}   (질환↔처방, 처방↔약재, 병리↔질병 등)
  text_to_entities:  텍스트 → {소속 엔티티들}     (역인덱스)
  • 동의어 관계: 같은 그룹 내 용어 간 양방향 link
  • 질환-처방 관계: 병증 데이터에서 질환↔처방 link
  • 처방-약재 관계: 처방 데이터에서 처방↔구성약재 link
  • 병리-질병/처방/약재 관계: 한방병리학에서 다중 link

2-2. 배제 집합(Exclusion Set) 계산

주어진 텍스트에서 2-hop 이내의 모든 관련 텍스트를 수집하여 네거티브 후보에서 제외합니다:

예: query = "간열두통(肝熱頭痛)"
  → 1-hop: 이 질환의 증상, 치법, 맥, 설 텍스트
  → 2-hop: 연결된 처방의 주치, 구성약재
  → 모두 네거티브에서 제외 (false negative 방지)

2-3. 네거티브 선택 전략 (Random 7 + Similarity 3)

각 pair에 대해 같은 type 내의 positive 텍스트 풀에서:

방법 개수 설명
랜덤 네거티브 7개 온톨로지 배제 후 남은 후보에서 랜덤 샘플링
유사도 기반 하드 네거티브 3개 BGE-m3로 코사인 유사도 계산 → 0.4~0.6 범위에서 선택
(너무 유사하면 false negative, 너무 다르면 쉬운 네거티브)
  • 유사도 범위 내 후보가 부족하면 가용한 만큼 사용 + 랜덤 보충
  • 최종 네거티브: pair당 10개

Step 3: Text Format Transformation (3 Versions)

원본은 한글한자 병기 형태이며, 정규표현식으로 2가지 추가 포맷을 생성합니다:

포맷 변환 규칙 예시
Both (병기) 원본 그대로 고열번갈(高熱煩渴)
Korean (한글만) \(漢字+\) 제거 고열번갈
Chinese (한자만) 한글(漢字)漢字 치환 高熱煩渴

query, pos, neg 모든 필드에 동일 변환을 적용하여 포맷별 파일을 각각 생성합니다.

Step 4: Train/Test Split

단계 설명
셔플 행 인덱스를 seed=42로 랜덤 셔플 (3포맷 동일 인덱스 유지)
분할 80% 학습 / 20% 테스트
학습 파일 3포맷 합본 → unified_train.jsonl (302,676건 = 100,892 × 3)
테스트 파일 포맷별 분리 → test_both/korean/chinese.jsonl (각 25,223건)
합본 셔플 학습 데이터 합본 후 재셔플하여 포맷이 골고루 섞이도록

Final JSONL Format

{
  "query": "자락법(刺絡法)",
  "pos": ["자락(刺絡)"],
  "neg": ["반관맥(反關脈)", "경맥(經脈)", "대추(大椎)", "합곡(合谷)", "침구(鍼灸)", "맥진(脈診)", "보법(補法)", "족삼리(足三里)", "사관혈(四關穴)", "위중(委中)"]
}

Data Scale Summary

Raw Data (18 files) → 126,115 positive pairs (10 types)
  ↓ Ontology-aware hard negative mining (random 7 + similarity 3 = 10/pair)
  ↓ 3 text format transformations (Both / Korean / Chinese)
  ↓ 126,115 × 3 = 378,345 total samples
  ↓ 80/20 train-test split
Train: 302,676 samples (3-format unified, shuffled)
Test:  25,223 × 3 formats (format-separated)

Training Environment

항목
GPU NVIDIA RTX PRO 6000 Blackwell (96GB VRAM)
Framework sentence-transformers 5.2.2, PEFT 0.18.1
PyTorch 2.10.0+cu128
Precision bf16

Architecture

SentenceTransformer(
  (0): Transformer({'max_seq_length': 256, 'do_lower_case': False, 'architecture': 'XLMRobertaModel'})
       + LoRA(r=16, alpha=32, target=['query', 'key', 'value'])
  (1): Pooling({'pooling_mode_cls_token': True})
  (2): Normalize()
)

Intended Use

  • 한의학 용어 검색 및 의미 유사도 계산
  • RAG(Retrieval-Augmented Generation) 시스템의 한의학 도메인 리트리버
  • 한의학 문헌 클러스터링 및 분류
  • 한의학 지식 그래프 구축 지원

Limitations

  • 한의학 도메인에 특화되어 일반 도메인 성능은 베이스 모델보다 낮을 수 있음
  • 최대 256 토큰까지 지원 (긴 문서는 청크 분할 필요)
  • 한국어/한자 중심, 영어 의학 용어에 대한 성능은 미검증

Citation

@misc{kiom-embedding-bge-m3,
  title={Korean Medicine Embedding Model based on BGE-m3},
  author={Korea Institute of Oriental Medicine (KIOM)},
  year={2026},
  url={https://huggingface.co/kmkeum/kiom-embedding-bge-m3}
}

Acknowledgments

  • Base model: BAAI/bge-m3
  • Data source: 한국한의학연구원(KIOM) 한의학 온톨로지
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for kmkeum/kiom-embedding-bge-m3

Base model

BAAI/bge-m3
Adapter
(5)
this model