| name | wikimedia-ml-services |
| description | Score article quality, revert risk, edit quality (goodfaith/damaging), readability, topic classification, reference quality, language identification, content translation recommendations, article descriptions, and article country using Wikimedia ML inference APIs (Lift Wing and legacy ORES) |
| depends_on | ["wikimedia-api-access"] |
| license | MIT |
| compatibility | opencode |
| skill_discovery_hints | [{"keywords":["revert","vandalism","quality","FA","GA","Start","Stub","article quality","goodfaith","damaging"]},{"keywords":["readability","grade level","Flesch-Kincaid","reading score"]},{"keywords":["topic","classification","category prediction","outlink","article topic"]},{"keywords":["Lift Wing","ORES","ML","machine learning","inference","model score"]},{"keywords":["reference","citation quality","reference need","unsourced","reference risk"]},{"keywords":["language detection","langid","identify language"]},{"keywords":["translation","content translation","cross-language","recommendation"]}] |
| last_verified | "2026-06-10T00:00:00.000Z" |
โ ๏ธ User-Agent required: All API calls below need a descriptive User-Agent header. See the wikimedia-api-access skill for the correct format and rate-limiting patterns.
Context: Two Eras of Wikimedia ML Services
Wikimedia has two ML inference pipelines:
| Era | Status | Architecture | Base URL |
|---|
| ORES | Deprecated (unmaintained since late 2023, may break) | Python scoring server, GET-based, batch scoring | https://ores.wikimedia.org/v3/scores/{wiki}/{revid} |
| Lift Wing | Active (current WMF ML platform) | Kubernetes/KServe, POST-based, one model per endpoint | https://api.wikimedia.org/service/lw/inference/v1/models/{model-name}:predict |
Always prefer Lift Wing. ORES is documented here only for migrating existing code. New tools must use Lift Wing.
Reference: Available Lift Wing Models
Lift Wing serves two tiers of models:
Revscoring Models (Frozen โ migrated from ORES, no further improvements)
| Model Name | Input | Output | Purpose | Modern Replacement |
|---|
{wiki}-goodfaith | rev_id | {"prediction": true/false, "probability": {"true": float, "false": float}} | Good/bad faith edit | revertrisk-* |
{wiki}-damaging | rev_id | Same structure | Is edit damaging? | revertrisk-* |
{wiki}-reverted | rev_id | Same structure | Will edit be reverted? | revertrisk-* |
{wiki}-articlequality | rev_id | {"prediction": "FA"/"GA"/"B"/"C"/"Start"/"Stub", "probability": {...}} | Article quality class | articlequality (modern model, continuous score) |
{wiki}-draftquality | rev_id | {"prediction": "...", "probability": {...}} | Draft quality | โ |
{wiki}-articletopic | rev_id | {"prediction": [...], "probability": {...}} | Article topic scores | outlink-topic-model |
{wiki}-drafttopic | rev_id | Same structure | Draft topic scores | โ |
wikidatawiki-itemquality | rev_id | Same structure | Wikidata item quality | โ |
wikidatawiki-itemtopic | rev_id | Same structure | Wikidata item topic | โ |
Replace {wiki} with the wiki code (e.g., enwiki, frwiki, arwiki). Available wikis vary per model โ check the model list.
Modern Models (Actively developed, preferred for new tools)
| Model Name | Input | Output (Key Fields) | Best For |
|---|
revertrisk-language-agnostic | {"rev_id": int, "lang": string} | output.prediction (bool), output.probabilities.{true, false} (float) | Anti-vandalism โ single score replacing goodfaith+damaging combined |
revertrisk-multilingual | {"rev_id": int, "lang": string} | output.prediction (bool), output.probabilities.{true, false} (float) | Anti-vandalism across 300+ languages |
revertrisk-wikidata | {"rev_id": int} | output.prediction (bool), output.probabilities.{true, false} (float) | Wikidata-specific revert risk |
readability | {"rev_id": int, "lang": string} | output.score (float 0โ1), output.fk_score_proxy (grade level) | Readability scoring โ complexity and grade level |
reference-need | {"rev_id": int, "lang": string} | reference_need_score (float 0โ1) | Find unsourced claims in an article |
reference-risk | {"rev_id": int, "lang": string} | reference_risk_score (float), reference_count (int), survival_ratio (dict) | Reference quality risk โ are citations reliable? |
outlink-topic-model | {"page_title": string, "lang": string} | prediction.results[] โ array of {topic: string, score: float} | Topic classification โ replaces articletopic, link-based |
articlequality | {"rev_id": int, "lang": string} | score (float 0โ1) | Quality scoring โ continuous quality score (modern model, different from Revscoring grades) |
article-country | {"title": string, "lang": string} | prediction.results[] โ array of {country: string, score: float, source: {...}} | Predict which country an article is about |
article-descriptions | {"title": string, "lang": string, "num_beams": int} | (generates Wikidata-style short description โ heavy model, may be slow) | Generate a Wikidata-like short description |
langid | {"text": string} | wikicode (string), score (float confidence) | Language identification of raw text |
๐ก Prefer modern models. The Revscoring models are frozen โ no retraining, no new wikis. The modern models (especially revertrisk-*, outlink-topic-model) are trained on fresher data and cover more wikis.
โ ๏ธ Model naming is inconsistent. The modern articlequality model is called just articlequality (not articlequality-language-agnostic). The content translation service is a GET REST API at /service/lw/recommendation/api/v1/translation, not a POST inference model. See the individual SOPs below.
SOP: Making Lift Wing API Calls
Common Request Pattern
All Lift Wing models use POST to the same base URL pattern:
POST https://api.wikimedia.org/service/lw/inference/v1/models/{MODEL_NAME}:predict
Content-Type: application/json
Authorization: Bearer {TOKEN} (optional โ needed for >50k req/hr)
User-Agent: MyBot/1.0 (user@example.com) ContentGapResearch
import requests
headers = {
"User-Agent": "MyBot/1.0 (user@example.com) ContentGapResearch",
"Content-Type": "application/json",
}
url = "https://api.wikimedia.org/service/lw/inference/v1/models/enwiki-articlequality:predict"
data = {"rev_id": 123456789}
resp = requests.post(url, json=data, headers=headers, timeout=30)
result = resp.json()
Authentication for Higher Rate Limits
| Client Type | Rate Limit (req/h) | Rate Limit (req/s) | How to Qualify |
|---|
| Anonymous | 50,000 | 15 | No auth needed |
| Browser session | 50,000 | 50 | Login cookie |
| Authenticated | 100,000 | 100 | OAuth token via api.wikimedia.org/wiki/Authentication |
| Known client (Toolforge, approved bots) | 200,000 | 200 | OAuth token + known user-agent |
To authenticate, follow the Wikimedia API authentication guide to obtain an OAuth access token, then include it in requests:
headers = {
"Authorization": f"Bearer {access_token}",
"User-Agent": "MyBot/1.0 (user@example.com) ContentGapResearch",
"Content-Type": "application/json",
}
Handling Response Structure
โ ๏ธ This is the single most common source of bugs. The response formats are nested and non-obvious. Always check the response structure before writing access code.
Revscoring models on Lift Wing use the old ORES response format (not the Lift Wing envelope):
{
"enwiki": { # โ key is the wiki code (changes per model!)
"models": {
"articlequality": {"version": "0.9.2"}
},
"scores": {
"123456789": { # โ key is the revision ID as a STRING
"articlequality": { # โ key is the model name
"score": {
"prediction": "C", # โ "FA"/"GA"/"B"/"C"/"Start"/"Stub"
"probability": { # โ per-class confidence (sums to 1.0)
"B": 0.02, "C": 0.78, "FA": 0.0,
"GA": 0.12, "Start": 0.07, "Stub": 0.01
}
}
}
}
}
}
}
Access pattern:
result[wiki]["scores"][str(rev_id)][model_name]["score"]["prediction"]
grade = result["enwiki"]["scores"]["123456789"]["articlequality"]["score"]["prediction"]
Modern revert-risk models use a flat unified envelope:
{
"model_name": "revertrisk-language-agnostic",
"model_version": "3",
"wiki_db": "enwiki",
"revision_id": 123456789,
"output": {
"prediction": false, # โ bool: true = likely reverted
"probabilities": {
"true": 0.34, # โ float 0-1: probability of revert
"false": 0.66
}
}
}
Access pattern:
risk = result["output"]["probabilities"]["true"]
prediction = result["output"]["prediction"]
Modern articlequality model (continuous score):
{
"model_name": "articlequality",
"model_version": "1",
"wiki_db": "enwiki",
"revision_id": 123456789,
"output": {
"prediction": {"score": 0.72} # โ float 0-1, NOT a discrete grade
}
}
Access pattern:
score = result["output"]["prediction"]["score"]
Modern models have per-model response schemas. See the model-specific SOPs below.
SOP: Editing the Page โ How Lift Wing and EventStreams Work Together
Lift Wing ML predictions integrate naturally with the EventStreams real-time feed. The most common production pattern is:
- Consume
recentchange or revision-create events via EventStreams (see the wikimedia-eventstreams skill)
- Score each new revision via Lift Wing (revert risk, damaging, goodfaith)
- Act on the score (flag for review, auto-revert, pass through)
import requests, json
HEADERS = {"User-Agent": "MyBot/1.0 (user@example.com) ContentGapResearch"}
def score_revision_revscoring(wiki: str, rev_id: int, model: str) -> dict:
"""Score a single revision using a Revscoring model on Lift Wing.
Note: Revscoring models return the old ORES response format.
"""
url = f"https://api.wikimedia.org/service/lw/inference/v1/models/{wiki}-{model}:predict"
resp = requests.post(url, json={"rev_id": rev_id}, headers=HEADERS, timeout=30)
resp.raise_for_status()
return resp.json()
result = score_revision_revscoring("enwiki", 123456789, "goodfaith")
prediction = result["enwiki"]["scores"]["123456789"]["goodfaith"]["score"]["prediction"]
confidence = result["enwiki"]["scores"]["123456789"]["goodfaith"]["score"]["probability"]["true"]
SOP: Revert Risk Scoring (Anti-Vandalism)
The revertrisk-* models are the recommended replacement for the older goodfaith + damaging pair. They provide a single probability score for whether an edit will be reverted.
Language-Agnostic Revert Risk
import requests
headers = {"User-Agent": "MyBot/1.0 (user@example.com) ContentGapResearch"}
url = "https://api.wikimedia.org/service/lw/inference/v1/models/revertrisk-language-agnostic:predict"
data = {"rev_id": 123456789, "lang": "en"}
resp = requests.post(url, json=data, headers=headers, timeout=30)
result = resp.json()
Multilingual Revert Risk
Same pattern, different model name โ covers 300+ languages with a single model:
url = "https://api.wikimedia.org/service/lw/inference/v1/models/revertrisk-multilingual:predict"
data = {"rev_id": 123456789, "lang": "en"}
Threshold Guidance
| Revert Risk Score | Action |
|---|
< 0.3 | Low risk โ pass through |
0.3 โ 0.7 | Medium risk โ flag for human review |
> 0.7 | High risk โ escalate (tag, auto-revert if confident) |
Calibrate thresholds to your tool's precision/recall requirements. The model card provides precision-recall curves: Language-agnostic revert risk model card.
๐ฎ Try it: python3 assets/patrol_simulator.py Albert_Einstein โ simulates patrolling the latest edit and produces a verdict.
SOP: Article Quality Scoring
With Revscoring Model (Frozen โ uses ORES response format)
import requests
headers = {"User-Agent": "MyBot/1.0 (user@example.com) ContentGapResearch"}
url = "https://api.wikimedia.org/service/lw/inference/v1/models/enwiki-articlequality:predict"
data = {"rev_id": 123456789}
resp = requests.post(url, json=data, headers=headers, timeout=30)
result = resp.json()
scores = result["enwiki"]["scores"]["123456789"]["articlequality"]["score"]
grade = scores["prediction"]
probs = scores["probability"]
๐ก The modern articlequality model provides a continuous quality score (float 0โ1), while the Revscoring {wiki}-articlequality model provides a discrete grade (FA/GA/B/C/Start/Stub). The modern model name is just articlequality โ not articlequality-language-agnostic.
Integration with Page Assessment
Combine ML quality scores with WikiProject assessment data from the wikimedia-page-assessment skill:
ml_grade = scores["prediction"]
Use ML scores as a fallback when PageAssessments are not available (most wikis don't have the extension), or as a second opinion for unassessed articles.
๐ฎ Try it: python3 assets/article_quality_report.py Albert_Einstein en โ generates a full report with quality + readability + topics + reference risk.
SOP: Topic Classification
The outlink-topic-model replaces the older articletopic model. It uses the article's outlinks to predict topics and is available for more wikis.
import requests
headers = {"User-Agent": "MyBot/1.0 (user@example.com) ContentGapResearch"}
url = "https://api.wikimedia.org/service/lw/inference/v1/models/outlink-topic-model:predict"
data = {"page_title": "Douglas_Adams", "lang": "en"}
resp = requests.post(url, json=data, headers=headers, timeout=30)
result = resp.json()
topics = {r["topic"]: r["score"] for r in result["prediction"]["results"]}
Topic Hierarchy
The outlink topic model uses a hierarchical taxonomy. Topics are dot-separated paths (e.g., Culture.Media.Books, STEM.Science.Physics). The top-level categories are:
| Top-Level | Examples |
|---|
Culture | Media, Books, Television, Music, Sports, Food |
Geography | Regions, Countries, Cities |
History | Events, People, Periods |
People | Biographical topics |
STEM | Science, Technology, Engineering, Mathematics |
Society | Law, Education, Politics, Religion |
Interpret scores by their top-level prefix for broad categorization, or drill into subcategories for fine-grained classification.
๐ฎ Try it: bash scripts/playground.sh and choose option 4 โ interactive topic classification.
SOP: Readability Scoring
The readability model scores how readable an article's content is using standard metrics.
import requests
headers = {"User-Agent": "MyBot/1.0 (user@example.com) ContentGapResearch"}
url = "https://api.wikimedia.org/service/lw/inference/v1/models/readability:predict"
data = {"rev_id": 123456789, "lang": "en"}
resp = requests.post(url, json=data, headers=headers, timeout=30)
result = resp.json()
score = result["output"]["score"]
grade = result["output"]["fk_score_proxy"]
Interpreting Readability Scores
| Field | Range | Interpretation |
|---|
output.score | 0โ1 | Higher = more readable. >0.6 = accessible. <0.3 = very difficult. |
output.fk_score_proxy | 0โ20+ | US grade level (approximate). 8โ10 = average adult. >14 = complex academic text. |
๐ฎ Try it: python3 assets/article_quality_report.py Albert_Einstein en includes a readability section.
SOP: Reference Quality Scoring
Two models help assess citation quality in articles. Both use rev_id + lang (not page_title).
Reference Need (Find Unsourced Claims)
import requests
headers = {"User-Agent": "MyBot/1.0 (user@example.com) ContentGapResearch"}
url = "https://api.wikimedia.org/service/lw/inference/v1/models/reference-need:predict"
data = {"rev_id": 123456789, "lang": "en"}
resp = requests.post(url, json=data, headers=headers, timeout=30)
result = resp.json()
score = result["reference_need_score"]
Reference Risk (Citation Quality)
url = "https://api.wikimedia.org/service/lw/inference/v1/models/reference-risk:predict"
data = {"rev_id": 123456789, "lang": "en"}
resp = requests.post(url, json=data, headers=headers, timeout=30)
result = resp.json()
risk = result["reference_risk_score"]
ref_count = result["reference_count"]
SOP: Language Identification
The langid model predicts what language a piece of text is written in. It takes raw text (not a page reference).
import requests
headers = {"User-Agent": "MyBot/1.0 (user@example.com) ContentGapResearch"}
url = "https://api.wikimedia.org/service/lw/inference/v1/models/langid:predict"
data = {"text": "Albert Einstein was a German-born theoretical physicist."}
resp = requests.post(url, json=data, headers=headers, timeout=30)
result = resp.json()
To get the text of a Wikipedia article for language identification, first fetch the page content via the REST API.
๐ฎ Try it: python3 assets/language_explorer.py โ interactive REPL. Type any text and see the detected language. Or python3 assets/language_explorer.py --samples to test 10 languages at once.
SOP: Article Country Prediction
The article-country model predicts which countries an article is about, with confidence scores and evidence sources.
import requests
headers = {"User-Agent": "MyBot/1.0 (user@example.com) ContentGapResearch"}
url = "https://api.wikimedia.org/service/lw/inference/v1/models/article-country:predict"
data = {"title": "Albert_Einstein", "lang": "en"}
resp = requests.post(url, json=data, headers=headers, timeout=30)
result = resp.json()
top_country = result["prediction"]["results"][0]["country"]
all_countries = {r["country"]: r["score"] for r in result["prediction"]["results"]}
Note: uses title (not page_title) as the parameter name.
SOP: Content Translation Recommendations
The content translation recommendation is a GET-based REST API (not a POST inference model).
import requests
headers = {"User-Agent": "MyBot/1.0 (user@example.com) ContentGapResearch"}
url = "https://api.wikimedia.org/service/lw/recommendation/api/v1/translation"
params = {
"source": "en",
"target": "fr",
"count": 3,
"seed": "Apple",
}
resp = requests.get(url, params=params, headers=headers, timeout=30)
result = resp.json()
| Parameter | Type | Required | Description |
|---|
source | string | โ
| Source wiki language code (e.g., en) |
target | string | โ
| Target wiki language code (e.g., fr) |
count | int | โ | Number of recommendations (default 12) |
seed | string | โ | Seed article title for personalized recommendations (pipe ` |
topic | string | โ | Article topic filter (pipe ` |
include_pageviews | bool | โ | Include pageview counts (true/false, default false) |
search_algorithm | string | โ | morelike or mostpopular (default morelike) |
SOP: Migrating from ORES (Legacy Code)
If you encounter code that calls ORES, here is the migration pattern:
ORES Call (Legacy)
curl -s -H "User-Agent: MyBot/1.0 (user@example.com) LiftWingMigration" \
'https://ores.wikimedia.org/v3/scores/enwiki/12345?models=goodfaith|damaging'
Equivalent Lift Wing Calls
curl -s -X POST -H "User-Agent: MyBot/1.0 (user@example.com) LiftWingMigration" \
'https://api.wikimedia.org/service/lw/inference/v1/models/enwiki-goodfaith:predict' \
-H 'Content-Type: application/json' \
-d '{"rev_id": 12345}'
curl -s -X POST -H "User-Agent: MyBot/1.0 (user@example.com) LiftWingMigration" \
'https://api.wikimedia.org/service/lw/inference/v1/models/enwiki-damaging:predict' \
-H 'Content-Type: application/json' \
-d '{"rev_id": 12345}'
ORES โ Lift Wing Feature Extraction
curl -s -H "User-Agent: MyBot/1.0 (user@example.com) LiftWingMigration" \
'https://ores.wikimedia.org/v3/scores/enwiki/12345/goodfaith?features=True'
curl -s -X POST -H "User-Agent: MyBot/1.0 (user@example.com) LiftWingMigration" \
'https://api.wikimedia.org/service/lw/inference/v1/models/enwiki-goodfaith:predict' \
-H 'Content-Type: application/json' \
-d '{"rev_id": 12345, "extended_output": "True"}'
ORES โ Modern Revert Risk
curl -s -H "User-Agent: MyBot/1.0 (user@example.com) LiftWingMigration" \
'https://ores.wikimedia.org/v3/scores/enwiki/12345?models=goodfaith|damaging'
curl -s -X POST -H "User-Agent: MyBot/1.0 (user@example.com) LiftWingMigration" \
'https://api.wikimedia.org/service/lw/inference/v1/models/revertrisk-language-agnostic:predict' \
-H 'Content-Type: application/json' \
-d '{"rev_id": 12345, "lang": "en"}'
Key ORES โ Lift Wing Differences
| Aspect | ORES | Lift Wing |
|---|
| HTTP method | GET | POST |
| Batch support | Yes (multiple models, multiple revisions in one call) | No (one model per call) |
| Caching | Yes (pre-cached scores for recent edits) | No (must implement your own cache) |
| Features | ?features=True | "extended_output": "True" (per model) |
| Auth | None | OAuth for higher rate limits |
| Response | {"wiki": {"models": {"model": {"scores": {...}}}}} | Per-model response (see individual SOPs) |
SOP: Implementing Caching (Lift Wing Has None)
Lift Wing does not cache predictions (unlike ORES which pre-cached scores). If you score the same revision twice, you pay two inference calls. For production tools, implement your own cache:
import time
class MLScoreCache:
def __init__(self, ttl_seconds: int = 3600):
self._cache = {}
self._ttl = ttl_seconds
def get(self, model: str, rev_id: int) -> dict | None:
key = (model, rev_id)
if key in self._cache:
entry = self._cache[key]
if time.time() - entry["ts"] < self._ttl:
return entry["data"]
del self._cache[key]
return None
def set(self, model: str, rev_id: int, data: dict):
self._cache[(model, rev_id)] = {"data": data, "ts": time.time()}
cache = MLScoreCache()
def scored_revision(wiki, rev_id):
cached = cache.get(f"{wiki}-goodfaith", rev_id)
if cached:
return cached
result = call_liftwing(f"{wiki}-goodfaith", {"rev_id": rev_id})
cache.set(f"{wiki}-goodfaith", rev_id, result)
return result
Guardrails
โ Don't use ORES for new tools
ORES is deprecated. Always use Lift Wing. The ORES service could stop working at any time without notice.
โ Don't use frozen Revscoring models when modern alternatives exist
- Use
revertrisk-* instead of goodfaith + damaging
- Use
outlink-topic-model instead of articletopic
The frozen models won't be retrained, won't gain new language support, and their accuracy degrades over time (model drift).
โ Don't assume all models cover all wikis
Revscoring models only cover the wikis they were trained on. Check the model list before using a wiki-specific model. Modern models (revertrisk-multilingual, outlink-topic-model) are language-agnostic and cover more wikis.
โ Don't ignore model cards
Every model has a model card on Meta-Wiki that documents:
- Training data and methodology
- Performance metrics (precision, recall, F1)
- Known biases and limitations
- Appropriate use cases
Read the model card before using a model in production. Links are in the reference table below.
โ ๏ธ Implement caching for repeated scoring
Since Lift Wing has no caching, scoring the same revision multiple times wastes rate limit quota and adds latency. Use an in-memory cache (as shown above) for short-lived tools, or a persistent cache (Redis, SQLite) for long-running services.
โ ๏ธ Respect per-second rate limits, not just per-hour
The per-second limits (15 req/s anonymous, 100 req/s authenticated) are tighter than the per-hour limits. For batch operations:
- Add
time.sleep(0.1) between requests (10 req/s)
- Use
requests.Session() for connection reuse
- Implement exponential backoff on 429 responses
โ ๏ธ Some models are internal-only
Models in the "experimental" Kubernetes namespace are only accessible from WMF production infrastructure. The externally accessible models are documented in the API reference. If a model is not listed there, it's internal.
Model Card Reference
Known Limitations
| Limitation | Affected Models | Impact | Workaround |
|---|
| Revert-risk models return HTTP 422 for revision 1. New pages have no parent revision to compare against, so the model cannot compute a score. | revertrisk-language-agnostic, revertrisk-multilingual, revertrisk-wikidata | Cannot score brand-new page creations โ a common use case for real-time patrol tools. | Use the articlequality model as a fallback for new pages (it scores the revision itself, not the diff). Note that articlequality has ~60s processing latency (see below). |
| Articlequality model has ~60s processing latency. Newly created revisions are not immediately available for scoring. The model returns empty scores for revisions less than ~60 seconds old. | articlequality, {wiki}-articlequality | Real-time patrol tools may get empty scores for very new pages. | Retry with exponential backoff (max 3 attempts, 30s apart). Or accept the empty score as "unknown" and re-score later. |
| Lift Wing has no prediction cache. Unlike ORES (which pre-computed scores), every call to Lift Wing runs a fresh inference. | All models | Scoring the same revision twice wastes rate limit quota and doubles latency. Risk: rate limit exhaustion in batch operations. | Implement your own cache (see SOP: Implementing Caching). Use an LRU cache with TTL for short-lived tools, Redis/SQLite for persistent services. |
Revscoring models are frozen โ no retraining. The {wiki}-goodfaith, {wiki}-damaging, {wiki}-articlequality etc. models are ported from ORES with no further updates. | All Revscoring models ({wiki}-*) | Model accuracy degrades over time (model drift). No new language coverage. | Migrate to modern models (revertrisk-*, articlequality continuous, outlink-topic-model) where available. Check the model list for coverage. |
| Not all models cover all wikis. Revscoring models only work on the wikis they were trained on. | {wiki}-* Revscoring models | Calling a model with an unsupported wiki returns a 404 or empty prediction. | Check the model list before using a wiki-specific model. Use language-agnostic modern models for broader coverage. |
| Per-second rate limits are tighter than per-hour. Anonymous: 15 req/s. Authenticated: 100 req/s. Batch operations can hit the per-second limit before the per-hour limit. | All models | 429 errors during batch scoring. | Add time.sleep(0.1) between requests (10 req/s). Use requests.Session() for connection reuse. Implement exponential backoff on 429. Authenticate via OAuth for 100 req/s. |
| Some models are internal-only. Models in the "experimental" Kubernetes namespace are not accessible from external clients. | Varies | 403/404 errors when calling models not in the public API. | Only use models listed in the public API reference. |
article-descriptions model is heavy and slow. Generating a short description is computationally expensive due to the beam search pattern. | article-descriptions | Requests can take 10-30 seconds or timeout. | Use num_beams=1 for faster (but lower quality) results. Increase HTTP timeout to 60s. |
Tooling
๐ง CLI Scripts
| Script | Purpose | Usage Example |
|---|
scripts/score-revision.sh | Score a single revision or page via curl | ./score-revision.sh enwiki 123456789 revertrisk-language-agnostic en |
scripts/batch-score.sh | Batch score multiple revisions from stdin or a file | cat revids.txt | ./batch-score.sh enwiki revertrisk-multilingual --output csv |
scripts/playground.sh | Interactive menu โ pick a model, enter input, see results. No arguments to memorize | bash scripts/playground.sh |
๐ Python Assets
| Script | Purpose | Usage Example |
|---|
assets/liftwing_multi_model.py | Score a revision against multiple models in parallel with caching | python3 liftwing_multi_model.py enwiki 123456789 --all |
assets/article_quality_report.py | Full article report: quality + readability + topics + reference need | python3 article_quality_report.py Albert_Einstein en |
assets/patrol_simulator.py | Simulate patrolling โ score the latest edit to a page with revert-risk + goodfaith + damaging, get a verdict | python3 patrol_simulator.py Albert_Einstein |
assets/language_explorer.py | Language explorer โ type text and see what language langid detects, with confidence | python3 language_explorer.py --samples (built-in test suite in 10 languages) |
๐ Reference Docs
| Document | Contents |
|---|
references/model-schemas.md | Complete request/response schema for all 15+ externally accessible models, available wikis per model, and rate limit tables |
๐ก The code examples in the SOPs above are self-contained and ready to copy-paste.
The scripts and assets add CLI convenience, batch processing, and production patterns.