diff --git a/Docs/Blog/PUBLICACION.md b/Docs/Blog/PUBLICACION.md index 9bd2433..32edbd5 100644 --- a/Docs/Blog/PUBLICACION.md +++ b/Docs/Blog/PUBLICACION.md @@ -308,6 +308,8 @@ de los seis (video / voz / cola en segundos): | `signsofai-baseline-story.{en,es}.html` | WordPress · Blogger — **generados** | | `signsofai-calibration-story.{en,es}.md` | dev.to · Hashnode · Medium — **sexto artículo**, sin publicar | | `signsofai-calibration-story.{en,es}.html` | WordPress · Blogger — **generados** | +| `signsofai-verdict-story.{en,es}.md` | dev.to · Hashnode · Medium — **séptimo artículo**, sin publicar | +| `signsofai-verdict-story.{en,es}.html` | WordPress · Blogger — **generados** | **Generar el HTML.** Los dos primeros artículos se escribieron como HTML a mano. Transcribir 1.500 palabras dos veces más, en dos idiomas, es la forma segura de corregir un párrafo en una copia y no @@ -1095,6 +1097,117 @@ MIT y gratis: https://github.com/peopleworks/SignsofAI #IntegridadAcadémica #IA #EdTech #Estadística #DotNet ``` +### X / Twitter — séptimo artículo (EN) +``` +My AI detector never once gave a verdict. Not one, in any language, since the feature shipped. + +The report gated the verdict behind the threshold measured for that specific language. My corpus has +65 English texts and 25 Spanish; bounding a rate under 5% takes ~75. So the threshold was null for +both, and the condition after it was false. Always. + +Meanwhile the CLI printed "Strong signs of AI writing" on the same text, in the same run. + +340 tests. Not one compared the two. + +https://github.com/peopleworks/SignsofAI +``` + +### X / Twitter — séptimo artículo (ES) +``` +Mi detector de IA no emitió un veredicto ni una sola vez. Ninguno, en ningún idioma, desde que existe +la función. + +El informe exigía el umbral medido para ese idioma concreto. Mi corpus tiene 65 textos en inglés y 25 +en español; acotar una tasa por debajo del 5% pide unos 75. El umbral era null en los dos, y la +condición siguiente, falsa. Siempre. + +Mientras tanto el CLI decía "Señales fuertes de escritura con IA" del mismo texto, en la misma +ejecución. + +340 pruebas. Ninguna comparaba las dos. + +https://github.com/peopleworks/SignsofAI +``` + +### LinkedIn — séptimo artículo (EN) +``` +The same text, the same build of my own tool, the same minute. + +Command line: 90/100, "Strong signs of AI writing". +The exported report — the document a teacher prints and carries to an integrity meeting: no verdict +at all. + +The report withheld its verdict below the threshold measured for the language it was reading. That +rule is right. But my corpus holds 65 English texts and 25 Spanish, and bounding a false-positive +rate under 5% needs roughly 75 in a group. Neither group qualifies. The threshold was null for both +languages, so the condition was false for every document ever analysed. + +Two things let it live there: + +The bands were written out in nine places, kept in step by a comment. They had already drifted — one +page cut at 40 where the rest cut at 45. + +And nothing compared the surfaces. I had 340 tests, each checking one face against its own +expectations. None asked whether the three faces agreed about the same text. + +Underneath sat something worse. This project publishes a measured threshold of 25/100. The product +drew its line at 20 and called it "light signs of AI writing" — five points below the number on my +own calibration page, and below the highest-scoring human text in the corpus. + +Publishing a calibrated figure and shipping an uncalibrated one is exactly what I criticise other +detectors for. + +Two independent reviewers found the always-false condition before I wrote a line of code. Then they +disagreed about the fix, which was more useful than agreement. + +Four bands are now two. Above the measured line: "Signs of AI writing". Below it: "No signs above the +measured boundary" — a statement about the tool, not about the person. That was the last place the +product said anything about a human being rather than about my own instrument. + +Full write-up, and the command that regenerates every number in it: +https://github.com/peopleworks/SignsofAI +``` + +### LinkedIn — séptimo artículo (ES) +``` +El mismo texto, la misma compilación de mi herramienta, el mismo minuto. + +Línea de comandos: 90/100, "Señales fuertes de escritura con IA". +El informe exportado — el documento que un profesor imprime y lleva a una comisión de integridad: +ningún veredicto. + +El informe retenía el veredicto por debajo del umbral medido para el idioma que estaba leyendo. Esa +regla está bien. Pero mi corpus tiene 65 textos en inglés y 25 en español, y acotar una tasa de +falsos positivos por debajo del 5% pide unos 75 por grupo. Ninguno llega. El umbral era null en los +dos idiomas, así que la condición era falsa para todos los documentos analizados. + +Dos cosas le permitieron vivir ahí: + +Las bandas estaban escritas en nueve sitios, sincronizadas por un comentario. Ya se habían desviado: +una página cortaba en 40 donde el resto cortaba en 45. + +Y nada comparaba las caras entre sí. Tenía 340 pruebas, cada una comprobando una superficie contra +sus propias expectativas. Ninguna preguntaba si las tres coincidían sobre el mismo texto. + +Debajo había algo peor. Este proyecto publica un umbral medido de 25/100. El producto trazaba su +línea en 20 y lo llamaba "señales leves de escritura con IA": cinco puntos por debajo de la cifra de +mi propia página de calibración, y por debajo del texto humano más alto del corpus. + +Publicar una cifra calibrada y entregar otra sin calibrar es exactamente lo que le critico a otros +detectores. + +Dos revisores independientes encontraron la condición siempre falsa antes de que yo escribiera una +línea de código. Luego discreparon sobre el arreglo, que fue más útil que si hubieran coincidido. + +Cuatro bandas son ahora dos. Por encima de la línea medida: "Señales de escritura con IA". Por +debajo: "Sin señales por encima del umbral medido" — una afirmación sobre la herramienta, no sobre +la persona. Era el último sitio donde el producto decía algo sobre un ser humano en vez de sobre mi +propio instrumento. + +El artículo completo, y el comando que regenera cada número que contiene: +https://github.com/peopleworks/SignsofAI +``` + ## 8. Notas de publicación - Sube el `.srt` de cada video como subtítulos (clave para reproducción sin sonido en Shorts/Reels/TikTok). - Cruza los enlaces: el video enlaza al artículo del blog y viceversa; ambos enlazan al demo. diff --git a/Docs/Blog/signsofai-verdict-story.en.html b/Docs/Blog/signsofai-verdict-story.en.html new file mode 100644 index 0000000..5d92dd2 --- /dev/null +++ b/Docs/Blog/signsofai-verdict-story.en.html @@ -0,0 +1,175 @@ + + + + + +My AI detector never once gave a verdict, and nothing noticed for weeks · SignsOfAI + + + + +
+ +
+ SignsOfAI + PeopleWorks · Microsoft MVP for .NET +
+ +
Maker story · Engineering
+

My AI detector never once gave a verdict, and nothing noticed for weeks

+

The same text, the same engine, the same run: 90/100 and 'Strong signs of AI writing' on screen, and no verdict at all in the document a teacher would print. One condition was false for every document ever analysed, and nothing in 340 tests compared the two.

+

Pedro Hernández (PeopleWorks)

+ + ▶ Download or try it — free, MIT, web and Windows. + +
+ +

Here is the same text, run through the same build of my own tool, in the same minute.

+

The command line:

+
  90/100  Strong signs of AI writing   (23 signals, English)
+

The report — the document a teacher exports, prints, and carries to an academic integrity meeting:

+
  **89.9/100**
+
+  *Below the threshold this build can support, so no verdict is given.*
+

One engine. Two answers. And the second one was not a rare edge case: the exported report had never printed a verdict, for any document, in any language, since the feature shipped.

+

An if that was always false

+

The report withholds its verdict below the threshold the build can support. That is deliberate and I still think it is right — a score with no error rate beside it is the thing this whole project exists to complain about.

+

The check looked like this:

+
return c.For(result.Language)?.RecommendedThreshold is { } threshold
+    && result.OverallScore >= threshold;
+

Read it slowly. It asks for the threshold measured for that specific language.

+

My calibration corpus has 90 texts published before generative models existed: 65 English, 25 Spanish. To bound a false-positive rate under 5% with nothing flagged, the statistics need roughly 75 texts in a group. Neither group has 75. So the per-language threshold is null for English, null for Spanish, and the condition after it is false. Always. For everyone.

+

I had written a careful rule — never quote a rate measured on another language — and then applied it to a question it did not govern. The result was a report that refused to speak about anything, ever, while the screen next to it spoke freely about everything.

+

Why nothing caught it

+

Two reasons, and both are more interesting than the bug.

+

The bands lived in nine places. The verdict thresholds were written out in the analysis result, the report, the interface's localiser, the CLI's colour picker, two switches in the web page, the batch page, the live-rewrite panel. Kept in step by a comment: "mirrors the bands in AnalysisResult.Verdict".

+

A comment is not a mechanism. They had already drifted. The batch page cut at 40 where everything else cut at 45, so a single build could colour the same document two different ways depending on which page you opened it in.

+

Nothing compared the surfaces. I had 340 tests. Every one of them checked a surface against its own expectations. Not one asked whether the CLI, the web page and the exported report said the same thing about the same text. The disagreement was not hiding in a corner; it was the loudest thing in the product, and it was invisible because no test was pointed at it.

+

That is the transferable lesson, and it cost me nothing to learn only because nobody was using the report yet. If you ship one engine behind several faces, write the test that runs one input through all of them and fails when they disagree. It is ten lines. Mine fails on the parent commit, which is how I know it tests something.

+

The part that was actually embarrassing

+

Under the bug sat something worse, and I had known about it for two days without connecting them.

+

This project publishes a measured threshold. From the calibration page: at 25/100, the tool flags at most 5% of writing known to be human — 0 of 90 texts, with a 95% interval reaching 4.1%.

+

The product drew its line at 20, in prose: "Light signs of AI writing". That number was picked by hand, early, before there was anything to pick it against. One human text in the corpus scored above it. The highest-scoring human text in the whole corpus reached 23.4, comfortably inside the range the product was calling "light signs of AI writing".

+

Publishing a calibrated figure and shipping an uncalibrated one is precisely the failure I criticise other detectors for. I had done it in my own repository, in public, for weeks, on the same page as the measurement.

+

Two reviewers, one disagreement, and the distinction that resolved it

+

I now run design reviews before writing code, with two independent models given the same brief and told to attack it. Both found the always-false condition on their own, without being told. That is the entire argument for the practice: I had stared at that method and not seen it.

+

They then disagreed, which was more useful than agreement.

+

One said: fall back to the pooled threshold when a language has none of its own. Otherwise the tool waits years for Spanish and helps nobody.

+

The other said: no — the codebase has an explicit rule against borrowing the aggregate, and either you honour it or you delete it, but you do not quietly break it.

+

Both are right, about different things, and the distinction took me an embarrassing while to see:

+ +

Same number, two different acts. One is a claim about how often I am wrong. The other is a line in the sand.

+

So the boundary is now borrowed and the rate never is — and there are three states, not two. A language in the corpus borrows the line and carries its own bound. A language absent from it gets no verdict at any score, because there would be nothing on the page to correct the impression a verdict leaves. A build with no calibration of its own says nothing about anything.

+

The reviewer who proposed the flat fallback would have broken that third case. I checked instead of agreeing, and a test that was right caught it.

+

Four bands became two

+

The old scale read "Strong", "Moderate", "Light", "Reads mostly human". Four measured-sounding degrees.

+

Exactly one of those boundaries was measured. My corpus can locate the line where human writing stops and says nothing whatever about 45 or 70. No text known to be human came within twenty points of either. Grading "moderate" against "strong" would require a corpus of machine-written text, and the same calibration page argues at length against ever collecting one: it samples whichever models were convenient that month, ages badly, and flatters whoever assembled it.

+

The obvious compromise was to keep the words and add a footnote admitting they are unmeasured. I nearly did. What killed it: the footnote is read once and the heading is read every time. A page whose headline says "Strong signs of AI writing" and whose small print says "we cannot measure this" has not been honest — it has been honest in a place nobody looks.

+

So above the line the tool now says "Signs of AI writing" and lets the findings carry the weight, which is what findings are for.

+

Below the line was the more revealing one. The report said "Reads mostly human". The interface said "Minimal signs of AI writing". Same state, two different claims, and the first one was never mine to make. A detector that detects nothing also returns a low score, and I have deliberately never measured how much machine writing this catches. Both now read: "No signs above the measured boundary." A statement about the tool, not about the person.

+

It was the last place in the product where I said something about a human being rather than about my own instrument.

+

The one that mattered

+

Then I went looking for what the change had made stale, and found something that had nothing to do with it.

+

The teacher package — syllabus language, a student sheet, a procedure for integrity committees — includes a paragraph for a teacher to copy into a disciplinary finding. It handed them the pooled rate: "under 4.1% overall". Whatever language the work was in.

+

For a Spanish essay, the honest figure is 13.3%.

+

A committee judging a Spanish-speaking student was being handed a tool three times better than the one actually used, in the teacher's own handwriting, in a document that gets read at appeal. The student sheet had the same defect: both language editions quoted the pooled number, including the Spanish one written for the students most likely to be harmed by a rate measured mostly on English.

+

I had fixed exactly this bug inside the report two days earlier. I fixed it in the code and left it standing in the document that carries the code's output into a room where it can end someone's semester.

+

Every edition now quotes its own figure, and says the pooled one is more flattering and that is why it is not being used.

+

What I would take from this

+

The verdict change moved no scores. I re-ran the calibration before and after and the published file is byte-identical: same fingerprint, same 90 texts, same threshold, same interval. That check exists so nobody, me included, can shift a boundary and present the improved number as an achievement.

+

Three things I would keep:

+

One input, every surface, one test. If several faces share an engine, something must fail when they disagree. Mine had 340 tests and none of them looked.

+

A comment is not a mechanism. Nine copies of a number synced by a sentence in a doc block drift, and they had.

+

Check whether your product does what your measurement says. The gap between a published figure and shipped behaviour is the exact thing I built this tool to point out in other people's work. It was in mine, in public, next to the measurement, for weeks.

+

The code is MIT, the corpus manifest and the calibration are in the repository, and the command that regenerates them is one line: github.com/peopleworks/SignsofAI.

+ + + +
+ + diff --git a/Docs/Blog/signsofai-verdict-story.en.md b/Docs/Blog/signsofai-verdict-story.en.md new file mode 100644 index 0000000..2e29c71 --- /dev/null +++ b/Docs/Blog/signsofai-verdict-story.en.md @@ -0,0 +1,131 @@ +--- +title: "My AI detector never once gave a verdict, and nothing noticed for weeks" +description: "The same text, the same engine, the same run: 90/100 and 'Strong signs of AI writing' on screen, and no verdict at all in the document a teacher would print. One condition was false for every document ever analysed, and nothing in 340 tests compared the two." +canonical_url: "https://github.com/peopleworks/SignsofAI" +cover_image: "https://raw.githubusercontent.com/peopleworks/SignsofAI/main/Docs/Blog/social/verdict-story-cover.png" +tags: [ai, testing, academicintegrity, dotnet] +author: "Pedro Hernández (PeopleWorks)" +lang: en +--- + +# My AI detector never once gave a verdict, and nothing noticed for weeks + +Here is the same text, run through the same build of my own tool, in the same minute. + +The command line: + +``` + 90/100 Strong signs of AI writing (23 signals, English) +``` + +The report — the document a teacher exports, prints, and carries to an academic integrity meeting: + +``` + **89.9/100** + + *Below the threshold this build can support, so no verdict is given.* +``` + +One engine. Two answers. And the second one was not a rare edge case: the exported report had **never printed a verdict, for any document, in any language, since the feature shipped**. + +## An `if` that was always false + +The report withholds its verdict below the threshold the build can support. That is deliberate and I still think it is right — a score with no error rate beside it is the thing this whole project exists to complain about. + +The check looked like this: + +```csharp +return c.For(result.Language)?.RecommendedThreshold is { } threshold + && result.OverallScore >= threshold; +``` + +Read it slowly. It asks for the threshold measured **for that specific language**. + +My calibration corpus has 90 texts published before generative models existed: 65 English, 25 Spanish. To bound a false-positive rate under 5% with nothing flagged, the statistics need roughly 75 texts in a group. Neither group has 75. So the per-language threshold is `null` for English, `null` for Spanish, and the condition after it is false. Always. For everyone. + +I had written a careful rule — *never quote a rate measured on another language* — and then applied it to a question it did not govern. The result was a report that refused to speak about anything, ever, while the screen next to it spoke freely about everything. + +## Why nothing caught it + +Two reasons, and both are more interesting than the bug. + +**The bands lived in nine places.** The verdict thresholds were written out in the analysis result, the report, the interface's localiser, the CLI's colour picker, two switches in the web page, the batch page, the live-rewrite panel. Kept in step by a comment: *"mirrors the bands in AnalysisResult.Verdict"*. + +A comment is not a mechanism. They had already drifted. The batch page cut at 40 where everything else cut at 45, so a single build could colour the same document two different ways depending on which page you opened it in. + +**Nothing compared the surfaces.** I had 340 tests. Every one of them checked a surface against its own expectations. Not one asked whether the CLI, the web page and the exported report said the same thing about the same text. The disagreement was not hiding in a corner; it was the loudest thing in the product, and it was invisible because no test was pointed at it. + +That is the transferable lesson, and it cost me nothing to learn only because nobody was using the report yet. If you ship one engine behind several faces, write the test that runs one input through all of them and fails when they disagree. It is ten lines. Mine fails on the parent commit, which is how I know it tests something. + +## The part that was actually embarrassing + +Under the bug sat something worse, and I had known about it for two days without connecting them. + +This project publishes a measured threshold. From the calibration page: **at 25/100, the tool flags at most 5% of writing known to be human** — 0 of 90 texts, with a 95% interval reaching 4.1%. + +The product drew its line at **20**, in prose: *"Light signs of AI writing"*. That number was picked by hand, early, before there was anything to pick it against. One human text in the corpus scored above it. The highest-scoring human text in the whole corpus reached 23.4, comfortably inside the range the product was calling "light signs of AI writing". + +Publishing a calibrated figure and shipping an uncalibrated one is precisely the failure I criticise other detectors for. I had done it in my own repository, in public, for weeks, on the same page as the measurement. + +## Two reviewers, one disagreement, and the distinction that resolved it + +I now run design reviews before writing code, with two independent models given the same brief and told to attack it. Both found the always-false condition on their own, without being told. That is the entire argument for the practice: I had stared at that method and not seen it. + +They then disagreed, which was more useful than agreement. + +One said: fall back to the pooled threshold when a language has none of its own. Otherwise the tool waits years for Spanish and helps nobody. + +The other said: no — the codebase has an explicit rule against borrowing the aggregate, and either you honour it or you delete it, but you do not quietly break it. + +Both are right, about different things, and the distinction took me an embarrassing while to see: + +- Borrowing the aggregate **error rate** misstates reliability. Telling a Spanish writer their essay was judged by a tool wrong 4.1% of the time, when the measurement for Spanish alone supports only 13.3%, hands them a number three times better than anything measured on their language. That stays forbidden. +- Borrowing the aggregate **boundary** asserts nothing about reliability. It decides when the tool opens its mouth. It is measured, it is published, and it is printed on the page beside the language's own figure. + +Same number, two different acts. One is a claim about how often I am wrong. The other is a line in the sand. + +So the boundary is now borrowed and the rate never is — and there are three states, not two. A language **in** the corpus borrows the line and carries its own bound. A language **absent** from it gets no verdict at any score, because there would be nothing on the page to correct the impression a verdict leaves. A build with no calibration of its own says nothing about anything. + +The reviewer who proposed the flat fallback would have broken that third case. I checked instead of agreeing, and a test that was right caught it. + +## Four bands became two + +The old scale read "Strong", "Moderate", "Light", "Reads mostly human". Four measured-sounding degrees. + +Exactly one of those boundaries was measured. My corpus can locate the line where human writing stops and says **nothing whatever** about 45 or 70. No text known to be human came within twenty points of either. Grading "moderate" against "strong" would require a corpus of machine-written text, and the same calibration page argues at length against ever collecting one: it samples whichever models were convenient that month, ages badly, and flatters whoever assembled it. + +The obvious compromise was to keep the words and add a footnote admitting they are unmeasured. I nearly did. What killed it: **the footnote is read once and the heading is read every time.** A page whose headline says "Strong signs of AI writing" and whose small print says "we cannot measure this" has not been honest — it has been honest in a place nobody looks. + +So above the line the tool now says "Signs of AI writing" and lets the findings carry the weight, which is what findings are for. + +Below the line was the more revealing one. The report said *"Reads mostly human"*. The interface said *"Minimal signs of AI writing"*. Same state, two different claims, and the first one was never mine to make. A detector that detects nothing also returns a low score, and I have deliberately never measured how much machine writing this catches. Both now read: **"No signs above the measured boundary."** A statement about the tool, not about the person. + +It was the last place in the product where I said something about a human being rather than about my own instrument. + +## The one that mattered + +Then I went looking for what the change had made stale, and found something that had nothing to do with it. + +The teacher package — syllabus language, a student sheet, a procedure for integrity committees — includes a paragraph for a teacher to copy into a disciplinary finding. It handed them the pooled rate: *"under 4.1% overall"*. Whatever language the work was in. + +For a Spanish essay, the honest figure is 13.3%. + +A committee judging a Spanish-speaking student was being handed a tool three times better than the one actually used, in the teacher's own handwriting, in a document that gets read at appeal. The student sheet had the same defect: **both** language editions quoted the pooled number, including the Spanish one written for the students most likely to be harmed by a rate measured mostly on English. + +I had fixed exactly this bug inside the report two days earlier. I fixed it in the code and left it standing in the document that carries the code's output into a room where it can end someone's semester. + +Every edition now quotes its own figure, and says the pooled one is more flattering and that is why it is not being used. + +## What I would take from this + +The verdict change moved no scores. I re-ran the calibration before and after and the published file is byte-identical: same fingerprint, same 90 texts, same threshold, same interval. That check exists so nobody, me included, can shift a boundary and present the improved number as an achievement. + +Three things I would keep: + +**One input, every surface, one test.** If several faces share an engine, something must fail when they disagree. Mine had 340 tests and none of them looked. + +**A comment is not a mechanism.** Nine copies of a number synced by a sentence in a doc block drift, and they had. + +**Check whether your product does what your measurement says.** The gap between a published figure and shipped behaviour is the exact thing I built this tool to point out in other people's work. It was in mine, in public, next to the measurement, for weeks. + +The code is MIT, the corpus manifest and the calibration are in the repository, and the command that regenerates them is one line: [github.com/peopleworks/SignsofAI](https://github.com/peopleworks/SignsofAI). diff --git a/Docs/Blog/signsofai-verdict-story.es.html b/Docs/Blog/signsofai-verdict-story.es.html new file mode 100644 index 0000000..44a7e2c --- /dev/null +++ b/Docs/Blog/signsofai-verdict-story.es.html @@ -0,0 +1,175 @@ + + + + + +Mi detector de IA no emitió un veredicto ni una sola vez, y nada lo notó durante semanas · SignsOfAI + + + + +
+ +
+ SignsOfAI + PeopleWorks · Microsoft MVP for .NET +
+ +
Historia de taller · Ingeniería
+

Mi detector de IA no emitió un veredicto ni una sola vez, y nada lo notó durante semanas

+

El mismo texto, el mismo motor, la misma ejecución: 90/100 y «Señales fuertes de escritura con IA» en pantalla, y ningún veredicto en el documento que un profesor imprime. Una condición era falsa para todos los documentos, y ninguna de 340 pruebas comparaba las dos caras.

+

Pedro Hernández (PeopleWorks)

+ + ▶ Descárgalo o pruébalo — gratis, MIT, web y Windows. + +
+ +

Este es el mismo texto, pasado por la misma compilación de mi propia herramienta, en el mismo minuto.

+

La línea de comandos:

+
  90/100  Strong signs of AI writing   (23 signals, English)
+

El informe — el documento que un profesor exporta, imprime y lleva a una comisión de integridad académica:

+
  **89.9/100**
+
+  *Por debajo del umbral que esta compilación puede respaldar, no se emite ningún veredicto.*
+

Un motor. Dos respuestas. Y la segunda no era un caso raro: el informe exportado no había emitido un veredicto nunca, para ningún documento, en ningún idioma, desde que la función existe.

+

Un if que siempre era falso

+

El informe retiene el veredicto por debajo del umbral que la compilación puede respaldar. Eso es deliberado y sigo pensando que está bien: una puntuación sin su tasa de error al lado es exactamente lo que este proyecto existe para criticar.

+

La comprobación era esta:

+
return c.For(result.Language)?.RecommendedThreshold is { } threshold
+    && result.OverallScore >= threshold;
+

Léala despacio. Pide el umbral medido para ese idioma concreto.

+

Mi corpus de calibración tiene 90 textos publicados antes de que existiera la escritura con IA: 65 en inglés, 25 en español. Para acotar una tasa de falsos positivos por debajo del 5% sin nada marcado, la estadística necesita unos 75 textos en el grupo. Ninguno de los dos grupos llega a 75. Así que el umbral por idioma es null en inglés, null en español, y la condición que viene después es falsa. Siempre. Para todo el mundo.

+

Yo había escrito una regla cuidadosa —nunca cites una tasa medida sobre otro idioma— y luego la apliqué a una pregunta que esa regla no gobernaba. El resultado fue un informe que se negaba a hablar de nada, jamás, mientras la pantalla de al lado hablaba de todo sin problema.

+

Por qué no lo detectó nada

+

Dos razones, y las dos son más interesantes que el fallo.

+

Las bandas vivían en nueve sitios. Los umbrales del veredicto estaban escritos a mano en el resultado del análisis, en el informe, en el localizador de la interfaz, en el color del CLI, en dos condicionales de la página web, en la página de lote, en el panel de reescritura. Sincronizados por un comentario: «refleja las bandas de AnalysisResult.Verdict».

+

Un comentario no es un mecanismo. Ya se habían desviado. La página de lote cortaba en 40 donde todo lo demás cortaba en 45, así que una misma compilación podía colorear el mismo documento de dos formas según en qué página lo abrieras.

+

Nada comparaba las caras entre sí. Tenía 340 pruebas. Todas comprobaban una superficie contra sus propias expectativas. Ninguna preguntaba si el CLI, la página web y el informe exportado decían lo mismo sobre el mismo texto. La contradicción no estaba escondida en un rincón: era lo más ruidoso del producto, y era invisible porque ninguna prueba apuntaba ahí.

+

Esa es la lección aprovechable, y me salió gratis solo porque nadie usaba todavía el informe. Si publica un motor detrás de varias caras, escriba la prueba que pasa una entrada por todas y falla cuando no coinciden. Son diez líneas. La mía falla en el commit anterior, que es como sé que comprueba algo.

+

La parte que sí daba vergüenza

+

Debajo del fallo había algo peor, y llevaba dos días sabiéndolo sin conectar ambas cosas.

+

Este proyecto publica un umbral medido. De la página de calibración: en 25/100, la herramienta marca como mucho el 5% de la escritura que se sabe humana — 0 de 90 textos, con un intervalo del 95% que llega al 4,1%.

+

El producto trazaba su línea en 20, y en prosa: «Señales leves de escritura con IA». Ese número lo elegí a mano, pronto, antes de que existiera nada contra lo que elegirlo. Un texto humano del corpus puntuaba por encima. El texto humano más alto de todo el corpus llegó a 23,4, cómodamente dentro del rango que el producto llamaba «señales leves de escritura con IA».

+

Publicar una cifra calibrada y entregar otra sin calibrar es exactamente el fallo que le critico a otros detectores. Lo tenía en mi propio repositorio, en público, durante semanas, en la misma página que la medición.

+

Dos revisores, un desacuerdo, y la distinción que lo resolvió

+

Ahora hago revisiones de diseño antes de escribir código, con dos modelos independientes a los que doy el mismo encargo y la orden de atacarlo. Los dos encontraron por su cuenta la condición siempre falsa, sin que nadie se la señalara. Ese es el argumento entero a favor de la práctica: yo había mirado ese método y no lo había visto.

+

Y luego discreparon, que fue más útil que si hubieran coincidido.

+

Uno dijo: cuando un idioma no tenga umbral propio, usa el agregado. Si no, la herramienta espera años por el español y no ayuda a nadie.

+

El otro dijo: no — el código tiene una regla explícita contra tomar prestado el agregado, y o la respetas o la borras, pero no la rompes en silencio.

+

Los dos tenían razón sobre cosas distintas, y me costó vergonzosamente ver la diferencia:

+ +

El mismo número, dos actos distintos. Uno es una afirmación sobre cuánto me equivoco. El otro es una raya en el suelo.

+

Así que la frontera ahora se presta y la tasa nunca — y hay tres estados, no dos. Un idioma presente en el corpus toma la línea y lleva su propia cota. Un idioma ausente no recibe veredicto con ninguna puntuación, porque no habría nada en la página que corrigiera la impresión que deja un veredicto. Una compilación sin calibración propia no dice nada de nada.

+

El revisor que proponía el respaldo plano habría roto ese tercer caso. Comprobé en vez de asentir, y una prueba que estaba bien lo atrapó.

+

Cuatro bandas se volvieron dos

+

La escala vieja decía «fuertes», «moderadas», «leves», «parece escrito mayormente por una persona». Cuatro grados con sonido de medición.

+

Exactamente una de esas fronteras estaba medida. Mi corpus puede situar la línea donde termina la escritura humana y no dice absolutamente nada sobre el 45 ni sobre el 70. Ningún texto conocidamente humano se acercó a menos de veinte puntos de ninguno de los dos. Graduar «moderadas» frente a «fuertes» exigiría un corpus de texto escrito por máquina, y esa misma página de calibración argumenta largamente contra reunir uno jamás: muestrea los modelos que estuvieran a mano ese mes, envejece mal y adula a quien lo montó.

+

El compromiso obvio era conservar las palabras y añadir una nota al pie admitiendo que no están medidas. Estuve a punto. Lo que lo mató: la nota al pie se lee una vez y el titular se lee siempre. Una página cuyo encabezado dice «Señales fuertes de escritura con IA» y cuya letra pequeña dice «esto no lo podemos medir» no ha sido honesta: ha sido honesta en un sitio donde nadie mira.

+

Así que por encima de la línea la herramienta ahora dice «Señales de escritura con IA» y deja que los hallazgos carguen con el peso, que es para lo que están los hallazgos.

+

Por debajo de la línea estaba lo más revelador. El informe decía «Parece escrito mayormente por una persona». La interfaz decía «Señales mínimas de escritura con IA». El mismo estado, dos afirmaciones distintas, y la primera nunca me correspondió hacerla. Un detector que no detecta nada también devuelve una puntuación baja, y yo deliberadamente nunca he medido cuánta escritura de máquina caza esta herramienta. Las dos dicen ahora: «Sin señales por encima del umbral medido.» Una afirmación sobre la herramienta, no sobre la persona.

+

Era el último sitio del producto donde yo decía algo sobre un ser humano en lugar de sobre mi propio instrumento.

+

El que de verdad importaba

+

Después fui a buscar qué había dejado obsoleto el cambio, y encontré algo que no tenía nada que ver con él.

+

El paquete para el docente — texto para el programa de la asignatura, una hoja para el estudiante, un procedimiento para comisiones de integridad — incluye un párrafo para que el profesor lo copie en una resolución disciplinaria. Le entregaba la tasa agregada: «inferior al 4,1% en agregado». Fuera cual fuera el idioma del trabajo.

+

Para un ensayo en español, la cifra honesta es 13,3%.

+

A una comisión que juzgaba a un estudiante hispanohablante se le estaba entregando una herramienta tres veces mejor que la que realmente se usó, de puño y letra del profesor, en un documento que se lee en apelación. La hoja del estudiante tenía el mismo defecto: las dos ediciones citaban el número agregado, incluida la española, escrita para los estudiantes con más probabilidades de salir perjudicados por una tasa medida sobre todo en inglés.

+

Yo había arreglado exactamente ese fallo dentro del informe dos días antes. Lo arreglé en el código y lo dejé intacto en el documento que lleva la salida del código a una sala donde puede terminar el semestre de alguien.

+

Cada edición cita ahora su propia cifra, y dice que la agregada es más favorable y que por eso no se usa.

+

Qué me llevo de esto

+

El cambio del veredicto no movió ninguna puntuación. Re-ejecuté la calibración antes y después y el archivo publicado es idéntico byte a byte: misma huella, mismos 90 textos, mismo umbral, mismo intervalo. Esa comprobación existe para que nadie, yo el primero, pueda mover una frontera y presentar el número mejorado como un logro.

+

Tres cosas que me quedo:

+

Una entrada, todas las caras, una prueba. Si varias caras comparten un motor, algo tiene que fallar cuando se contradicen. Yo tenía 340 pruebas y ninguna miraba ahí.

+

Un comentario no es un mecanismo. Nueve copias de un número sincronizadas por una frase en un bloque de documentación se desvían, y ya se habían desviado.

+

Compruebe si su producto hace lo que dice su medición. La distancia entre una cifra publicada y el comportamiento entregado es justo lo que construí esta herramienta para señalar en el trabajo de otros. Estaba en el mío, en público, al lado de la medición, durante semanas.

+

El código es MIT, el manifiesto del corpus y la calibración están en el repositorio, y el comando que los regenera es una línea: github.com/peopleworks/SignsofAI.

+ + + +
+ + diff --git a/Docs/Blog/signsofai-verdict-story.es.md b/Docs/Blog/signsofai-verdict-story.es.md new file mode 100644 index 0000000..5eeb3d9 --- /dev/null +++ b/Docs/Blog/signsofai-verdict-story.es.md @@ -0,0 +1,131 @@ +--- +title: "Mi detector de IA no emitió un veredicto ni una sola vez, y nada lo notó durante semanas" +description: "El mismo texto, el mismo motor, la misma ejecución: 90/100 y «Señales fuertes de escritura con IA» en pantalla, y ningún veredicto en el documento que un profesor imprime. Una condición era falsa para todos los documentos, y ninguna de 340 pruebas comparaba las dos caras." +canonical_url: "https://github.com/peopleworks/SignsofAI" +cover_image: "https://raw.githubusercontent.com/peopleworks/SignsofAI/main/Docs/Blog/social/verdict-story-cover.png" +tags: [ia, testing, integridadacademica, dotnet] +author: "Pedro Hernández (PeopleWorks)" +lang: es +--- + +# Mi detector de IA no emitió un veredicto ni una sola vez, y nada lo notó durante semanas + +Este es el mismo texto, pasado por la misma compilación de mi propia herramienta, en el mismo minuto. + +La línea de comandos: + +``` + 90/100 Strong signs of AI writing (23 signals, English) +``` + +El informe — el documento que un profesor exporta, imprime y lleva a una comisión de integridad académica: + +``` + **89.9/100** + + *Por debajo del umbral que esta compilación puede respaldar, no se emite ningún veredicto.* +``` + +Un motor. Dos respuestas. Y la segunda no era un caso raro: el informe exportado **no había emitido un veredicto nunca, para ningún documento, en ningún idioma, desde que la función existe**. + +## Un `if` que siempre era falso + +El informe retiene el veredicto por debajo del umbral que la compilación puede respaldar. Eso es deliberado y sigo pensando que está bien: una puntuación sin su tasa de error al lado es exactamente lo que este proyecto existe para criticar. + +La comprobación era esta: + +```csharp +return c.For(result.Language)?.RecommendedThreshold is { } threshold + && result.OverallScore >= threshold; +``` + +Léala despacio. Pide el umbral medido **para ese idioma concreto**. + +Mi corpus de calibración tiene 90 textos publicados antes de que existiera la escritura con IA: 65 en inglés, 25 en español. Para acotar una tasa de falsos positivos por debajo del 5% sin nada marcado, la estadística necesita unos 75 textos en el grupo. Ninguno de los dos grupos llega a 75. Así que el umbral por idioma es `null` en inglés, `null` en español, y la condición que viene después es falsa. Siempre. Para todo el mundo. + +Yo había escrito una regla cuidadosa —*nunca cites una tasa medida sobre otro idioma*— y luego la apliqué a una pregunta que esa regla no gobernaba. El resultado fue un informe que se negaba a hablar de nada, jamás, mientras la pantalla de al lado hablaba de todo sin problema. + +## Por qué no lo detectó nada + +Dos razones, y las dos son más interesantes que el fallo. + +**Las bandas vivían en nueve sitios.** Los umbrales del veredicto estaban escritos a mano en el resultado del análisis, en el informe, en el localizador de la interfaz, en el color del CLI, en dos condicionales de la página web, en la página de lote, en el panel de reescritura. Sincronizados por un comentario: *«refleja las bandas de AnalysisResult.Verdict»*. + +Un comentario no es un mecanismo. Ya se habían desviado. La página de lote cortaba en 40 donde todo lo demás cortaba en 45, así que una misma compilación podía colorear el mismo documento de dos formas según en qué página lo abrieras. + +**Nada comparaba las caras entre sí.** Tenía 340 pruebas. Todas comprobaban una superficie contra sus propias expectativas. Ninguna preguntaba si el CLI, la página web y el informe exportado decían lo mismo sobre el mismo texto. La contradicción no estaba escondida en un rincón: era lo más ruidoso del producto, y era invisible porque ninguna prueba apuntaba ahí. + +Esa es la lección aprovechable, y me salió gratis solo porque nadie usaba todavía el informe. Si publica un motor detrás de varias caras, escriba la prueba que pasa una entrada por todas y falla cuando no coinciden. Son diez líneas. La mía falla en el commit anterior, que es como sé que comprueba algo. + +## La parte que sí daba vergüenza + +Debajo del fallo había algo peor, y llevaba dos días sabiéndolo sin conectar ambas cosas. + +Este proyecto publica un umbral medido. De la página de calibración: **en 25/100, la herramienta marca como mucho el 5% de la escritura que se sabe humana** — 0 de 90 textos, con un intervalo del 95% que llega al 4,1%. + +El producto trazaba su línea en **20**, y en prosa: *«Señales leves de escritura con IA»*. Ese número lo elegí a mano, pronto, antes de que existiera nada contra lo que elegirlo. Un texto humano del corpus puntuaba por encima. El texto humano más alto de todo el corpus llegó a 23,4, cómodamente dentro del rango que el producto llamaba «señales leves de escritura con IA». + +Publicar una cifra calibrada y entregar otra sin calibrar es exactamente el fallo que le critico a otros detectores. Lo tenía en mi propio repositorio, en público, durante semanas, en la misma página que la medición. + +## Dos revisores, un desacuerdo, y la distinción que lo resolvió + +Ahora hago revisiones de diseño antes de escribir código, con dos modelos independientes a los que doy el mismo encargo y la orden de atacarlo. Los dos encontraron por su cuenta la condición siempre falsa, sin que nadie se la señalara. Ese es el argumento entero a favor de la práctica: yo había mirado ese método y no lo había visto. + +Y luego discreparon, que fue más útil que si hubieran coincidido. + +Uno dijo: cuando un idioma no tenga umbral propio, usa el agregado. Si no, la herramienta espera años por el español y no ayuda a nadie. + +El otro dijo: no — el código tiene una regla explícita contra tomar prestado el agregado, y o la respetas o la borras, pero no la rompes en silencio. + +Los dos tenían razón sobre cosas distintas, y me costó vergonzosamente ver la diferencia: + +- Tomar prestada la **tasa de error** agregada tergiversa la fiabilidad. Decirle a quien escribe en español que su ensayo lo juzgó una herramienta que se equivoca el 4,1% de las veces, cuando la medición solo para español respalda un 13,3%, es entregarle una cifra tres veces mejor que cualquier cosa medida sobre su idioma. Eso sigue prohibido. +- Tomar prestada la **frontera** agregada no afirma nada sobre fiabilidad. Decide cuándo la herramienta abre la boca. Está medida, está publicada, y se imprime en la página junto a la cifra propia del idioma. + +El mismo número, dos actos distintos. Uno es una afirmación sobre cuánto me equivoco. El otro es una raya en el suelo. + +Así que la frontera ahora se presta y la tasa nunca — y hay tres estados, no dos. Un idioma **presente** en el corpus toma la línea y lleva su propia cota. Un idioma **ausente** no recibe veredicto con ninguna puntuación, porque no habría nada en la página que corrigiera la impresión que deja un veredicto. Una compilación sin calibración propia no dice nada de nada. + +El revisor que proponía el respaldo plano habría roto ese tercer caso. Comprobé en vez de asentir, y una prueba que estaba bien lo atrapó. + +## Cuatro bandas se volvieron dos + +La escala vieja decía «fuertes», «moderadas», «leves», «parece escrito mayormente por una persona». Cuatro grados con sonido de medición. + +Exactamente una de esas fronteras estaba medida. Mi corpus puede situar la línea donde termina la escritura humana y **no dice absolutamente nada** sobre el 45 ni sobre el 70. Ningún texto conocidamente humano se acercó a menos de veinte puntos de ninguno de los dos. Graduar «moderadas» frente a «fuertes» exigiría un corpus de texto escrito por máquina, y esa misma página de calibración argumenta largamente contra reunir uno jamás: muestrea los modelos que estuvieran a mano ese mes, envejece mal y adula a quien lo montó. + +El compromiso obvio era conservar las palabras y añadir una nota al pie admitiendo que no están medidas. Estuve a punto. Lo que lo mató: **la nota al pie se lee una vez y el titular se lee siempre.** Una página cuyo encabezado dice «Señales fuertes de escritura con IA» y cuya letra pequeña dice «esto no lo podemos medir» no ha sido honesta: ha sido honesta en un sitio donde nadie mira. + +Así que por encima de la línea la herramienta ahora dice «Señales de escritura con IA» y deja que los hallazgos carguen con el peso, que es para lo que están los hallazgos. + +Por debajo de la línea estaba lo más revelador. El informe decía *«Parece escrito mayormente por una persona»*. La interfaz decía *«Señales mínimas de escritura con IA»*. El mismo estado, dos afirmaciones distintas, y la primera nunca me correspondió hacerla. Un detector que no detecta nada también devuelve una puntuación baja, y yo deliberadamente nunca he medido cuánta escritura de máquina caza esta herramienta. Las dos dicen ahora: **«Sin señales por encima del umbral medido.»** Una afirmación sobre la herramienta, no sobre la persona. + +Era el último sitio del producto donde yo decía algo sobre un ser humano en lugar de sobre mi propio instrumento. + +## El que de verdad importaba + +Después fui a buscar qué había dejado obsoleto el cambio, y encontré algo que no tenía nada que ver con él. + +El paquete para el docente — texto para el programa de la asignatura, una hoja para el estudiante, un procedimiento para comisiones de integridad — incluye un párrafo para que el profesor lo copie en una resolución disciplinaria. Le entregaba la tasa agregada: *«inferior al 4,1% en agregado»*. Fuera cual fuera el idioma del trabajo. + +Para un ensayo en español, la cifra honesta es 13,3%. + +A una comisión que juzgaba a un estudiante hispanohablante se le estaba entregando una herramienta tres veces mejor que la que realmente se usó, de puño y letra del profesor, en un documento que se lee en apelación. La hoja del estudiante tenía el mismo defecto: **las dos** ediciones citaban el número agregado, incluida la española, escrita para los estudiantes con más probabilidades de salir perjudicados por una tasa medida sobre todo en inglés. + +Yo había arreglado exactamente ese fallo dentro del informe dos días antes. Lo arreglé en el código y lo dejé intacto en el documento que lleva la salida del código a una sala donde puede terminar el semestre de alguien. + +Cada edición cita ahora su propia cifra, y dice que la agregada es más favorable y que por eso no se usa. + +## Qué me llevo de esto + +El cambio del veredicto no movió ninguna puntuación. Re-ejecuté la calibración antes y después y el archivo publicado es idéntico byte a byte: misma huella, mismos 90 textos, mismo umbral, mismo intervalo. Esa comprobación existe para que nadie, yo el primero, pueda mover una frontera y presentar el número mejorado como un logro. + +Tres cosas que me quedo: + +**Una entrada, todas las caras, una prueba.** Si varias caras comparten un motor, algo tiene que fallar cuando se contradicen. Yo tenía 340 pruebas y ninguna miraba ahí. + +**Un comentario no es un mecanismo.** Nueve copias de un número sincronizadas por una frase en un bloque de documentación se desvían, y ya se habían desviado. + +**Compruebe si su producto hace lo que dice su medición.** La distancia entre una cifra publicada y el comportamiento entregado es justo lo que construí esta herramienta para señalar en el trabajo de otros. Estaba en el mío, en público, al lado de la medición, durante semanas. + +El código es MIT, el manifiesto del corpus y la calibración están en el repositorio, y el comando que los regenera es una línea: [github.com/peopleworks/SignsofAI](https://github.com/peopleworks/SignsofAI). diff --git a/Docs/Blog/social/verdict-story-cover.png b/Docs/Blog/social/verdict-story-cover.png new file mode 100644 index 0000000..0fe3804 Binary files /dev/null and b/Docs/Blog/social/verdict-story-cover.png differ diff --git a/Docs/Blog/social/verdict-story-cover.svg b/Docs/Blog/social/verdict-story-cover.svg new file mode 100644 index 0000000..22e0088 --- /dev/null +++ b/Docs/Blog/social/verdict-story-cover.svg @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 90 + /100 + + + + + + + + + + + + + + + + + + 90 + /100 + + + + + + + + + + + + + + + + + + + + + + +