Field Log · Entry
Reranker 학습 데이터: Positive·Hard Negative·False Negative (7/14)
이번 글의 결론
- Reranker는 random corpus가 아니라 first-stage retriever가 실제로 헷갈리는 후보 분포에서 학습해야 합니다.
- Hard negative는 단순히 score가 높은 negative가 아닙니다. 잘못된 entity·attribute·version·authority처럼 production failure를 대표하면서 실제로는 negative임을 확인한 후보입니다.
- Gold를 candidate에 강제로 넣을 수는 있지만
gold_injected=true를 남겨야 retrieval miss와 reranker training을 혼동하지 않습니다.- 미라벨 문서를 negative로 간주하면 false negative가 됩니다. Harder mining일수록 positive를 더 잘 찾는 역설이 있어 relabeling과 uncertainty 처리가 필요합니다.
- Dataset에는 text뿐 아니라 retriever·corpus·label rubric·teacher·split version이 들어가야 재현과 rollback이 가능합니다.
앞 글까지 model이 후보를 어떻게 읽는지 살폈습니다. 하지만 같은 architecture라도 어떤 후보를 보여 주느냐에 따라 전혀 다른 ranker가 됩니다.
easy random negatives
→ "주제가 같은가?"만 배움
production hard candidates
→ "같은 주제 안에서 entity·status·answer support가 맞는가?"를 배움
Reranker data engineering의 핵심은 example 수보다 confusion의 질과 provenance입니다.
1. 학습 단위는 Query와 Candidate List다
최소 record는 다음 정보를 가져야 합니다.
type RankingExample = {
queryId: string;
query: string;
queryMetadata: {
language: string;
domain: string;
intent: string;
timestamp?: string;
};
candidates: Array<{
documentId: string;
text: string;
documentVersion: string;
retrievalRank: number | null;
retrievalScore: number | null;
retrievalChannels: string[];
relevanceGrade: 0 | 1 | 2 | 3 | null;
labelSource: "human" | "behavior" | "teacher" | "synthetic" | null;
labelConfidence: number | null;
goldInjected: boolean;
}>;
retrieverVersion: string;
corpusVersion: string;
rubricVersion: string;
split: "train" | "validation" | "test";
};
retrievalRank=null과 goldInjected=true는 해당 문서가 원래 candidate에 없었다는 뜻입니다. 이 사실을 숨기지 않습니다.
2. Label Rubric부터 쓴다
“관련 있음”은 annotator마다 다르게 해석될 수 있습니다. RAG용 예시는 다음처럼 정할 수 있습니다.
| grade | 의미 | 예 |
|---|---|---|
| 3 | 질문에 직접 답하고 사용할 수 있는 authoritative evidence | 승인된 S2 manual의 88°C 문장 |
| 2 | 답의 일부·필수 연결 근거 또는 강한 supporting context | S2가 어떤 controller인지 설명 |
| 1 | topic은 관련 있지만 답을 지지하지 않음 | S2 일반 운용 범위 |
| 0 | 무관하거나 조건을 위반 | S1, draft, pressure, contradiction |
Query 시점과 사용자 권한도 Label 문맥이다
query timestamp: 2026-07-20
document valid_to: 2025-12-31
현재 정책 질문에는 outdated일 수 있지만 역사 질문에는 relevant합니다. Tenant-private 문서는 relevance와 별개로 접근 불가입니다. Security filter를 grade에 녹여 숨기기보다 별도 field로 관리합니다.
Multi-hop은 개별 Grade만으로 부족하다
두 passage를 함께 써야 답할 수 있다면 evidence set ID를 둡니다.
{
"document_id": "acquisition-record",
"relevance_grade": 2,
"evidence_sets": ["set-a"]
}
{
"document_id": "support-policy-b",
"relevance_grade": 2,
"evidence_sets": ["set-a"]
}
두 문서가 함께 grade 3의 answer utility를 만들 수 있습니다. Pointwise label만으로는 이 complementarity를 표현하기 어렵습니다.
3. Positive는 어디서 오는가
Human Qrels
Query-document 관계를 사람이 판정합니다. 가장 직접적이지만 비용과 disagreement가 있습니다.
기록할 값:
- annotator ID 또는 pool
- annotation timestamp
- rubric version
- confidence
- adjudication 여부
- disagreement distribution
Answer Citation과 Support
기존 QA 답변에 연결된 source passage를 positive로 쓸 수 있습니다. Citation이 붙었다는 사실만으로 claim을 실제 지지하는지는 별도 entailment 검사가 필요합니다.
Behavior Signal
Click, dwell time, save, purchase, issue resolution을 쓸 수 있습니다. Position·exposure·UI·brand bias를 제거하지 않으면 popularity ranker를 학습할 수 있습니다.
Teacher Label
강한 Cross-Encoder나 LLM이 grade·preference를 생성합니다. 빠르게 확장할 수 있지만 teacher bias와 prompt artifact가 student로 전달됩니다.
Synthetic Query
문서에서 답 가능한 query를 생성해 해당 문서를 positive로 둡니다. Query가 passage 문구를 그대로 복사하면 lexically easy data가 됩니다. 실제 query style과 difficulty를 제어합니다.
4. Random Negative가 약한 이유
Query: S2 emergency shutdown temperature
Random negative:
사내 식당 7월 메뉴
Model은 S2, shutdown, temperature 같은 표면 단서만 찾아도 맞힙니다. Production에서는 first-stage retriever가 이런 문서를 거의 top-100에 넣지 않습니다.
실제 negative는 다음처럼 생깁니다.
same product, wrong attribute
same attribute, wrong product
same answer number, wrong unit
same policy, outdated version
same title, draft instead of approved
keyword present inside a negated sentence
partial evidence without the answer
secondary commentary instead of primary source
OCR-corrupted near match
Reranker가 배워야 할 decision boundary에 가깝습니다.
5. Hard Negative의 분류표
| type | positive와 공유하는 것 | 다른 핵심 |
|---|---|---|
| Lexical hard | exact keyword | 질문 의도 |
| Semantic hard | paraphrased topic | answer 없음 |
| Entity hard | 제품군·이름 | entity ID·version |
| Attribute hard | entity·event | temperature vs pressure |
| Temporal hard | policy topic | current vs expired |
| Authority hard | 주장 내용 | primary vs unofficial |
| Negation hard | 거의 같은 문장 | polarity |
| Numerical hard | 숫자·단위 | value·unit·range |
| Partial evidence | 일부 사실 | 필요한 연결 근거 누락 |
| Contradiction | 질문과 직접 관련 | 반대 사실·폐기된 주장 |
| Multilingual hard | 같은 의미권 | translation·code-switch 오류 |
| Layout/OCR hard | 시각적으로 같은 page | 잘못 추출된 cell·column |
Dataset manifest에 negative type을 붙이면 slice evaluation과 targeted augmentation이 가능합니다.
6. Production Retriever에서 Mine한다
가장 직접적인 흐름입니다.
from dataclasses import dataclass
@dataclass(frozen=True)
class Query:
query_id: str
text: str
def mine_candidates(query, retriever, judgments, *, depth=100):
hits = retriever.search(query.text, k=depth)
rows = []
for hit in hits:
judgment = judgments.get((query.query_id, hit.document_id))
rows.append(
{
"document_id": hit.document_id,
"text": hit.text,
"retrieval_rank": hit.rank,
"retrieval_score": hit.score,
"retrieval_channels": hit.channels,
"relevance_grade": None if judgment is None else judgment.grade,
"label_source": None if judgment is None else judgment.source,
"gold_injected": False,
}
)
return rows
중요한 점은 judgment is None을 grade 0으로 바꾸지 않는 것입니다. Unjudged는 irrelevant가 아닙니다.
7. 한 Retriever의 Negative에 과적합하지 않는다
BM25는 lexical near-miss를, dense retriever는 semantic near-miss를, hybrid는 둘의 혼합을 만듭니다.
BM25 candidates
+ dense candidates
+ learned sparse candidates
+ previous reranker mistakes
→ deduplicate
→ judge / sample
HYRR 연구는 hybrid retriever로 training data를 선택해 서로 다른 first-stage retriever와 domain에 더 robust한 reranker를 만드는 방향을 제안했습니다.
Candidate source 비율을 기록합니다.
negative_mix:
bm25_top: 0.25
dense_top: 0.25
hybrid_unique: 0.20
prior_reranker_errors: 0.20
random_easy: 0.10
Random easy negative를 완전히 버릴 필요는 없습니다. Basic topic boundary와 안정적인 curriculum에 유용할 수 있지만 hard candidate를 대체하지 않습니다.
8. Injected Gold를 숨기지 않는다
Retriever가 gold를 top-100에 넣지 못했는데 positive 없는 list로는 ranking loss를 만들기 어렵습니다. Gold를 강제로 추가할 수 있습니다.
def ensure_positive(rows, gold_documents):
if any((row["relevance_grade"] or 0) > 0 for row in rows):
return rows
gold = gold_documents[0]
return rows + [
{
"document_id": gold.document_id,
"text": gold.text,
"retrieval_rank": None,
"retrieval_score": None,
"retrieval_channels": [],
"relevance_grade": gold.grade,
"label_source": gold.label_source,
"gold_injected": True,
}
]
하지만 비율을 report합니다.
organic positive rate: 78%
injected positive rate: 22%
Injected list가 너무 많으면 training은 가능해도 serving distribution과 멀어집니다. First-stage retriever부터 개선해야 한다는 신호입니다.
9. False Negative가 Hard Mining에서 커진다
Retriever top-k의 미라벨 후보를 모두 0으로 두면 실제 relevant passage도 negative로 학습됩니다.
Harder retriever일수록 relevant but unjudged 문서를 더 많이 발견할 수 있습니다.
strong retriever
→ annotation pool 밖의 relevant document 발견
→ unjudged를 0으로 처리
→ false negative 증가
2025년 Hard Negatives, Hard Lessons 연구는 대규모 retrieval data의 false negative를 재검토하고 relabeling이 in-domain·out-of-domain 성능을 개선할 수 있음을 보고했습니다.
대응 방법
- Top uncertain candidates를 human review합니다.
- 여러 teacher의 agreement를 사용합니다.
- Positive와 near-duplicate인 후보를 자동 negative에서 제외합니다.
- Unjudged는 mask하고 confirmed negative만 loss에 넣습니다.
- Soft label과 confidence weight를 사용합니다.
- Pooling depth를 늘려 evaluation qrel도 보강합니다.
loss weight = label confidence × sampling weight
Teacher가 확신하지 못하는 example을 hard negative라는 이유로 큰 weight로 주지 않습니다.
10. Duplicate와 Near-duplicate를 다룬다
같은 내용의 HTML, PDF, translation, version이 여러 document ID로 존재할 수 있습니다.
Training 문제
- Positive의 duplicate를 negative로 잘못 둡니다.
- 거의 같은 문서를 여러 번 넣어 list diversity를 왜곡합니다.
- Train과 test에 같은 template가 들어가 leakage가 생깁니다.
Serving 문제
- Reranker가 상위 5개를 같은 내용으로 채웁니다.
- nDCG는 좋아도 RAG evidence coverage가 낮습니다.
Content hash, canonical document ID, semantic duplicate cluster를 보존합니다.
{
"document_id": "manual-s2-v4-html",
"canonical_id": "manual-s2-v4",
"duplicate_cluster": "dup-8831"
}
Split은 cluster 단위로 나눕니다.
11. Synthetic Label Pipeline
Human label이 부족하면 teacher를 사용하되 여러 gate를 둡니다.
source documents
→ query generation
→ answerability check
→ candidate retrieval
→ teacher graded judgments
→ contradiction / duplicate audit
→ confidence filter
→ small human sample audit
Query 생성 Contract
query_generation:
intents:
- exact_fact
- comparison
- temporal
- troubleshooting
- multi_hop
language_mix:
ko: 0.70
ko_en_code_switch: 0.20
en: 0.10
forbidden:
- copy_full_answer_sentence
- mention_document_title_without_user_reason
Teacher Label Contract
Teacher에게 answer를 생성하게 하고 그럴듯함으로 grade를 정하지 않습니다. Passage가 query를 실제로 지지하는지 evidence span과 함께 판정하도록 합니다.
{
"grade": 3,
"evidence_spans": [
{"start": 418, "end": 487}
],
"reason_code": "direct_answer_current_primary_source",
"confidence": 0.91
}
Free-form rationale는 audit 보조물이지 label truth 자체가 아닙니다.
12. Active Learning으로 Label Budget을 쓴다
모든 candidate를 같은 비용으로 annotation할 필요는 없습니다.
우선순위 후보:
- current model score가 비슷한 top-rank pair
- 여러 reranker의 순위 disagreement가 큰 문서
- teacher confidence가 낮은 candidate
- 새 domain·language·document type
- online bad case와 user escalation
- high-traffic query의 rank flip
uncertainty
+ expected metric impact
+ traffic weight
+ slice coverage
→ annotation priority
단순 uncertainty만 고르면 모두 같은 edge case일 수 있습니다. Diversity constraint를 둡니다.
13. Retriever가 바뀌면 Replay한다
새 retriever는 다른 negative distribution을 만듭니다.
retriever v1
→ lexical confusions
retriever v2
→ semantically close, answerless confusions
Reranker가 v1 후보에서만 학습됐다면 v2의 hard negative를 못 다룰 수 있습니다.
Release 절차:
- 새 retriever로 train query를 replay합니다.
- 새 unique candidate와 rank movement를 분석합니다.
- 기존 label을 join하고 unjudged top candidate를 audit합니다.
- Old+new candidate mix에서 current reranker를 평가합니다.
- 필요한 confusion만 추가 학습합니다.
항상 처음부터 재학습할 필요는 없지만 distribution shift를 측정해야 합니다.
14. Split 설계
Random Query Split
가장 단순하지만 template·entity leakage를 놓칠 수 있습니다.
Time Split
과거 query·document로 학습하고 미래 data로 평가합니다. Freshness와 production drift를 반영합니다.
Domain Holdout
한 제품군·고객·업무 domain을 통째로 test에 둡니다. Zero-shot transfer를 봅니다.
Document-family Holdout
같은 manual의 다른 version이 train·test에 갈라지지 않게 합니다.
Query-template Holdout
Synthetic query generator가 만든 표현 pattern을 분리합니다.
최종 test는 model selection 과정에서 반복해서 들여다보지 않습니다. Validation leaderboard 최적화가 test leakage로 바뀌지 않게 합니다.
15. Dataset Manifest
ranking_dataset:
id: support-reranker-ds-v12
created_at: 2026-07-20
corpus_version: support-corpus-v181
retrievers:
- bm25-v8
- dense-v14
- hybrid-rrf-v6
query_split: time-and-product-holdout-v3
rubric: answer-support-rubric-v4
grades: [0, 1, 2, 3]
label_sources:
human: 18420
teacher: 91000
behavior: 22000
candidates:
organic_positive_rate: 0.81
injected_positive_rate: 0.19
unjudged_rate: 0.23
duplicate_policy: canonical-cluster-v2
teacher:
model: PINNED_MODEL
prompt: judgment-prompt-v7
Count뿐 아니라 분포를 report합니다.
queries by language / domain / intent
grades per query
negative types
candidate rank of first positive
document token lengths
label confidence and disagreement
16. Data Audit 체크리스트
- Candidate가 실제 production retriever 또는 명시된 mixture에서 왔다.
- Unjudged를 자동으로 0으로 바꾸지 않는다.
- Injected gold를 별도 표시하고 비율을 보고한다.
- Graded rubric이 answer support·freshness·authority를 정의한다.
- Hard negative type이 production failure를 대표한다.
- False negative audit sample이 있다.
- Duplicate cluster를 train·test에 걸쳐 분리했다.
- Synthetic query가 source 문장을 그대로 복사하는 비율을 측정했다.
- Teacher model·prompt·revision을 고정했다.
- Retriever update 때 candidate replay 절차가 있다.
- Test set을 반복적인 model selection에 사용하지 않는다.
스스로 확인하기
- Random negative만으로 학습한 reranker가 production top-k에서 약한 이유는 무엇인가?
- Strong retriever가 오히려 false negative를 늘릴 수 있는 이유는 무엇인가?
- Gold를 candidate list에 강제로 넣을 때 어떤 metadata를 남겨야 하는가?
- BM25와 dense candidate를 함께 mine하면 어떤 robustness를 기대할 수 있는가?
- Query split 외에 document-family split이 필요한 상황은 언제인가?
다음 글에서는 이 dataset으로 pointwise·pairwise·listwise loss를 구현하고, teacher distillation·multi-task·score calibration까지 연결합니다.
참고자료
- HYRR: Hybrid Infused Reranking for Passage Retrieval
- Towards Robust Ranker for Text Retrieval — R2anker
- Hard Negatives, Hard Lessons: Revisiting Training Data Quality for Robust Information Retrieval with LLMs
- RocketQAv2: Joint Training for Dense Passage Retrieval and Passage Re-ranking
- DocReRank: Hard Negative Query Generation for Multi-Modal RAG Rerankers