Skip to content

feat: extractive transcript summarizer (summarize.py)#188

Open
seonghobae wants to merge 1 commit into
mainfrom
feat/transcript-summary
Open

feat: extractive transcript summarizer (summarize.py)#188
seonghobae wants to merge 1 commit into
mainfrom
feat/transcript-summary

Conversation

@seonghobae

Copy link
Copy Markdown
Contributor

Why

Transcripts produced by the pipeline are long walls of text — great for archival, poor for skimming. This adds a summarization step that turns any transcript into concise notes with key points, giving real archival value without adding a single dependency.

What

New module summarize.py — an honest extractive summarizer (it selects existing sentences verbatim; it never generates or paraphrases text, and makes no LLM or network calls):

  • summarize_text(text, max_sentences=5) -> Summary — dataclass with summary_text, key_sentences (list, original document order), and word_count of the input.
  • Algorithm: regex sentence tokenization → word-frequency table over lowercased whitespace tokens with a small built-in English stopword list → sentences scored by average content-word frequency (so long sentences don't win on length alone) → top-N returned in original order so the summary reads chronologically.
  • summarize_segments(segments, max_sentences=5) — accepts any iterable of duck-typed objects exposing .text (e.g. timestamped transcription segments); joins them so sentences spanning segment boundaries are reassembled.
  • Edge cases: empty/whitespace input → empty Summary; input with ≤ max_sentences sentences passes through unchanged; max_sentences < 1 raises ValueError; CJK sentence terminators (。!?) recognized; Korean/CJK input handled without crashing. Limitation documented in the module docstring: whitespace tokenization means unspaced CJK scripts get coarse frequency scoring.
  • Stdlib only (re, dataclasses). Full docstrings.

Tests

tests/test_summarize.py — 19 tests, no network, no mocks of external services:

  • top sentences selected by frequency (dominant-term sentences beat filler)
  • original document order preserved in key_sentences and summary_text
  • empty and whitespace-only input
  • short input returned as-is; single sentence without terminal punctuation
  • max_sentences respected; < 1 raises ValueError
  • stopword-only sentences never win
  • very long input (500 sentences) produces a bounded summary
  • Korean text summarized without crashing; full-width 。 splitting behavior
  • deterministic tie-breaking by earlier position
  • segment joining, boundary reassembly, empty segment list, duck typing

Gates (python3.14):

  • unittest discover -s tests: 132 tests, no new failures (only the 5 pre-existing macOS os.listxattr errors remain)
  • interrogate -c pyproject.toml: 100% docstring coverage repo-wide
  • .coveragerc source list untouched; no existing files modified

🤖 Generated with Claude Code

Turn long transcripts into skimmable notes with a stdlib-only extractive
summarizer — no external deps, no LLM or network calls.

- summarize_text(text, max_sentences=5) -> Summary(summary_text,
  key_sentences, word_count): regex sentence splitting, word-frequency
  scoring with a small stopword list (average frequency, so long
  sentences don't win on length), top-N sentences returned in original
  document order.
- summarize_segments(segments) accepts duck-typed objects with a .text
  attribute (e.g. timestamped transcription segments) and reassembles
  sentences that span segment boundaries.
- Edge cases covered: empty/whitespace input, short input passthrough,
  very long input, max_sentences validation, CJK terminators (。!?)
  recognized and Korean/CJK text handled without crashing (whitespace
  tokenization limitation documented honestly in the module docstring).
- 19 new tests in tests/test_summarize.py; interrogate 100% repo-wide.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CJRVbDrp1vGYkJgNHMGPpG
@seonghobae seonghobae enabled auto-merge (squash) July 6, 2026 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant