Views
No views yet
xlm-roberta-base that scores a YouTube comment as bot or authentic.
Built for Kratt, a media-literacy tool that helps viewers read comment sections more critically —
it flags likely bot activity, it never deletes or hides anything.niche <niche_tag> . <likes bucket> . <replies bucket> . <cleaned comment text>niche low effort . few likes . no replies . first!!| Piece | Values | Rule |
|---|---|---|
niche_tag | genuine, copycat, low effort | property of the video, hyphens replaced with spaces |
| likes bucket | few likes (<2), some likes (2–9), many likes (≥10) | from like_count |
| replies bucket | no replies (0), has replies (>0) | from reply_count |
| comment text | lowercased except ALL-CAPS tokens (shouting is a signal); URLs/@mentions/#hashtags replaced with <URL> / <USER> / <TAG>; emoji kept as-is | see Preprocessing below |
niche_tag is a video-level property that determines a large
part of the label, so the model cannot infer it from the comment text alone.<URL>, <USER>, <TAG> are registered as tokenizer special tokens
— load the tokenizer from this repo, not a fresh xlm-roberta-base tokenizer, or these will be
split into sub-word garbage.1import re
2from transformers import AutoTokenizer, AutoModelForSequenceClassification
3import torch
4
5REPO = "geraldadli/Kratt" # replace with your HF repo id
6tokenizer = AutoTokenizer.from_pretrained(REPO)
7model = AutoModelForSequenceClassification.from_pretrained(REPO)
8
9INVISIBLE_RE = re.compile('[]')
10URL_RE = re.compile(r'(?:https?://|www\.)\S+', re.IGNORECASE)
11USER_RE = re.compile(r'@[\w.\-]+')
12TAG_RE = re.compile(r'#\w+')
13
14def clean_text(text):
15 s = INVISIBLE_RE.sub('', str(text))
16 s = URL_RE.sub(' <URL> ', s)
17 s = USER_RE.sub(' <USER> ', s)
18 s = TAG_RE.sub(' <TAG> ', s)
19 return ' '.join(t if (len(t) >= 2 and t.isupper()) else t.lower() for t in s.split())
20
21def like_phrase(n): return 'many likes' if n >= 10 else ('some likes' if n >= 2 else 'few likes')
22def reply_phrase(n): return 'has replies' if n > 0 else 'no replies'
23
24def build_input(text, niche_tag, like_count, reply_count):
25 return (f"niche {niche_tag.replace('-', ' ')} . {like_phrase(like_count)} . "
26 f"{reply_phrase(reply_count)} . {clean_text(text)}")
27
28model_input = build_input(
29 text="first!!", niche_tag="low-effort", like_count=0, reply_count=0)
30
31inputs = tokenizer(model_input, truncation=True, max_length=128, return_tensors="pt")
32with torch.no_grad():
33 probs = torch.softmax(model(**inputs).logits, dim=-1)[0]
34
35print({model.config.id2label[i]: round(p.item(), 3) for i, p in enumerate(probs)})| id | label |
|---|---|
| 0 | bot |
| 1 | authentic |
genuine / copycat / low-effort / ads_spam, combined with each
comment's video-level niche_tag (genuine / copycat / low-effort).(niche_tag, comment_tag) → authenticity-score
matrix converts the combination into a binary label (authentic if score ≥ 0.5) and a per-sample
training weight (|score − 0.5| × 2). The core idea: the same comment type means different things
in different niches — e.g. a low-effort comment under a genuine-niche video (tutorial, stunt) is
usually just a casual human (high authenticity), while the same comment type under a low-effort
video (fast-consume clips) matches an observed bot pattern (low authenticity). Ambiguous
combinations (e.g. copycat in a genuine niche, score 0.5) get a training weight near zero and
barely influence the model.ads_spam-tagged comments were excluded from training — spam detection is handled by a separate
rule engine in the product, not this classifier.xlm-roberta-base (multilingual, cased — casing matters for the ALL-CAPS signal)fp16video_id (no video's comments appear in both train and test) with a
per-video cap of 500 comments so one large video can't dominate a niche's data or degenerate the
split, plus a guard requiring ≥2 videos and 15–25% share in the test set precision recall f1-score support
bot 0.72 0.79 0.75 991
authentic 0.77 0.70 0.74 1009
accuracy 0.75 2000
macro avg 0.75 0.75 0.75 2000
weighted avg 0.75 0.75 0.75 2000bot; a false positive means an authentic comment
flagged as bot — the costlier error for a media-literacy tool, since it wrongly casts doubt on
a real person.handcheck_sample.csv in the training notebook) is the
real validation step./analyze pipeline: score each fetched comment, aggregate into a bot-likelihood
percentage and evidence breakdown shown to the end user.