The Doozer Brainlive from the knowledge bundle · v2.2.618 · 2026-09-13 17:14 ETall pages · one page

Content Generation Pipeline (providers, models, timeouts)

systems/content-generation.md · System · ai, content, providers, reliability, seo

unverified: no trust signals recorded yet

How AI site prose is actually produced — the two provider paths, model config, the 90s timeout, the anti-boilerplate footer, and every failure mode that bit us.

Content Generation Pipeline

This is the engine behind Content Generation and Healing. It produces businesses.ai_generated_content (headline, about, services, why_choose_us, faq, meta_description, suggested_colors). Hard-won operational truths live here — read before touching AI content, model config, or regeneration.

The governing principle (why site voice varies so much place to place) lives in Per-Location Data Enrichment: a site's voice is signal-in, signal-out. The lever for a thin site is more/better input data, never a forced tone.

Entry point + the TWO paths (keep both in sync)

generateBusinessContent($businessRow) in includes/ai-content.php is the entry. It takes the business row (from getBusinessById()), NOT a Google-Places shape. There is no generateContent() — calling that name silently broke every content regen with "Content generator unavailable" (fixed v2.2.235).

It tries two paths, and a change to ANY of prompt / timeout / model must cover BOTH:

  1. Flexible path (tried FIRST, used in production): generateContentFlexible() in
  2. includes/ai-provider-system.php. Reads the per-content-type model config, builds the prompt from the DB template, calls callAnthropic() / callOpenAICompatible().

  3. Legacy path (fallback): ai-content.php's own callAnthropic/callOpenAI. Has its own
  4. model resolution + the historical default claude-3-5-sonnet-20241022.

DURABLE RULE: the flexible path is what runs ~always. If you only patch ai-content.php you patched the wrong path. (This exact trap meant the anti-boilerplate footer didn't apply for a full cycle — see below.)

Model config (settings, not code)

Per-content-type provider/model lives in the ai_content_configs table (rows: business_website, photo_vision), joined to ai_models + ai_providers. Set it via Admin → AI Management (it's under the Infrastructure menu, ?page=admin&section=ai → Content Configuration → Configure), NOT a migration. Class aliases resolve via aiModelResolve() over the includes/ai-models.php catalog.

DURABLE RULE: the content primary model must be a FAST quality model — claude-sonnet-4-6. Do NOT set a reasoning model (gpt-5, o-series) as the synchronous content primary: they take far longer than the timeout for a 2048-token generation and every call aborts with HTTP 0. (gpt-5 as a primary is what caused the June 2026 network-wide content outage.)

Timeout (why 90s)

Content asks for up to 2048 output tokens; a quality model needs 25-60s for that length. The historical 30s cURL timeout aborted generation mid-stream → cURL returns HTTP 0. Fixed: AI_TIMEOUT_SECONDS = 90 in config/app.php (legacy path) AND callAnthropic/callOpenAICompatible in ai-provider-system.php default their cURL timeout to AI_TIMEOUT_SECONDS (v2.2.238). Both paths, or it regresses. Safe because content gen runs via the queue worker (post-response) or CLI batches, and admin synchronous regen is rare/one-at-a-time — not a visitor FPM hot path.

Anti-boilerplate (the SEO-load-bearing part)

_aiContentProseQualityFooter() (ai-content.php) prepends the shared Design Standards rules + an ORIGINALITY block that BANS templated openers ("nestled", "in the heart of", "stands as a beacon", "more than just a", "steeped in tradition") and em-dashes, and requires a page-specific opener built from real data. It is appended in BOTH paths (legacy always; flexible since v2.2.239). Without it, similar businesses get near-identical prose — the near-duplicate cluster that triggered the [elks.club scaled-content demotion]. See the project_seo_cliff_recovery memory + site-quality scoring for measuring boilerplate.

Failure modes (decode these fast)

Regeneration + batch rollout

regenerationRun($businessId, 'content') ([regeneration.php]) wraps generateBusinessContent with a readability quality gate (keeps prior content if the new draft fails) + manifest stamp. Fleet rollout = worst-first over site-quality-score boilerplate-flagged pages, rate-limited, resumable (re-run skips now-clean). ALWAYS dz ai_status first — a big batch on an empty credit balance fails silently. Operator preference: drive batches via the Dev API, not raw php -r pasted into a root shell.

Diagnostics

See also hosting infrastructure (the queue + drain) and design standards (the prose rules enforced at the source).

Clouds (curated directories)Context-city poisoning (never name a place after where you found it)