Quería bajar lo que cuesta pasarle archivos grandes a un modelo. Sonaba fácil: el texto se repite mucho, así que tiene que poderse comprimir.

Estuve probando ideas y midiéndolas. Fueron seis y ninguna funcionó.

Primero, qué es un token

El modelo no lee letras ni palabras.

Lee tokens, que son pedazos de texto que tiene guardados en una lista de 200 mil. Esa lista es pública y la puedes revisar en el repositorio de tiktoken.

Y te cobran por token.

Esta frase, por ejemplo:

la esperanza es lo ultimo que se pierde

Son 8 tokens. Uno por palabra.

La pregunta era esa: ¿cómo hago que cueste menos de 8?

Las seis que no funcionaron

Hubo una que sí bajó los tokens: comprimir el archivo con gzip, que es lo que usan los .zip de toda la vida. Bajaba 3 veces.

Pero el modelo no puede abrir un zip.

Lo único que sabe hacer con lo que le mandas es leerlo.

Y ese es el problema de fondo: por muy barato que salga, si el modelo no lo entiende, no sirve.

Por qué el lenguaje se repite tanto

Lee esto:

El g_to se sub__ al te__do y no se qu_so ba__r.

Lo entendiste igual.

Le faltan letras y no importó, porque tu cabeza las rellena sola.

Eso es la redundancia del lenguaje, y es la razón por la que nos entendemos.

Es lo que te deja leer con faltas, entender un acento cerrado, o escuchar a alguien en un bar con música.

Claude Shannon, el matemático que sentó las bases de cómo se transmite la información, la midió en 1951 y le puso número: cerca del 75%.

Ahí está la trampa, porque ese 75% es justo lo que yo quería quitar:

Ese relleno que yo veía como desperdicio resulta que es lo que hace posible entender.

Mis seis ideas estaban intentando quitar justo eso, cada una a su manera, y por eso todas chocaban con lo mismo.

Lo que sí funciona es borrar

Si no puedes escribirlo mejor, solo queda decir menos.

Probé LLMLingua-2, de Microsoft, que corre en tu laptop y es gratis.

Lo que hace es ir palabra por palabra decidiendo si la deja o la quita, y te devuelve las que quedaron tal cual estaban, sin resumir ni reescribir nada.

Así se ve. Esto entra:

Of course, by now you and I know that the customer who has accepted and used the BUG products has been trapped into facing the influence of the reciprocity rule.

Y esto sale:

customer accepted BUG products reciprocity rule

De 33 tokens a 7.

Se fueron el of course, el you and I know, el who has, los the. Quedaron las palabras que dicen de qué va la frase, y con esas el modelo se arma el resto.

Para saber si de verdad servía, agarré dos páginas de un libro y anoté todos los datos concretos que traían. Salieron 12, cosas así:

Después comprimí el texto a distintos niveles y fui contando cuántos de esos 12 datos seguían apareciendo:

El de 5 veces es el que me sorprendió, y ahí están midiéndose dos cosas distintas.

Comprimir 5 veces quiere decir que se fue el 80% de las palabras. De cada cinco palabras del original, quedó una.

Pero de los 12 datos solo desapareció uno.

O sea, se va casi todo el texto y casi ninguna información.

Y lo que borra es más o menos ese relleno que midió Shannon. Está quitando lo predecible y apostando a que el modelo lo reponga, igual que hiciste tú con la frase del gato.

Cómo lo probé

Por si quieres reproducirlo, es poco código.

pip install tiktoken llmlingua

Para contar tokens uso tiktoken, que es el tokenizador de los modelos de OpenAI. Le pasas texto y te devuelve la lista de tokens:

import tiktoken

enc = tiktoken.get_encoding("o200k_base")

enc.encode("la esperanza es lo ultimo que se pierde")
# 8 tokens

[enc.decode([t]) for t in enc.encode("la esperanza es lo ultimo que se pierde")]
# ['la', ' esperanza', ' es', ' lo', ' ultimo', ' que', ' se', ' pierde']

El segundo enseña por dónde parte cada palabra. Ahí se ve que el espacio va pegado al token.

Y para comprimir, LLMLingua-2. El rate es cuánto quieres conservar, así que 0.25 es comprimir 4 veces:

from llmlingua import PromptCompressor

compresor = PromptCompressor(
    model_name="microsoft/llmlingua-2-bert-base-multilingual-cased-meetingbank",
    use_llmlingua2=True,
    device_map="cpu",
)

resultado = compresor.compress_prompt(texto, rate=0.25)
print(resultado["compressed_prompt"])

La primera vez se descarga el modelo, que pesa unos cientos de megas. Después, las dos páginas que usé de ejemplo las procesó en menos de un segundo.

Dos cosas que sí encontré

Donde sí queda margen

Todo lo de arriba lo probé sobre texto escrito, o sea frases seguidas: un libro, un correo, un contrato.

Con una hoja de cálculo, un CSV o un export de la base de datos la cosa cambia.

En una tabla de 3.000 filas la misma columna trae el mismo valor una y otra vez, exactamente igual. Eso sí lo puedes escribir una vez y referenciarlo, sin perder nada.

En un texto escrito eso casi no pasa. Las frases se parecen, pero es raro que dos sean idénticas.

Así que la idea del diccionario, la que me falló con la y que, sí sirve. Solo que en una hoja de cálculo, no en un libro.

Qué usar hoy

Yo no construí nada nuevo, pero estas tres ya existen y hacen el trabajo:

Lo que me llevo

Lo mejor fue medir antes de programar. Cada idea se caía enseguida.

No construí lo que quería, pero terminé entendiendo el problema un poco mejor.

No encontré una forma válida, pero si se te ocurre algo, bienvenida la idea.