diff --git a/packages/api/src/llm/blog-prompts.ts b/packages/api/src/llm/blog-prompts.ts index d55e00f..d7479ae 100644 --- a/packages/api/src/llm/blog-prompts.ts +++ b/packages/api/src/llm/blog-prompts.ts @@ -1,451 +1,441 @@ /** - * Blog generation prompt templates — v2 (2026-03-28 overhaul) + * Blog generation prompt templates — v3 (2026-04-04 overhaul) * - * Complete rewrite based on field engineer feedback. - * Previous version produced shallow template text. - * This version enforces: - * - Real-world scenarios with technical depth - * - Power budget calculations (mandatory) - * - CLI examples and DOM readings - * - Cause-effect explanations, not bullet dumps - * - Product integration only when contextually relevant - * - Decision logic / diagnosis frameworks + * Complete rewrite based on real editorial feedback from Gold-standard reviews. + * v2 produced technically correct but structurally weak articles: + * - Too many spec dumps (dBm, TX/RX tables) + * - Visible prompt artifacts (section labels, repeated headings) + * - AI transition phrases ("In today's world", "This highlights") + * - Whitepaper tone instead of human engineering voice + * - Repetitive concepts across sections * - * Multi-pass pipeline: - * 1. MASTER pass — Full article generation with structure enforcement - * 2. DEPTH pass — Add concrete values, power budget, CLI examples - * 3. ANTI_GENERIC pass — Kill marketing language, fix intro - * 4. QUALITY_CONTROL pass — Final validation against quality gates - * 5. PROCUREMENT pass — (optional) Add cost context for sales audience + * v3 enforces: + * - ONE core idea per article, no topic mixing + * - Continuous narrative flow, no visible structure + * - Experience-driven voice (engineer explaining, not teaching) + * - Auto-Kill Layer: removes spec blocks, formulas, AI phrasing + * - Reduction Engine: 40% cut after generation + * - Hard Delete List: specific phrases banned outright * - * Voice: Senior optical network engineer with 10+ years field experience. - * NOT a content writer. NOT marketing. NOT generic AI. + * Pipeline (8 stages): + * 1. MASTER pass — Full article generation + * 2. NARRATIVE CONTROL — Enforce continuous flow, kill structure + * 3. AUTO-KILL LAYER — Remove spec residue, AI phrases, repetition + * 4. REDUCTION ENGINE — Cut 40% (keep strongest version of each idea) + * 5. DEPTH pass — Add concrete values where NEEDED (not dumped) + * 6. QUALITY CONTROL — Final validation + * 7. PROCUREMENT pass — (optional) Cost context for sales audience + * 8. LINKEDIN pass — Generate matching LinkedIn post + * + * Voice: Someone explaining a real deployment problem — not teaching a class. */ // ═══════════════════════════════════════════════════════ -// SYSTEM PROMPT — Persona & Rules +// SYSTEM PROMPT — Persona & Narrative Rules // ═══════════════════════════════════════════════════════ -export const SYSTEM_PROMPT = `You are a senior optical network engineer and technical writer with real field experience in data center, ISP, and DWDM environments. +export const SYSTEM_PROMPT = `You are a senior optical network engineer with real field experience in data center, ISP, and DWDM environments. -Your job is to create high-quality, practical, and technically accurate blog articles about optical transceivers and network troubleshooting. +You write blog articles for other engineers. Not tutorials. Not whitepapers. Not marketing copy. -Do NOT write generic, shallow, or marketing-style content. -Do NOT use buzzwords, filler phrases, or vague explanations. -Write like an experienced engineer explaining real problems to other engineers. +Your writing style is calm, direct, and experience-based. You sound like someone explaining a real problem over coffee — not presenting at a conference. -Your content must: -- Be technically correct and precise -- Include real-world scenarios -- Provide actionable troubleshooting steps -- Explain WHY issues happen, not just WHAT to do -- Include measurements, thresholds, and interpretation -- Reflect field experience (NOC, deployment, escalation cases) +VOICE RULES: +- Write in continuous narrative. No visible sections, no bullet-list articles. +- One core idea per article. Everything serves that idea. +- Short paragraphs. 2-4 sentences max. White space between thoughts. +- Vary sentence length. Mix short punchy lines with longer explanations. +- First person where natural ("I've seen this", "we ran into this"). +- No hedging — say what you mean. "is" not "could be", "should" not "might consider". -Reference values you know from experience: -- SFP+ SR: Tx -8.2 to +0.5 dBm, Rx sensitivity -18.0 dBm, alarm below -11.0 dBm -- QSFP28 LR4: Tx -4.3 to +4.5 dBm, Rx sensitivity -13.7 dBm -- QSFP-DD DR4: Tx -2.9 to +3.0 dBm per lane, Rx sensitivity -7.7 dBm -- 400ZR: Tx -10.0 to +2.0 dBm, Rx sensitivity -21.0 dBm, OSNR > 20 dB required -- BER: pre-FEC < 2.4×10^-4 acceptable (KP4 FEC), post-FEC < 10^-15 target -- CRC errors: > 100/min = dirty fiber, > 10000/min = bad optic or wrong fiber type -- Temperature: COM 0-70°C, IND -40 to +85°C, alarm above 75°C -- Power budget: include Tx power, fiber loss (0.35 dB/km SMF @ 1310nm, 0.22 dB/km @ 1550nm), connector loss (0.3 dB each), splice loss (0.1 dB), margin (3 dB recommended) +WHAT MAKES GOOD CONTENT: +- Real operational behavior (what happens when you deploy this) +- One clear narrative thread from start to finish +- Practical engineering insight from field experience +- Natural human tone — less polished, less structured, more lived-in +- Quiet confidence. No dramatic framing. No false authority. -CLI examples to use where relevant: - show interface transceiver details - show interface counters errors - show interfaces diagnostics optics - show ip interface brief - show logging | include transceiver|optics|SFP +═══════════ HARD DELETE LIST ═══════════ +These phrases are BANNED. Never use them: +- "Let me tell you something" +- "In conclusion" +- "Let's break this down" +- "Here's what you need to know" +- "The key takeaway" +- "This highlights" +- "It is important to note" +- "In a real-world scenario" +- "This couldn't be further from the truth" +- "recipe for disaster" +- "ticking time bomb" +- "the numbers don't lie" +- "robust validation strategy" +- "proper cleaning protocols are crucial" +- "significant benefits" +- "cutting-edge" +- "future-proof solution" +- "production-ready and future-proof" +- "real-world implications are far from trivial" +- "In today's rapidly evolving" +- "plays a key role" +- "increasingly important" +- "optimize" / "leverage" / "enhance" +- "consider implementing" +- "may indicate" +- "could potentially" +- "on paper" (unless genuinely needed) +- "in reality" (unless genuinely needed) -ANTI-PATTERNS (STRICTLY FORBIDDEN): -- Generic introductions ("In today's fast-paced world", "The optical transceiver market continues") -- Empty phrases ("optimize", "leverage", "enhance", "plays a key role", "increasingly important") -- Bullet lists without explanation -- Random product dumps unconnected to the text -- Copy-paste datasheet language -- Surface-level explanations without cause-effect reasoning -- Placeholders, TODO markers, or unfinished sections +═══════════ SOFT DELETE LIST ═══════════ +Only keep these if the sentence genuinely needs them: +- "most of the time" +- "usually" +- "the problem is" +- "what actually happens" +- "that's where" +- "the issue is not" +If the sentence works without them, drop them. -GOOD style example: -"If Tx drops below -10 dBm on a module rated for -8.2 to +0.5, the laser is degrading. You have maybe 2-4 weeks before it dies completely. Replace now during a maintenance window — don't wait for the 2 AM page." +═══════════ AUTO-KILL CATEGORIES ═══════════ +NEVER include any of these in your output: -BAD style to avoid: -"Low power may indicate issues with the transceiver module." +A) SPEC BLOCKS — No TX/RX power values, no dBm ranges, no comparison tables, + no multi-technology spec listings. Keep ONLY operational meaning. -FORMAT RULES: -- Write in flowing paragraphs, not repetitive bullet lists with identical structure -- Each section should read like an experienced colleague explaining over coffee -- Vary your sentence structure — don't start every paragraph the same way -- Tables are fine for reference data, but analysis MUST be narrative -- NEVER use the same template for every item (e.g., don't list "Deployment Reality / Interop / Price / Readiness / Issues" for every technology — group and compare instead) +B) FORMULA RESIDUE — No optical budget calculations, no attenuation formulas, + no lane math. Replace with plain-language insight ("margins get tighter", + "less room for mistakes"). -TOPIC SEPARATION (CRITICAL): -- Strategy/investment articles MUST NOT contain troubleshooting content -- Troubleshooting articles MUST NOT contain investment strategy -- Comparison articles focus on product differences, not operations -- Every article has ONE clear purpose. Do not mix purposes. +C) SECTION LEAKAGE — No visible section labels like "What breaks in production", + "Hidden costs nobody mentions", "Vendor bullshit vs reality". Write continuous prose. -OPINION RULES: -- Have a clear point of view. Neutral advice is worthless. -- Use "is", "will", "should not" instead of "could", "might", "typically" -- Make explicit recommendations: BUY / AVOID / CONSIDER -- Before writing, ask: "What decision does the reader make after reading this?" -- Then write to support exactly that decision.`; +D) GENERIC TRANSITIONS — No "For example", "In today's world", "This means that", + "This is where things get interesting". Just progress directly between ideas. + +E) REPETITION — Each concept appears ONCE, in its strongest form. Never explain + the same thing twice (cleaning, MMF vs SMF, polarity, production vs lab). + +F) SKU MENTIONS — No vendor part codes (FX-400DR4-001 etc.) unless the article + is specifically about product comparison. + +G) FALSE AUTHORITY — No "This is something we see regularly", "Everyone knows", + "The reality hits hard". Calm, experienced, understated. + +H) OVER-EXPLAINED BASICS — The audience is experienced network engineers. + Don't explain what MMF means. Don't explain what CRC stands for. + +I) WHITEPAPER TONE — No "It is essential to implement", "A structured + pre-deployment testing strategy", "This enables organizations to", + "best practices", "robust framework". + +J) FAKE PRECISION — No invented firmware versions, no overly specific costs + unless verified, no "every 45 seconds", no hallucinated numbers. + +FORMAT: +- Markdown with horizontal rules (---) as thought breaks +- No H2/H3 within the body — title only, then flowing text +- Short paragraphs separated by blank lines +- Tables ONLY for genuine reference data that serves the argument +- End quietly. No "In conclusion". Just stop when you're done. + +TOPIC SEPARATION: +- Strategy articles: NO troubleshooting, NO CLI examples +- Troubleshooting articles: NO investment strategy, NO market analysis +- Comparison articles: product differences only, not operations +- Every article has ONE purpose. Do not mix.`; // ═══════════════════════════════════════════════════════ // MASTER PROMPTS — Per Topic Type // ═══════════════════════════════════════════════════════ -export const TUTORIAL_PROMPT = `Create a blog article as a practical troubleshooting guide. +export const TUTORIAL_PROMPT = `Write a blog article about a real troubleshooting scenario. -Target audience: -- Network engineers (mid to senior level) -- Data center operators -- ISP engineers -- Technical buyers with engineering background +Start with a moment engineers recognize. Not a textbook scenario — something that actually happens. A link that doesn't quite fail but doesn't quite work either. An error counter that creeps up over hours. A module swap that changes nothing. -STRUCTURE REQUIREMENTS: +Then walk through the diagnosis the way it actually happens in the field. Not the clean version from the textbook. The messy version where you check three wrong things before finding the real cause. -1. **Strong Opening (Hook + Scenario)** - Start with a realistic field scenario (e.g. outage, alert, escalation). - Make it relatable (2 AM, NOC alert, customer escalation). - Clearly define the problem. Include the environment (spine-leaf, DWDM ring, campus core). - Example: "It's 2 AM. NOC pager goes off. Core spine link between pods is flapping — 200G aggregate capacity lost. You SSH into the switch, check the optics, and see Tx power at -14.3 dBm on a module rated for -8.2 to +0.5. The transceiver is dying. Here's how you diagnose this in under 5 minutes." +WHAT TO INCLUDE: +- A real scenario as the opening (specific, not generic) +- The diagnostic path — including the wrong turns +- What the actual problem turned out to be +- Why it wasn't obvious +- What to check next time to find it faster -2. **Quick Diagnosis Framework** - Provide simple decision logic usable under pressure: - - IF link is down → check Tx/Rx power → if Tx low, replace optic; if Rx low, check fiber - - IF link is up but BER high → check fiber end-faces → check fiber type match → check power budget - - IF intermittent flapping → check temperature → check DOM trends over time → check fiber routing - Make this a clear flowchart in text form. +WHAT NOT TO INCLUDE: +- Spec sheet dumps (no TX/RX tables, no dBm listings) +- Step-by-step procedures in numbered lists +- Product recommendations (this is troubleshooting, not sales) +- Definitions of basic concepts the audience already knows -3. **Deep Dive Sections** (each MUST include): - - Symptoms (specific alarms, log messages, metrics) - - Root causes (technical explanation of WHY) - - Measurements (exact Tx, Rx, OSNR, BER values and what they mean) - - Interpretation (how to read DOM output, what values indicate) - - Fix (step-by-step with specific commands) - - "What engineers usually get wrong" insight +Write as continuous narrative. No section headings within the body. +The article should feel like someone recounting a real experience, not writing a manual. - Cover these issues: - a) Low transmit power / dying laser - b) High BER or CRC errors (pre-FEC vs post-FEC) - c) Temperature and environmental problems - d) Fiber type mismatches (SMF vs MMF, wrong wavelength) - e) Coherent (400ZR/ZR+) link issues (if applicable) +Minimum 800 words. Maximum 1200 words. Shorter is better if it's tighter.`; -4. **Power Budget Section (MANDATORY)** - This is the most commonly ignored cause of transceiver issues. - Explain with a concrete example: - - Tx power: X dBm - - Fiber loss: Y km × Z dB/km = A dB - - Connector loss: N connectors × 0.3 dB = B dB - - Splice loss: M splices × 0.1 dB = C dB - - Total loss: A + B + C = D dB - - Rx power: Tx - D = E dBm - - Rx sensitivity: F dBm - - Margin: E - F = G dB (need ≥ 3 dB) - Show common mistakes (forgotten patch panels, dirty connectors eating 1-2 dB each). +export const HYPE_CYCLE_PROMPT = `Write a blog article with a clear investment position on transceiver technology. -5. **Tools & Commands** - Include real CLI examples with expected output. - Mention physical tools: OTDR, optical power meter, fiber inspection scope, cleaning supplies. - For coherent: spectrum analyzer, OSNR measurement. +Pick ONE thesis and argue it. Not "here's every speed class and what we think" — instead something like "400G is the new 10G" or "800G is not ready and here's why your vendor won't tell you that." -6. **Common Mistakes Engineers Make** - 3-5 real mistakes from field experience. Example: - - "Replacing a $2,400 QSFP-DD when the problem is a dirty connector" - - "Using MMF patch cable with an LR optic and wondering why the link won't come up" - - "Ignoring pre-FEC BER trending until post-FEC errors start" +Start with the thesis. Then support it with what's actually happening in deployments — not announcements, not press releases, not vendor roadmaps. What are people actually buying, deploying, and having problems with? -7. **When to Replace the Transceiver vs Fix the Fiber** - Clear decision criteria with thresholds. +WHAT TO INCLUDE: +- A clear, opinionated thesis in the first few lines +- What's actually shipping vs. what's announced +- Where the cost curves are (direction matters, exact numbers don't) +- What decision this helps the reader make +- A quiet, confident ending — not a call to action -8. **Key Takeaways** - 3-5 practical rules engineers can remember under pressure. +WHAT NOT TO INCLUDE: +- Speed-by-speed spec comparisons +- Neutral "it depends on your requirements" advice +- Power consumption tables or per-port wattage breakdowns +- Market size projections or analyst quotes +- Press release language ("revolutionary", "industry-leading") -OUTPUT: Complete, clean markdown. No notes, no placeholders, no generic filler. Minimum 1500 words.`; +Write as continuous narrative. One argument flowing through the entire piece. +The reader should finish with a clear point of view they didn't have before. -export const HYPE_CYCLE_PROMPT = `You are a senior optical network architect and industry expert. +Minimum 600 words. Maximum 1000 words.`; -Write a blog post that provides clear investment guidance on transceiver speeds. +export const COMPARISON_PROMPT = `Write a blog article that helps engineers decide between two or more transceiver options. -TARGET AUDIENCE: Network architects and CTOs making $2M+ infrastructure decisions. They need to decide WHAT to buy, WHEN, and WHY — not how transceivers work. +Not a feature comparison table. Not "Option A has X, Option B has Y." Instead, tell the story of when each option is the right choice — and more importantly, when it's the wrong one. -CRITICAL RULES: -- Have a STRONG opinion. Take a clear position. -- Make explicit recommendations: BUY / AVOID / CONSIDER for each speed class. -- Do NOT be neutral. Neutral advice is useless advice. -- Do NOT include troubleshooting content. This is a STRATEGY article. -- Do NOT dump product lists without context. Every product mentioned must serve the argument. -- Focus on BUSINESS IMPACT: cost per Gbit, power per port, rack density, ROI timeline. -- Do NOT mix topics. This is investment guidance. Not a tutorial. Not troubleshooting. +Ground it in a real procurement scenario. Someone needs N optics for a deployment. What actually matters when choosing? -STRUCTURE: +WHAT TO INCLUDE: +- A real decision scenario as the framing +- What actually differs in practice (not on the datasheet) +- When the cheaper option is genuinely fine +- When it's not, and why +- The thing most people overlook in this comparison -1. **Provocative Opening** (3-5 sentences) - Start with a thesis that challenges conventional thinking. - Example: "If you're still planning new 100G leaf-spine deployments in 2026, you're designing yesterday's network. The cost per Gbit on 400G QSFP-DD has dropped below 100G QSFP28 when you factor in port density and power. Here's what the numbers actually say." +WHAT NOT TO INCLUDE: +- Side-by-side spec tables +- Per-unit pricing (price direction is fine, exact quotes aren't) +- Vendor marketing claims +- Generic "total cost of ownership" sections +- Troubleshooting advice (this is procurement, not operations) -2. **Market Reality** (2-3 paragraphs) - - AI/ML traffic explosion: east-west traffic in GPU clusters doubling every 12 months - - Hyperscaler trends driving commoditization of 400G - - Enterprise following hyperscale with 2-3 year lag - - Supply chain: where is pricing heading, what's actually available vs announced +Write as a narrative. The comparison emerges from the story, not from a table. -3. **Speed-by-Speed Investment Analysis** — For EACH speed class, state clearly: - - **Verdict**: BUY / LEGACY / AVOID / EARLY (one word, bold) - - **Cost per Gbit** (actual numbers) - - **Where it makes sense** (specific use case) - - **Where it does NOT make sense** (specific anti-pattern) +Minimum 600 words. Maximum 1000 words.`; - Cover these speed classes: - - **100G QSFP28** — Legacy. Still deployed but declining cost advantage over 400G. - - **200G** — Skip tier. Being bypassed in most new designs. - - **400G QSFP-DD/OSFP** — Current sweet spot. Best price/performance/maturity balance. - - **800G OSFP/QSFP-DD800** — Emerging. AI fabric and hyperscale spine only. - - **1.6T** — Watch. Not production-ready. +export const NEW_PRODUCT_PROMPT = `Write a blog article analyzing a new transceiver product or technology. -4. **Investment Decision Matrix** - Clear DO / AVOID / CONSIDER framework: - - **DO**: Deploy 400G broadly for leaf-spine. Budget 800G for spine/AI interconnect. - - **AVOID**: New 100G designs. 200G unless forced by existing chassis. - - **CONSIDER**: Infrastructure readiness (fiber quality, power budget, cooling capacity). +Cut through the announcement. What does this actually change for someone designing a network this quarter? Is this worth evaluating now, or is it a press release for a product that ships in 18 months? -5. **Hidden Cost Analysis** (MANDATORY) - The optic is 30-40% of the real cost. Include: - - Power consumption per port (W): 400G ~12W, 800G ~18-25W - - Cooling cost: $0.10-0.15 per watt per year in a typical DC - - Fiber infrastructure: SMF for everything >25G, patch panel capacity - - Spares inventory: 5-10% of deployed base - - Engineering time: team training for new form factors - - Calculate a concrete example: "200 ports × 400G at $350/optic + $12W × $0.12/W/yr = $X total over 3 years" +Start with your verdict — don't make the reader scroll to find it. -6. **Actionable Recommendations** (3-5 clear statements) - Each must be specific enough to act on. Not "consider your needs" — instead: - "If deploying a new 32-pod leaf-spine in Q3 2026, use 400G QSFP-DD DR4 for spine and 25G SFP28 for server access. Budget $X per port. Plan 800G spine upgrade for 2028." +WHAT TO INCLUDE: +- Clear verdict up front: deploy now / evaluate / wait / skip +- What's genuinely new vs. incremental improvement +- Who this is actually for (be specific — "AI training clusters with >2000 GPUs", not "enterprises") +- What it replaces and whether the replacement is worth it +- When second-source and pricing pressure arrives (historically) -ANTI-PATTERNS (STRICTLY FORBIDDEN): -- Mixing in troubleshooting or operational content -- Listing products without explaining WHY they matter for the investment decision -- Being neutral ("it depends") — take a position -- Generic market statements without numbers -- Using "could", "might", "typically" — use "is", "will", "should not" -- Referencing products not discussed in the article body +WHAT NOT TO INCLUDE: +- Spec sheet rewrites (the datasheet exists, engineers can read it) +- Detailed power/thermal analysis unless that's the whole point +- Feature lists without context +- Press release language +- Troubleshooting content -OUTPUT: Complete markdown, minimum 1500 words. No placeholders. No meta-comments.`; +Write as narrative. Your opinion should be clear from the first paragraph. -export const COMPARISON_PROMPT = `Write a practical comparison guide for optical transceivers. +Minimum 500 words. Maximum 900 words.`; -Target audience: Engineers evaluating options for a specific deployment. - -STRUCTURE: - -1. **Opening**: Real procurement/deployment scenario. Example: "You need 200 optics for a new leaf-spine build. The OEM quotes $3,200 per QSFP-DD DR4. A compatible vendor offers the same at $890. Your boss asks: 'What's the catch?' Here's the honest answer." - -2. **What Actually Matters** (not spec sheet comparisons): - - Interoperability reality (vendor locking, firmware checks, authentication) - - Power budget differences between vendors (they're not all equal) - - Temperature behavior under load (top-of-rack vs. middle-of-rack) - - DOM accuracy (some compatibles report less accurate readings) - - Warranty and RMA experience - - When "compatible" causes real problems vs. when it works perfectly - -3. **Head-to-Head Comparison** - For each product option from the context data: - - Real-world performance (not just datasheet specs) - - Price positioning - - Known issues or advantages - - Best use case - -4. **Decision Framework** - - When to buy OEM (mission-critical, specific vendor requirements) - - When compatible is the right choice (cost optimization, proven modules) - - When to avoid specific options (new/untested, poor DOM support) - -5. **Total Cost of Ownership** - - Optics cost is only 30-40% of the real cost - - Factor in: spares inventory, RMA turnaround, engineering time, risk - - Include concrete calculations with numbers - -6. **Key Takeaways** — Decision rules for procurement. - -Include specific price ranges and performance data from the context provided. -Do NOT be a shill for any vendor. Be honest about tradeoffs.`; - -export const NEW_PRODUCT_PROMPT = `Write a new product analysis article for optical transceivers. - -TARGET AUDIENCE: Network architects and procurement engineers deciding whether to adopt a new module NOW or WAIT. They need a clear verdict, not a press release rewrite. - -CRITICAL RULES: -- Do NOT rewrite the vendor's spec sheet. Engineers can read datasheets themselves. -- Do NOT include troubleshooting content. This is a product analysis, not an operations guide. -- Have a CLEAR VERDICT: BUY NOW / WAIT / SKIP for each product discussed. -- Every claim must have a number. No "improved performance" — say "12W vs 14W previous gen." -- Compare explicitly to the product this replaces. If there's no predecessor, say so. - -STRUCTURE: - -1. **Provocative Opening** (3-5 sentences) - Cut through the hype. What does this product actually change? - Example: "Another 800G OSFP. The fourth this quarter. Before your vendor's sales rep schedules a 'strategic technology briefing' — here's what's actually different this time, and whether it matters for your network." - -2. **What's Actually New vs. Marketing Noise** - - Silicon: same Broadcom/Marvell DSP as competitors, or genuinely new? Which generation? - - Optics: same InP laser, or new EML/VCSEL approach? - - Power: actual module power draw vs. previous generation (watts, not "improved efficiency") - - Thermal: TDP and operating range — does this need active cooling? - - Form factor: backward compatible or requires new line cards? - -3. **Product Analysis** — For EACH product/variant: - | Spec | This Product | Previous Gen | Delta | - Table format with actual numbers. - - Then a narrative verdict: - - **BUY NOW** if: [specific scenario with concrete criteria] - - **WAIT** if: [specific scenario — what changes in 3-6 months that makes waiting worthwhile] - - **SKIP** if: [specific scenario — this product doesn't fit this use case] - -4. **The Hidden Costs Nobody Mentions** - The module price is 30-40% of total deployment cost. Include: - - Switch/line card compatibility (which platforms support this TODAY, not "planned") - - Firmware requirements (specific NX-OS/EOS/Junos versions) - - Fiber infrastructure (does this need new fiber types or cleaner connectors?) - - Power budget impact (per-port and per-switch) - - Spares strategy (new products = higher infant mortality, budget 10% spares not 5%) - -5. **Procurement Timing** - - Current pricing and where it's heading (based on supply chain data) - - Lead times from OEM vs compatible vendors - - Volume discount thresholds - - When second-source silicon drops prices (historically 6-9 months after launch) - -6. **Bottom Line** (3-5 decisive statements) - Not "consider your needs." Instead: - "If you're building a new AI training cluster in Q3 2026, this module is the right choice at $X. If you're running a standard enterprise leaf-spine, skip it — 400G DR4 at $350 does the job at 1/10th the cost." - -ANTI-PATTERNS (STRICTLY FORBIDDEN): -- Press release language ("revolutionary", "industry-leading", "next-generation") -- Neutral non-advice ("evaluate based on your requirements") -- Product lists without verdicts -- Mixing in troubleshooting or operational content -- Being nice to vendors who ship bad products - -OUTPUT: Complete markdown, minimum 1200 words. No placeholders.`; - -// Keep the old MASTER_PROMPT name as alias for backward compatibility +// Keep backward compatibility export const MASTER_PROMPT = TUTORIAL_PROMPT; // ═══════════════════════════════════════════════════════ -// REFINEMENT PASSES +// REFINEMENT PASSES — Post-Generation Pipeline // ═══════════════════════════════════════════════════════ -export const DEPTH_PROMPT = `Take the existing article and improve it with technical depth. - -ADD where missing: -1. Concrete numeric values (exact dBm ranges per form factor, BER thresholds, OSNR requirements) -2. Power budget calculations (if the article discusses reach or link issues) -3. CLI command examples with realistic output snippets -4. Cause-effect explanations (WHY does this happen, not just WHAT to do) -5. Real-world context (what does this look like in a running network) -6. DOM reading interpretation - -SPECIFIC ADDITIONS: -- For Tx power: specify exact dBm ranges per form factor - SFP+ SR: -8.2 to +0.5 dBm, alarm at -11.0 dBm - QSFP28 LR4: -4.3 to +4.5 dBm, alarm at -7.0 dBm - QSFP-DD DR4: -2.9 to +3.0 dBm per lane - 400ZR: -10.0 to +2.0 dBm (tunable) -- For BER: differentiate pre-FEC vs post-FEC - KP4 FEC threshold: 2.4×10^-4 pre-FEC - Post-FEC target: < 10^-15 - Explain: "Corrected errors are expected. Uncorrected errors mean the FEC can't keep up — that's when you page the on-call." -- For coherent: OSNR requirements per speed - 100G DP-QPSK: 12 dB minimum - 400G 16QAM: 20 dB minimum - 800G: 24 dB minimum -- For temperature: why top-of-rack runs hotter, impact on laser lifetime +/** + * NARRATIVE CONTROL — Enforce continuous flow, kill visible structure + * Runs FIRST after master generation. + */ +export const NARRATIVE_CONTROL_PROMPT = `Rewrite this article to read as one continuous narrative. REMOVE: -- Vague statements ("may indicate issues", "consider checking") -- Generic filler that adds no technical value -- Redundant explanations already covered elsewhere in the article +- All H2/H3 headings within the body (keep only the title) +- All numbered lists that read like procedures +- All bullet lists that should be prose +- All visible section labels ("What breaks", "The real cost", "Key takeaways") +- All repeated structural patterns (don't use the same format for each point) -Do NOT make the text longer unless it adds real technical value. -Preserve the markdown structure. -Keep the engineer voice — direct, confident, slightly opinionated.`; +RESTRUCTURE: +- Convert lists into flowing paragraphs +- Use horizontal rules (---) as thought breaks between major shifts +- Vary paragraph length — mix 1-sentence paragraphs with 3-4 sentence ones +- Make transitions invisible — the next thought should follow naturally -export const ANTI_GENERIC_INTRO_PROMPT = `Rewrite the introduction of this article. +The text should feel like someone talking, not someone presenting slides. -KILL any generic or marketing-style opening. Engineers close the tab immediately if they see: -- "In today's rapidly evolving network landscape" -- "Optical transceivers play a key role" -- "As data center bandwidth demands increase" -- Any sentence that could apply to any article about any topic +Return the complete rewritten article. Preserve the core content and insights.`; -REPLACE WITH a real scenario that the reader immediately recognizes from their own experience. -Make the reader feel "this person has been in my shoes." -Include specific technical details in the opening (model names, dBm values, error counts). +/** + * AUTO-KILL LAYER — Remove all patterns that make text feel generated + * This is the most critical pass. It catches everything the master prompt missed. + */ +export const AUTO_KILL_PROMPT = `Clean this article with the Auto-Kill Layer. -The intro should be 3-5 sentences maximum. Get to the point. +Delete or rewrite anything that feels like: +- Data sheet residue (raw spec values, dBm ranges, TX/RX numbers) +- Formula residue (calculations, equations, budget math) +- Section leakage (visible module labels, "What breaks in production") +- Generic AI transitions ("For example", "This means that", "This highlights") +- Repeated concepts (same idea explained twice in different sections) +- SKU mentions (vendor part codes like FX-400DR4-001) +- Exaggerated authority ("This is something we see regularly", "Let me tell you") +- Over-explained basics (defining terms the audience already knows) +- Whitepaper language ("It is essential to", "A structured strategy", "best practices") +- Fake precision (invented firmware versions, unverifiable exact costs) +- Dramatic framing ("ticking time bomb", "recipe for disaster", "the numbers don't lie") -Example of a great opening: -"It's 2 AM. NOC pager goes off. Core spine link between pods is flapping — 200G aggregate capacity lost. You SSH into the switch, check the optics, and see Tx power at -14.3 dBm on a module rated for -8.2 to +0.5. The transceiver is dying. Here's how you diagnose this in under 5 minutes." +HARD DELETE — Remove these phrases entirely if found: +"Let me tell you something", "In conclusion", "Let's break this down", +"Here's what you need to know", "The key takeaway", "This highlights", +"It is important to note", "In a real-world scenario", "recipe for disaster", +"ticking time bomb", "the numbers don't lie", "robust validation strategy", +"proper cleaning protocols are crucial", "significant benefits", "cutting-edge", +"future-proof solution", "increasingly important", "plays a key role" -Return the complete article with the fixed introduction. Do not change the rest.`; +Keep ONLY: +- Real operational behavior +- One clear narrative +- Practical engineering insight +- Natural human tone -export const QUALITY_CONTROL_PROMPT = `Check this article for the following issues and fix ALL of them: +The text must feel less polished, less structured, and more lived-in. -QUALITY GATES (every article MUST pass): +Return the complete cleaned article.`; -1. NUMERIC VALUES — Every technical claim MUST have a number attached. - BAD: "Low power indicates a problem" - GOOD: "Tx below -11.0 dBm on a 10G SR module means the laser is degrading" +/** + * REDUCTION ENGINE — Cut 40% of the text + * Brevity is the goal. Every sentence must earn its place. + */ +export const REDUCTION_PROMPT = `Cut this article by 40%. -2. GENERIC PHRASES — Kill all of these: - "plays a key role", "increasingly important", "it is important to note", - "in today's rapidly evolving", "optimize", "leverage", "enhance", - "consider implementing", "may indicate", "could potentially" - Replace with direct, specific statements. +REMOVE: +- Repetition (keep only the strongest version of each idea) +- Secondary explanations that add nothing new +- "Nice to have" details that don't serve the core argument +- Sentences that exist only because they sound complete +- Any paragraph that could be removed without losing the thread -3. PLACEHOLDER TEXT — Zero tolerance for TODO, NOTE, FIXME, , or incomplete sections. +KEEP: +- The core argument / thesis +- The strongest anecdote or example +- Sentences that change the reader's understanding +- The opening hook +- The quiet closing -4. EMPTY SECTIONS — Every H2/H3 section must have at least 100 words of substantive content. +After cutting, read it back. If any sentence feels like filler, cut it too. -5. POWER BUDGET — If the article discusses fiber links or reach, there MUST be a power budget calculation. +The best version of this article is the shortest one that still lands. -6. CLI EXAMPLES — At least 2 real CLI commands in the article. +Return the complete reduced article.`; -7. CAUSE-EFFECT — Every "do X" must explain WHY. No unexplained instructions. +/** + * DEPTH PASS — Add technical substance WHERE NEEDED + * v3 change: No longer dumps specs. Only adds depth where the text is vague. + */ +export const DEPTH_PROMPT = `Review this article for vague claims that need specifics. -8. PRODUCT INTEGRATION — Products are mentioned ONLY when they solve a specific problem discussed in the article. No random product dumps. +ONLY add detail where the text makes a claim without backing it up. -9. INTRODUCTION — Must start with a scenario, NOT with "The optical transceiver market..." +GOOD addition: Replacing "margins get tighter" with "at 400G, a connector that added +0.5 dB of loss — invisible at 100G — eats into a budget that's already half as generous" -10. MINIMUM DEPTH — Article must be at least 1200 words. If under that, add depth to existing sections (don't add filler). - -For each issue found, rewrite the affected section to fix it. -Return the complete fixed article in markdown.`; - -/** Optional procurement-focused notes for sales/customer audience */ -export const PROCUREMENT_LAYER_PROMPT = `Add short procurement-focused notes where relevant in this article. +BAD addition: Inserting a TX power range table or a power budget calculation Rules: -- Maximum 1-2 sentences per note, woven naturally into the text -- Focus on cost of misdiagnosis and unnecessary replacements -- Mention price context only when it helps the reader make better decisions -- Keep the engineer voice — you're helping them save money, not selling +- Add specifics that support the narrative, not spec blocks +- If a claim is already clear without numbers, leave it alone +- Never add CLI examples unless the article is explicitly a troubleshooting guide +- Never add comparison tables +- Keep the human voice — additions must sound natural, not inserted -Good example: -"Before RMA'ing a $2,400 QSFP-DD module, clean the fiber end-face. In our experience, 40% of RMA'd optics test perfectly fine at the vendor — the problem was contaminated connectors." +Return the complete article with additions woven in naturally.`; -Another example: -"A compatible QSFP28 LR4 runs $180 vs $1,100 for the OEM version. If your switch doesn't do vendor locking (most modern ones don't), there's no technical reason to pay 6x more." +/** + * ANTI-GENERIC INTRO — Fix weak openings + * Kept from v2 but simplified. + */ +export const ANTI_GENERIC_INTRO_PROMPT = `Rewrite only the first 3-5 sentences of this article. -Do NOT turn this into marketing content. Keep the engineer voice. -Return the complete article with the notes added.`; +The opening must be a moment the reader recognizes from their own experience. +Not a market overview. Not a definition. Not a rhetorical question. + +Something specific happened. Start there. + +Return the complete article with only the introduction changed.`; + +/** + * QUALITY CONTROL — Final validation + * Simplified from v2. Checks for Auto-Kill failures. + */ +export const QUALITY_CONTROL_PROMPT = `Final quality check. Fix any remaining issues: + +1. Any phrases from the Hard Delete List still present? Remove them. +2. Any spec blocks (dBm values, TX/RX tables) still present? Remove them. +3. Any visible section headings within the body? Remove them (keep title only). +4. Any repeated ideas? Keep only the stronger version. +5. Any numbered procedure lists? Convert to narrative. +6. Any whitepaper language? Rewrite in plain engineering voice. +7. Does the article have ONE clear purpose? If it drifts, cut the drift. +8. Is the ending quiet and confident? No "In conclusion", no call to action. +9. Word count check: if over 1200 words, cut more. Shorter is better. + +Return the complete fixed article.`; + +/** Optional procurement notes for sales/customer audience */ +export const PROCUREMENT_LAYER_PROMPT = `Add 1-2 short cost-context notes where they naturally fit. + +Rules: +- Maximum 1 sentence each, woven into the existing flow +- Focus on cost of misdiagnosis or the real price difference +- Keep the engineer voice — you're helping them avoid waste, not selling +- If there's no natural place for cost context, don't force it + +Return the complete article with notes added naturally.`; + +/** + * LINKEDIN POST — Generate matching LinkedIn post + * New in v3. Every blog gets a LinkedIn companion. + */ +export const LINKEDIN_PROMPT = `Write a LinkedIn post for this blog article. + +Rules: +- 6-10 lines maximum +- Start with the single strongest insight from the article +- No bullet lists +- No spec values +- No dramatic framing +- End with "Full breakdown in the blog — link in first comment." +- Add 4-5 relevant hashtags (always include #Flexoptix) +- The post should make someone stop scrolling and want to read the full article + +Do NOT summarize the article. Pick the one thing that would surprise someone +and lead with that.`; + +// ═══════════════════════════════════════════════════════ +// SCORING — Post-pipeline quality assessment +// ═══════════════════════════════════════════════════════ + +export const SCORING_PROMPT = `Score this article from 1-10 on each dimension: + +1. CLEANLINESS — No spec residue, no formula residue, no AI phrases +2. NARRATIVE CONTINUITY — Reads as one continuous thought, not assembled modules +3. NON-AI FEEL — Would a reader think a person wrote this, not an LLM? +4. OPERATIONAL RELEVANCE — Does this help an engineer make a better decision? + +For each score below 8, list what should still be removed or rewritten. + +Return ONLY the scores and issues as JSON: +{"cleanliness": N, "narrative": N, "non_ai": N, "relevance": N, "issues": ["..."]}`; // ═══════════════════════════════════════════════════════ // TOPIC PROMPT BUILDER — Injects context data @@ -475,38 +465,34 @@ export function buildTopicPrompt( parts.push(NEW_PRODUCT_PROMPT); } - // Append gathered data as context — clearly separated + // Append gathered data as MINIMAL context — not to be dumped into the article if (data.products.length > 0) { - parts.push("\n\n--- PRODUCT DATA (use as reference, integrate contextually — do NOT list randomly) ---"); - for (const p of data.products.slice(0, 15)) { - const price = p.price ? `, ~€${p.price}` : ""; - parts.push(`• ${p.standard_name || p.slug}: ${p.form_factor} ${p.speed}, reach ${p.reach_label || "N/A"}, fiber ${p.fiber_type || "N/A"}, vendor ${p.vendor || "N/A"}${price}`); + parts.push("\n\n--- CONTEXT DATA (use as background knowledge, do NOT list or dump into article) ---"); + for (const p of data.products.slice(0, 10)) { + parts.push(`• ${p.standard_name || p.slug}: ${p.form_factor} ${p.speed}, ${p.reach_label || ""}, ${p.vendor || ""}`); } } if (data.news.length > 0) { - parts.push("\n\n--- RECENT INDUSTRY NEWS (reference only if genuinely relevant to the topic) ---"); - for (const n of data.news.slice(0, 5)) { - parts.push(`• ${n.title} (${n.source || "unknown"}, ${n.date || "recent"})`); + parts.push("\n\n--- RECENT NEWS (reference only if genuinely relevant to the narrative) ---"); + for (const n of data.news.slice(0, 3)) { + parts.push(`• ${n.title} (${n.source || "unknown"})`); } } - // Only include troubleshooting data for tutorial/troubleshooting articles - // Strategy articles (hype_cycle, comparison, new_product) must NOT mix in troubleshooting + // Troubleshooting data only for tutorial articles if (topic === "tutorial" && data.troubleshooting.length > 0) { - parts.push("\n\n--- TROUBLESHOOTING DATA (incorporate into relevant sections with full context) ---"); - for (const t of data.troubleshooting) { - parts.push(`• Symptom: ${t.symptom}`); - parts.push(` Cause: ${t.cause}`); - parts.push(` Fix: ${t.solution}`); + parts.push("\n\n--- TROUBLESHOOTING CONTEXT (weave into narrative, do NOT list as procedures) ---"); + for (const t of data.troubleshooting.slice(0, 3)) { + parts.push(`• ${t.symptom} → ${t.cause} → ${t.solution}`); } } - // FAQ data only for tutorials and comparisons - if ((topic === "tutorial" || topic === "comparison") && data.faq.length > 0) { - parts.push("\n\n--- FAQ DATA (address these questions naturally in the article flow) ---"); - for (const f of data.faq.slice(0, 5)) { - parts.push(`• Q: ${f.question} → A: ${f.answer}`); + // FAQ only for tutorials + if (topic === "tutorial" && data.faq.length > 0) { + parts.push("\n\n--- FAQ CONTEXT (address naturally in flow, do NOT create Q&A section) ---"); + for (const f of data.faq.slice(0, 3)) { + parts.push(`• ${f.question}`); } } diff --git a/packages/api/src/routes/blog.ts b/packages/api/src/routes/blog.ts index f0dc262..d0d5fc0 100644 --- a/packages/api/src/routes/blog.ts +++ b/packages/api/src/routes/blog.ts @@ -1,13 +1,23 @@ /** - * Blog Draft Generator API + * Blog Draft Generator API — v3 (2026-04-04) * - * POST /api/blog/generate — Generate a blog draft via LLM (multi-pass pipeline) + * POST /api/blog/generate — Generate a blog draft via 8-stage LLM pipeline * GET /api/blog — List all drafts * GET /api/blog/:id — Get a specific draft * PUT /api/blog/:id/status — Update draft status * - * Pipeline: gather data → LLM master pass → depth improvement → quality control - * Voice: Senior optical network engineer, not marketing. + * Pipeline v3 (8 stages): + * 1. MASTER — Article generation with narrative voice + * 2. NARRATIVE CONTROL — Kill visible structure, enforce continuous flow + * 3. AUTO-KILL LAYER — Remove spec residue, AI phrases, repetition + * 4. REDUCTION ENGINE — Cut 40% (keep strongest version of each idea) + * 5. DEPTH — Add specifics only where text is vague (no spec dumps) + * 6. QUALITY CONTROL — Final validation against hard delete list + * 7. PROCUREMENT — (optional) Cost context for sales audience + * 8. LINKEDIN — Generate companion LinkedIn post + * + * Voice: Someone explaining a real deployment problem — not teaching a class. + * Based on editorial Gold-standard feedback and Auto-Kill Layer v1.0. */ import { Router, Request, Response } from "express"; import { pool } from "../db/client"; @@ -15,14 +25,20 @@ import { semanticSearch } from "../embeddings/client"; import { generate, checkHealth } from "../llm/client"; import { SYSTEM_PROMPT, + NARRATIVE_CONTROL_PROMPT, + AUTO_KILL_PROMPT, + REDUCTION_PROMPT, DEPTH_PROMPT, ANTI_GENERIC_INTRO_PROMPT, QUALITY_CONTROL_PROMPT, PROCUREMENT_LAYER_PROMPT, + LINKEDIN_PROMPT, + SCORING_PROMPT, buildTopicPrompt, } from "../llm/blog-prompts"; // Anti-patterns list for quality validation +// Hard Delete List — v3 Auto-Kill Layer const GENERIC_PHRASES = [ "plays a key role", "increasingly important", @@ -36,6 +52,23 @@ const GENERIC_PHRASES = [ "consider implementing", "may indicate issues", "could potentially", + "let me tell you", + "in conclusion", + "let's break this down", + "here's what you need to know", + "the key takeaway", + "this highlights", + "in a real-world scenario", + "recipe for disaster", + "ticking time bomb", + "the numbers don't lie", + "robust validation", + "significant benefits", + "cutting-edge", + "future-proof", + "production-ready and future-proof", + "best practices", + "robust framework", ]; export const blogRouter = Router(); @@ -834,7 +867,22 @@ async function processLlmQueue(): Promise { if (llmQueue.length > 0) processLlmQueue(); } -/** Run LLM pipeline and update draft in-place */ +/** + * Run LLM pipeline v3 — 8-stage blog generation + * + * Pipeline: + * 1. MASTER — Full article generation + * 2. NARRATIVE CONTROL — Kill visible structure, enforce flow + * 3. AUTO-KILL — Remove spec residue, AI phrases, repetition + * 4. REDUCTION — Cut 40% (keep strongest version of each idea) + * 5. DEPTH — Add specifics only where text is vague + * 6. QUALITY CONTROL — Final validation against kill list + * 7. PROCUREMENT — (optional) Cost context for sales audience + * 8. LINKEDIN — Generate companion LinkedIn post + * + * Each pass uses low temperature (0.3-0.4) except master (0.7). + * Scoring runs at the end but doesn't modify the article. + */ async function runLlmPipeline( draftId: string, title: string, @@ -843,71 +891,116 @@ async function runLlmPipeline( data: Awaited>, ): Promise { try { - console.log(`Blog LLM: Starting pipeline for ${draftId}`); + console.log(`Blog LLM v3: Starting 8-stage pipeline for ${draftId}`); + const passOpts = { temperature: 0.4, maxTokens: 6144, timeoutMs: 480000 }; - // Warmup: tiny prompt to ensure model is loaded in memory + // Warmup: tiny prompt to ensure model is loaded await generate("You are a test.", "Reply OK.", { - temperature: 0.1, - maxTokens: 8, - timeoutMs: 60000, - }).catch(() => { /* warmup failure is non-fatal */ }); + temperature: 0.1, maxTokens: 8, timeoutMs: 60000, + }).catch(() => { /* non-fatal */ }); - // Pass 1: Master generation with full structure enforcement + // ── Pass 1: MASTER GENERATION ── const topicPrompt = buildTopicPrompt(selectedTopic, data); const pass1 = await generate(SYSTEM_PROMPT, `Title: "${title}"\n\n${topicPrompt}`, { - temperature: 0.7, - maxTokens: 6144, - timeoutMs: 480000, + temperature: 0.7, maxTokens: 6144, timeoutMs: 480000, }); - console.log(` Pass 1 (master): ${pass1.evalCount} tokens`); + console.log(` 1/8 Master: ${pass1.evalCount} tokens, ${pass1.text.split(/\s+/).length} words`); - // Check intro quality — merge anti-generic into depth pass if needed - const introCheck = pass1.text.split("\n").slice(0, 10).join("\n").toLowerCase(); + // ── Pass 2: NARRATIVE CONTROL ── + const pass2 = await generate(SYSTEM_PROMPT, [ + NARRATIVE_CONTROL_PROMPT, + "", "--- ARTICLE ---", "", pass1.text, + ].join("\n"), passOpts); + console.log(` 2/8 Narrative: ${pass2.evalCount} tokens`); + + // ── Pass 3: AUTO-KILL LAYER ── + const pass3 = await generate(SYSTEM_PROMPT, [ + AUTO_KILL_PROMPT, + "", "--- ARTICLE ---", "", pass2.text, + ].join("\n"), passOpts); + console.log(` 3/8 Auto-Kill: ${pass3.evalCount} tokens`); + + // ── Pass 4: REDUCTION ENGINE ── + const pass4 = await generate(SYSTEM_PROMPT, [ + REDUCTION_PROMPT, + "", "--- ARTICLE ---", "", pass3.text, + ].join("\n"), passOpts); + const wordsAfterReduction = pass4.text.split(/\s+/).length; + console.log(` 4/8 Reduction: ${pass4.evalCount} tokens, ${wordsAfterReduction} words`); + + // ── Pass 5: DEPTH (selective) ── + const pass5 = await generate(SYSTEM_PROMPT, [ + DEPTH_PROMPT, + "", "--- ARTICLE ---", "", pass4.text, + ].join("\n"), passOpts); + console.log(` 5/8 Depth: ${pass5.evalCount} tokens`); + + // ── Pass 6: QUALITY CONTROL ── + // Check intro first + const introCheck = pass5.text.split("\n").slice(0, 8).join("\n").toLowerCase(); const needsIntroFix = introCheck.includes("the optical transceiver market") || introCheck.includes("in today") || introCheck.includes("increasingly") || introCheck.includes("plays a key role"); - // Pass 2: Combined depth + quality + intro fix - const issues = validateArticle(pass1.text); - const combinedPrompt = [ - DEPTH_PROMPT, - "", - "ADDITIONALLY, apply these quality controls:", + const issues = validateArticle(pass5.text); + const qcPrompt = [ QUALITY_CONTROL_PROMPT, - needsIntroFix ? `\nALSO: ${ANTI_GENERIC_INTRO_PROMPT}` : "", - issues.length > 0 ? `\nDETECTED ISSUES TO FIX: ${issues.join("; ")}` : "", - "", - "--- ARTICLE TO IMPROVE ---", - "", - pass1.text, + needsIntroFix ? `\nALSO FIX THE INTRO:\n${ANTI_GENERIC_INTRO_PROMPT}` : "", + issues.length > 0 ? `\nREMAINING ISSUES: ${issues.join("; ")}` : "", + "", "--- ARTICLE ---", "", pass5.text, ].join("\n"); - const pass2 = await generate(SYSTEM_PROMPT, combinedPrompt, { - temperature: 0.4, - maxTokens: 6144, - timeoutMs: 480000, - }); - console.log(` Pass 2 (depth+quality): ${pass2.evalCount} tokens`); - if (needsIntroFix) console.log(" (included intro fix)"); - if (issues.length > 0) console.log(` Quality issues fixed: ${issues.join(", ")}`); + const pass6 = await generate(SYSTEM_PROMPT, qcPrompt, passOpts); + console.log(` 6/8 QC: ${pass6.evalCount} tokens${needsIntroFix ? " (intro fixed)" : ""}${issues.length > 0 ? ` (${issues.length} issues)` : ""}`); - let draftContent = `# ${title}\n\n${pass2.text}`; + let draftContent = `# ${title}\n\n${pass6.text}`; - // Optional: Add procurement notes for sales/customer audience + // ── Pass 7: PROCUREMENT LAYER (optional) ── if (targetAudience === "sales" || targetAudience === "customer") { try { - const procPass = await generate(SYSTEM_PROMPT, `${PROCUREMENT_LAYER_PROMPT}\n\n--- ARTICLE ---\n\n${draftContent}`, { - temperature: 0.4, - maxTokens: 4096, - timeoutMs: 240000, - }); - draftContent = procPass.text; - console.log(` Procurement layer: ${procPass.evalCount} tokens`); + const pass7 = await generate(SYSTEM_PROMPT, [ + PROCUREMENT_LAYER_PROMPT, + "", "--- ARTICLE ---", "", draftContent, + ].join("\n"), { temperature: 0.4, maxTokens: 4096, timeoutMs: 240000 }); + draftContent = pass7.text; + console.log(` 7/8 Procurement: ${pass7.evalCount} tokens`); } catch { - console.log(" Procurement pass skipped (timeout)"); + console.log(" 7/8 Procurement: skipped (timeout)"); } + } else { + console.log(" 7/8 Procurement: skipped (audience: " + targetAudience + ")"); + } + + // ── Pass 8: LINKEDIN POST ── + let linkedinPost = ""; + try { + const pass8 = await generate(SYSTEM_PROMPT, [ + LINKEDIN_PROMPT, + "", "--- BLOG ARTICLE ---", "", draftContent, + ].join("\n"), { temperature: 0.5, maxTokens: 1024, timeoutMs: 120000 }); + linkedinPost = pass8.text; + console.log(` 8/8 LinkedIn: ${pass8.evalCount} tokens`); + } catch { + console.log(" 8/8 LinkedIn: skipped (timeout)"); + } + + // ── SCORING (non-destructive) ── + let scores: Record = {}; + try { + const scoreResult = await generate(SYSTEM_PROMPT, [ + SCORING_PROMPT, + "", "--- ARTICLE ---", "", draftContent, + ].join("\n"), { temperature: 0.2, maxTokens: 512, timeoutMs: 60000 }); + // Try to parse JSON from response + const jsonMatch = scoreResult.text.match(/\{[\s\S]*\}/); + if (jsonMatch) { + scores = JSON.parse(jsonMatch[0]); + } + console.log(` Scoring: ${JSON.stringify(scores)}`); + } catch { + console.log(" Scoring: skipped"); } const wordCount = draftContent.split(/\s+/).length; @@ -916,21 +1009,27 @@ async function runLlmPipeline( // Update the draft in DB await pool.query( `UPDATE blog_drafts - SET draft_content = $1, word_count = $2, generated_by = 'tip-blog-engine-llm', + SET draft_content = $1, word_count = $2, generated_by = 'tip-blog-engine-v3', outline = $3, status = 'draft', updated_at = NOW() WHERE id = $4::uuid`, [ draftContent, wordCount, - JSON.stringify({ generation_method: "llm", quality_issues: finalIssues }), + JSON.stringify({ + generation_method: "llm-v3", + pipeline: "8-stage", + quality_issues: finalIssues, + scores, + linkedin_post: linkedinPost, + }), draftId, ], ); - console.log(`Blog LLM: Draft ${draftId} updated — ${wordCount} words, LLM-generated`); + console.log(`Blog LLM v3: Draft ${draftId} updated — ${wordCount} words, scores: ${JSON.stringify(scores)}`); } catch (llmErr) { - console.warn(`Blog LLM pipeline failed for ${draftId}: ${(llmErr as Error).message}`); - // Draft stays as template-fallback, no update needed + console.warn(`Blog LLM v3 pipeline failed for ${draftId}: ${(llmErr as Error).message}`); + // Draft stays as template-fallback } }