AI 변형 파이프라인 — 1제 → 3제 증식 + 검수 자동화

목적

외주 강사 납품분 1,500제(initial pool) → AI 변형 3배 증식 → 검수 통과분 ~4,500제(final pool) 확보. P0 베타 출시 시 학생당 콘텐츠 풀이 충분하도록.

자가 검토 (작성자 점검)

본 파이프라인의 안전 장치:

  • 수학적 오류 차단: LLM 셀프 체크 + 사람 5% 샘플 + 학생 시범 풀이 3중
  • 저작권 보호: 변형은 발주처 자산 (계약서 §8) — 강사에게 사전 통지
  • 비용 관리: Haiku 4.5 사용 (Sonnet 대비 1/12) → 4,500제 변형 비용 ~10만원 추정

1. 변형 종류 (3가지)

각 원본 1문항당 다음 3가지 변형 1개씩 생성:

Type V1: 수치 치환 (Number Substitution)

가장 안전한 변형. 정답·풀이 알고리즘 동일, 숫자만 변경.

예시:

  • 원본: 1.45 + 2.78 = ? → 변형: 2.36 + 3.59 = ?
  • 원본: 1/2 + 1/3 = ? → 변형: 1/4 + 1/5 = ?

위험: 변형 후 결과가 학년 학습 범위를 벗어나는 경우 (예: 초3에 약분 결과 등장)

Type V2: 맥락 치환 (Context Substitution)

일상 맥락 변경. 수학 구조는 동일.

예시:

  • 원본: 피자 6조각 중 2조각 → 변형: 케이크 6조각 중 2조각
  • 원본: 종이학 5마리/일 → 변형: 책 5쪽/일

위험: 학년·문화 부적절 맥락 (예: 초1에 주식·환율)

Type V3: 표현 치환 (Representation Substitution)

문제 표현 형식 변경. 수학 구조 동일.

예시:

  • 원본: 객관식 → 변형: 단답형 (정답을 직접 입력)
  • 원본: 표 형식 → 변형: 산문 형식 (“종이학을 매일 5마리씩…”)
  • 원본: 수치 → 변형: 도형 (분수를 그림으로)

위험: 표현 변형 시 난이도가 미세하게 바뀜 → 난이도 재검수 필요


2. 파이프라인 단계

[원본 1제 from RFP 강사 납품분]
        ↓
[Step 1: 모델 선택 — Haiku 4.5]
        ↓
[Step 2: 프롬프트 주입 — 변형 종류 V1/V2/V3]
        ↓
[Step 3: 변형 결과 생성 (1제 → 3제)]
        ↓
[Step 4: LLM 셀프 검증 — Sonnet으로 수학 정확성 체크]
        ↓
[Step 5: 자동 형식 검증 — 부록 E 11~15, 41~50번 자동화 가능 항목]
        ↓
[Step 6: 통과율 ≥ 95% → DB 저장 / 미만 → 인간 검수 큐]
        ↓
[Step 7: 5% 샘플 인간 검수 (강사 또는 발주처)]
        ↓
[Step 8: 베타 학생 시범 풀이 → 정답률·시간 측정 → 이상 발견 시 변형 폐기]

3. 프롬프트 (Step 2 — Haiku)

시스템 프롬프트

당신은 초등 수학 콘텐츠 변형 전문가입니다.

원본 문항 1개를 입력받아 동일한 학습 목표를 가진 변형 문항 3개를 생성합니다.
변형 종류 1개씩 균형 있게 생성하세요:
- V1 수치 치환: 숫자만 변경, 풀이 알고리즘 동일
- V2 맥락 치환: 일상 맥락 변경, 수학 구조 동일
- V3 표현 치환: 표현 형식 변경, 학습 목표 동일

원본 문항의 다음 메타데이터를 모두 유지:
- unit_id, grade, domain, difficulty, type

변형 후 다음을 보장:
1. 수학적 정확성 — 정답 도달 가능
2. 학년 적합성 — 해당 학년 학습 범위 내
3. 일상 맥락 적절성 — 학년·문화 적합
4. 보기 (객관식의 경우) 5개 모두 distinct + 학생 실수 패턴 1개 이상

출력은 JSON 형식:
{
  "variants": [
    { "type": "V1", "id": "<생성 ID>", ...원본과 동일 필드 },
    { "type": "V2", "id": "<생성 ID>", ... },
    { "type": "V3", "id": "<생성 ID>", ... }
  ]
}

유저 프롬프트 (예시)

원본 문항:

```yaml
id: "E5-1-2-MID-MC-007"
unit_id: "E5-1-2"
unit_path: "초5 > 1학기 > 약수와 배수"
domain: "NUM"
grade: "E5"
difficulty: "MID"
type: "MC"
body_md: |
  12의 약수를 모두 구하시오.
choices:
  - "1, 2, 3, 4, 6"
  - "1, 2, 3, 4, 6, 12"
  - "2, 3, 4, 6"
  - "1, 12"
  - "1, 2, 3, 6, 12"
answer_index: 1
solution_md: |
  12를 나누어떨어지게 하는 자연수가 약수입니다.
  $12 = 1 \times 12 = 2 \times 6 = 3 \times 4$
  따라서 약수는 1, 2, 3, 4, 6, 12.
tags: ["약수", "자연수"]
estimated_time_sec: 60

위 원본을 변형하여 V1 (수치 치환), V2 (맥락 치환), V3 (표현 치환) 1개씩 생성하세요.


### 변형 ID 명명 규칙

원본 ID에 `-V{1|2|3}` 접미사:
- 원본: `E5-1-2-MID-MC-007`
- 변형: `E5-1-2-MID-MC-007-V1`, `-V2`, `-V3`

---

## 4. LLM 셀프 검증 (Step 4 — Sonnet)

Haiku로 생성한 결과를 Sonnet으로 검증. Haiku가 빠르고 저렴하지만 수학 오류 가능성이 약간 더 높음.

### Sonnet 검증 프롬프트

다음 변형 문항이 수학적으로 정확한지 검증하세요.

[변형 문항 입력]

검증 항목 (RFP 부록 E 영역 2): 11. 정답이 수학적으로 옳음 — 직접 풀어 도달 가능? 12. 풀이 해설이 정답을 도출 — 단계별 논리 일관? 13. 풀이 단계 중 계산 오류 없음? 14. 객관식 답이 보기 중 정확히 1개? 15. LaTeX 수식이 의도한 의미를 표기?

각 항목에 PASS / FAIL 표기 + 실패 시 사유 명시.

추가 검증:

  • 학년 학습 범위 위반 여부
  • 보기 분포 자연스러움 (객관식)
  • estimated_time_sec 적절성

JSON 출력: { “verdict”: “PASS” | “FAIL”, “checks”: [{ “id”: 11, “result”: “PASS”/“FAIL”, “reason”: ”…” }, …], “additional”: { “out_of_scope”: false, … } }


### 통과 기준

- 영역 2 (5항목) **모두 PASS** → 자동 통과
- 1건이라도 FAIL → 인간 검수 큐로 이관

---

## 5. 자동 형식 검증 (Step 5 — Code-based)

LLM 호출 없이 코드로 검증할 수 있는 항목 (부록 E 영역 5):

```python
def validate_format(variant):
    checks = {
        # 메타데이터
        "id_regex": bool(re.match(r"^E[1-6]-[12]-[1-6]-(LOW|MID|HIGH)-(MC|SA|DE)-[0-9]{3}-V[1-3]$", variant["id"])),
        "unit_exists": variant["unit_id"] in known_unit_ids,
        "domain_match": variant["domain"] == unit_to_domain[variant["unit_id"]],
        # 길이
        "body_under_1000": len(variant["body_md"]) <= 1000,
        "solution_under_2000": len(variant["solution_md"]) <= 2000,
        # 객관식 구조
        "mc_5_choices": len(variant.get("choices", [])) == 5 if variant["type"] == "MC" else True,
        "answer_index_in_range": 0 <= variant.get("answer_index", -1) <= 4 if variant["type"] == "MC" else True,
        # 시간 추정
        "time_in_range": time_range_for(variant["grade"], variant["difficulty"])[0] <= variant["estimated_time_sec"] <= time_range_for(...)[1],
        # 태그
        "tags_3_to_7": 3 <= len(variant.get("tags", [])) <= 7,
        # YAML 인코딩
        "valid_utf8": is_valid_utf8(variant),
    }
    return all(checks.values()), checks

6. 인간 검수 큐 (Step 7)

다음 조건에 해당하는 변형은 자동 통과 X, 인간 검수 큐로:

  1. Step 4 LLM 셀프 검증 FAIL
  2. Step 5 자동 형식 검증 FAIL
  3. 무작위 5% 샘플 — 모든 단계 통과해도 5% 검수 (RFP §5 3단계와 동일)
  4. 고난이도 (HIGH) 변형 — 100% 인간 검수 (실수 비용이 큼)
  5. 서술형 (DE) 변형 — 100% 인간 검수 (rubric 검증 필요)

검수자 인터페이스 권장

  • 원본 vs 변형 좌우 비교 뷰
  • 검수 결과: PASS / FAIL / EDIT (수정 후 PASS)
  • 검수 시간 기록 → SLA 관리 (1건 평균 90초 목표)

7. 베타 학생 시범 풀이 (Step 8)

베타 출시 후 변형 문항이 풀이될 때 메트릭 자동 수집:

지표임계값위반 시
정답률< 20% 또는 > 95%변형 폐기 또는 난이도 재분류
평균 풀이시간> estimated × 2 또는 < estimated × 0.3estimated_time_sec 갱신
학생 신고”이 문제 이상해요” 버튼인간 재검수 큐
보기 선택 분포 (MC)정답에 < 30% 집중보기 재구성

자동 폐기되는 변형은 Question.status = 'archived'. 학습지 추천에서 제외.


8. 비용 추정

Haiku (Step 2 변형 생성)

  • 입력: 원본 1제 + 시스템 프롬프트 ≈ 1,500 토큰
  • 출력: 변형 3제 + 메타 ≈ 3,000 토큰
  • Haiku 4.5 가격: 1.25/M 출력
  • 1제당 비용: 0.00375 = $0.0041 ≈ 6원
  • 1,500제 변형: ~9,000원 (= 약 1만원)

Sonnet (Step 4 셀프 검증)

  • 입력: 변형 1제 + 검증 프롬프트 ≈ 2,000 토큰
  • 출력: PASS/FAIL JSON ≈ 500 토큰
  • Sonnet 4.6 가격: 15/M 출력
  • 1제당 비용: 0.0075 = $0.0135 ≈ 19원
  • 4,500 변형 검증: ~85,500원 (= 약 9만원)

인간 검수 비용

  • 5% 샘플 + HIGH·DE 100% ≈ 500제
  • 1제당 90초 × 외주 강사 시급 30,000원 = 750원
  • 500제 검수: ~37만원

총 변형 파이프라인 비용

1만 + 9만 + 37만 = 약 47만원

이는 단위 경제 v0.1 §2.5 추정에 추가 — 일회성 비용이라 단가에 분산 불필요.


9. 운영 체크리스트

P0 출시 전:

  • Haiku·Sonnet API 키 획득 + 비용 limit 설정
  • 변형 생성 스크립트 (Python) 작성
  • 자동 형식 검증 코드 (Step 5) 작성
  • 인간 검수 인터페이스 (Notion DB 또는 simple web app)
  • 베타 메트릭 수집 (Supabase RLS·Edge Function)

P0 출시 후 (운영):

  • 매주 변형 통계 (생성·통과·폐기 건수)
  • 매월 비용 모니터링 (LLM API 사용량)
  • 분기별 프롬프트 개선 (실패 패턴 분석)

10. PRD v0.2 영향

본 파이프라인 결정으로 PRD v0.1 §2 데이터 모델에 다음 추가:

Question (기존)
  ...
  source: enum(self_made, ai_variant, public_link)
  source_question_id?: int      ← AI 변형의 원본 (이미 있음)
  variant_type?: enum(V1, V2, V3)  ← 신규
  ai_check_passed: boolean       ← 신규 (Step 4 통과 여부)
  human_reviewed: boolean        ← 신규 (Step 7 통과 여부)
  status: enum(draft, active, archived)  ← 확장 (기존 deprecated 추가)
  beta_metrics: jsonb?           ← 신규 (정답률·풀이시간·신고)

PRD v0.2에 본 파이프라인 §2~§7을 §3.5(콘텐츠 풀 운영)로 통합 권장.