DEV Community

shashank ms
shashank ms

Posted on

LLM Models for Text Generation and Creative Writing for Content Creation

We are building a creative writing pipeline that turns a one-line brief into a publish-ready blog post. It is useful for content teams and solo founders who need consistent drafts without managing token budgets across multiple providers. Because Oxlo.ai uses flat per-request pricing, running multi-step chains with long context does not inflate costs.

What you'll need

Step 1: Set up the client

I always start by confirming the API key works. This snippet initializes the OpenAI SDK pointing at Oxlo.ai and runs a quick sanity check.

from openai import OpenAI
import os

client = OpenAI(
    base_url="https://api.oxlo.ai/v1",
    api_key=os.environ.get("OXLO_API_KEY", "YOUR_OXLO_API_KEY")
)

# Sanity check
response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[{"role": "user", "content": "Say hello"}],
    max_tokens=10
)
print(response.choices[0].message.content)

Step 2: Define the system prompt

The system prompt locks the model into a consistent editorial voice. I treat this as a config variable so I can tweak tone without touching logic.

SYSTEM_PROMPT = """You are a senior content strategist and creative writer.
Your job is to turn briefs into engaging, accurate blog posts.
Follow these rules:
- Write in a conversational but authoritative tone.
- Use short paragraphs and concrete examples.
- Avoid generic fluff and marketing jargon.
- When given an outline, expand every point into at least one substantial paragraph.
- Output only the requested content, no meta commentary."""

Step 3: Generate an outline

I split the work into an outline step because it gives me a checkpoint I can edit before the model burns context on a full draft. I use Llama 3.3 70B for its strong general-purpose output.

def generate_outline(topic, audience):
    user_message = (
        f"Create a 5-point outline for a blog post about '{topic}'. "
        f"The target audience is {audience}. "
        f"Return only the outline, one item per line."
    )
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
    )
    return response.choices[0].message.content.strip()

Step 4: Write the first draft

With the outline in hand, I ask the model to write the full post. Because Oxlo.ai uses per-request pricing, I can pass the entire outline plus a detailed brief in a single call without worrying about input token costs.

def write_draft(topic, audience, outline):
    user_message = (
        f"Write a complete blog post about '{topic}' for {audience}. "
        f"Use the following outline:\n\n{outline}\n\n"
        f"The post should be around 600 words. Include a title and subheadings."
    )
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
    )
    return response.choices[0].message.content.strip()

Step 5: Self-critique and polish

I run a second pass to catch weak transitions and filler. For this reasoning-heavy critique step, I switch to Qwen 3 32B, which handles agentic workflows well. I feed the draft back in and ask for a refined version.

def polish_draft(draft):
    user_message = (
        "Critique the following blog post for clarity, flow, and specificity. "
        "Then rewrite it incorporating your critique.\n\n"
        f"{draft}"
    )
    response = client.chat.completions.create(
        model="qwen-3-32b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
    )
    return response.choices[0].message.content.strip()

Step 6: Wire the pipeline together

The main block ties the three stages together and prints intermediate results so I can audit the process.

if __name__ == "__main__":
    import sys

    topic = sys.argv[1] if len(sys.argv) > 1 else "API design best practices"
    audience = sys.argv[2] if len(sys.argv) > 2 else "software engineers"

    print("=== OUTLINE ===")
    outline = generate_outline(topic, audience)
    print(outline)

    print("\n=== FIRST DRAFT ===")
    draft = write_draft(topic, audience, outline)
    print(draft[:500] + "...")

    print("\n=== FINAL POLISH ===")
    final = polish_draft(draft)
    print(final)

Run it

Save the script as writer.py, export your key, and pass a topic and audience.

export OXLO_API_KEY="sk-oxlo.ai-..."
python writer.py "per-request LLM pricing" "developer advocates"

Example output:

=== OUTLINE ===
1. Why token pricing surprises teams at scale
2. How per-request pricing changes the math
3. Comparing long-context workloads on Oxlo.ai
4. Agentic loops without budget anxiety
5. Switching your pipeline to a flat-rate provider

=== FIRST DRAFT ===
Title: The Hidden Tax on Long Inputs

If you have ever shipped a RAG pipeline, you know the sting...

=== FINAL POLISH ===
Title: The Hidden Tax on Long Inputs

Shipping a RAG pipeline teaches you one lesson fast: cost scales with context, not value. When you pay by the token, every retrieved document and every system prompt nudges your bill upward. For agentic workflows that chain multiple model calls, that tax compounds quickly.

Flat per-request pricing flips the model. You pay once whether your prompt is fifty tokens or fifty thousand. That predictability matters for content pipelines, too. You can pass full style guides, prior drafts, and detailed briefs in a single call without watching a meter spin.

...

Next steps

Swap the polish step for Kimi K2.6 if you need vision support to critique layouts, or host the script behind a FastAPI endpoint and stream responses back to an editor UI. You can also cache the outline stage and let human editors rewrite it before the draft step, turning this into a human-in-the-loop workflow.

Top comments (0)