Jev Case Study: Multilingual Review Moderation (Full Code)
TL;DR: This Jev case study moderates marketplace reviews in any language with two Jev 1.13 calls: a judgment question (“does this review violate the rules?”) and, only if it does, a choice question for the category (
spam,abuse,policy-violation). Full code below.
Scenario
We run a marketplace where buyers review sellers. Reviews arrive in a dozen languages — Spanish, Japanese, Polish, Portuguese — and moderation used to mean either hiring per-language moderators or letting the queue rot. The rules, however, are language-independent: no spam, no abuse, no policy violations (off-platform payment attempts, fake discounts, counterfeit claims).
So we split the job the way Jev’s question types want it split:
- A judgment question: does this review violate the rules?
yes/no/unclear. - Only if the answer is
yes: a choice question — which category?spam/abuse/policy-violation.
Two design points worth copying:
- The second call is conditional. A review that clears the judgment step never costs a second call, and the category question never has to handle the “actually it’s fine” case — its input space is already filtered.
- The language is never translated. We pass the review as-is. Asking Jev to first judge and then justify in one call keeps the rationale in the model’s own reading of the original text, and the system prompts pin the question language to English regardless of the review’s language.
Jev is TypeSafe AI’s System One judgment model (September 2026); both calls go through the OpenRouter OpenAI-compatible endpoint.
Request
Call 1 — violation check (judgment question):
{
"model": "typesafe/jev-1.13",
"messages": [
{
"role": "system",
"content": "Judgment question. Does this product review violate the marketplace rules (spam, abuse, or policy violation)? Answer yes, no, or unclear. Reply with JSON only: {\"answer\": <yes|no|unclear>, \"confidence\": <0-1>, \"rationale\": <one sentence>}"
},
{
"role": "user",
"content": "Review: \"El reloj llegó rápido, pero es una réplica obvia. Si quieres el Original más barato, escríbeme por WhatsApp al +34 600 000 000.\""
}
]
}
Call 2 — category (choice question), sent only when call 1 answers yes:
{
"model": "typesafe/jev-1.13",
"messages": [
{
"role": "system",
"content": "Choice question. Classify the violation as exactly one of: spam, abuse, policy-violation. Reply with JSON only: {\"answer\": <spam|abuse|policy-violation>, \"confidence\": <0-1>, \"rationale\": <one sentence>}"
},
{
"role": "user",
"content": "Review: \"El reloj llegó rápido, pero es una réplica obvia. Si quieres el Original más barato, escríbeme por WhatsApp al +34 600 000 000.\""
}
]
}
Response
Example fixtures — illustrative output, not a live capture.
Call 1:
{
"answer": "yes",
"confidence": 0.97,
"rationale": "The review pivots from a product complaint to an off-platform solicitation offering a cheaper 'original', which violates the counterfeit and off-platform-contact rules."
}
Call 2:
{
"answer": "policy-violation",
"confidence": 0.94,
"rationale": "The message solicits off-platform contact to sell a counterfeit item, matching the policy-violation category rather than generic spam or abuse."
}
Reproduce
Save as moderate.py, set OPENROUTER_API_KEY, and run python3 moderate.py:
import json, os, urllib.request
URL = "https://openrouter.ai/api/v1/chat/completions"
MODEL = "typesafe/jev-1.13" # confirm exact slug on the OpenRouter model page
JUDGE = ('Judgment question. Does this product review violate the marketplace '
'rules (spam, abuse, or policy violation)? Answer yes, no, or unclear. '
'Reply with JSON only: {"answer": <yes|no|unclear>, "confidence": <0-1>, '
'"rationale": <one sentence>}')
CLASSIFY = ('Choice question. Classify the violation as exactly one of: spam, '
'abuse, policy-violation. Reply with JSON only: '
'{"answer": <spam|abuse|policy-violation>, "confidence": <0-1>, '
'"rationale": <one sentence>}')
def call(system, user):
body = {"model": MODEL, "messages": [
{"role": "system", "content": system},
{"role": "user", "content": user}]}
req = urllib.request.Request(URL, data=json.dumps(body).encode(),
headers={"Authorization": "Bearer " + os.environ["OPENROUTER_API_KEY"],
"Content-Type": "application/json"})
with urllib.request.urlopen(req) as res:
payload = json.load(res)
return json.loads(payload["choices"][0]["message"]["content"])
review = ('"El reloj llegó rápido, pero es una réplica obvia. Si quieres el '
'Original más barato, escríbeme por WhatsApp al +34 600 000 000."')
verdict = call(JUDGE, review)
print(verdict)
if verdict["answer"] == "yes":
print(call(CLASSIFY, review))
Key parameters
| Field | Value | Why it matters |
|---|---|---|
model | typesafe/jev-1.13 | Pin the version. Confirm the exact slug on the OpenRouter model page. |
Call 1 messages[0] | Judgment question + rules summary + JSON shape | The rules summary defines what “violate” means; keep it identical to your published policy. |
Call 2 messages[0] | Choice question + three categories + JSON shape | Sent only after a yes verdict, so the option list stays short and unambiguous. |
messages[1] (user) | The review, untranslated | Original language in, verdict out; no translation step to drift. |
answer sequence | yes → policy-violation | The workflow: judgment gates the choice. |
confidence values | 0.97 / 0.94 (example fixtures) | Low-confidence verdicts at either step should go to the human queue. |
| Price | $0.0462 per 1M input tokens | Most clean reviews cost one call only; verify current pricing on OpenRouter before budgeting. |
Notes
- Responses are example fixtures; verify field names against official docs before relying on them. Official API details live at typesafe.ai — see the System One announcement post.
- Confirm the exact model slug (
typesafe/jev-1.13) on the OpenRouter model page before shipping. - Route
unclearverdicts to humans — a borderline review is precisely what moderators should see. - If you add categories, update the choice question’s option list; the judgment question only needs its rules summary refreshed.
- Applies to Jev 1.13 (released September 2026) via the OpenRouter demonstration channel.