We will build a lightweight CLI content generator that turns a topic, audience, and tone into a structured blog post. It streams output from Oxlo.ai and saves the draft to a Markdown file. This is useful for technical writers and developer advocates who need repeatable first drafts without token-counting overhead.
What you'll need
- Python 3.10 or newer
- An Oxlo.ai API key from https://portal.oxlo.ai
- The OpenAI SDK:
pip install openai
Step 1: Configure the Oxlo.ai client
First, instantiate the OpenAI SDK pointing at Oxlo.ai. Paste your key directly for testing, or load it from an environment variable in production.
from openai import OpenAI
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Say hello"},
],
)
print(response.choices[0].message.content)
Step 2: Define the system prompt
I keep the system prompt in a module-level constant so I can tweak style and structure without touching the request logic.
SYSTEM_PROMPT = """You are a technical content writer. When given a topic, audience, and tone, generate a complete blog post with this exact structure:
1. A compelling headline
2. A three bullet outline
3. An introduction paragraph of two to three sentences
4. Three body sections with subheadings
5. A one paragraph conclusion
Keep paragraphs short. Use concrete examples. Match the requested tone precisely."""
Step 3: Build the generator function
This function formats the user inputs and calls Llama 3.3 70B on Oxlo.ai. I set temperature to 0.7 for a balance of creativity and consistency.
def generate_blog_post(topic, audience, tone):
user_message = f"Topic: {topic}\nAudience: {audience}\nTone: {tone}"
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
],
temperature=0.7,
max_tokens=1500,
)
return response.choices[0].message.content
Step 4: Stream the response
Waiting for the full article feels slow. Streaming lets us watch the draft appear word by word. Oxlo.ai supports this with no cold starts on popular models.
def generate_blog_post_streaming(topic, audience, tone):
user_message = f"Topic: {topic}\nAudience: {audience}\nTone: {tone}"
stream = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
],
temperature=0.7,
max_tokens=1500,
stream=True,
)
full_text = ""
for chunk in stream:
token = chunk.choices[0].delta.content
if token:
full_text += token
print(token, end="", flush=True)
print()
return full_text
Step 5: Save the draft to disk
I timestamp and slugify the filename so I never overwrite an earlier version. This turns the script into a useful daily tool.
import datetime
def save_post(slug, content):
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"{slug}_{timestamp}.md"
with open(filename, "w", encoding="utf-8") as f:
f.write(content)
print(f"\nSaved: {filename}")
if __name__ == "__main__":
print("Drafting post...")
content = generate_blog_post_streaming(
topic="Request-based pricing for LLM inference",
audience="engineering managers",
tone="practical and concise"
)
save_post("content_gen_guide", content)
Run it
Run the script from your terminal. You should see the headline and sections stream in, followed by a save confirmation.
$ python content_generator.py
Drafting post...
**Headline:** How Request-Based Pricing Cuts LLM Inference Costs
**Outline:**
- Why token counting complicates budgets
- When flat per-request pricing wins
- A migration checklist for engineering teams
**Introduction**
Engineering managers often struggle to forecast API spend...
[body sections stream here]
Saved: content_gen_guide_20250615_143022.md
If you want to experiment, swap model="llama-3.3-70b" for qwen-3-32b or kimi-k2.6. All use the same Oxlo.ai endpoint and SDK pattern.
Next steps
Try adding JSON mode to parse the headline and outline into separate fields for a CMS. Alternatively, wire the generator into a Slack bot so your team can request drafts from a slash command. Both extensions are straightforward because Oxlo.ai supports function calling and streaming on the same endpoint.
Top comments (0)