Build an AI Content Generator with Python
Every project so far has been grounded in specific, provided facts — the whole point being to prevent invention. This part is genuinely different: content generation, where creative, original output is the actual goal, not a risk to manage. The real use case: draft blog posts for Bright Leaf Coffee's content marketing.
The real, complete generator
# content_generator.py
from shared.ai_client import get_client
def generate_blog_draft(topic: str, funnel_stage: str, word_count: int = 400) -> str:
client = get_client()
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=2048,
system=(
f"Write a {word_count}-word blog post draft for Bright "
f"Leaf Coffee, a small-batch coffee subscription business. "
f"This post targets the {funnel_stage} stage of the "
f"customer journey. Use a warm, direct, knowledgeable "
f"tone. Include a clear H2 structure. Do not invent "
f"specific customer testimonials or statistics."
),
messages=[{"role": "user", "content": f"Topic: {topic}"}],
)
return response.content[0].textWhy "funnel stage" is a real, deliberate parameter, not decoration
generate_blog_draft(
topic="why coffee goes stale",
funnel_stage="Awareness (educational, not sales-focused)",
)
generate_blog_draft(
topic="how our Gift Subscription works",
funnel_stage="Decision (directly addressing purchase hesitation)",
)This directly reuses the exact real framework from the Content Marketing series' own funnel-stage guidance — an Awareness-stage draft and a Decision-stage draft on the same general subject need genuinely different tones and structures, and making that distinction an explicit, real parameter is what keeps this generator producing content that actually fits a real content strategy, rather than generic, undifferentiated blog copy.
The real, deliberate constraint against inventing evidence
"Do not invent specific customer testimonials or statistics"This is a genuinely important, real guardrail even in a creative-generation context — while the tone and structure of this task is meant to be creative, specific factual claims (a customer quote, a statistic) still carry the exact same hallucination risk covered throughout this series. A real blog draft inventing a fabricated customer testimonial is a genuine, real problem, distinct from and worse than the acceptable creative latitude in phrasing and structure.
This is the real, precise line between "creative" and "ungrounded" worth understanding clearly: original phrasing, structure, and tone are exactly what this task wants the model to generate freely; specific, checkable factual claims still need the same grounding discipline as every earlier project in this series. Treating the entire output as equally "creative" and equally acceptable to fabricate is a real, common mistake.
A real, structured output for programmatic use
def generate_blog_draft_structured(topic: str, funnel_stage: str) -> dict:
system = (
f"Write a blog post draft for Bright Leaf Coffee on '{topic}' "
f"for the {funnel_stage} stage. Respond with ONLY valid JSON "
f"in this exact format: "
f'{{"title": "...", "meta_description": "...", "body_markdown": "..."}}'
)
# ...same real request structure, then json.loads() the responseRequesting a real, structured JSON response — rather than raw prose — directly sets this generator up to feed a real CMS or the SEO series' own title tag and meta description guidance programmatically, generating not just body content but the actual real SEO metadata alongside it in one request.
A real, honest role for this tool: draft, not publish
This generator produces a real, genuine FIRST DRAFT — a meaningful
head start, not a finished, publish-ready postEvery real post this tool generates still needs real, human review — for factual accuracy (per this project's own constraint above), for genuine brand voice fit beyond what a prompt alone guarantees, and for the kind of real, first-hand insight and specific detail (the Content Marketing series' own thought-leadership guidance) that a generic AI draft, however fluent, genuinely can't originate on its own.
Next: keeping AI-generated content on-brand — real, concrete techniques for making this generator's output consistently sound like Bright Leaf Coffee, not generic AI copy.