# Retrieval metric toy — 실행 범위와 검산

이 예제는 사람이 정한 2차원 vector, relevance grade, reranker score로 **exact cosine 검색과 frozen-candidate 평가의 규약**을 검산합니다. 모델 학습, 한국어 embedding 성능, GPU latency, ANN, RAG 답변 품질을 측정하지 않습니다. 출력의 개선량은 의도적으로 구성한 예시 데이터의 계산 결과입니다.

## 실행

같은 폴더에 [retrieval-toy.mjs](./retrieval-toy.mjs), [fixture.json](./fixture.json), [expected.json](./expected.json)을 저장합니다. Node.js 20 이상이 필요하며 외부 패키지 설치나 API key, GPU는 필요 없습니다. 검증 환경은 Node.js 22.22.3입니다.

```bash
node retrieval-toy.mjs
```

다른 fixture를 실험하려면 `node retrieval-toy.mjs my-fixture.json`처럼 경로를 전달합니다. 저장소 안에서는 다음 명령으로 실행과 회귀 검사를 할 수 있습니다.

```bash
node public/examples/research/retrieval-toy.mjs
node --test tests/researchExamples.test.mjs
```

## 평가 계약

- Corpus 문서 4개 전체를 cosine으로 비교해 query별 후보 2개를 고릅니다. 동일 score는 document ID의 오름차순으로 정합니다.
- Reranker는 fixture의 수동 score로 **같은 후보 두 개의 순서만** 바꿉니다. 후보 밖 문서를 추가하지 않습니다.
- `Recall@2`의 분모는 corpus 전체 qrel에서 grade가 양수인 문서 수입니다. nDCG@2는 `gain=2^grade−1`, `discount=log2(rank+1)`을 쓰며 IDCG도 corpus 전체 qrel로 계산합니다.
- Qrel에 없는 문서는 이 닫힌 toy에서 grade 0으로 취급합니다. 실제 pooling 평가의 unjudged가 irrelevant라는 뜻은 아닙니다.
- Positive qrel이 없는 query는 metric을 `null`로 반환하고 relevance macro 평균에서 제외하되 건수를 별도 표시합니다. No-answer 답변의 정확도를 측정한 결과는 아닙니다.
- Paired delta는 같은 query의 차이를 평균합니다. Query가 두 개뿐이므로 통계적 유의성이나 일반화를 주장하지 않습니다. 평균은 반올림 전 값으로 계산하고 출력만 소수점 여섯 자리로 반올림합니다.

## 기대 결과를 손으로 확인하기

1. q1의 후보는 `[d1,d2]`이고 qrel은 `d2:3, d3:1`입니다. Reranking은 `[d2,d1]`로 바꾸지만 d3가 후보에 없으므로 recall은 전후 모두 1/2입니다.
2. q1의 IDCG@2는 `7 + 1/log2(3)`입니다. Baseline DCG는 `7/log2(3)`, challenger DCG는 `7`이므로 challenger nDCG도 1보다 작습니다.
3. q2의 gold d4는 후보 `[d3,d2]` 밖에 있습니다. 어떤 reranker 순서도 이 후보 안에서는 recall과 nDCG를 0보다 높이지 못합니다.
4. q3에는 positive qrel이 없습니다. 이 예제는 q3를 제외하고 q1·q2 두 query로 평균을 계산합니다.

주요 출력은 다음과 같습니다. 전체 query별 출력은 `expected.json`과 비교합니다.

```json
{
  "evaluatedQueries": 2,
  "excludedNoPositiveQueries": 1,
  "candidateRecall": 0.25,
  "baselineNdcg": 0.289382,
  "challengerNdcg": 0.45866,
  "pairedNdcgDelta": 0.169278
}
```

이 작은 예제의 목적은 모델 성능 경쟁 전에 denominator, candidate ceiling, tie-breaking, no-positive 처리와 paired 비교가 같은 뜻인지 확인하는 것입니다. 실제 모델 실험에서는 별도로 데이터·모델 revision·dependency lock·hardware·실행 로그를 제공해야 합니다.
