blog: calibration v8 — AI phrasing blacklist, STEP8 6-step rewrite, Flexoptix author identity
- STRICTLY FORBIDDEN section: comprehensive AI phrasing blacklist (leverage, utilize, Furthermore, robust, seamless, delve into, in conclusion, etc.) - STEP8 rewritten into 6 structured steps: hunt AI words, break rhythm, add human element, fix label formats, structural cleanup, ensure Flexoptix identity - Banned sentence structures added (parallel triplets, same-length paragraphs) - STEP6 author identity: reader should know this came from Flexoptix - Version bump to 0.3.0
This commit is contained in:
parent
e1877672c0
commit
8b187a5dac
@ -69,7 +69,7 @@ app.get("/", (_req, res) => {
|
|||||||
app.get("/api", (_req, res) => {
|
app.get("/api", (_req, res) => {
|
||||||
res.json({
|
res.json({
|
||||||
name: "Transceiver Intelligence Platform",
|
name: "Transceiver Intelligence Platform",
|
||||||
version: "0.2.6",
|
version: "0.3.0",
|
||||||
endpoints: [
|
endpoints: [
|
||||||
"GET /api/transceivers?q=&form_factor=&speed=&category=&fiber_type=&wdm_type=&coherent=",
|
"GET /api/transceivers?q=&form_factor=&speed=&category=&fiber_type=&wdm_type=&coherent=",
|
||||||
"GET /api/transceivers/:id",
|
"GET /api/transceivers/:id",
|
||||||
|
|||||||
@ -42,9 +42,39 @@ VOICE:
|
|||||||
- Occasionally blunt or sarcastic
|
- Occasionally blunt or sarcastic
|
||||||
- Prioritize clarity over completeness
|
- Prioritize clarity over completeness
|
||||||
|
|
||||||
STRICTLY FORBIDDEN:
|
STRICTLY FORBIDDEN — AI PHRASING BLACKLIST (any of these = rewrite):
|
||||||
|
|
||||||
|
BANNED WORDS & PHRASES (AI fingerprints — never use):
|
||||||
|
- "leverage", "optimize", "enhance", "plays a key role", "unlock", "empower"
|
||||||
|
- "In today's fast-paced world", "In the ever-evolving landscape", "it goes without saying"
|
||||||
|
- "it is worth noting", "it is important to note", "it should be noted"
|
||||||
|
- "that being said", "with that in mind", "at the end of the day"
|
||||||
|
- "delve into", "dive into", "explore", "unpack", "shed light on"
|
||||||
|
- "game-changer", "game-changing", "cutting-edge", "state-of-the-art", "industry-leading"
|
||||||
|
- "robust", "seamless", "scalable", "holistic", "comprehensive" (as empty adjectives)
|
||||||
|
- "it is crucial to", "it is essential to", "it is vital to"
|
||||||
|
- "in conclusion", "to summarize", "in summary", "to wrap up"
|
||||||
|
- "Furthermore", "Additionally", "Moreover", "Consequently", "Subsequently"
|
||||||
|
- "This is why X is not optional, but part of the baseline operating model" — McKinsey speak
|
||||||
|
- "X rarely comes from a single obvious source" — vague academic hedge
|
||||||
|
- "The discussion around X is often framed as" — consulting opening
|
||||||
|
- "In practice, things tend to behave differently" — too soft, say HOW they behave
|
||||||
|
- "a testament to", "a reflection of", "underscores the importance of"
|
||||||
|
- "revolutionary", "industry-leading", "next-generation", "world-class"
|
||||||
|
- "streamline", "streamlined", "best-in-class", "cutting edge"
|
||||||
|
- "nuanced", "multifaceted", "ecosystem" (when used vaguely)
|
||||||
|
- "paradigm", "synergy", "utilize" (say "use")
|
||||||
|
|
||||||
|
BANNED SENTENCE STRUCTURES (AI patterns):
|
||||||
|
- Perfectly parallel sentences: "X does A. Y does B. Z does C." — vary the rhythm
|
||||||
|
- Every paragraph same length — break it
|
||||||
|
- Sentences starting with "This" three times in a row — AI hallmark
|
||||||
|
- Ending a section with a 3-4 word summary sentence that restates what was just said
|
||||||
|
- "Both X and Y have their place" — wishy-washy non-conclusion
|
||||||
|
- "Ultimately, the decision depends on..." without saying what it depends on specifically
|
||||||
|
|
||||||
|
BANNED STRUCTURAL PATTERNS:
|
||||||
- "In today's fast-paced world" or ANY generic intro
|
- "In today's fast-paced world" or ANY generic intro
|
||||||
- "leverage", "optimize", "enhance", "plays a key role"
|
|
||||||
- Empty bullet lists without context
|
- Empty bullet lists without context
|
||||||
- Neutral non-advice ("it depends on your requirements")
|
- Neutral non-advice ("it depends on your requirements")
|
||||||
- Textbook explanations of basic concepts
|
- Textbook explanations of basic concepts
|
||||||
@ -332,33 +362,66 @@ Article:
|
|||||||
// STEP 8: KILL AI TONE
|
// STEP 8: KILL AI TONE
|
||||||
// ═══════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════
|
||||||
|
|
||||||
export const STEP8_KILL_AI_TONE = `Rewrite this article to remove ALL signs of AI-generated text.
|
export const STEP8_KILL_AI_TONE = `Your task: make this article sound like it was written by a human engineer who has actual opinions — not by a language model trying to be balanced and comprehensive.
|
||||||
|
|
||||||
REMOVE:
|
STEP 1 — HUNT AND DESTROY AI WORDS (scan every sentence, replace or delete):
|
||||||
- Overly perfect sentence structures
|
These words are AI fingerprints. Any of them = rewrite that sentence.
|
||||||
- Repetitive paragraph patterns (same opening, same length)
|
→ "leverage" → use "use"
|
||||||
- Generic transition phrases ("Furthermore", "Additionally", "It's worth noting")
|
→ "utilize" → use "use"
|
||||||
- Lists that all follow identical format
|
→ "Furthermore", "Additionally", "Moreover" → delete the word, rewrite transition naturally or cut
|
||||||
- Perfect grammar everywhere — add occasional conversational shortcuts
|
→ "It is worth noting", "It is important to note", "it should be noted" → delete entirely, just say the thing
|
||||||
- Phrases like "it is important to note", "one should consider"
|
→ "delve into", "dive into", "explore" → skip the preamble, start doing it
|
||||||
- Any section that ends with a tidy 4-item bullet list
|
→ "robust" as empty adjective → name what makes it robust, or delete
|
||||||
- Perfectly symmetrical sections (same length = AI fingerprint)
|
→ "seamless" → delete, nothing is seamless
|
||||||
- ALL markdown headers: ##, ###, ####, **Bold Section Title:** — strip every single one. Write plain text only.
|
→ "holistic", "comprehensive" as empty adjectives → delete
|
||||||
- Repeated explanations: if cleaning, polarity, or power is in two sections, merge them into the first occurrence and remove the second.
|
→ "that being said", "with that in mind", "at the end of the day" → delete
|
||||||
- "Cause:" / "Fix:" / "Example:" labels — these are documentation format, not blog format. Integrate into prose.
|
→ "in conclusion", "to summarize", "in summary" → delete, article already said it
|
||||||
BAD: "**Cause:** Mismatched firmware versions. **Fix:** Validate compatibility before deployment."
|
→ "a testament to", "underscores the importance of", "a reflection of" → rewrite directly
|
||||||
GOOD: "Firmware mismatches are rarely obvious. In one deployment, optics initialized cleanly but started flapping under load — the issue turned out to be a version mismatch between switch and transceiver firmware that only surfaced under realistic traffic."
|
→ "nuanced", "multifaceted" → say what you actually mean
|
||||||
- Repeated MMF→SMF transitions: if the cabling change is explained more than once, merge into one place.
|
→ "streamline", "streamlined" → say what changes specifically
|
||||||
- "fraught with hidden risks" or similar fear-selling language — replace with "introduces additional operational considerations"
|
→ "paradigm" → delete or say "approach"
|
||||||
- "When Not to Use" as a bullet list — integrate into prose: "In smaller environments or legacy MMF deployments, the overhead of validation and migration can outweigh the cost advantage."
|
→ "synergy" → delete always
|
||||||
- "Example:" as a standalone label before a quote — weave the example into the surrounding paragraph naturally.
|
→ "it is crucial to", "it is essential to", "it is vital to" → just say the thing without the preamble
|
||||||
|
→ "This is why X is not optional, but part of the baseline operating model" → say "X is required. Period."
|
||||||
|
→ "In practice, things tend to behave differently" → say HOW they behave differently, with an example
|
||||||
|
→ "The discussion is often framed as X versus Y" → skip framing, start with the actual point
|
||||||
|
→ "Both X and Y have their place" → take a position or cut the sentence
|
||||||
|
→ "Ultimately" as sentence opener → delete or rephrase
|
||||||
|
|
||||||
REPLACE WITH:
|
STEP 2 — BREAK PERFECT AI RHYTHM:
|
||||||
- Natural, slightly imperfect flow
|
AI writes in perfectly even waves. Humans don't. Fix it:
|
||||||
- Varied sentence lengths (some very short, some longer)
|
→ After 3 same-length sentences: add ONE very short one. "It usually doesn't." or "That's the problem."
|
||||||
- Conversational asides ("Look, ...", "Here's the thing:", "Don't get me started on...")
|
→ After a long technical paragraph: one direct opinion sentence. "Most teams don't catch this until it's too late."
|
||||||
- Direct address ("You know this is true if...")
|
→ Vary paragraph length — some 1 sentence, some 4. Never all the same.
|
||||||
- Specific instead of generic ("the Nexus 93180 in rack 14" not "your network switch")
|
→ If every paragraph starts with "The" or "In" — vary the opening words
|
||||||
|
|
||||||
|
STEP 3 — ADD ONE HUMAN ELEMENT PER ARTICLE:
|
||||||
|
Choose ONE of these and add it naturally:
|
||||||
|
→ A conversational aside: "Look, nobody is going to tell you this in a sales call, but..."
|
||||||
|
→ A direct address: "If you've been on a pager call at 2AM for a dirty connector, you know exactly what I mean."
|
||||||
|
→ A blunt Flexoptix statement: "We sell compatible optics. We've also seen what happens when teams skip validation. The optics aren't the problem."
|
||||||
|
→ An admission: "There's no clean answer here. The right choice depends on whether you've done the work upfront."
|
||||||
|
|
||||||
|
STEP 4 — FIX LABEL FORMATS:
|
||||||
|
→ "Cause:" / "Fix:" / "Example:" as labels → integrate into prose narrative
|
||||||
|
BAD: "Cause: Firmware mismatch. Fix: Validate before deployment."
|
||||||
|
GOOD: "In one deployment, links came up cleanly but started flapping under load. The root cause was a firmware version gap between switch and transceiver — something that only surfaced under real traffic. Aligning firmware across both platforms fixed it."
|
||||||
|
→ "When Not to Use" as bullet list → one flowing paragraph
|
||||||
|
→ "BUY / WAIT / SKIP" sections → delete, say it as one direct sentence instead
|
||||||
|
|
||||||
|
STEP 5 — STRUCTURAL CLEANUP:
|
||||||
|
→ ALL markdown headers: ##, ###, #### → remove, plain text only
|
||||||
|
→ Repeated topics (cleaning in two sections, MMF/SMF twice) → merge into first occurrence, delete second
|
||||||
|
→ "fraught with" → replace with specific description of what happens
|
||||||
|
→ Sentences starting "This" three times in a row → vary the opener
|
||||||
|
→ ALL markdown headers: ##, ###, ####, **Bold Section Title:** → strip every single one
|
||||||
|
|
||||||
|
STEP 6 — ENSURE FLEXOPTIX IS RECOGNIZABLE AS AUTHOR:
|
||||||
|
→ The reader should know this came from Flexoptix — not a generic tech blog
|
||||||
|
→ If Flexoptix appears 0 times in the article: add it once naturally
|
||||||
|
Example: "This is something we see regularly at Flexoptix — teams that saved 70% on optics and spent twice that on troubleshooting because they skipped the validation step."
|
||||||
|
→ The author sells optics. They have an opinion. They've seen what fails. Show that.
|
||||||
|
→ One sentence of Flexoptix perspective is enough — don't make it an ad, just make it human
|
||||||
|
|
||||||
PROSE STYLE OPTION (use when article currently feels too structured/sectioned):
|
PROSE STYLE OPTION (use when article currently feels too structured/sectioned):
|
||||||
If the article has many headers and bullet points and reads like a slide deck, consider
|
If the article has many headers and bullet points and reads like a slide deck, consider
|
||||||
|
|||||||
@ -14,7 +14,7 @@ healthRouter.get("/", async (_req: Request, res: Response) => {
|
|||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
status: "healthy",
|
status: "healthy",
|
||||||
version: "0.2.6",
|
version: "0.3.0",
|
||||||
uptime: process.uptime(),
|
uptime: process.uptime(),
|
||||||
database: {
|
database: {
|
||||||
connected: true,
|
connected: true,
|
||||||
|
|||||||
@ -21,10 +21,10 @@
|
|||||||
}
|
}
|
||||||
blogPipelineRunning = true;
|
blogPipelineRunning = true;
|
||||||
|
|
||||||
var blogList = document.getElementById('blog-list');
|
var pipelineEl = document.getElementById('blog-pipeline-status');
|
||||||
if (blogList) {
|
if (pipelineEl) {
|
||||||
blogList.innerHTML =
|
pipelineEl.innerHTML =
|
||||||
'<div style="background:linear-gradient(135deg,#1a1a1a,#2a2a2a);color:white;padding:2rem;border-radius:12px;text-align:center">' +
|
'<div style="background:linear-gradient(135deg,#1a1a1a,#2a2a2a);color:white;padding:2rem;border-radius:12px;text-align:center;margin-bottom:1rem">' +
|
||||||
'<div style="font-size:1.4rem;font-weight:700;margin-bottom:1rem">Generating Blog with AI...</div>' +
|
'<div style="font-size:1.4rem;font-weight:700;margin-bottom:1rem">Generating Blog with AI...</div>' +
|
||||||
'<div id="bp-status" style="font-size:1rem;color:#FF8100;margin-bottom:0.5rem">Starting 10-step Flexoptix Style pipeline...</div>' +
|
'<div id="bp-status" style="font-size:1rem;color:#FF8100;margin-bottom:0.5rem">Starting 10-step Flexoptix Style pipeline...</div>' +
|
||||||
'<div id="bp-step" style="font-size:0.85rem;color:#aaa">Connecting to LLM (qwen2.5:14b)</div>' +
|
'<div id="bp-step" style="font-size:0.85rem;color:#aaa">Connecting to LLM (qwen2.5:14b)</div>' +
|
||||||
@ -63,15 +63,36 @@
|
|||||||
function pollPipeline(id, attempt) {
|
function pollPipeline(id, attempt) {
|
||||||
if (attempt > 80) {
|
if (attempt > 80) {
|
||||||
blogPipelineRunning = false;
|
blogPipelineRunning = false;
|
||||||
|
var pipelineEl = document.getElementById('blog-pipeline-status');
|
||||||
|
if (pipelineEl) pipelineEl.innerHTML = '';
|
||||||
if (typeof showToast === 'function') showToast('Timeout', 'Pipeline took too long. Check the blog list.');
|
if (typeof showToast === 'function') showToast('Timeout', 'Pipeline took too long. Check the blog list.');
|
||||||
if (typeof loadBlogDrafts === 'function') loadBlogDrafts();
|
if (typeof loadBlogDrafts === 'function') loadBlogDrafts();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Poll progress endpoint (fast) + blog status endpoint (to detect completion)
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
fetch((API || '') + '/api/blog/' + id).then(function(r) { return r.json(); }).then(function(data) {
|
// 1) Fetch real-time progress from server
|
||||||
|
fetch((API || '') + '/api/blog/' + id + '/progress')
|
||||||
|
.then(function(r) { return r.json(); })
|
||||||
|
.then(function(prog) {
|
||||||
|
if (prog.running) {
|
||||||
|
var bar = document.getElementById('bp-bar');
|
||||||
|
var pct = document.getElementById('bp-pct');
|
||||||
|
var status = document.getElementById('bp-status');
|
||||||
|
var step = document.getElementById('bp-step');
|
||||||
|
if (bar) bar.style.width = prog.pct + '%';
|
||||||
|
if (pct) pct.textContent = prog.pct + '%';
|
||||||
|
if (status) status.textContent = prog.label || ('Step ' + prog.step + '/10');
|
||||||
|
if (step) step.textContent = 'Running on qwen2.5:14b via Ollama...';
|
||||||
|
}
|
||||||
|
}).catch(function() {});
|
||||||
|
|
||||||
|
// 2) Fetch blog draft to detect pipeline completion
|
||||||
|
fetch((API || '') + '/api/blog/' + id)
|
||||||
|
.then(function(r) { return r.json(); })
|
||||||
|
.then(function(data) {
|
||||||
var d = data.draft || data;
|
var d = data.draft || data;
|
||||||
var gen = d.generated_by || '';
|
var gen = d.generated_by || '';
|
||||||
var steps = d.pipeline_steps_completed || 0;
|
|
||||||
var done = gen && gen !== 'tip-blog-engine-template' && gen.length > 0;
|
var done = gen && gen !== 'tip-blog-engine-template' && gen.length > 0;
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
@ -82,29 +103,21 @@
|
|||||||
var step = document.getElementById('bp-step');
|
var step = document.getElementById('bp-step');
|
||||||
if (bar) bar.style.width = '100%';
|
if (bar) bar.style.width = '100%';
|
||||||
if (pct) pct.textContent = '100%';
|
if (pct) pct.textContent = '100%';
|
||||||
if (status) { status.textContent = 'Blog generated! ' + (d.word_count || '?') + ' words'; status.style.color = '#2d6a4f'; }
|
if (status) { status.textContent = '✓ Blog fertig! ' + (d.word_count || '?') + ' Wörter'; status.style.color = '#2d6a4f'; }
|
||||||
if (step) step.textContent = 'Generated by: ' + gen;
|
if (step) step.textContent = 'Engine: ' + gen;
|
||||||
blogPipelineRunning = false;
|
blogPipelineRunning = false;
|
||||||
if (typeof showToast === 'function') showToast('Blog Ready!', (d.title || 'Article') + ' — ' + (d.word_count || '?') + ' words');
|
if (typeof showToast === 'function') showToast('Blog Ready!', (d.title || 'Article') + ' — ' + (d.word_count || '?') + ' words');
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
|
var pipelineEl = document.getElementById('blog-pipeline-status');
|
||||||
|
if (pipelineEl) pipelineEl.innerHTML = '';
|
||||||
if (typeof loadBlogDrafts === 'function') loadBlogDrafts();
|
if (typeof loadBlogDrafts === 'function') loadBlogDrafts();
|
||||||
if (typeof viewBlogDraft === 'function') viewBlogDraft(id);
|
if (typeof viewBlogDraft === 'function') viewBlogDraft(id);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
} else {
|
} else {
|
||||||
// Still processing
|
|
||||||
var pctVal = Math.min(95, steps * 10 + 5);
|
|
||||||
var bar = document.getElementById('bp-bar');
|
|
||||||
var pct = document.getElementById('bp-pct');
|
|
||||||
var status = document.getElementById('bp-status');
|
|
||||||
var step = document.getElementById('bp-step');
|
|
||||||
if (bar) bar.style.width = pctVal + '%';
|
|
||||||
if (pct) pct.textContent = pctVal + '%';
|
|
||||||
if (status) status.textContent = 'Step ' + steps + '/10';
|
|
||||||
if (step && steps > 0 && steps <= 10) step.textContent = STEP_NAMES[steps - 1] || 'Processing...';
|
|
||||||
pollPipeline(id, attempt + 1);
|
pollPipeline(id, attempt + 1);
|
||||||
}
|
}
|
||||||
}).catch(function() { pollPipeline(id, attempt + 1); });
|
}).catch(function() { pollPipeline(id, attempt + 1); });
|
||||||
}, 15000);
|
}, 8000); // Poll every 8s instead of 15s for snappier UI
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hot topics loader
|
// Hot topics loader
|
||||||
@ -149,6 +162,13 @@
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// Called via data attributes to avoid quote-escaping issues in onclick
|
||||||
|
window.blogDeleteClick = function(el) {
|
||||||
|
var id = el.getAttribute('data-blog-id');
|
||||||
|
var title = el.getAttribute('data-blog-title');
|
||||||
|
if (id) window.deleteBlogDraft(id, title);
|
||||||
|
};
|
||||||
|
|
||||||
// Delete a single blog draft
|
// Delete a single blog draft
|
||||||
window.deleteBlogDraft = function(id, title) {
|
window.deleteBlogDraft = function(id, title) {
|
||||||
if (!confirm('Delete "' + title + '"?')) return;
|
if (!confirm('Delete "' + title + '"?')) return;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user