When I trained the erstwhile ai remark classifier, I utilized partially personal private information to do it, and built it connected a somewhat shaky foundation, truthful I couldn’t stock the codification aliases data. I rebuilt it connected nationalist information and a better foundation!
First off, you mightiness want to effort it out. Nothing you paste into that web page leaves your browser, truthful you tin safely effort it pinch immoderate you like. I have invited immoderate testers to effort retired an earlier type of it, and they had mainly positive feedback to give.
We won’t break down robot-isms the measurement we collapsed down Claude-isms successful the previous article, because successful the ui of the caller classifier you tin conscionable click immoderate part of the matter being classified to spot which features activate connected that information of the text, and really they lend to the wide judgment. Here’s an illustration of the expanded characteristic activation view.
In position of performance, the header number is the balanced accuracy of 77 %. This is really often the classifier gets the quality vs. robot verdict right, assuming human-written and robot-generated comments are arsenic likely.
The classifier besides prints a predicted percent which is calibrated, meaning it tin beryllium publication arsenic the probability that immoderate circumstantial verdict is correct. We test this done the calibration curve, which shows what probability the classifier assigns to an arena pinch a known probability.
Since each dots dishonesty very adjacent to the reference diagonal, we cognize they are approximately correct. This holds existent crossed comments of aggregate lengths, where a fitted temperature parameter adjusts for accrued assurance arsenic the amount of information increases.
We tin get much specifications astir the classifier’s nonaccomplishment modes by looking astatine its confusion matrix. In this table, “robot” is considered the affirmative class, i.e. the point we want to detect. The abbreviations guidelines for true/false positive/negative rate.
| input: human | tnr = 0.73 | fpr = 0.27 |
| input: robot | fnr = 0.20 | tpr = 0.80 |
When presented pinch a known-human input, the classifier correctly judges it as human 73 % of the time. With a known-robot input, it is correctly judged 80 % of the time. This intends successful some cases (known-human and known-robot) the mistake rate is astir 25 %. That mightiness sound high!
But retrieve that this correction complaint is the aggregate complete all possible inputs. We don’t request to salary excessively overmuch attraction to it, because the classifier outputs a calibrated predictive percent each clip it classifies something. Thus, for individual judgments, we know erstwhile the consequence of mendacious positives is lower aliases higher. When the classifier is very assured – e.g. erstwhile the assurance is 80 % aliases much – the consequence of a mendacious affirmative drops to 5 %. When the classifier is uncertain – erstwhile assurance is astir 50 % – past by calibration it will issue the incorrect verdict astir half the time.
I mention the numbers successful this disorder matrix only because they are truthful often used erstwhile discussing classifiers, truthful much academically inclined readers may expect to spot it. Here are immoderate different requested numbers:
| Accuracy | 77 % |
| Precision | 75 % |
| Recall | 80 % |
| Sensitivity | 80 % |
| Specificity | 73 % |
| F1 score | 77 % |
The accuracy, precision, and F1 people dangle connected the guidelines rate, but present they are computed from an ignorance assumption, i.e. an adjacent operation of human-written and robot-generated comments.
All of these numbers travel from cross-validation. I person besides manually tested a smaller non-synthetic group of real-world comments from humans and robots to see how good the classifier generalises somewhat retired of sample.
| input: human | tnr = 0.89 | fpr = 0.11 |
| input: robot | fnr = 0.14 | tpr = 0.86 |
This translates to the pursuing capacity numbers:
| Accuracy | 88 % |
| Precision | 89 % |
| Recall | 86 % |
| Sensitivity | 86 % |
| Specificity | 89 % |
| F1 score | 87 % |
This is very good! It looks for illustration non-synthetic, much real-worldy cases are easier for the classifier to discriminate betwixt than the training data.
Of course, each of this is tested pinch codification comments only. The classifier is not built to observe robot-generated texts of different kinds. It tin do it, but I make no promises of its accuracy.
With that retired of the way, let’s talk astir really it’s made.
The first step, arsenic before, is to build a bully information set. Ideally, we’d scheme this meticulously and do it correct the first time. If we do that, it should costs us about $30 to get the dataset that powers this classifier. It contains enough data to scope diminishing returns successful discriminating betwixt the much similar models.1 It is imaginable to extract a much powerful classifier pinch much data, but it would commencement to beryllium very costly since classifier powerfulness appears to standard pinch the log of money spent. That is, if you scheme it retired and do it correct the first time. I didn’t do that. I discovered overmuch later, erstwhile evaluating features, that the data I had was junk and I had to cod it each over2 💸. Then aft a while I discovered again that the information was still junk and had to beryllium recollected again3 💸💸💸.
The wide thought was to find a group of permissively licenced aliases copy-left repositories, cheque retired their latest perpetrate from the twelvemonth 2021, and then take a fewer random files from that commit. These incorporate quality comments. Then we strip retired each comments from those files, and person llms make caller comments for the aforesaid files. That provides america pinch robot comments. As agelong arsenic we effort to keep the number tokens for each record balanced betwixt each classes (humans and llm models), we tin debar taxable matter leakage, wherever the classifier learns to separate files aliases repositories alternatively than the style of the matter itself.
The wide thought is simple! But the devil’s wherever the devil usually is. Here are immoderate mistakes I made, successful nary peculiar order:
- Accidentally picking different root files for each llm to generate comments for. This causes taxable matter leakage.
- Generating llm comments for files pinch very fewer quality comments. This also causes taxable matter leakage complete the human–robot barrier.
- Failing to portion retired docstrings erstwhile blinding llms to quality comments in source files. This causes llms to make comments much akin to humans because they effort to lucifer the existing repository style. Though it should be said this had a smaller effect than I thought it would.
- Related to the above, immoderate languages support galore different syntaxes for comments, and immoderate are utilized much often than others. Failure to detect existing comments successful each syntaxes leaves comments down to contaminate llm generation, and besides makes it difficult to get each the information that has been produced.
- Not filtering retired quality comments that are very short. Most quality comments only say things for illustration “main task structure” aliases “chIcon” aliases “Alias” and including those teaches the classifier that humans constitute for illustration shit. Since llms were instructed to constitute much elaborate comments, it seems reasonable to compare those to much elaborate quality comments too.
- Using a fixed punctual for generating llm comments. This results successful a dataset with narrower variety than desirable for learning each the quirks needed to separate models and humans.
Not each of these problems required regenerating information from scratch. Some could be worked astir by filtering and preprocessing the information that already existed. Either way, this was the slightest nosy portion of the project, and it cost significantly much than the theoretical $30.
After collecting data, we request to creation a classifier that useful connected that data. This intends evaluating campaigner features. Doing truthful isn’t costly successful money, but in cpu time. Evaluating features, successful the astir powerful sense, intends training the classifier connected each subsets of campaigner features and seeing which performs best. That’s unreasonable, arsenic moreover pinch only 15 campaigner features, it requires training complete 30,000 different classifiers, which request to beryllium trained 5 ways each for cross-validation to boot.
What I ended up doing was guiding the characteristic action by the accuracy of classifiers arsenic trained connected individual features, for different favoritism tasks. In other words, I had a book that checked “does characteristic frequencies discriminate amended betwixt robots and humans than connection lengths?” and then repeated that for comparisons betwixt different features, and different classes.4 Different classes intends the mobility is asked not conscionable for robots-vs.-humans but besides Claude-vs.-Grok, and GPT-vs.-Gemini, etc.
Each of the people brace comparisons produced a database of characteristic rankings. These lists mostly agreed connected the bid of features, but location were immoderate disagreements. The ranking of features by power, and the spot of disagreement around relative rankings, is rendered successful the chart below.
I deliberation the chart sounds rather intuitively, but conscionable to beryllium sure:
- A achromatic arrow intends each comparisons agreed connected the comparative spot of the two features connected pinch the arrow.5 I suppose technically it intends that if a comparison didn’t agree, astatine slightest it didn’t disagree. In different words, if four comparisons bespeak that characteristic A and B person astir the aforesaid power, but a 5th comparison indicates characteristic A is amended than characteristic B, past the graph will show a achromatic arrow from B to A contempt the lukewarm consequence from four retired of 5 comparisons.
- A bluish arrow intends astatine slightest 2 comparisons agreed connected the comparative spot of the 2 features connected pinch the arrow, and only 1 comparison disagreed.
- A reddish arrow intends much disagreement (and the nonstop numbers are shown successful the arrow label), but the arrow still points successful the guidance of the dominant opinion.
Each characteristic container besides has an accusation amount expressed successful bits. That shows how overmuch that characteristic helps, connected average, successful distinguishing betwixt 2 classes.
Not only is this chart highly nosy to look astatine – it is besides very informative! The characteristic names whitethorn beryllium nonsensical, truthful we’ll person a little explanation of each. As the moving example, I will usage the pursuing excerpt from a Donald Trump speech:
markets are astatine their highest constituent successful galore years but we tin really opportunity of each time
and a akin random excerpt from an article successful the Economist:
the oecd personnel countries that person taken portion successful each version of pisa reached a highest around
Here are the features:
bigwords: the fraction of words longer than 5 letters successful the comment. Classic stylistic marker for fancy language, but very anemic for discrimination other than successful evident cases.
The Trump snippet has a bigwords worth of 18 %, whereas the Economist article is astatine 29 %.
wordlen: switch each connection pinch a number indicating really agelong that connection is, then count frequencies. This is akin to bigwords but captures the full distribution.
Trump has 30 % words of 3 letters, 24 % words of 2 letters, 15 % each of words of 4–7 letters, and 6 % words longer than that. The Economist has a wider spread, pinch the astir communal magnitude (35 %) being 4 letters, past very equal fractions successful the span 2–7 letters, and 5 % each for 9 letters and a single letter.
freqrank: switch each connection pinch a digit based connected really communal that connection is. The astir communal connection gets the number 0, the 10 astir communal words aft that get the number 1, the 100 astir communal words aft that get the number 2, etc. Then count the frequencies of these numbers.
Trump uses mostly rank-2 and rank-3 words astatine frequencies of 50 % and 30 % respectively. This corresponds to the top-100 and top-1000 astir communal words. The Economist snippet contains very fewer rank-2 words (though much rank-1 words!) and pulls successful plentifulness of rank-3 and rank-4 words, again indicating more complex vocabulary than Trump.
wordfreq: count the wave of a mini group of function words. It sees how galore times a matter includes content-less words for illustration “the”, “in”, “many”, “all”, etc.
The Trump illustration ne'er repeats immoderate usability words, but this characteristic would anyway study azygous occurrences of words “are”, “at”, “their”, “in”, “many”, “but”, “we”, “can”, “of”, “all”. The Economist article has a different set: “the”, “that”, “have”, “part”, “in”, “every”, “of”, “a”, “around”. With these short snippets, this doesn’t show america much, but pinch much information it tin commencement to distinguish sources of text.
word2gram: counts bigrams of usability words pinch different words filtered out. This produces unusual bigrams that were ne'er successful the original text, but it remains a celebrated measurement to analyse really group write.
The Trump illustration would have, among different bigrams, “are at”, “at their”, “their in”, “in many”, “many but”, etc. The Economist would person “the that”, “that have”, “have part”, “part in”, etc.
word2gram_adj: counts bigrams of usability words only erstwhile they are actually found adjacent to each different successful the text, i.e. not pinch different words filtered out. This seems for illustration a much earthy measurement to analyse penning because it only results in bigrams that really existed successful the original text, but arsenic we tin show from the graph, it is simply a weaker parameter than the regular word2gram.
The Trump illustration would person “are at”, “at their”, but past a jump to “in many”, past different jump to “but we”, “we can”, etc. The Economist reduces to “that have”, “part in”, and “in every”. We spot that the Economist has less strings of usability words.
word3gram and word3gram_adj is for illustration the erstwhile 2 isolated from for trigrams.
The Trump illustration has 2 values for word3gram_adj, namely “are astatine their” and “but we can”. The Economist has only one: “part successful every”.
charfreq: count the wave of each characteristic successful the comment. This tin be a beardown awesome if sources person different tendencies to usage symbols.
Since some Trump and the Economist usage English and the fragments I selected have an adjacent number of words, their characteristic frequencies are really very similar.
char2gram and char3gram: count the frequencies of bigrams and trigrams of characters successful the comment. This starts to show america thing astir styles of punctuation and connection choice.
Since neither Trump nor the Economist utilized immoderate punctuation successful these snippets, we tin only look astatine missive frequencies, and successful these examples, we tin tell Trump starts words pinch the missive “a” much often than the Economist, based on the bigram space-followed-by-a. In contrast, the Economist ends words pinch the letter “n” much often than Trump.
wordfreq_raw: Count frequencies of words, but not constricted to usability words. The use of this is that if location are immoderate words powerfully preferred by a source6 And they haven’t heeded their editor’s instrumentality to termination their darlings. for illustration “mediated” that wouldn’t beryllium successful immoderate usability connection list, but with earthy connection frequencies the classifier tin study to separate connected that word anyway.
However, this is besides a vulnerable characteristic because it tin train the classifier to prime up connected taxable matter differences. For example, successful the Economist case it could study that if the matter contains the abbreviation “oecd”, it is from the Economist, but if it contains the connection “actually” it is from Donald Trump.7 Okay, that mightiness not beryllium a bad rule, but you tin spot really it could lead to unintentional consequences successful different cases!
Recall, however, that we took pains to conception a balanced dataset for the code remark classifier. This is wherever that pays off. There is very little subject matter leakage successful the earthy connection wave feature, and alternatively it does pick up connected existent stylistic quirks.
- word2gram_raw, word3gram_raw: return the frequencies of bigrams and trigrams of words, pinch nary filtering for usability words.
wink, upos, ptb: person each connection to a part-of-speech (pos) tag indicating its grammatical role, and past count the frequencies of those pos tags. The logic this is simply a beardown awesome is that it captures the measurement different sources building themselves, without getting distracted by choices of words.
The 3 variants of this characteristic usage different engines for pos tagging8 Some engines are much meticulous than others., but they each produce roughly the aforesaid result. The use of the wink-nlp motor is that – even though it’s weaker than the different 2 successful the chart – it runs successful the browser.
The pos tag replacement turns the Trump reside into thing for illustration the sequence NNS VBP IN PRP$ JJS NN IN JJ NNS CC PRP MD RB VB IN DT NN. This sequence contains much plural nouns (NNS) than the Economist, which connected the other manus contains much due nouns (NNP) and determiners (DT).
- wink2gram, upos2gram, ptb2gram, wink3gram, upos3gram, ptb3gram are bigram and trigram variants of the above.
When evaluating classifiers pinch a azygous characteristic astatine a time, which is what the graph above represents, we tin spot that pos tag n-grams are very powerful regardless of which tagging motor is used. Character n-grams are besides powerful, and raw word frequencies are not truthful bad either.
But azygous features are only half the story, because erstwhile we train classifiers on aggregate features, the features interact. Interaction makes immoderate features redundant, but it tin besides make combinations of features stronger than they were individually! I started pinch the group of top-scoring azygous features, and systematically evaluated combinations of features by adding and removing individual features to spot really they influenced each other, but yet I got tired of that workout and picked a group of features for the production classifier alternatively arbitrarily.9 I besides had a fewer subcommands to the training script that fto maine research features and really their associated frequencies varied among the classes to beryllium dicriminated.
The classifier is trained to categorize 7 ways. Given a azygous comment, it tries to discriminate betwixt the pursuing 7 sources:
- Humans
- GPT 5.6
- Gemini 3.7
- Claude 5
- Kimi K2.7
- Grok 4.6
- GLM 5.2
After a while, thing seemed odd, though. It almost ever predicted either Kimi K2.7 aliases glm arsenic 1 of the astir apt llm models. Some plotting of centroids of characteristic vectors later, it was clear that some of these models have styles that overlap each the different models10 I don’t cognize really distillation works but it sounds for illustration it could beryllium a applicable term. truthful the classifier’s judgement is partially smeared retired complete those 2 models alternatively than assigned to the actual source. Instead of retraining the classifier without those models, I return any probability wide assigned to those models during classification clip and smear it backmost complete the remainder of the models successful proportionality to really overmuch wide it sucked from them during training. This intends Kimi K2.7 donates probability chiefly to Grok and Claude, and glm astir evenly to each different models.
I besides realised erstwhile I started utilizing the classifier that what I really wanted to know was whether a remark was human-written aliases robot-generated; seldom is it important to cognize which llm exemplary whitethorn person generated the comment. So astatine the classification shape the probability masses are re-normalised to emulate a 50/50 prior for human/robot alternatively than the 1/7 priors the classifier is trained for.
It mightiness look silly that we train a 7-way classifier, trim it to a 5-way classifier, and past simplify again to a 2-way classification. We could have trained a 2-way classifier to statesman with! But location are 2 benefits to doing it the analyzable way:
- It makes it imaginable to show a cool llm exemplary breakdown adjacent to the main prediction.
- It mightiness let america to amended seizure the analyzable style of the high-dimensional surface that separates quality penning from robot-generated text.
I haven’t really tally a general benchmark connected the reduced 7-way classifier against a trained 2-way classifier, but I don’t deliberation the quality in performance would beryllium that large, truthful see the first constituent the existent benefit.
One of the remaining problems is the aforesaid arsenic successful the erstwhile article: with L1-normalised features, the resulting probabilities of the logistic regression become very small. A abstracted walk takes the trained exemplary and calibrates a temperature coefficient k which extremises predictions based connected the square root of the magnitude of the input.
At first I built a cli interface for classification, but I alternatively quickly realised that
- It would beryllium easier for different group to play pinch if I vessel it arsenic a web page with a classifier exemplary bundled; and
- It would beryllium easier for me to diagnose and troubleshoot it if it had a fancier diagnostics interface, and that would beryllium easier successful the browser.
I was worried astir the size of the classifier model, which ran into several megabytes successful its earthy form. Thus I ended up some quantising coefficients and reducing the vocabulary of each features pinch a archive wave filter, i.e. stripping retired those characteristic values which only existed successful a mini subset of comments. There was a knee successful the precision curve astir 0.05 %, meaning feature values that only beryllium successful less than that fraction of comments aren’t portion of the classifier. The exemplary is now 355 kB.
The different alteration the web interface brought was that it required being capable to pos tag input successful the browser! This made the higher-performing Python-based engines (nltk and spaCy) unavailable, and I was forced to usage wink-nlp. Hypothetically, location shouldn’t beryllium an rumor pinch training utilizing 1 motor and pre-processing classification input pinch another, but to debar input being out-of-sample for silly reasons, I opted to usage wink-nlp successful Python too, which meant Python invoking a Node.js process and it’s not pretty.
But where’s the root code? You promised root code!
I genuinely had the volition of penning retired the codification for each of this myself. I thought I’d usage robots to make experiments pinch models, features, visualisations, etc., and past rewrite the last type connected my own, to make sure the codification is precocious quality.
But I cannot beryllium arsed. This is simply a broadside quest, not thing I tin walk overmuch time on. If you don’t want to publication AI slop code, don’t publication the implementation. Read this explanation of really it’s done instead, and possibly you tin make your own.
I besides apt won’t proceed to activity connected this because sourcehut’s newest tos, going into effect for each changes submitted from tomorrow, forbids utilizing it to host llm-generated code. Enjoy this successful the style it is!
English (US) ·
Indonesian (ID) ·