We will build a content quality optimizer that scores rough drafts against a rubric and iteratively rewrites them until they hit a quality threshold. This helps teams ship consistent blog posts, docs, and product copy without manual editing loops. We will run it on Oxlo.ai using flat per-request pricing so iteration cost stays predictable.
What you'll need
- Python 3.10+
- The OpenAI SDK:
pip install openai - An Oxlo.ai API key from https://portal.oxlo.ai
Step 1: Define the rubric and initialize the client
I will set up the Oxlo.ai client and define the four quality criteria we will use to judge every draft.
from openai import OpenAI
import json
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
RUBRIC = {
"clarity": "Sentences are direct and easy to follow. Jargon is defined or avoided.",
"structure": "Logical flow with clear transitions between ideas.",
"tone": "Consistent voice appropriate for the target audience.",
"actionability": "Reader knows what to do next after reading."
}
QUALITY_THRESHOLD = 8
MAX_ITERATIONS = 3
Step 2: Build the evaluator
The evaluator sends the draft to a reasoning model and returns structured JSON scores. I use kimi-k2.6 here because its advanced reasoning produces consistent numerical scores.
def evaluate_content(draft, audience="technical"):
prompt = f"""Evaluate the following draft against this rubric. Score each category 1-10.
Rubric: {json.dumps(RUBRIC, indent=2)}
Target audience: {audience}
Draft:
{draft}
Return ONLY valid JSON in this exact format:
{{"scores": {{"clarity": int, "structure": int, "tone": int, "actionability": int}}, "top_issue": "string", "revision_priority": "string"}}"""
response = client.chat.completions.create(
model="kimi-k2.6",
messages=[{"role": "user", "content": prompt}],
response_format={"type": "json_object"}
)
return json.loads(response.choices[0].message.content)
Step 3: Build the revision agent
Next I need the reviser. It takes the original draft plus the evaluator feedback and rewrites the text. I keep the system prompt strict so it does not add fluff or commentary.
SYSTEM_PROMPT = """You are a senior content editor. Your job is to rewrite drafts to maximize quality.
Rules:
- Preserve the original intent and key facts.
- Address every issue mentioned in the feedback.
- Maintain the target tone for the specified audience.
- Do not add fluff or generic conclusions.
- Output only the revised text, no commentary."""
def revise_content(draft, evaluation, audience="technical"):
feedback = f"""Scores: {json.dumps(evaluation['scores'])}
Top issue: {evaluation['top_issue']}
Priority: {evaluation['revision_priority']}
Audience: {audience}"""
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": f"Draft:\n{draft}\n\nFeedback:\n{feedback}\n\nRevise the draft."}
]
)
return response.choices[0].message.content
Step 4: Wire the optimization loop
Now I connect the two functions in a loop that runs until the average score hits 8 or we reach three iterations. Because Oxlo.ai charges per request rather than per token, adding this evaluation loop stays cost predictable even when drafts grow to long-context lengths. See https://oxlo.ai/pricing for plan details.
def optimize_content(draft, audience="technical"):
current_draft = draft
history = []
for i in range(MAX_ITERATIONS):
eval_result = evaluate_content(current_draft, audience)
history.append({"iteration": i + 1, "scores": eval_result["scores"]})
avg_score = sum(eval_result["scores"].values()) / len(eval_result["scores"])
if avg_score >= QUALITY_THRESHOLD:
break
current_draft = revise_content(current_draft, eval_result, audience)
return current_draft, history
Run it
Here is how I call the finished pipeline with a genuinely rough draft.
ROUGH_DRAFT = """
Our new api is really good. It has fast speed and you can use it for many things.
Pricing is cheap. You should try it because it's better than others.
Contact us to learn more.
"""
final_draft, score_history = optimize_content(ROUGH_DRAFT, audience="technical developers")
print("=== Score History ===")
for h in score_history:
print(f"Iteration {h['iteration']}: {h['scores']}")
print("\n=== Final Draft ===")
print(final_draft)
Typical output looks like this:
=== Score History ===
Iteration 1: {'clarity': 5, 'structure': 4, 'tone': 5, 'actionability': 3}
Iteration 2: {'clarity': 8, 'structure': 8, 'tone': 7, 'actionability': 7}
Iteration 3: {'clarity': 9, 'structure': 9, 'tone': 8, 'actionability': 8}
=== Final Draft ===
Oxlo.ai provides a developer-first inference API with flat per-request pricing.
You get predictable costs regardless of prompt length, which makes it ideal for
long-context and agentic workloads. The API is fully OpenAI SDK compatible, so
migration takes minutes. Start with the free tier at https://oxlo.ai/pricing and
scale to dedicated GPUs when you need them.
Wrap-up
Two concrete ways to extend this.
First, replace the hardcoded rubric with a project-specific style guide stored in a vector database. Retrieve the right guide at runtime so one optimizer handles multiple brands.
Second, add a final fact-checking step using qwen-3-32b or deepseek-v3.2 to verify technical claims before the draft goes live. This turns the tool from a style editor into a full pre-publish pipeline.
Top comments (0)