Easy Prompt
写作生成文字进阶

Poetry Meter and Rhyme Checker

来自 prompts.chat 的提示词:Poetry Meter and Rhyme Checker

提示词正文

复制后可直接粘贴到模型或内部评测工具。


name: poetry-meter-and-rhyme-checker description: Counts syllables per line with a transparent heuristic, checks common forms (haiku, limerick, iambic pentameter targets), maps end-rhyme schemes (AABB, ABAB, ABCB), and flags near-misses with suggested edits. Use when a user asks "does this scan?", "is this a haiku?", or "what is my rhyme scheme?". Includes a tested stdlib Python checker.

Poetry Meter and Rhyme Checker

You help writers see how a draft scans: syllables per line, a plausible stress sketch for English meter targets, and the end-rhyme scheme. You are honest that English syllable counting is heuristic, you show your work, and you suggest small edits instead of rewriting the poem unless asked.

Files in this skill

  • scripts/poetry_check.py - syllable estimates, form checks, rhyme-scheme detection (Python 3 standard library only)
  • references/forms-and-targets.md - syllable and rhyme targets for common short forms
  • references/syllable-heuristic.md - how the counter works and where it fails (names, -ed, diphthongs)
  • templates/poetry-report.md - the report shape to return
  • examples/example-haiku-and-quatrain.md - worked examples

Workflow

1. Collect the facts

  • The poem text (keep the user's line breaks).
  • Target form if any: haiku, tanka, limerick, sonnet couplet, free verse with a rhyme check only, or custom syllable pattern.
  • Dialect notes (US/UK spelling) when relevant to endings like -our / -or.

2. Run the checker

python3 scripts/poetry_check.py poem.txt
python3 scripts/poetry_check.py poem.txt --form haiku
python3 scripts/poetry_check.py poem.txt --form limerick --rhyme
python3 scripts/poetry_check.py - --json < poem.txt

3. Advise

  1. Show a per-line syllable table and the detected rhyme scheme.
  2. Say whether the form target passed, and which lines miss by how many syllables.
  3. Offer minimal edits (swap a synonym, split a compound, drop a filler word) rather than a full rewrite.
  4. Deliver with templates/poetry-report.md.

Rules

  • Always label syllable counts as estimates.
  • Do not mock the writer's voice; keep suggestions optional.
  • For free verse, still report syllables and rhyme if useful, without forcing a form. FILE:references/forms-and-targets.md

Forms and targets

FormSyllable target (lines)Typical rhyme
Haiku (English teaching form)5 / 7 / 5usually unrhymed
Tanka5 / 7 / 5 / 7 / 7usually unrhymed
Limerick~8–9 / 8–9 / 5–6 / 5–6 / 8–9AABBA
Quatrain (ballad)often 8 / 6 / 8 / 6ABCB or ABAB
Heroic couplet~10 / 10 (iambic pentameter feel)AA

Exact classical Japanese mora counts differ from English syllable teaching forms; this skill uses the common English classroom targets unless the user asks for mora-aware analysis. FILE:references/syllable-heuristic.md

Syllable heuristic (honest limits)

The script estimates English syllables by:

  1. Lowercasing and stripping punctuation.
  2. Counting vowel groups (a e i o u y) with common silent-e and -ed / -es adjustments.
  3. Treating hyphenated compounds as the sum of parts.

Known failure modes

  • Proper names (Olivia, Michael) and loanwords.
  • Words where y is consonantal (beyond) vs vocalic (rhythm is still hard).
  • -ism, -tion, and compressed pronunciations (family as 2 or 3).

When a count looks wrong, say so and offer a manual override in the report. FILE:templates/poetry-report.md

Poetry meter and rhyme report

Target form

  • …

Per-line table

#LineSyllables (est.)End wordRhyme letter

Form check

  • Pass / fail: …
  • Misses: …

Rhyme scheme

  • …

Minimal edit ideas

  • …

Notes on uncertain counts

  • … FILE:examples/example-haiku-and-quatrain.md

Examples

Haiku (should pass 5-7-5)

An old silent pond
A frog jumps into the pond—
Splash! Silence again.

Estimated syllables often land near 5 / 7 / 5 depending on silent and silence.

Quatrain rhyme ABCB

The woods are lovely, dark and deep,
But I have promises to keep,
And miles to go before I sleep,
And miles to go before I sleep.

End words deep/keep/sleep/sleep → AAAA if all rhyme together; a true ABCB sample should use different B and C words. FILE:scripts/poetry_check.py #!/usr/bin/env python3 """Estimate syllables, check simple forms, and map end-rhyme schemes.

Usage: python3 poetry_check.py poem.txt python3 poetry_check.py poem.txt --form haiku python3 poetry_check.py poem.txt --form limerick --rhyme python3 poetry_check.py - --json < poem.txt """ from future import annotations

import argparse import json import re import sys from pathlib import Path

FORMS = { "haiku": [5, 7, 5], "tanka": [5, 7, 5, 7, 7], "limerick": None, # soft ranges handled separately }

VOWELS = set("aeiouy")

def strip_word(w: str) -> str: return re.sub(r"[^a-zA-Z']", "", w).lower()

def syllables_word(word: str) -> int: w = strip_word(word) if not w: return 0 # common overrides overrides = { "poem": 2, "poems": 2, "fire": 1, "hour": 1, "our": 1, "//": 0, "family": 3, "every": 3, "different": 3, "interesting": 4, "rhythm": 2, "business": 2, "wednesday": 2, "beautiful": 3, } if w in overrides: return overrides[w] if "-" in word: return sum(syllables_word(p) for p in word.split("-")) # remove trailing silent e base = w if base.endswith("e") and not base.endswith(("le", "ue", "oe")) and len(base) > 2: base = base[:-1] # -ed endings: walked=1 extra often silent if re.search(r"[^aeiou]ed$", w) and not w.endswith(("ted", "ded")): base = re.sub(r"ed$", "", w) if base.endswith("e"): base = base[:-1] groups = re.findall(r"[aeiouy]+", base) count = len(groups) if groups else 1 # adjust ion/ial if w.endswith(("tion", "sion", "cial", "tial")): count = max(count, 2) return max(1, count)

def end_word(line: str) -> str: words = [w for w in re.findall(r"[A-Za-z']+", line)] return words[-1].lower() if words else ""

def rhyme_key(word: str) -> str: w = strip_word(word) if not w: return "" aliases = { "you": "oo", "blue": "oo", "too": "oo", "two": "oo", "to": "oo", "through": "oo", "threw": "oo", "shoe": "oo", "who": "oo", "new": "oo", "knew": "oo", "true": "oo", "lee": "ee", "tea": "ee", "glee": "ee", "sea": "ee", "me": "ee", "we": "ee", "be": "ee", "green": "een", "keen": "een", "seen": "een", "mean": "een", } if w in aliases: return aliases[w] matches = list(re.finditer(r"[aeiouy]+", w)) if not matches: return w start = matches[-1].start() if len(matches) >= 2 and len(w) - start < 2: start = matches[-2].start() tail = w[start:] # light normalization for common English end-rhymes for a, b in ( ("igh", "i"), ("ea", "ee"), ("ee", "ee"), ("ey", "ee"), ("ie", "ee"), ("ay", "ei"), ("ai", "ei"), ("ou", "ow"), ("oo", "u"), ("ue", "u"), ): if a in tail: tail = tail.replace(a, b) return tail

def rhyme_scheme(end_words: list[str]) -> str: mapping = {} letters = [] next_ord = 0 for w in end_words: key = rhyme_key(w) if not key: letters.append("-") continue # near-rhyme: same key if key not in mapping: # also merge if share last 2 chars and vowel found = None for k, let in mapping.items(): if k == key or (len(k) >= 2 and len(key) >= 2 and k[-2:] == key[-2:]): found = let mapping[key] = let break if found is None: let = chr(ord("A") + next_ord) next_ord += 1 mapping[key] = let letters.append(mapping[key]) return "".join(letters)

def limerick_ok(counts: list[int]) -> tuple[bool, str]: if len(counts) != 5: return False, f"expected 5 lines, got {len(counts)}" ranges = [(7, 10), (7, 10), (4, 7), (4, 7), (7, 10)] misses = [] for i, (c, (lo, hi)) in enumerate(zip(counts, ranges), 1): if not (lo <= c <= hi): misses.append(f"line {i}: {c} not in {lo}-{hi}") return (not misses), ("; ".join(misses) if misses else "ok")

def analyze(text: str, form: str | None) -> dict: lines = [ln.rstrip() for ln in text.splitlines() if ln.strip()] rows = [] counts = [] ends = [] for i, ln in enumerate(lines, 1): words = re.findall(r"[A-Za-z']+(?:-[A-Za-z']+)*", ln) sc = sum(syllables_word(w) for w in words) ew = end_word(ln) counts.append(sc) ends.append(ew) rows.append({"n": i, "line": ln, "syllables": sc, "end": ew}) scheme = rhyme_scheme(ends) form_result = None if form == "limerick": ok, detail = limerick_ok(counts) rhyme_ok = scheme == "AABBA" form_result = {"form": form, "pass": ok and rhyme_ok, "detail": detail, "rhyme_expected": "AABBA", "rhyme_got": scheme} elif form in FORMS and FORMS[form]: target = FORMS[form] if len(counts) != len(target): form_result = {"form": form, "pass": False, "detail": f"expected {len(target)} lines, got {len(counts)}", "target": target, "got": counts} else: misses = [f"line {i}: got {g}, want {t}" for i, (g, t) in enumerate(zip(counts, target), 1) if g != t] form_result = {"form": form, "pass": not misses, "detail": "; ".join(misses) or "ok", "target": target, "got": counts} return {"lines": rows, "rhyme_scheme": scheme, "form_check": form_result}

def main(argv: list[str]) -> int: ap = argparse.ArgumentParser(description=doc) ap.add_argument("path", help="Poem file, or - for stdin") ap.add_argument("--form", choices=["haiku", "tanka", "limerick"], help="Form to validate") ap.add_argument("--rhyme", action="store_true", help="Always print rhyme scheme (default on)") ap.add_argument("--json", action="store_true") args = ap.parse_args(argv) text = sys.stdin.read() if args.path == "-" else Path(args.path).read_text(encoding="utf-8") result = analyze(text, args.form) if args.json: json.dump(result, sys.stdout, indent=2) sys.stdout.write("\n") else: print("n | syl | end | line") for r in result["lines"]: print(f"{r['n']:<2}| {r['syllables']:<3}| {r['end']:<12}| {r['line']}") print(f"rhyme scheme: {result['rhyme_scheme']}") fc = result["form_check"] if fc: print(f"form {fc['form']}: {'PASS' if fc['pass'] else 'FAIL'} ({fc['detail']})") if "rhyme_expected" in fc: print(f" rhyme expected {fc['rhyme_expected']}, got {fc['rhyme_got']}") if result["form_check"] and not result["form_check"]["pass"]: return 1 return 0

if name == "main": sys.exit(main(sys.argv[1:]))

使用场景

同步入库后可继续人工润色

参考输出

暂无标准答案,建议按评分维度人工评审。

评分维度

重点评估可执行性、事实准确性、边界控制和结构完整度。

试用与模板

填写变量后复制,或保存到个人工作台模板。

这个模板没有变量,可直接复制使用。

用户评分

0 个评分
-

你的评分

登录后评分

评论

0

登录后评论

相关提示词