"""Prompt templates — claim-atom rewrite flow (not line-by-line humanizing). New content-creation logic -------------------------- AI detectors latch onto *global* essay rhythm: tidy intros, even sentences, parallel points, soft transitions. Synonym-swapping keeps that skeleton. This pipeline throws away the skeleton: 1) Atomize → bare claims/facts only 2) (Best) Interview → human questions from those claims 3) (Best) Answer → short uneven answers (no essay frame) 4) Weave → stitch into continuous prose with a rotating style seed 5) Bridge → fix seams only 6) Mechanics (code) → strip leftover AI phrases / force burstiness """ from __future__ import annotations AI_TELLS = ( "delve", "dive into", "landscape", "robust", "seamless", "cutting-edge", "game-changer", "unlock", "leverage", "harness", "it's important to note", "it is worth noting", "in today's world", "in conclusion", "to summarize", "furthermore", "moreover", "additionally", "consequently", "thus", "tapestry", "realm", "embark", "pivotal", "multifaceted", "comprehensive overview", "plays a crucial role", "serves as a testament", "in the ever-evolving", "a myriad of", "when it comes to", "at the end of the day", "as an AI", ) TONE_GUIDE = { "Neutral": "Clear colleague voice—plain English, slight opinion, not a brochure.", "Formal": "Professional but human. Plain words. No legalistic padding.", "Casual": "Candid email/blog. Contractions. Direct. No forced slang.", "Academic": "Careful, concrete, no ornate filler.", } # Rotating micro-styles break the single “model voice” across a document. STYLE_SEEDS = ( "Start mid-thought. No intro sentence that restates the topic.", "Lead with the most concrete fact or number, then explain.", "Use mostly short sentences. Allow one longer sentence mid-way.", "Sound slightly impatient and direct—cut soft padding.", "Write like notes cleaned into paragraphs, not an essay.", "Prefer 'you/we' address if it fits. Avoid abstract noun stacks.", "One one-line paragraph is required somewhere.", "Open one paragraph with And/But/So/Still.", ) def style_seed(index: int = 0) -> str: return STYLE_SEEDS[index % len(STYLE_SEEDS)] def length_budget(source_words: int, preserve_length: bool = True) -> tuple[int, int, str]: source_words = max(1, int(source_words)) if preserve_length: target = source_words max_words = max(target, int(source_words * 1.05)) min_words = max(1, int(source_words * 0.85)) rule = ( f"LENGTH BUDGET (strict): ~{target} words " f"(stay {min_words}-{max_words}). " "Do NOT expand. No new examples/intros/conclusions. Shorter beats longer." ) else: target = max(1, int(source_words * 0.7)) max_words = max(target, int(source_words * 0.8)) min_words = max(1, int(source_words * 0.55)) rule = ( f"LENGTH BUDGET (strict): ~{target} words " f"(stay {min_words}-{max_words}). Cut fluff. Keep key facts." ) return target, max_words, rule def _banned_line() -> str: return "Never use: " + ", ".join(AI_TELLS[:22]) + "." def _craft(tone: str) -> str: guide = TONE_GUIDE.get(tone, TONE_GUIDE["Neutral"]) return f"""Voice: {guide} Human craft: uneven sentence lengths; contractions when tone allows; plain verbs (use/get/make/show/fix); concrete nouns; optional fragments; no tidy 3-point essay shape. {_banned_line()} Keep every fact/name/number. Invent nothing. Output document text only.""" # ----- Step 1: atomize ------------------------------------------------------- def system_atomize() -> str: return ( "You extract atomic claims from text. " "Output ONLY a numbered list of bare facts/claims. " "No adjectives for style, no transitions, no intro/outro." ) def user_atomize(text: str) -> str: return f"""Break this into atomic claims (facts, numbers, names, decisions, causes, effects). Rules: - One claim per line, numbered 1) 2) 3) … - 6–18 atoms for typical paragraphs; more only if needed - Strip rhetoric and filler - Do not invent - Do not write paragraphs Text: \"\"\" {text} \"\"\" """ # ----- Step 2 (Best): interview --------------------------------------------- def system_interview() -> str: return ( "You turn claim atoms into plain questions a curious human would ask. " "Output ONLY numbered questions. No answers." ) def user_interview(atoms: str) -> str: return f"""From these claim atoms, write 5–10 plain questions that would pull the same facts out in conversation. Do not add new topics. Atoms: \"\"\" {atoms} \"\"\" """ # ----- Step 3 (Best): answer bank ------------------------------------------- def system_answer(tone: str) -> str: return f"""You answer questions in short human bursts—not essay form. {_craft(tone)} Rules: - Answer each question in 1–3 sentences - Do NOT restate the question - Do NOT label answers as Q1/A1 - Separate answers with a blank line - Uneven lengths between answers on purpose""" def user_answer(questions: str, atoms: str) -> str: return f"""Answer using ONLY facts from the atoms. Stay brief. Questions: \"\"\" {questions} \"\"\" Atoms (source of truth): \"\"\" {atoms} \"\"\" """ # ----- Step 4: weave --------------------------------------------------------- def system_weave(tone: str) -> str: return f"""You weave raw material into continuous human prose. {_craft(tone)} Critical: - Build from the provided material ONLY - Do not copy sentence shapes from any AI source excerpt - Follow the STYLE SEED for this section - Obey LENGTH BUDGET - Continuous prose only (no bullets, no Q/A labels)""" def user_weave( *, material: str, tone: str, seed: str, length_rule: str, voice_sample: str = "", anti_source: str = "", ) -> str: voice_block = "" if voice_sample.strip(): voice_block = f""" Match this writer's cadence (do not copy sentences): \"\"\" {voice_sample.strip()[:1600]} \"\"\" """ anti_block = "" if anti_source.strip(): anti_block = f""" Anti-pattern (do NOT echo rhythm/phrasing): \"\"\" {anti_source.strip()[:1800]} \"\"\" """ return f"""Tone: {tone} STYLE SEED: {seed} {length_rule} {voice_block} Raw material to weave: \"\"\" {material} \"\"\" {anti_block} Write the continuous section now.""" # ----- Step 5: bridge -------------------------------------------------------- def system_bridge(tone: str) -> str: return f"""You only fix seams between paragraphs. You are not rewriting the piece. {_craft(tone)} Allowed: - Smooth an awkward jump with a short connective clause - Split/merge a paragraph for rhythm - Replace an AI leftover phrase Forbidden: - Adding new points - Lengthening more than ~5% - Turning it back into a tidy essay""" def user_bridge(draft: str, max_words: int = 0) -> str: cap = f"Hard max {max_words} words." if max_words else "Do not lengthen." return f"""Bridge-edit only. {cap} \"\"\" {draft} \"\"\" """ # ----- Compress / fast path -------------------------------------------------- def system_compress() -> str: return ( "Compress to a strict word limit. Keep key facts and human uneven rhythm. " "Delete padding. Output only the text." ) def user_compress(text: str, max_words: int) -> str: return f"""At most {max_words} words: \"\"\" {text} \"\"\" """ def system_fast(tone: str) -> str: return f"""Rewrite from meaning, not phrasing. {_craft(tone)} Method: extract claims mentally → write fresh uneven prose → stop at length budget.""" def user_fast( text: str, tone: str, seed: str, length_rule: str, voice_sample: str = "", ) -> str: voice_block = "" if voice_sample.strip(): voice_block = f""" Voice sample (cadence only): \"\"\" {voice_sample.strip()[:1600]} \"\"\" """ return f"""Tone: {tone} STYLE SEED: {seed} {length_rule} {voice_block} Rewrite (new sentences, same facts): \"\"\" {text} \"\"\" """