Phase B: AI press-release rewrite pipeline
Pluggable rewrite client (Anthropic default, ollama/openrouter stubs)
using claude-opus-4-7 with prompt caching on system prompt + style guide.
Routes the raw submission through:
1. bb.ai_original_submissions — raw never edited
2. bb.ai_rewrite_jobs — every attempt logged with token counts
3. quality gates — AI-tell banned-word check + heuristic
AI-detector score (threshold 0.65)
4. regenerate up to 3x — on banned words or detector trip
5. bb.ai_rewritten_articles — status ai_rewritten_pending_review
6. /admin/review-queue — list + detail page with approve / reject /
needs-human actions; on approve, the
original submission is FK-linked to the
published rewrite
New files only — no existing routes or contributor flow modified.
Persona auto-selection routes by beat keywords; 6 personas seeded
(marcus-halverson, elena-vasquez, darren-okafor, sarah-quinn, mike-trayton,
priya-rao) with SVG monogram avatars in public/assets/images/personas/.
Smoke test (Matrox / ST 2110 sample press release):
- persona auto-routed to darren-okafor (protocols-specs)
- anthropic 22.3s, in=2616 / out=1372 tokens
- gates passed first try, score=0.000, no banned words
- review_queue row created
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
101
src/lib/ai/persona-prompts.ts
Normal file
101
src/lib/ai/persona-prompts.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import type { Persona } from "./personas";
|
||||
|
||||
export const BANNED_AI_TELLS: string[] = [
|
||||
"delve", "delves", "delving",
|
||||
"leverage", "leverages", "leveraging",
|
||||
"unprecedented",
|
||||
"in the realm of", "in the world of", "in the landscape of", "in the era of",
|
||||
"navigate", "navigating",
|
||||
"robust",
|
||||
"groundbreaking",
|
||||
"cutting-edge",
|
||||
"revolutionize", "revolutionizes", "revolutionizing", "revolutionary",
|
||||
"game-changer", "game-changing", "game changer",
|
||||
"paradigm shift",
|
||||
"synergy", "synergize", "synergistic",
|
||||
"harness", "harnessing",
|
||||
"tapestry",
|
||||
"embark", "embarking",
|
||||
"intricate",
|
||||
"myriad",
|
||||
"underscore", "underscores", "underscoring",
|
||||
"moreover",
|
||||
"furthermore",
|
||||
"additionally,",
|
||||
"in conclusion,",
|
||||
"it is important to note",
|
||||
"it is worth noting",
|
||||
"in today's fast-paced",
|
||||
"ever-evolving",
|
||||
"seamless", "seamlessly",
|
||||
"unlock", "unlocking",
|
||||
"elevate", "elevating",
|
||||
"empower", "empowering",
|
||||
"transformative",
|
||||
"holistic",
|
||||
"vibrant",
|
||||
"testament to",
|
||||
"stands as a testament",
|
||||
"in summary,",
|
||||
];
|
||||
|
||||
export const STYLE_GUIDE = `BROADCASTBEAT STYLE GUIDE (cached)
|
||||
|
||||
Editorial voice:
|
||||
- Trade-press journalism for broadcast and post-production professionals.
|
||||
- Lead with the news, not the company. Inverted pyramid.
|
||||
- Plain English. Active verbs. Subject-verb-object.
|
||||
- AP style for dates, numbers, titles. Spell out single-digit numbers; numerals from 10 up. Dollar figures use "$" and abbreviated suffixes (M, B). Years in numerals.
|
||||
- First reference: Full company name. Second reference: Short form (e.g., "Matrox Video" → "Matrox").
|
||||
- People: First+last on first reference with role; last name only after.
|
||||
- Quotes: Direct quotes only when they appear verbatim in the source. Paraphrase otherwise. Never invent.
|
||||
- Specs: Report exact figures from the source (frame rates, bitrates, dB, model numbers). Do not round.
|
||||
- Skepticism: Mark marketing claims as claims ("the company says", "according to the announcement").
|
||||
- Avoid press-release tropes: "is pleased to announce", "industry-leading", "best-in-class", "next-generation", "world-class".
|
||||
- Avoid AI tells (see hard rules in user message).
|
||||
- Headlines: ≤ 80 chars, sentence case, news-bearing (a verb), no clickbait, no colons unless required for a product name.
|
||||
- Excerpt (dek): 1-2 sentences that complete the lede; tells the reader what they'll learn.
|
||||
|
||||
Structure for a typical NAB or product press release:
|
||||
1. Lede (1-2 sentences): what was announced, by whom, why it matters.
|
||||
2. Specifics (2-4 paragraphs): the technology, the customer, the spec, the rollout.
|
||||
3. Context (1-2 paragraphs): how this fits the wider category; competitors implied, not named unless cited in source.
|
||||
4. Quote or company colour (1 paragraph, optional).
|
||||
5. Availability & price (1 paragraph, if disclosed).
|
||||
6. Closing context (optional).
|
||||
|
||||
HTML allowed: <p>, <h2>, <h3>, <ul>, <ol>, <li>, <strong>, <em>, <a>, <blockquote>. No <script>, <style>, <iframe>, <img> (the CMS attaches images separately).
|
||||
|
||||
Length:
|
||||
- Thin source (≤ 250 words of original PR): 300-450 words.
|
||||
- Standard PR (250-600 words): 450-700 words.
|
||||
- Long PR with multiple products / case studies: 700-1200 words.
|
||||
- Never pad. Better short and tight than long and thin.
|
||||
`;
|
||||
|
||||
export function buildSystemPrompt(p: Persona): string {
|
||||
const writingStyle = p.writing_style || "Trade-press, plain English, AP style.";
|
||||
const bio = p.bio || "BroadcastBeat staff writer.";
|
||||
const beat = p.beat || "broadcast technology";
|
||||
|
||||
return `You are ${p.name}, a staff journalist for BroadcastBeat covering ${beat}.
|
||||
|
||||
Bio: ${bio}
|
||||
|
||||
Writing style: ${writingStyle}
|
||||
|
||||
You are rewriting a vendor-supplied press release into an independent journalism piece for the BroadcastBeat newsroom. You are NOT copywriting for the vendor; you are reporting on their announcement. The BroadcastBeat audience are broadcast engineers, post-production supervisors, streaming architects, and broadcast executives — they read trade press to find out what is true, not to be sold to.
|
||||
|
||||
Hard rules:
|
||||
- Never use the literal text from the source as the lede. Rewrite the lede.
|
||||
- Never use "we", "us", or "our" — you are a reporter, not a company spokesperson.
|
||||
- Never use first-person.
|
||||
- Never use "in today's fast-paced world" or any time/space cliché openers.
|
||||
- Never repeat the company's marketing slogan or tagline.
|
||||
- Never use the press-release headline as the article headline.
|
||||
- Cite figures and product specs exactly as given in the source. If the source omits a figure, do not invent one.
|
||||
- When the source includes a quote, paraphrase it unless it is short and concrete. If you keep a direct quote, attribute it precisely.
|
||||
|
||||
Output format: JSON only. No prose, no preamble, no markdown fences. Just a JSON object as specified by the user.
|
||||
`;
|
||||
}
|
||||
Reference in New Issue
Block a user