Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,13 @@ cython_debug/
# Ruff stuff:
.ruff_cache/

# Newsletter evaluation
reports/
data/newsletter-labels/*.pdf
data/newsletter-labels/*.jpg
data/newsletter-labels/*.jpeg
data/newsletter-labels/*.png

# PyPI configuration file
.pypirc

Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ Windows PowerShell에서는 다음처럼 가상환경을 활성화합니다.
- `POST /ai/newsletters/extract-items`: 날짜 후보 기반 baseline 항목 추출
- `POST /ai/newsletters/prompt-preview`: LLM 입력용 prompt와 최종 분석 response schema 미리보기

## 분석 평가

라벨링된 가정통신문 JSON으로 baseline 또는 OpenAI adapter 결과를 평가할 수 있습니다.

```powershell
python scripts/evaluate_newsletter_labels.py data/newsletter-labels --report-output reports/newsletter-eval-baseline.json
```

기본 모드는 비용이 발생하지 않는 baseline입니다. 실제 OpenAI 호출은 `--mode openai`를 명시한 경우에만 실행합니다.

## 작업 규칙

- 기본 브랜치: `develop`
Expand All @@ -45,3 +55,4 @@ Windows PowerShell에서는 다음처럼 가상환경을 활성화합니다.
- `docs/deploy.md`: Docker image와 EC2 배포 방식
- `docs/newsletter-extraction.md`: 가정통신문 분석 구현 경계와 유지 결정
- `docs/newsletter-labeling-guide.md`: 정답 데이터 라벨링 기준
- `docs/newsletter-evaluation.md`: 라벨링 데이터 기반 분석 평가 실행 방법
2 changes: 1 addition & 1 deletion app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def from_env(cls) -> "OpenAISettings":
return cls(
enabled=_read_bool("OPENAI_ENABLED", default=False),
api_key=_read_str("OPENAI_API_KEY"),
model=_read_str("OPENAI_MODEL", "gpt-4o-mini") or "gpt-4o-mini",
model=_read_str("OPENAI_MODEL", "gpt-4.1-mini") or "gpt-4.1-mini",
base_url=_read_str("OPENAI_BASE_URL", "https://api.openai.com/v1")
or "https://api.openai.com/v1",
timeout_seconds=_read_float("OPENAI_TIMEOUT_SECONDS", 60.0, min_value=0.001),
Expand Down
53 changes: 53 additions & 0 deletions data/newsletter-labels/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# 가정통신문 라벨링 데이터

이 디렉터리는 가정통신문 분석 평가에 사용하는 JSON 정답셋을 둔다.

## 파일 매칭

- JSON 파일명과 원본 파일명은 같은 번호를 사용한다.
- 예: `newsletter-001.json`의 원본은 `newsletter-001.pdf`
- 원본 파일 확장자는 `pdf`, `jpg`, `png`를 사용할 수 있다.
- `hwp`는 현재 파이프라인 입력으로 사용하지 않는다.

## 커밋 기준

- JSON 라벨 파일은 평가 재현을 위해 repo에 포함한다.
- PDF/JPG/PNG 원본은 로컬 검수와 Notion 공유용으로 유지하고 repo에는 포함하지 않는다.
- 원본이 필요하면 Notion 자료 또는 로컬 파일명 번호로 JSON과 매칭한다.

## 현재 JSON 스키마

현재 라벨 파일은 다음 구조를 사용한다.

```json
{
"documentId": "doc_001",
"documentTitle": "문서 제목",
"documentDate": "2026-03-24",
"school": "학교명",
"dateCandidates": [
{
"id": "dc_001_1",
"raw": "5월 20일",
"resolved": "2026-05-20",
"note": "제출 마감일"
}
],
"labels": [
{
"type": "schedule | deadline | checklist | reminder",
"title": "항목 제목",
"evidenceText": "원문 근거 텍스트",
"selectedDateCandidateId": "dc_001_1 또는 null",
"dateStatus": "confirmed | ambiguous | missing",
"date": "YYYY-MM-DD 또는 null",
"target": "parent | student | both",
"actionRequired": true,
"schoolContext": "학교 문화 맥락 설명 또는 null"
}
]
}
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.

`originalText`가 없는 라벨은 평가 스크립트가 `documentTitle`, `school`, `documentDate`, `labels[].evidenceText`를 이어 붙여 baseline 입력으로 사용한다.
OCR 원문까지 평가하려면 추후 JSON에 `originalText`를 추가한다.
86 changes: 86 additions & 0 deletions data/newsletter-labels/newsletter-001.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"documentId": "doc_001",
"documentTitle": "2026학년도 1학기 학습준비물 안내",
"documentDate": "2026-03-24",
"school": "서울세륜초등학교",
"dateCandidates": [],
"labels": [
{
"type": "reminder",
"title": "학교 지원 vs 가정 구매 준비물 구분 안내",
"evidenceText": "학부모님의 부담을 경감하고자 학생들에게 학습준비물을 지원하고 있습니다. / 학년 공통으로 지원되는 학습준비물 / 가정에서 직접 구매가 필요한 학습준비물",
"selectedDateCandidateId": null,
"dateStatus": "missing",
"date": null,
"target": "parent",
"actionRequired": false,
"schoolContext": "한국 초등학교는 일부 학용품을 학교 예산으로 무료 제공합니다. '학교 지원' 목록에 있는 것은 구매하지 않아도 됩니다. '가정 구매' 목록에 있는 것만 직접 준비하면 됩니다."
},
{
"type": "checklist",
"title": "1학년 가정 구매 준비물 준비",
"evidenceText": "가정에서 직접 구매가 필요한 학습준비물 / 1학년: A4 클리어파일(미술작품보관용)",
"selectedDateCandidateId": null,
"dateStatus": "missing",
"date": null,
"target": "parent",
"actionRequired": true,
"schoolContext": null
},
{
"type": "checklist",
"title": "2학년 가정 구매 준비물 준비",
"evidenceText": "2학년: 가위, 풀, 색연필, 사인펜, 투명 테이프, 15cm 자, 줄노트, 연필 등",
"selectedDateCandidateId": null,
"dateStatus": "missing",
"date": null,
"target": "parent",
"actionRequired": true,
"schoolContext": null
},
{
"type": "checklist",
"title": "3학년 가정 구매 준비물 준비",
"evidenceText": "3학년: 자, 네임펜, 공책, 연필, 지우개 등",
"selectedDateCandidateId": null,
"dateStatus": "missing",
"date": null,
"target": "parent",
"actionRequired": true,
"schoolContext": null
},
{
"type": "checklist",
"title": "4학년 가정 구매 준비물 준비",
"evidenceText": "4학년: 리코더, 삼각자(작년에 나눠준 리코더, 컴퍼스 세트 없는 사람 준비), 풀, 테이프, 공책류 등",
"selectedDateCandidateId": null,
"dateStatus": "missing",
"date": null,
"target": "parent",
"actionRequired": true,
"schoolContext": "리코더는 한국 초등학교 음악 수업에서 자주 사용하는 부는 악기입니다. 문서에 “작년에 나눠준 리코더, 컴퍼스 세트 없는 사람 준비”라고 되어 있으므로, 이미 학교에서 받은 물품이 있으면 다시 사지 않아도 되고 없는 경우에만 준비하면 됩니다."
},
{
"type": "checklist",
"title": "5학년 가정 구매 준비물 준비",
"evidenceText": "5학년: 필기도구(천으로 된 필통, 연필 3자루 이상, 지우개, 플라스틱 15cm 자), 가위, 풀, 스카치테이프, 검정색 네임펜, 색연필(12색), 싸인펜(12색), L자 파일(가정통신문 배부용), 줄노트, 줄넘기",
"selectedDateCandidateId": null,
"dateStatus": "missing",
"date": null,
"target": "parent",
"actionRequired": true,
"schoolContext": "L자 파일은 학교에서 가정으로 보내는 종이 공지문(가정통신문)을 보관하는 용도입니다. 한국 학교는 공지사항을 종이로 인쇄해 학생 편에 보내는 문화가 있습니다. 문구점에서 쉽게 구매할 수 있습니다."
},
{
"type": "checklist",
"title": "6학년 가정 구매 준비물 준비",
"evidenceText": "6학년: 필기도구(천으로 된 필통, 연필 3자루 이상, 지우개, 플라스틱 15cm 자), 가위, 풀, 스카치테이프, 검정색 네임펜, 색연필(12색), 싸인펜(12색), L자 파일(가정통신문 배부용), 줄노트, 부는 악기류(음악시간 안내)",
"selectedDateCandidateId": null,
"dateStatus": "missing",
"date": null,
"target": "parent",
"actionRequired": true,
"schoolContext": "L자 파일은 학교에서 가정으로 보내는 종이 공지문(가정통신문)을 보관하는 용도입니다. '부는 악기류'는 음악 수업 시작 시 담임 선생님이 별도로 안내합니다."
}
]
}
117 changes: 117 additions & 0 deletions data/newsletter-labels/newsletter-002.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
{
"documentId": "doc_002",
"documentTitle": "세륜 한마음 대운동회 안내",
"documentDate": "2026-04-24",
"school": "서울세륜초등학교",
"dateCandidates": [
{
"id": "dc_003_1",
"raw": "2026. 5. 4.(월)",
"resolved": "2026-05-04",
"note": "운동회 당일 날짜"
},
{
"id": "dc_003_2",
"raw": "9:00",
"resolved": "2026-05-04T09:00",
"note": "운동회 시작 시간"
},
{
"id": "dc_003_3",
"raw": "13:40",
"resolved": "2026-05-04T13:40",
"note": "1~2학년 하교 시간"
},
{
"id": "dc_003_4",
"raw": "14:30",
"resolved": "2026-05-04T14:30",
"note": "3~6학년 하교 시간"
},
{
"id": "dc_003_5",
"raw": "12시",
"resolved": "2026-05-04T12:00",
"note": "급식 시작 시간"
}
],
"labels": [
{
"type": "schedule",
"title": "세륜 한마음 대운동회",
"evidenceText": "일시: 2026. 5. 4.(월) 9:00~14:30 / 장소: 본교 운동장 (우천 시, 순연)",
"selectedDateCandidateId": "dc_003_1",
"dateStatus": "confirmed",
"date": "2026-05-04",
"target": "both",
"actionRequired": false,
"schoolContext": "한국 초등학교 운동회는 학부모도 참관할 수 있는 공개 행사입니다. 학교가 지정한 학부모 관람 구역(학부모석)이 있으며, 돗자리 등을 직접 가져와 앉아서 관람합니다. 별도 입장권은 필요 없습니다."
},
{
"type": "reminder",
"title": "우천 시 행사 순연 안내",
"evidenceText": "장소: 본교 운동장 (우천 시, 순연)",
"selectedDateCandidateId": null,
"dateStatus": "missing",
"date": null,
"target": "parent",
"actionRequired": false,
"schoolContext": "비가 오면 행사가 취소되는 것이 아니라 날짜가 뒤로 미뤄집니다(순연). 순연 날짜는 학교가 별도로 공지하므로 학교 홈페이지나 알림 앱을 확인하세요."
},
{
"type": "reminder",
"title": "운동회 당일 하교 시간 변경",
"evidenceText": "운동회 당일 하교 시간 안내: 1~2학년 13:40분, 3~6학년 14:30분에 하교할 예정입니다.",
"selectedDateCandidateId": "dc_003_1",
"dateStatus": "confirmed",
"date": "2026-05-04",
"target": "parent",
"actionRequired": false,
"schoolContext": "운동회 당일은 평소와 하교 시간이 다릅니다. 자녀를 데리러 오시는 경우 위 시간을 참고하세요."
},
{
"type": "checklist",
"title": "돗자리 등 관람 준비물 지참",
"evidenceText": "학부모님은 학부모석(출진문 옆 천막)에서 자유롭게 관람합니다(돗자리 등 준비).",
"selectedDateCandidateId": "dc_003_1",
"dateStatus": "confirmed",
"date": "2026-05-04",
"target": "parent",
"actionRequired": true,
"schoolContext": null
},
{
"type": "checklist",
"title": "편한 복장 및 운동화 착용",
"evidenceText": "운동회 진행 시 각 팀의 학부모 참여를 요청할 수 있으므로 편한 복장과 운동화를 신고 참여해 주시기 바랍니다.",
"selectedDateCandidateId": "dc_003_1",
"dateStatus": "confirmed",
"date": "2026-05-04",
"target": "parent",
"actionRequired": true,
"schoolContext": "한국 운동회에서는 학부모도 일부 경기(줄다리기 등)에 직접 참여하는 경우가 있습니다. 편한 옷과 운동화를 준비하세요."
},
{
"type": "reminder",
"title": "외부 음식 학급 전달 금지",
"evidenceText": "학생 및 학급에 외부음식 전달은 금지합니다.",
"selectedDateCandidateId": null,
"dateStatus": "missing",
"date": null,
"target": "parent",
"actionRequired": false,
"schoolContext": "운동회 당일 학교 급식이 제공됩니다. 식품 알레르기와 형평성 문제를 방지하기 위해 학부모가 교실이나 학생에게 별도 음식을 전달하는 것은 금지됩니다."
},
{
"type": "checklist",
"title": "학부모 점심 간편식 지참",
"evidenceText": "학부모님의 점심식사는 간편식으로 준비해 오셔서 드시기를 권장합니다.",
"selectedDateCandidateId": "dc_003_1",
"dateStatus": "confirmed",
"date": "2026-05-04",
"target": "parent",
"actionRequired": true,
"schoolContext": "학교 급식은 학생에게만 제공됩니다. 참관하는 학부모는 점심을 직접 준비해 오셔야 합니다."
}
]
}
Loading