Vamos a crear: un pipeline de inteligencia documental usando Transloadit
El mercado de inteligencia documental está en pleno auge. Empresas como Reducto.ai están ganando tracción al ayudar a las empresas a extraer datos estructurados desde PDFs y documentos escaneados. Su propuesta de valor es convincente: sube un documento, define un esquema y recibe JSON limpio de vuelta.
Dicho eso, si quieres control a nivel de producto —routing personalizado, storage, cumplimiento e integración estrecha con el resto de tus workflows de archivos—, a menudo es más potente crear tu propia experiencia al estilo Reducto sobre primitivas.
Transloadit tiene todo lo que necesitas para proporcionarte esas primitivas. En esta guía, te mostraremos cómo combinar nuestros Robots de procesamiento de documentos con 🤖 /ai/chat para crear un pipeline flexible y guiado por esquemas, que puedes moldear como tu propio producto de IA documental.
Si quieres un producto listo para usar, un proveedor dedicado de IA documental puede ser una excelente opción. Pero si necesitas combinar extracción de documentos con uploads, conversiones, storage y workflows posteriores, construir sobre Transloadit te da más apalancamiento.
Qué significa realmente la inteligencia documental
En esencia, la inteligencia documental implica tres capacidades clave:
- Analizar: extraer texto de documentos usando OCR, preservando el layout y la estructura.
- Dividir: separar documentos de varias páginas en fragmentos manejables.
- Extraer: obtener datos estructurados que coincidan con un esquema predefinido.
Construyamos cada una de estas capacidades usando el versátil toolkit de Transloadit.
Configurar tu proyecto TypeScript
Primero, configura un proyecto usando el SDK de Node de Transloadit:
yarn init -y
yarn add transloadit
Nota
El SDK de Node v4 requiere Node.js 20 o más reciente. Si estás actualizando desde v3 o CommonJS, consulta la guía de migración.
Crea tu cliente:
import { Transloadit } from 'transloadit'
const transloadit = new Transloadit({
authKey: process.env.TRANSLOADIT_AUTH_KEY!,
authSecret: process.env.TRANSLOADIT_AUTH_SECRET!,
})
Paso 1: Análisis de documentos con OCR (opcional)
El Robot 🤖 /document/ocr extrae texto de PDFs, incluidos PDFs escaneados. Soporta múltiples proveedores y puede devolver resultados con coordenadas de layout o texto plano. Si tu fuente no es un PDF, conviértela primero usando el Robot 🤖 /document/convert.
Si estás usando un modelo compatible con PDF, como Claude Sonnet 4, puedes omitir OCR y enviar el PDF directamente al Robot 🤖 /ai/chat. OCR sigue siendo útil cuando necesitas coordenadas de layout o quieres normalizar primero archivos que no son PDF.
const parseResult = await transloadit.createAssembly({
params: {
steps: {
ocr_extract: {
robot: '/document/ocr',
use: ':original',
provider: 'gcp',
format: 'json',
granularity: 'full',
result: true,
},
},
},
files: {
document: './invoice.pdf',
},
waitForCompletion: true,
})
const ocrResults = parseResult.results.ocr_extract
La opción granularity: 'full' devuelve coordenadas de bounding box para cada bloque de texto, lo que resulta útil para entender el layout.
Paso 2: División de documentos
Para documentos grandes, el Robot 🤖 /document/split te permite extraer páginas específicas:
const splitResult = await transloadit.createAssembly({
params: {
steps: {
first_pages: {
robot: '/document/split',
use: ':original',
pages: ['1-5'],
},
remaining_pages: {
robot: '/document/split',
use: ':original',
pages: ['6-'],
},
},
},
files: {
document: './large-report.pdf',
},
waitForCompletion: true,
})
Paso 3: Extracción de datos guiada por esquemas con IA
Aquí es donde ocurre la magia. El Robot 🤖 /ai/chat puede procesar documentos y devolver JSON estructurado que coincide con tu esquema. Esto es directamente comparable con la Extract API de Reducto. Claude Sonnet 4 soporta PDFs, así que usaremos model: 'anthropic/claude-4-sonnet-20250514' abajo. Cuando configuras format: 'json', la salida es un archivo JSON en los resultados del Assembly.
Zod v4 incluye un helper nativo z.toJSONSchema(). Los snippets de abajo usan un pequeño helper que lo llama cuando está disponible y recurre a zod-to-json-schema para proyectos con Zod v3.
Si tu cuenta no tiene credenciales de IA compartidas configuradas, crea Template Credentials de IA en el dashboard de Transloadit (para OpenAI, Anthropic o Google) y haz referencia a ellas mediante credentials.
Para empezar rápido, puedes omitir credentials y configurar test_credentials: true para usar claves de prueba proporcionadas por Transloadit. Aunque esto es conveniente para demos, las claves compartidas pueden estar sujetas a rate limits, por lo que las cargas de trabajo de producción deberían proporcionar sus propias credenciales.
import { z } from 'zod'
import { zodToJsonSchema } from 'zod-to-json-schema'
const toJsonSchema = (schema: z.ZodTypeAny) =>
typeof (z as { toJSONSchema?: (schema: z.ZodTypeAny) => unknown }).toJSONSchema === 'function'
? (z as { toJSONSchema: (schema: z.ZodTypeAny) => unknown }).toJSONSchema(schema)
: zodToJsonSchema(schema)
const invoiceSchema = z.object({
invoice_number: z.string(),
vendor_name: z.string(),
vendor_address: z.string().optional(),
invoice_date: z.string().optional(),
due_date: z.string().optional(),
total_amount: z.number(),
currency: z.string().optional(),
line_items: z
.array(
z.object({
description: z.string(),
quantity: z.number().optional(),
unit_price: z.number().optional(),
total: z.number().optional(),
}),
)
.optional(),
tax_amount: z.number().optional(),
payment_terms: z.string().optional(),
})
const extractionResult = await transloadit.createAssembly({
params: {
steps: {
extract_data: {
robot: '/ai/chat',
use: ':original',
credentials: 'my_ai_credentials',
model: 'anthropic/claude-4-sonnet-20250514',
format: 'json',
schema: JSON.stringify(toJsonSchema(invoiceSchema)),
messages: `Extract all invoice data from this document.
Be precise with amounts and dates.
If a field is not present, omit it from the response.`,
result: true,
},
},
},
files: {
invoice: './invoice.pdf',
},
waitForCompletion: true,
})
const extractedFile = extractionResult.results.extract_data[0]
const invoiceData = await fetch(extractedFile.ssl_url).then((response) => response.json())
console.log(`Invoice #${invoiceData.invoice_number}: $${invoiceData.total_amount}`)
Crear un pipeline completo
Ahora combinemos todo en un pipeline listo para producción que:
- opcionalmente extrae texto con OCR,
- divide archivos grandes,
- extrae datos estructurados con IA, y
- almacena los resultados en S3.
import { z } from 'zod'
import { zodToJsonSchema } from 'zod-to-json-schema'
import { Transloadit } from 'transloadit'
const toJsonSchema = (schema: z.ZodTypeAny) =>
typeof (z as { toJSONSchema?: (schema: z.ZodTypeAny) => unknown }).toJSONSchema === 'function'
? (z as { toJSONSchema: (schema: z.ZodTypeAny) => unknown }).toJSONSchema(schema)
: zodToJsonSchema(schema)
const financialDocumentSchema = z.object({
document_type: z.enum(['invoice', 'receipt', 'statement', 'contract']),
document_date: z.string(),
parties: z.array(
z.object({
name: z.string(),
role: z.enum(['vendor', 'customer', 'signatory']),
address: z.string().optional(),
}),
),
amounts: z.array(
z.object({
description: z.string(),
value: z.number(),
currency: z.string(),
}),
),
key_terms: z.array(z.string()).optional(),
summary: z.string(),
})
type FinancialDocument = z.infer<typeof financialDocumentSchema>
const transloadit = new Transloadit({
authKey: process.env.TRANSLOADIT_AUTH_KEY!,
authSecret: process.env.TRANSLOADIT_AUTH_SECRET!,
})
async function processFinancialDocument(filePath: string) {
const result = await transloadit.createAssembly({
params: {
steps: {
pdf_verified: {
robot: '/file/filter',
use: ':original',
accepts: [['${file.mime}', '==', 'application/pdf']],
},
non_pdf: {
robot: '/file/filter',
use: ':original',
accepts: [['${file.mime}', '!=', 'application/pdf']],
},
pdf_converted: {
robot: '/document/convert',
use: 'non_pdf',
format: 'pdf',
},
extract_structured: {
robot: '/ai/chat',
use: ['pdf_verified', 'pdf_converted'],
credentials: 'ai_credentials',
model: 'anthropic/claude-4-sonnet-20250514',
format: 'json',
schema: JSON.stringify(toJsonSchema(financialDocumentSchema)),
messages: 'Extract the structured data from this document.',
result: true,
},
store_results: {
robot: '/s3/store',
use: [':original', 'extract_structured'],
credentials: 's3_credentials',
path: 'documents/${file.name}/',
},
},
},
files: {
document: filePath,
},
waitForCompletion: true,
})
if (result.ok !== 'ASSEMBLY_COMPLETED') {
throw new Error(`Assembly failed: ${result.error}`)
}
const extractedFile = result.results.extract_structured[0]
return fetch(extractedFile.ssl_url).then((response) => response.json())
}
const data = await processFinancialDocument('./contract.pdf')
console.log(`Processed ${data.document_type}: ${data.summary}`)
La ruta /document/convert → PDF soporta los siguientes tipos de entrada:
- Word:
.doc,.docx - PowerPoint:
.ppt,.pptx,.pps,.ppz,.pot - Excel:
.xls,.xlsx,.xla - OpenDocument:
.odt,.ott,.odd,.oda - Web/markup:
.html,.xhtml,.xml, Markdown (.md) - Texto y rich text:
.txt,.csv,.rtf,.rtx,.tex/LaTeX - Imágenes:
.jpg,.jpeg,.png,.gif,.svg - Vector/impresión:
.ai,.eps,.ps
Si necesitas salida de OCR para workflows conscientes del layout, inserta un Step /document/ocr y cambia use: ':original' a use: 'ocr_text'; luego incluye ese Step en tus destinos de storage.
Procesar varios tipos de documentos
Con el Robot 🤖 /file/filter, puedes dirigir PDFs directamente al modelo mientras conviertes todo lo demás a PDF primero. Usar != hace explícita la rama de archivos que no son PDF:
// Reuse invoiceSchema + toJsonSchema from above.
const multiTypeResult = await transloadit.createAssembly({
params: {
steps: {
pdf_verified: {
robot: '/file/filter',
use: ':original',
accepts: [['${file.mime}', '==', 'application/pdf']],
},
non_pdf: {
robot: '/file/filter',
use: ':original',
accepts: [['${file.mime}', '!=', 'application/pdf']],
},
pdf_converted: {
robot: '/document/convert',
use: 'non_pdf',
format: 'pdf',
},
extract_data: {
robot: '/ai/chat',
use: ['pdf_verified', 'pdf_converted'],
credentials: 'ai_credentials',
model: 'anthropic/claude-4-sonnet-20250514',
format: 'json',
schema: JSON.stringify(toJsonSchema(invoiceSchema)),
messages: 'Extract data from this document.',
result: true,
},
},
},
files: {
doc1: './receipt.pdf',
doc2: './receipt-photo.jpg',
},
waitForCompletion: true,
})
Resumen del flujo:
:original
├─ pdf_verified (file/filter: mime == pdf) ──▶ /ai/chat
└─ non_pdf (file/filter: mime != pdf) ──▶ /document/convert (pdf) ──▶ /ai/chat
Usar Templates para reutilización
Para uso en producción, guarda tus Assembly Instructions como un Template y haz referencia a él por ID:
const result = await transloadit.createAssembly({
params: {
template_id: 'your-invoice-extraction-template',
fields: {
custom_prompt: 'Focus on extracting payment terms and due dates.',
},
},
files: {
document: './invoice.pdf',
},
waitForCompletion: true,
})
Manejar lotes grandes de documentos
Para procesar eficientemente un lote de muchos documentos, lo mejor es mantener la concurrencia limitada:
import pMap from 'p-map'
async function processBatch(files: string[]): Promise<Map<string, FinancialDocument>> {
const concurrency = 5
const batchResults = await pMap(
files,
async (file) => {
const result = await transloadit.createAssembly({
params: {
template_id: 'document-extraction-template',
},
files: { document: file },
waitForCompletion: true,
})
// Assumes the template includes a step named `extract_structured`.
const extractedFile = result.results.extract_structured[0]
const data = await fetch(extractedFile.ssl_url).then((response) => response.json())
return {
file,
data,
}
},
{ concurrency },
)
return new Map(batchResults.map(({ file, data }) => [file, data]))
}
Por qué los equipos eligen Transloadit para IA documental
- Una sola API cubre ingest, conversión, OCR, extracción con IA y entrega.
- Integraciones de import/export para cloud storage (S3, Azure, Google Cloud Storage, Dropbox y más).
- Las Assembly Instructions te permiten versionar, reutilizar y ramificar pipelines sin glue code.
- Un solo proveedor para documentos y cargas de trabajo de archivos más amplias (previews, thumbnails, escaneo de virus, procesamiento de imagen/audio/video).
Transloadit vs. plataformas dedicadas de IA documental
Piensa en Reducto como un producto enfocado y en Transloadit como una plataforma componible. Puedes replicar el flujo central de extracción y luego extenderlo con todo lo que lo rodea.
| Funcionalidad | Transloadit | Reducto.ai |
|---|---|---|
| OCR / extracción de texto | ✅ 🤖 /document/ocr (PDFs) | ✅ Parse API |
| División de documentos | ✅ 🤖 /document/split | ✅ Split API |
| Extracción basada en esquemas | ✅ 🤖 /ai/chat con JSON schema | ✅ Extract API |
| Integraciones de storage | ✅ Import/export a cloud storage | Herramientas externas |
| Orquestación de workflows | ✅ Assembly Instructions + Templates | Herramientas externas |
| Proveedores de IA | ✅ OpenAI, Anthropic, Google (con credentials) | — |
| Cargas de trabajo de archivos más amplias | ✅ Imagen/video/audio + previews + seguridad | Stack enfocado en documentos |
Cuándo usar este enfoque
Este enfoque basado en Transloadit encaja muy bien cuando:
- quieres crear tu propio producto de IA documental o plataforma interna,
- quieres un solo proveedor para ingest, conversión, extracción y entrega,
- necesitas combinar inteligencia documental con workflows de medios más amplios, y
- quieres flexibilidad para elegir proveedores de IA y precios predecibles.
¿Listo para construir?
La inteligencia documental no tiene por qué significar agregar otro proveedor especializado. Con los Robots 🤖 /document/ocr, 🤖 /document/split y 🤖 /ai/chat, puedes crear pipelines de extracción sofisticados que compiten con plataformas dedicadas.
Empieza explorando nuestra documentación de AI Robots y descubre hasta dónde puedes llevar tus workflows de documentos dentro de una sola plataforma.
