Calc/LLM_DEBUG_API_GUIDE.md

14 KiB

Simple Debug API - Guía para LLM

Propósito

Esta API permite debuggear la Calculadora MAV CAS sin modificar código fuente ni crear scripts adicionales.

Principio: texto → texto tal como se muestra en la aplicación. NO duplica lógica, solo encapsula llamadas directas al motor existente.

Como LLM, puedes usar esta herramienta para:

  • Diagnosticar problemas en el motor de evaluación
  • Verificar comportamiento de tipos personalizados (FourBytes, IntBase, IP4Mask, etc.)
  • Inspeccionar el estado interno del motor (variables, contexto, tipos registrados)
  • Testing de regresión para verificar que cambios no rompan funcionalidad existente

Flujo de Trabajo Recomendado

1. Crear archivo JSON con queries

2. Ejecutar: python simple_debug.py archivo.json

3. Analizar resultados en el archivo *_results.json


Tipos de Query

Query tipo input

Evalúa expresiones como si el usuario las escribiera en la calculadora. Resultado: texto tal como se muestra en la aplicación.

{"index": 0, "type": "input", "content": "10.1.1.1 + 1"}

Query tipo exec

Ejecuta código Python para inspeccionar el estado interno del motor. Resultado: valor directo de la evaluación Python.

{"index": 1, "type": "exec", "content": "type(engine.last_result).__name__"}

Plantilla Base

{
  "queries": [
    {"index": 0, "type": "input", "content": "EXPRESION_A_EVALUAR"},
    {"index": 1, "type": "exec", "content": "CODIGO_PYTHON_INSPECCION"}
  ]
}

Casos de Uso Comunes

Debugging de Tipos Personalizados

Problema: Verificar si FourBytes maneja correctamente operaciones IP.

{
  "queries": [
    {"index": 0, "type": "input", "content": "192.168.1.1 + 1"},
    {"index": 1, "type": "exec", "content": "type(engine.last_result).__name__"},
    {"index": 2, "type": "exec", "content": "engine.last_result.original"},
    {"index": 3, "type": "exec", "content": "engine.last_result._numeric_value"},
    {"index": 4, "type": "input", "content": "10.0.0.0/8 + 256"},
    {"index": 5, "type": "exec", "content": "engine.last_result.has_symbols"}
  ]
}

Debugging de Tokenización

Problema: La expresión 192.168.1.x + 16#FF no se tokeniza correctamente.

{
  "queries": [
    {"index": 0, "type": "exec", "content": "engine.parser.process_expression('192.168.1.x + 16#FF')"},
    {"index": 1, "type": "input", "content": "192.168.1.x + 16#FF"},
    {"index": 2, "type": "exec", "content": "engine.parser.get_tokenization_info()"},
    {"index": 3, "type": "exec", "content": "len(engine.parser.tokenizer.tokenization_rules)"}
  ]
}

Debugging de Errores

Problema: IP4Mask rechaza máscaras que deberían ser válidas.

{
  "queries": [
    {"index": 0, "type": "input", "content": "mask = 255.240.0.0"},
    {"index": 1, "type": "input", "content": "IP4Mask(mask)"},
    {"index": 2, "type": "exec", "content": "engine.last_result"},
    {"index": 3, "type": "input", "content": "IP4Mask(255.240.0.3)"},
    {"index": 4, "type": "exec", "content": "engine.last_result"}
  ]
}

Debugging de Estado del Motor

Problema: Las variables no se están guardando correctamente.

{
  "queries": [
    {"index": 0, "type": "input", "content": "x = 5"},
    {"index": 1, "type": "input", "content": "y = x + 10"},
    {"index": 2, "type": "exec", "content": "engine.symbol_table"},
    {"index": 3, "type": "exec", "content": "len(engine.symbol_table)"},
    {"index": 4, "type": "exec", "content": "list(engine.symbol_table.keys())"},
    {"index": 5, "type": "input", "content": "solve(z**2 + x, z)"},
    {"index": 6, "type": "exec", "content": "len(engine.equations)"}
  ]
}

Interpretación de Resultados

Estructura del Resultado

{
  "execution_info": {
    "timestamp": "2025-06-05T18:25:22.256442Z",
    "total_queries": 5,
    "successful": 4,
    "failed": 1
  },
  "results": [...]
}

Resultado Individual (Query input)

{
  "index": 0,
  "input": "10.1.1.1 + 1",
  "output": "10.1.1.2",                    // Texto tal como se muestra en la app
  "result_type": "FourBytes",              // Tipo del objeto resultado
  "success": true,
  "error": null
}

Resultado Individual (Query exec)

{
  "index": 1,
  "input": "type(engine.last_result).__name__",
  "output": "FourBytes",                   // String del resultado
  "result_type": "str",                    // Tipo del resultado de la evaluación
  "success": true,
  "error": null,
  "exec_result": "FourBytes"               // Valor directo (serializado si es necesario)
}

Resultado con Error

{
  "index": 2,
  "input": "IP4Mask(255.240.0.3)",
  "output": "None",
  "result_type": "NoneType",
  "success": false,
  "error": "❌ Máscara inválida: 255.240.0.3..."
}

Funciones de Inspección Útiles

Estado del Motor

"engine.symbol_table"                    # Variables actuales
"engine.last_result"                     # Último resultado
"engine.symbolic_mode"                   # ¿Modo simbólico activo?
"len(engine.equations)"                  # Cantidad de ecuaciones en el sistema
"engine.debug"                           # ¿Debug habilitado?
"list(engine.base_context.keys())[:10]"  # Funciones disponibles (muestra 10)

Información de Tipos

"engine.get_available_types()"           # Info completa de tipos registrados
"list(engine.registered_types_info['registered_classes'].keys())"  # Lista de tipos
"engine.registered_types_info['class_count']"  # Cantidad de tipos registrados
"type(engine.last_result).__name__"      # Tipo del último resultado
"hasattr(engine.last_result, 'has_symbols')"  # ¿El resultado tiene símbolos?

Tokenización y Parsing

"engine.parser.get_tokenization_info()"  # Info completa de tokenización
"engine.parser.process_expression('test')"  # Procesar expresión específica
"len(engine.parser.tokenizer.tokenization_rules)"  # Cantidad de reglas
"engine._classify_line('x = 5')"         # Clasificar tipo de línea
"engine._extract_variable_names('x + y')" # Extraer nombres de variables

Análisis de Objetos Específicos

# Para FourBytes
"engine.last_result.original"            # String original
"engine.last_result._numeric_value"      # Valor numérico interno
"engine.last_result.has_symbols"         # ¿Tiene símbolos?

# Para IntBase
"engine.last_result.base"                # Base numérica (10, 16, 8, 2)
"engine.last_result.value_str"           # String del valor
"engine.last_result._symbols"            # Símbolos detectados

# Para IP4Mask  
"engine.last_result.get_prefix_int()"    # Prefijo como entero
"engine.last_result.is_valid()"          # ¿Es máscara válida?

Patrones de Debugging

1. Debugging de Regresión

Cuándo usar: Verificar que cambios no rompan funcionalidad existente.

{
  "queries": [
    {"index": 0, "type": "input", "content": "10.1.1.1 + 1"},
    {"index": 1, "type": "exec", "content": "type(engine.last_result).__name__"},
    {"index": 2, "type": "input", "content": "16#FF + 10"},
    {"index": 3, "type": "exec", "content": "engine.last_result.base"},
    {"index": 4, "type": "input", "content": "IP4Mask(255.255.0.0)"},
    {"index": 5, "type": "exec", "content": "engine.last_result.get_prefix_int()"}
  ]
}

2. Debugging de Nuevas Funcionalidades

Cuándo usar: Verificar que nueva funcionalidad trabaja correctamente.

{
  "queries": [
    {"index": 0, "type": "input", "content": "NUEVA_FUNCIONALIDAD_AQUI"},
    {"index": 1, "type": "exec", "content": "type(engine.last_result)"},
    {"index": 2, "type": "exec", "content": "dir(engine.last_result)"},
    {"index": 3, "type": "exec", "content": "str(engine.last_result)"},
    {"index": 4, "type": "exec", "content": "engine.symbol_table"}
  ]
}

3. Debugging de Performance

Cuándo usar: Identificar operaciones lentas o problemáticas.

{
  "queries": [
    {"index": 0, "type": "exec", "content": "import time; start = time.time()"},
    {"index": 1, "type": "input", "content": "OPERACION_LENTA"},
    {"index": 2, "type": "exec", "content": "time.time() - start"},
    {"index": 3, "type": "exec", "content": "len(engine.symbol_table)"}
  ]
}

4. Debugging de Comportamiento

Cuándo usar: Verificar comportamiento específico de tipos o funciones.

{
  "queries": [
    {"index": 0, "type": "input", "content": "EXPRESION"},
    {"index": 1, "type": "exec", "content": "str(engine.last_result)"},
    {"index": 2, "type": "exec", "content": "repr(engine.last_result)"},
    {"index": 3, "type": "exec", "content": "type(engine.last_result).__name__"}
  ]
}

Comandos de Ejecución

# Ejecución básica
python simple_debug.py mi_debug.json

# Con archivo de salida específico
python simple_debug.py mi_debug.json --output resultados.json

# Modo verboso (para ver progreso)
python simple_debug.py mi_debug.json --verbose

Templates Existentes para Reutilizar

Casos Básicos

Archivo: debug_templates/basic_test.json

  • Operaciones con FourBytes e IntBase
  • Variables y SymPy básico

Testing de Errores

Archivo: debug_templates/error_debug.json

  • Máscaras inválidas
  • IPs fuera de rango
  • Expresiones malformadas

Información de Contexto

Archivo: debug_templates/context_debug.json

  • Estado completo del motor
  • Tipos registrados
  • Sistema de ecuaciones

Tokenización

Archivo: debug_templates/tokenization_test.json

  • Debug del sistema de parsing
  • Reglas de tokenización

Flujo de Resolución de Problemas

1. Identificar el Problema

  • ¿Es un error de evaluación?
  • ¿Es un problema de tokenización?
  • ¿Es un problema de estado del motor?

2. Crear Query de Diagnóstico

  • Usar query input para reproducir el problema
  • Usar query exec para inspeccionar el estado

3. Analizar Resultados

  • Verificar success: true/false
  • Examinar error si hay fallo
  • Comparar output (texto de la app) con exec_result (valor interno)

4. Iterar

  • Crear nuevas queries basadas en hallazgos
  • Profundizar en áreas problemáticas
  • Verificar soluciones con queries adicionales

Ejemplo Completo de Debugging

Problema: "La operación 192.168.1.x + 1 no funciona correctamente"

Paso 1: Crear archivo de debug

{
  "queries": [
    {"index": 0, "type": "input", "content": "192.168.1.x + 1"},
    {"index": 1, "type": "exec", "content": "type(engine.last_result).__name__"},
    {"index": 2, "type": "exec", "content": "engine.last_result.has_symbols"},
    {"index": 3, "type": "exec", "content": "engine.parser.process_expression('192.168.1.x + 1')"},
    {"index": 4, "type": "input", "content": "ip = 192.168.1.x"},
    {"index": 5, "type": "exec", "content": "type(engine.symbol_table['ip'])"},
    {"index": 6, "type": "input", "content": "ip.substitute(x=5)"}
  ]
}

Paso 2: Ejecutar

python simple_debug.py debug_problema.json

Paso 3: Analizar resultados

  • Verificar si 192.168.1.x + 1 se evalúa correctamente (campo output)
  • Comprobar el tipo resultante con exec
  • Verificar si tiene símbolos
  • Examinar cómo se tokeniza la expresión
  • Probar operaciones relacionadas

Este flujo te permite identificar exactamente dónde está el problema y verificar la solución.


Consejos para LLMs

  1. Siempre usa índices secuenciales en las queries para facilitar la lectura
  2. Combina queries input y exec para obtener contexto completo
  3. El campo output es texto tal como se muestra en la aplicación
  4. El campo exec_result es el valor directo de la evaluación Python
  5. Usa los templates existentes como punto de partida
  6. Examina success y error antes de analizar resultados
  7. Crea queries incrementales que construyan sobre resultados anteriores
  8. NO intentes duplicar lógica de la aplicación - usa solo llamadas directas

Referencia Rápida

Query Básica

{"index": N, "type": "input|exec", "content": "CONTENIDO"}

Comandos Esenciales

python simple_debug.py archivo.json                    # Ejecutar debug
python simple_debug.py archivo.json --verbose          # Con detalles
python simple_debug.py archivo.json -o resultado.json  # Salida específica

Inspección Básica del Motor

"engine.last_result"              # Último resultado
"type(engine.last_result)"        # Tipo del resultado  
"engine.symbol_table"             # Variables actuales
"engine.get_available_types()"    # Tipos registrados
"engine.parser.get_tokenization_info()"  # Info de parsing

Análisis de Resultado

"success": true/false             # ¿Éxito?
"error": "mensaje"                # Error si falla
"output": "resultado"             # Texto tal como se muestra en la app
"exec_result": valor              # Valor directo (exec queries)

Templates Disponibles

  • debug_templates/basic_test.json - Pruebas básicas
  • debug_templates/error_debug.json - Testing de errores
  • debug_templates/context_debug.json - Estado del motor
  • debug_templates/tokenization_test.json - Debug de parsing

Workflow Típico

  1. Identificar problema → Crear query input para reproducir
  2. Inspeccionar estado → Añadir queries exec para diagnosticar
  3. Analizar resultados → Examinar success, error, output
  4. Iterar → Crear nuevas queries basadas en hallazgos

Principio clave: texto → texto. La API no interpreta ni procesa, solo encapsula llamadas directas al motor existente.