Inicio / Artículos / anydoc: convertir 14 formatos de documento a Markdown en milisegundos

anydoc: convertir 14 formatos de documento a Markdown en milisegundos

Un vistazo a anydoc, de Firecrawl y escrito en Rust: lo rápido que convierte docx, pptx, xlsx y PDF a Markdown con un conjunto de pruebas nuevo, qué falla y cómo usarlo.

1196 palabras

Firecrawl ha liberado como código abierto un conversor de documentos llamado anydoc, y sus cifras llaman la atención. Convertir un docx con LibreOffice antes de pasárselo a un modelo puede llevar más de un segundo por archivo, sin contar los pasos manuales. anydoc baja la mediana a 4,4 milisegundos en 14 formatos habituales y siempre genera la misma variante de Markdown al estilo de GitHub.

Qué es

No es otro conversor de los de «ya vale así». Todo el pipeline se ha reescrito en Rust puro. Word, PowerPoint, Excel, OpenDocument, RTF, EPUB, CSV y PDF se traducen a un único modelo de documento compartido, y un solo serializador escribe la salida. Por eso un .doc antiguo de 2003 y un .pptx exportado ayer quedan igual: niveles de encabezado, celdas combinadas, notas al pie y listas de tareas se comportan de forma idéntica. Funciona en local, no llama a ningún servicio externo y no usa modelos de aprendizaje automático.

Se suele pensar que analizar documentos exige una cadena de herramientas cosidas entre sí o pasar por la nube. Esta velocidad y esta calidad se pueden conseguir en tu propia máquina. anydoc ya impulsa el endpoint Parse del propio Firecrawl, donde solo los PDF escaneados necesitan un paso adicional de OCR. Los PDF con texto y los archivos de ofimática se procesan en local de una sola pasada.

Comprobar lo prometido con un corpus nuevo

El benchmark del fabricante no se puede reproducir. El README dice que sus 100 archivos no pueden redistribuirse y no están en el repositorio. Así que se montó un conjunto de pruebas nuevo: 40 archivos por formato, cada uno de menos de 25 MB.

En total, 206 archivos, de los que 194 se convirtieron correctamente.

La promesa estrella de una mediana inferior a 5 ms solo se cumple para csv y xlsx. La mediana de docx fue de 6,4 ms, y pptx y pdf se quedaron en 22 cada uno. El pptx más lento tardó 346 ms, un archivo grande dentro de una muestra que incluía piezas de más de doscientos megas. La cifra de 5 ms es una mediana sobre todo el corpus mezclado, y los formatos orientados a líneas como csv la tiran hacia abajo.

En la práctica, mil archivos docx tardan unos 6 segundos, mientras que mil de PowerPoint superan los veinte. Ambas cosas son rápidas, pero conviene planificar con las cifras más lentas.

Ocho de los doce fallos no fueron culpa de la herramienta. Esos ocho archivos devolvieron malformed, así que se revisaron uno a uno con el comando file. Dos archivos .docx resultaron ser uno data y otro JSON data, y dos .xlsx y cuatro .pptx eran simplemente data. Ninguno era un documento de Office de verdad. anydoc lee el contenido por formato y no por extensión, así que no se dejó engañar. Quitando esas ocho falsificaciones, la tasa de éxito real es de 194 de 198, un 98 %.

Aquí hay un premio que nadie buscaba. Pásalo por una biblioteca de documentos, recoge todo lo que devuelva malformed y tendrás una lista lista de archivos dañados o mal etiquetados. No se diseñó para eso, pero funciona.

Por qué importa en los pipelines con LLM

Cuando le pasas un contrato a un modelo, el primer problema es saber en qué formato está realmente. La extensión dice .docx, pero el contenido puede ser un ZIP modificado. CSV no tiene firma, así que hay que declararlo a mano. Si cambias de herramienta, también cambian las reglas de salida: las tablas a veces se convierten en listas, las notas al pie desaparecen y la sangría de las listas anidadas se rompe.

Para comparar, la mediana de LibreOffice supera los 1100 milisegundos, y no cubre los 14 formatos. unstructured, markitdown y pandoc solo manejan parte del abanico, con puntuaciones de calidad que tocan techo en torno a 65. Con el mismo lote de 100 documentos reales, anydoc obtuvo 81 puntos en total: 87 en completitud, 79 en estructura, 78 en formato y 81 en limpieza. Y unas 250 veces más rápido.

No es solo una cifra de laboratorio. 500 archivos docx se procesan en 1,7 segundos, lo bastante rápido para meterlo directamente en el bucle de un agente. Antes habrías montado una cola asíncrona y esperado callbacks. Ahora hasta las llamadas síncronas parecen instantáneas.

Los archivos .xls y .odp antiguos con nombres equivocados se identificaron igualmente por la cabecera del archivo. CSV necesita una indicación explícita, porque sin firma la herramienta lo omite. Son detalles que conviene conocer antes de construir nada encima.

Cómo funciona por dentro

Cada archivo empieza con la detección de contenido: los PDF por la cabecera, el RTF por los grupos y los contenedores ZIP por el mimetype. Tras identificarlo, un parser específico rellena un modelo Document unificado con bloques, elementos en línea, tablas, notas al pie y recursos incrustados. Un único serializador de GitHub-Flavored Markdown remata el trabajo.

Por eso las celdas combinadas, los anclajes de encabezados, el tachado, los bloques de código y las notas del orador siguen las mismas reglas. Las imágenes y los objetos se convierten en Markdown con texto alternativo, mientras los bytes en bruto se quedan en el modelo para recuperarlos más tarde.

Los PDF pasan por pdf-inspector, que solo trata archivos con capa de texto. Un escaneo puro devuelve Unsupported en lugar de fingir que lo ha leído, y un archivo cifrado da un error claro. Esa honestidad es siempre mejor que una «conversión a lo que salga».

Al ser Rust puro, no hay sobrecarga de intérprete de Python ni archivos temporales en disco. El binding de Node usa el pool de hilos de libuv, así que no bloquea el event loop, y el binding de Python libera el GIL. Así es como se llega a una mediana de 4,4 ms.

Habrá quien diga que un parser en Rust es sobreingeniería. Otros lo empaquetan como skill de agente para que Claude o Cursor conviertan en Markdown cualquier archivo que aparezca. Los dos bandos tienen sus razones.

Cómo usarlo

La vía más directa es la línea de comandos:

npx @firecrawl/anydoc report.docx

La salida va a la terminal. Añade -o slides.md para escribirla en un archivo. Para leer CSV desde stdin:

npx @firecrawl/anydoc - --format csv < data.csv

En Node:

import { toMarkdown, toMarkdownBytes } from '@firecrawl/anydoc';

const md = await toMarkdown('report.docx');
const mdFromBytes = await toMarkdownBytes(bytes);
const mdCsv = await toMarkdownBytes(bytes, 'csv');

La versión de Python es parecida:

import anydoc

md = anydoc.to_markdown("report.docx")
md_bytes = anydoc.to_markdown_bytes(data)
md_csv = anydoc.to_markdown_bytes(data, "csv")

Existe también una versión para navegador, @firecrawl/anydoc-wasm, para que los archivos no salgan nunca de la máquina. Para Rust, ejecuta cargo add anydoc.

Con agentes es aún más sencillo. Tras ejecutar npx skills add firecrawl/anydoc, la cadena de herramientas lo llama automáticamente cada vez que aparece un documento.

Puedes esperar un Markdown limpio con tablas, listas y encabezados intactos. En documentos complejos se pierde de vez en cuando algún estilo en casos límite, que es una concesión del parser y no un fallo.

Límites a tener en cuenta

El proyecto está en la fase 0.1.x. Archivos muy corruptos u objetos incrustados enormes podrían, en teoría, provocar ResourceLimit. En producción, trata los errores devueltos por categorías y registra aparte los archivos cifrados y los no soportados, para que una sola entrada defectuosa no tumbe todo el pipeline.

Si la conversión puede hacerse en local, ahórrate el viaje a la nube y deja los documentos escaneados para endpoints con OCR. La velocidad y la calidad ya son suficientes, así que lo que queda es ver cómo encaja en tu propio pipeline. El proyecto está en github.com/firecrawl/anydoc.