Files
sebrief/README.md
T
jsahnandClaude Fable 5 d9dda79282 Add per-paper summary verification and cap safeguards
- Per-paper summary batches are fact-checked against abstracts (verify ->
  revise once on major issues -> re-verify), controlled by SEBRIEF_VERIFY_ENABLED
- The paper cap never drops papers already published in this week's digest
  (--force re-runs could otherwise erase them from every digest)
- SEBRIEF_MAX_PAPERS default 40 -> 60 (observed weekly volume ~47)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-02 17:21:41 +09:00

131 lines
7.6 KiB
Markdown

# SE-Brief — OA 소프트웨어공학 논문 주간 다이제스트 봇
매주 월요일 아침(07:00 KST), 지난주(월~일)에 발행된 오픈액세스(OA) 소프트웨어공학 논문을
OpenAlex에서 수집하고 MiniMax LLM으로 한국어 다이제스트를 만들어 **내부 게시**(파일 아카이브 +
tailnet 대시보드)하는 상주 프로그램입니다. 설계 문서는 [SEBRIEF_PLAN.md](SEBRIEF_PLAN.md)를 참고하세요.
US2KR의 파이프라인 철학을 그대로 따르는 별도 프로젝트입니다.
```
수집(OpenAlex · RSS) → SQLite 저장(DOI 중복 방지)
→ 논문별 요약(한줄요약·문제·방법·결과·시사점, DOI당 한 번 생성 후 재사용) + 배치 팩트체크
→ 주간 다이제스트 요약(JSON 스키마) → LLM 교차 검증(초록 대조 팩트체크, major면 1회 자동 수정)
→ Markdown 렌더 → 파일 아카이브 + 대시보드
```
## 수집 소스 (sebrief/sources.py)
| 소스 | 방식 |
|---|---|
| TOSEM (완전 OA) | ISSN 화이트리스트, 전량 |
| TSE · EMSE · IST · JSS (하이브리드) | ISSN 화이트리스트 + **논문 단위** `is_oa` 필터 |
| SoftwareX · JOSS | 전량 (도구/소프트웨어 논문) |
| IEEE Access · PeerJ CS (메가저널) | ISSN + OpenAlex Software 토픽(`topics.subfield.id:1712`) + **키워드 이중 필터** |
| e-Informatica SEJ 등 | `SEBRIEF_RSS_FEEDS`로 RSS 보조 (DOI 없는 항목은 스킵) |
| MDPI 전 저널 | **제외** — ISSN 블랙리스트 + 발행사 이름 검사로 이중 차단 |
- 한 논문은 DOI 기준으로 한 번만 요약됩니다. 다이제스트에 실린 논문은 동결(frozen)되어 재수집돼도
스킵되고, 수집 창(`SEBRIEF_BACKFILL_DAYS`)에 늦게 들어온 논문·캡 초과 논문은 다음 주로 이월됩니다.
- 다이제스트 idempotency 키는 ISO 주차(`2026-W36`) — US2KR의 krx_date 역할.
## 설치
```bash
# Python 3.12 + uv
uv venv --python 3.12 .venv
uv pip install --python .venv/bin/python -e ".[dev]"
cp .env.example .env # MINIMAX_API_KEY 필수
```
## 사용
```bash
.venv/bin/python -m sebrief.cli show-config # 설정 확인(시크릿 마스킹)
.venv/bin/python -m sebrief.cli next-run # 다음 다이제스트 주차/시각
.venv/bin/python -m sebrief.cli run-once --dry-run # 지금 즉시 생성해서 터미널에 출력(발행 X)
.venv/bin/python -m sebrief.cli run-once --dry-run --no-llm # LLM 없이 논문 목록만(축소 모드)
.venv/bin/python -m sebrief.cli run-once --week 2026-W35 # 특정 주차 생성·발행(끝난 주만)
.venv/bin/python -m sebrief.cli run-once --force # 이미 발행된 주여도 다시(재발행)
.venv/bin/python -m sebrief.cli test-notify # 발행 채널 점검(errors.log 기록)
.venv/bin/python -m sebrief.cli daemon # 상주 실행(주간 스케줄러)
```
종료 코드: `0` 성공 · `1` 오류(발행 채널 실패 포함) · `2` 스킵(이미 발행)
아직 끝나지 않은 주를 `--week`로 지정하면 `--dry-run`이 아닌 한 거부합니다(늦게 발행되는 논문이
동결돼 누락되고, 데몬의 정규 실행이 "이미 발행"으로 건너뛰기 때문). 발행 테스트는
`--week <지난 주> --force`로 하세요.
## 상주 실행(배포)
프로세스 생존은 OS에 맡기고, 프로그램은 "다음 실행 시각 계산 → 대기 → 실행"만 반복합니다.
재시작 후 실행 시각에서 `SEBRIEF_CATCHUP_WINDOW_HOURS`(기본 72시간) 이내면 놓친 다이제스트를 즉시
따라잡고, SQLite 기록으로 중복 발행을 막습니다. 주 1회 작업이라 월~목 사이 언제 재기동해도 따라잡습니다.
| 환경 | 방법 |
|---|---|
| macOS | `bash deploy/install-launchd.sh` (launchd, KeepAlive) |
| macOS (Apple container) | `bash deploy/install-apple-container.sh` — 데몬+대시보드 빌드·기동. `--boot`를 붙이면 로그인 시 자동 기동(LaunchAgent) 등록 |
| Linux | `deploy/sebrief.service` → `systemctl enable --now sebrief` |
| Docker | `docker compose -f deploy/compose.yaml up -d --build` |
`data/` `reports/` `logs/`는 호스트 디렉터리를 그대로 마운트하므로 배포 방식과 무관하게 산출물
위치가 같습니다.
## 설정(.env)
| 변수 | 기본값 | 설명 |
|---|---|---|
| `MINIMAX_API_KEY` | — | 필수. 글로벌 엔드포인트(`api.minimax.io`) 키 |
| `MINIMAX_MODEL` / `MINIMAX_FALLBACK_MODELS` | `MiniMax-M3` / `M2.7,M2.5` | 실패 시 순차 폴백 |
| `SEBRIEF_OPENALEX_MAILTO` | — | 이메일을 넣으면 OpenAlex polite pool (더 빠르고 안정적) |
| `SEBRIEF_BACKFILL_DAYS` | `7` | 수집 창을 주 시작보다 며칠 앞당길지 (늦은 색인 보완) |
| `SEBRIEF_MAX_PAPERS` | `60` | 다이제스트당 최대 논문 수 — 폭주 방어 안전판 (초과분은 다음 주 이월) |
| `SEBRIEF_PAPER_SUMMARY_ENABLED` | `true` | 논문 한 편씩 구조화 요약 생성 (초록 없는 논문은 스킵, 실패 배치는 다음 실행에서 재시도) |
| `SEBRIEF_PAPER_SUMMARY_BATCH_SIZE` | `8` | 논문별 요약 LLM 호출당 논문 수 |
| `SEBRIEF_RSS_FEEDS` | — | 보조 RSS CSV, 항목 `이름\|URL` |
| `SEBRIEF_EXTRA_BLACKLIST_ISSNS` | — | 기본 MDPI 블랙리스트에 더해 차단할 ISSN CSV |
| `SEBRIEF_RUN_WEEKDAY` / `SEBRIEF_RUN_TIME_KST` | `0` / `07:00` | 실행 요일(0=월)·시각 |
| `SEBRIEF_CATCHUP_WINDOW_HOURS` | `72` | 재시작 시 따라잡기 허용 창 |
| `SEBRIEF_VERIFY_ENABLED` | `true` | 요약 후 LLM 팩트체크(초록과 대조) — 주간 다이제스트와 논문별 요약 배치 모두. major 이슈 발견 시 1회 자동 수정 후 재검증. 검증 실패는 발행을 막지 않고 결과는 JSON·대시보드에 기록 |
| `SEBRIEF_LOG_LEVEL` | `INFO` | 로그 레벨 |
## 산출물
- `reports/YYYY-Wnn.md`, `.json` — ISO 주차 기준 아카이브. 주간 총평·하이라이트·주제별 그룹에 더해
**논문별 요약 카드**(한줄요약·문제·방법·결과·시사점)를 전 논문에 대해 포함
- `data/sebrief.sqlite3` — 논문(DOI 중복 방지·동결)·논문별 요약·다이제스트·발행 기록
- `logs/sebrief.log` — 일자별 회전, API 키 마스킹
## 대시보드 (dashboard/)
쌓인 다이제스트를 보는 웹 대시보드(TypeScript, 런타임 의존성 없는 Node 24 서버 + 번들 클라이언트).
`reports/*.json`만 읽는 읽기 전용 뷰라 데몬의 SQLite(WAL)와 절대 경합하지 않습니다.
- 선택 주차 요약 타일(논문·저널·하이라이트·주제 그룹·검증 상태), 주차별 논문 수 추이 차트(표 전환 가능)
- 다이제스트 목록(주차 갭 표시)/본문(Markdown 렌더, sanitize), 수집 결측·오류 로그 표시
- tailnet 전용, Apple container 배포 시 함께 기동: `http://localhost:8091` (포트: `SEBRIEF_DASHBOARD_PORT`)
```bash
cd dashboard
npm install
npm run build # tsc 타입체크 + esbuild 번들
SEBRIEF_REPORTS_DIR=../reports npm start # http://localhost:8091
```
## 개발
```bash
.venv/bin/python -m pytest -q
.venv/bin/ruff check sebrief tests
```
LLM은 `sebrief/llm/base.py`의 `LLMProvider` 인터페이스 뒤에 있으므로, 다른 모델로 바꾸려면 구현체만
추가하면 됩니다. Blogger 공개 발행은 아직 붙이지 않았습니다 — US2KR의 `BloggerDeliverer`를 그대로
이식해 `sebrief/deliver/__init__.py`의 `build_deliverers`에 추가하면 됩니다(Deliverer 프로토콜 동일).
## 저작권
OA 논문의 한국어 요약 + 출처·DOI 링크 표기입니다. 초록 원문은 전재하지 않고 자기 언어의 요약으로
재구성합니다(내부 게시라 리스크가 낮지만 공개 전환 대비 처음부터 지킵니다).