Uso de IA en el trabajo

Extraer texto desordenado a JSON con IA y validar el resultado en Python

La IA puede convertir notas desestructuradas en JSON, pero el resultado debe validarse por separado. Esta guía usa un pequeño ejemplo sintético y una comprobación en Python para verificar campos obligatorios, tipos, valores permitidos y coherencia básica.

Ver el índice

La traducción se ha realizado con IA. Comprueba el código, las unidades y los valores junto con el original. La revisión por hablantes nativos de cada idioma aún no se ha completado. English

Para quién esPersonas que usan un asistente de chat con IA para convertir notas, correos, formularios u otros textos desordenados en JSON estructurado y necesitan una validación repetible.

Preparación
  • Python 3.12
  • Conocimientos básicos de objetos JSON, cadenas, números y listas

01Por qué validar el JSON extraído por una IA

La IA resulta útil para convertir texto irregular en campos estructurados, pero una respuesta que parece un JSON válido todavía puede estar equivocada. Puede faltar una clave obligatoria, un número puede aparecer como texto, un campo puede contener un valor no permitido o la IA puede inferir información que nunca estuvo presente en la fuente.

El flujo más seguro separa la extracción de la validación. Primero pide a la IA que convierta el texto de origen a una estructura fija. Después comprueba el JSON devuelto mediante reglas explícitas. La validación no demuestra que todos los datos extraídos sean correctos, pero permite detectar muchos errores estructurales antes de copiar los datos a una hoja de cálculo, una base de datos, un script o un flujo de trabajo.

02Define una pequeña fuente sintética y un esquema

Este ejemplo es sintético. Supongamos que una nota breve de soporte contiene el nombre del cliente, el número de ticket, la prioridad, los productos afectados y una hora opcional para devolver la llamada.

Texto de origen: "Ticket 1842. Customer: Mira Lee. Login fails on the desktop app and web portal. Priority is high. Please call after 15:30. Products affected: Desktop, Web."

CampoRegla
ticket_idEntero obligatorio
customerCadena obligatoria no vacía
priorityObligatorio: low, medium o high
productsLista obligatoria no vacía de cadenas
callback_timeCadena con formato HH:MM o null

El esquema se mantiene deliberadamente simple para poder comprobarlo con la biblioteca estándar de Python. Estas reglas son más estrictas que limitarse a comprobar si la respuesta puede analizarse como JSON.

03Pide a la IA un objeto JSON restringido

Indica exactamente qué campos están permitidos y cómo deben tratarse los datos ausentes. Por ejemplo: "Extrae el siguiente texto en un único objeto JSON con exactamente estas claves: ticket_id, customer, priority, products, callback_time. ticket_id debe ser un entero. priority debe ser low, medium o high. products debe ser una lista de cadenas. Usa null para callback_time si no aparece. No infieras datos que falten. Devuelve solo JSON."

Un resultado correcto para la nota sintética tendría ticket_id 1842, customer Mira Lee, priority high, products Desktop y Web, y callback_time 15:30.

Una respuesta de IA plausible pero defectuosa podría devolver ticket_id como la cadena "1842", priority como "urgent" y añadir un campo no permitido como issue_summary. Puede parecer estructurada y legible, pero no cumple el esquema acordado.

04Valida el JSON con Python

El siguiente script utiliza únicamente la biblioteca estándar de Python. Carga una respuesta sintética de IA, comprueba que no existan claves inesperadas, verifica las claves y los tipos obligatorios, revisa los valores permitidos de priority, comprueba la lista de products y valida el formato de callback_time. Escribe un informe en outputs y se detiene si el informe ya existe.

python
import json
import re
from pathlib import Path

AI_RESPONSE = '''{
  "ticket_id": "1842",
  "customer": "Mira Lee",
  "priority": "urgent",
  "products": ["Desktop", "Web"],
  "callback_time": "15:30",
  "issue_summary": "Login problem"
}'''

REQUIRED_KEYS = {
    "ticket_id",
    "customer",
    "priority",
    "products",
    "callback_time",
}

ALLOWED_PRIORITIES = {"low", "medium", "high"}
TIME_PATTERN = re.compile(r"^(?:[01]\d|2[0-3]):[0-5]\d$")

errors = []

try:
    data = json.loads(AI_RESPONSE)
except json.JSONDecodeError as exc:
    raise SystemExit(f"Invalid JSON: {exc}")

if not isinstance(data, dict):
    errors.append("Top-level value must be a JSON object.")
else:
    actual_keys = set(data)
    missing = REQUIRED_KEYS - actual_keys
    unexpected = actual_keys - REQUIRED_KEYS

    if missing:
        errors.append("Missing keys: " + ", ".join(sorted(missing)))
    if unexpected:
        errors.append("Unexpected keys: " + ", ".join(sorted(unexpected)))

    if "ticket_id" in data and not isinstance(data["ticket_id"], int):
        errors.append("ticket_id must be an integer.")

    if "customer" in data:
        customer = data["customer"]
        if not isinstance(customer, str) or not customer.strip():
            errors.append("customer must be a non-empty string.")

    if "priority" in data:
        priority = data["priority"]
        if not isinstance(priority, str) or priority not in ALLOWED_PRIORITIES:
            errors.append("priority must be low, medium, or high.")

    if "products" in data:
        products = data["products"]
        if not isinstance(products, list) or not products:
            errors.append("products must be a non-empty list.")
        elif not all(isinstance(item, str) and item.strip() for item in products):
            errors.append("Every product must be a non-empty string.")

    if "callback_time" in data:
        callback = data["callback_time"]
        if callback is not None:
            if not isinstance(callback, str) or not TIME_PATTERN.fullmatch(callback):
                errors.append("callback_time must be HH:MM or null.")

status = "PASS" if not errors else "FAIL"
lines = [f"Validation: {status}"]
lines.extend(f"- {error}" for error in errors)

output_dir = Path("outputs")
output_dir.mkdir(exist_ok=True)
output_file = output_dir / "json_validation.txt"

if output_file.exists():
    raise SystemExit(f"Stop: {output_file} already exists.")

output_file.write_text("\n".join(lines) + "\n", encoding="utf-8")
print(f"Wrote {output_file}")

05Interpreta correctamente la validación estructural

En la respuesta sintética defectuosa, la validación debería fallar por tres motivos. ticket_id es una cadena en lugar de un entero. priority es urgent, que no pertenece al conjunto permitido. issue_summary es una clave inesperada. La lista de products y el formato de callback_time sí cumplen sus reglas estructurales.

ComprobaciónValor de la IAEsperadoResultado
ticket_id"1842"enteroFAIL
customer"Mira Lee"cadena no vacíaPASS
priority"urgent"low, medium o highFAIL
products["Desktop", "Web"]lista no vacía de cadenasPASS
callback_time"15:30"HH:MM o nullPASS
claves adicionalesissue_summaryningunaFAIL

Cuando falla el esquema, normalmente conviene devolver el resultado para corregirlo en lugar de convertir valores silenciosamente. Convertir automáticamente "1842" en 1842 puede ocultar que no se siguieron las instrucciones de extracción. La conveniencia de permitir conversiones depende del flujo de trabajo posterior.

06Compara los campos extraídos con el texto de origen

La validación estructural es solo una capa. También debes comparar los campos importantes con el texto original. En este ejemplo, ticket 1842, Mira Lee, high, Desktop, Web y 15:30 aparecen explícitamente en la fuente. La fuente no utiliza la palabra urgent, por lo que sustituir high por urgent cambia el valor indicado en lugar de limitarse a reformatearlo.

  • Confirma los identificadores y nombres frente al texto exacto de origen.
  • Comprueba que los campos con valores cerrados, como priority, respeten tanto el significado de la fuente como el valor permitido por el esquema.
  • Verifica que los elementos de las listas aparezcan realmente en el texto y no hayan sido inferidos.
  • Usa null para los campos opcionales ausentes en lugar de inventar valores.
  • Rechaza campos añadidos salvo que el esquema permita explícitamente propiedades adicionales.
  • Distingue entre normalización e invención; cambiar mayúsculas y minúsculas puede ser aceptable, pero añadir una fecha límite inexistente no lo es.

07Errores comunes y límites

Un error común es comprobar únicamente si json.loads acepta la respuesta. Que el análisis tenga éxito demuestra que la sintaxis es JSON válida, no que las claves obligatorias, los tipos o los valores sean correctos. Otro error es permitir campos adicionales arbitrarios, lo que puede hacer que el código posterior dependa de información que nunca formó parte de la especificación.

Con esquemas más grandes, el código de validación escrito a mano resulta más difícil de mantener. Puede ser apropiado utilizar un sistema de esquemas o una biblioteca de validación específica, pero las preguntas básicas siguen siendo las mismas: qué campos son obligatorios, qué tipos se permiten, qué valores son válidos y si la información ausente puede representarse como null.

La validación tampoco demuestra que el texto original sea completo o fiable. Si la fuente contiene un número de ticket incorrecto o una frase ambigua, una extracción estructuralmente correcta conservará ese problema. Mantén disponible el texto original para poder rastrear los campos importantes cuando falle una regla de validación o de negocio.

Registro de ejecución y verificación

2026-09-21 · hand-checked example · Python 3.12

  • Se comprobó que el texto sintético contiene ticket 1842, customer Mira Lee, priority high, products Desktop y Web, y callback time 15:30.
  • Se comprobó que el esquema previsto contiene exactamente cinco claves permitidas: ticket_id, customer, priority, products y callback_time.
  • Se comprobó que el ejemplo defectuoso usa la cadena "1842" en lugar del entero 1842.
  • Se comprobó que urgent no pertenece al conjunto permitido de priority: low, medium, high.
  • Se comprobó que issue_summary es una clave inesperada según el esquema definido.
  • Se comprobó que ["Desktop", "Web"] cumple la regla de lista no vacía de cadenas.
  • Se comprobó que 15:30 coincide con el patrón HH:MM de 24 horas indicado.
  • Se comprobó que el script escribe únicamente en outputs/json_validation.txt y se detiene si ese archivo ya existe.
Límites de la verificación
  • No ejecuté el código Python; el ejemplo sintético, las ramas de validación y los fallos esperados se revisaron por inspección.
  • Este validador escrito a mano cubre únicamente el pequeño esquema mostrado y no es una implementación general de JSON Schema.
  • La validación estructural no demuestra que los valores extraídos sean factualmente correctos; los valores importantes deben compararse con el texto de origen.
  • El ejemplo no devuelve automáticamente a la IA los resultados fallidos para corregirlos ni realiza filtrado de seguridad sobre texto de entrada arbitrario.

Criterios de redacción y verificación de todo el sitio

Fuentes de referencia

Las explicaciones y los ejemplos son de elaboración propia. Puedes consultar los comportamientos y conceptos relacionados en las siguientes fuentes oficiales.