Una constructora pequeña que vive de la obra pública recibe licitaciones cada semana. Cada una llega con un pliego administrativo, uno técnico, un proyecto con memoria, mediciones y planos, y a veces varias versiones de lo mismo. Alguien tiene que leerlo todo para responder a tres preguntas: ¿podemos hacerlo?, ¿cuánto nos cuesta?, ¿llegamos a tiempo?
Esta nota cuenta cómo resolvimos esa lectura con IA en un sistema a medida para una constructora, sin nombres y sin humo.
Por qué no basta con «resúmeme esto»
Pegar el pliego en un chat y pedir un resumen produce un texto razonable que no sirve para nada operativo. El jefe de obra no necesita prosa: necesita un coste por capítulos, unas fases con semanas y una lista de materiales que pueda contrastar con su experiencia. Y administración necesita la fecha límite y el importe sin tener que buscarlos.
Así que el sistema no pide un resumen: pide cuatro salidas con forma fija.
- Resumen: qué hay que hacer, alcance, criterios de adjudicación con su peso y requisitos relevantes.
- Coste: presupuesto base, IVA, coste estimado de ejecución, margen y partidas por capítulo.
- Planificación: plazo, fases en semanas e hitos.
- Materiales: lo que hay que comprar, con cantidades aproximadas y tipo de proveedor.
Además, una lista de riesgos (plazos imposibles, precios ajustados, interferencias, permisos) y los datos administrativos que aparezcan.
Salida estructurada: el esquema manda
La pieza clave es obligar al modelo a responder con un esquema JSON estricto. Si el campo no está en el esquema, no existe; si el tipo no cuadra, la respuesta se rechaza. Simplificado:
ESQUEMA = obj({
"campos": obj({"organismo": texto_o_null, "importe_licitacion": numero_o_null,
"plazo_meses": numero_o_null, "fecha_limite": texto_o_null}),
"tipo_obra": enum(["reforma", "edificacion", "urbanizacion"]),
"resumen": obj({"texto": texto, "criterios_adjudicacion": lista(obj({"criterio": texto, "peso": numero}))}),
"coste": obj({"presupuesto_base": numero_o_null, "coste_estimado": numero_o_null,
"partidas": lista(obj({"capitulo": texto, "importe": numero}))}),
"planificacion": obj({"fases": lista(obj({"fase": texto, "semanas": numero})), "hitos": lista(texto)}),
"materiales": obj({"lista": lista(obj({"material": texto, "cantidad": numero_o_null, "unidad": texto}))}),
"riesgos": lista(texto),
})
Con esto, el resultado se guarda directamente en la base de datos y se pinta como fichas, tablas y un diagrama de fases. Nadie copia y pega.
Tres reglas que evitan que la IA invente
1. Si no aparece, es null
Todos los datos administrativos y económicos admiten null, y el prompt lo dice sin rodeos: si un dato no aparece en los documentos, se deja vacío o se explica en el comentario. Un importe inventado es peor que un hueco, porque nadie lo revisa.
2. Las versiones de los documentos
Las carpetas reales están llenas de «pliego_v2», «copia de memoria» y «aux_borrar». La regla es simple: si dos documentos parecen versiones del mismo, vale el más reciente, salvo que el nombre indique copia, auxiliar o borrar. Esto se resuelve también al indexar, mirando las fechas de modificación, para que el modelo reciba menos ruido.
3. El contexto de la empresa, no el de una empresa cualquiera
El coste estimado no es el del presupuesto oficial: es el de esta constructora, con su tamaño y su zona. El prompt describe quién es la empresa y qué tipo de obra hace, porque la misma partida cuesta distinto a una constructora pequeña que a una grande.
El humano no desaparece: valida
La IA no presenta ofertas. El jefe de obra revisa cada una de las cuatro salidas y marca coste, plazos y planificación como conforme o no conforme. Con eso, administración calcula la oferta con su porcentaje de baja. Si la licitación se adjudica, la obra nace sola en el sistema con su estructura documental; si no, queda descartada con su análisis para la próxima vez.
La IA hace la lectura. La decisión sigue siendo de quien firma la oferta.
Qué modelo usar
El proveedor de IA es configurable por tarea. Para el análisis de pliegos conviene el modelo más capaz disponible, porque un error de lectura cuesta dinero; para tareas pequeñas, como interpretar un mensaje desde la obra, basta uno ligero. Y si la empresa lo prefiere, hay opción europea o local para lo que no debe salir de casa.
Lo que aprendimos
- El valor no está en «entender» el pliego, sino en devolverlo con la forma con la que se trabaja.
- Permitir vacíos honestos (
null) da más confianza que rellenarlo todo. - El orden de las carpetas importa tanto como el modelo: limpiar versiones antes de leer ahorra errores y dinero.