CreaRack-SL

Tabla D1: ai_eval_runs — Histórico de Evaluaciones de Modelos IA

Tabla D1: ai_eval_runs — Histórico de Evaluaciones de Modelos IA

Resumen

Tabla D1 del Workspace de CreaRack que persiste el histórico de ejecuciones de la Tool AI Eval. Introducida en la migración 0016 (2026-04-27) como parte del cierre de la Fase 4 del plan Gemini Lite Migration.

⚠️ Invariante de seguridad: las API keys de Gemini/OpenRouter NUNCA se almacenan en esta tabla. Solo se persisten identificadores de modelos, prompts, respuestas y metadatos de timing.


DDL

-- migrations/0016_create_ai_eval_runs.sql
CREATE TABLE IF NOT EXISTS ai_eval_runs (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    created_at  TEXT    NOT NULL DEFAULT (datetime('now')),
    user_email  TEXT,                        -- CF Access email (informacional)
    candidates  TEXT    NOT NULL,            -- JSON: [{model, provider, label?}]
    cases       TEXT    NOT NULL,            -- JSON: [{name, prompt, has_image, ...}]
    results     TEXT    NOT NULL,            -- JSON: {[caseName]: {[model]: CellResult}}
    total_cells INTEGER NOT NULL,            -- candidates.length × cases.length
    duration_ms INTEGER NOT NULL,            -- wall-clock total del run
    status      TEXT    NOT NULL DEFAULT 'completed'
                CHECK (status IN ('completed','partial','failed')),
    notes       TEXT                         -- anotación libre del usuario
);

CREATE INDEX IF NOT EXISTS idx_ai_eval_runs_created ON ai_eval_runs(created_at);
CREATE INDEX IF NOT EXISTS idx_ai_eval_runs_user    ON ai_eval_runs(user_email, created_at);

Esquema de columnas

ColumnaTipoNullableDescripción
idINTEGER PK AUTOINCREMENTNoIdentificador único del run
created_atTEXT (ISO 8601)NoTimestamp UTC de inserción
user_emailTEXTSíEmail Cloudflare Access del ejecutor (solo informacional)
candidatesTEXT (JSON)NoArray de modelos evaluados: [{provider, model, label?}]
casesTEXT (JSON)NoArray de casos: [{name, prompt, system_instruction?, temperature?, max_tokens?, response_json?, has_image}] — image_b64 nunca se persiste
resultsTEXT (JSON)NoMatriz resultado: {caseName → {modelKey → {answer, latency_ms, tokens_in?, tokens_out?, error?}}}
total_cellsINTEGERNocandidates.length × cases.length (cap: 25)
duration_msINTEGERNoTiempo total de ejecución del run completo
statusTEXTNocompleted | partial | failed
notesTEXTSíAnotación libre introducida por el usuario en la UI

Tipado JSON interno

candidates (array)

[
  { "provider": "gemini", "model": "gemini-2.0-flash-lite", "label": "Flash Lite" },
  { "provider": "openrouter", "model": "anthropic/claude-3-haiku" }
]

cases (array, versión almacenada)

[
  {
    "name": "mib_classify",
    "prompt": "...",
    "system_instruction": "...",
    "temperature": 0.1,
    "max_tokens": 8192,
    "response_json": true,
    "has_image": false
  }
]

El campo image_b64 del request original se sustituye por has_image: boolean en la versión almacenada.

results (objeto)

{
  "mib_classify": {
    "gemini:gemini-2.0-flash": {
      "answer": "{ \"device_type\": \"access_point\", ... }",
      "latency_ms": 1142,
      "tokens_in": 890,
      "tokens_out": 412
    },
    "openrouter:anthropic/claude-3-haiku": {
      "answer": "",
      "latency_ms": 3201,
      "error": "Rate limit exceeded"
    }
  }
}

Índices

NombreColumnasUso
idx_ai_eval_runs_createdcreated_atPaginación por fecha DESC (endpoint history)
idx_ai_eval_runs_user(user_email, created_at)Filtros por usuario (uso futuro)

Acceso desde endpoints

EndpointOperaciónNotas
POST /api/tools/ai-eval/runINSERTFallo D1 no rompe la respuesta al cliente (degradación graceful)
GET /api/tools/ai-eval/historySELECT paginadoSin ?id: omite columna results en el listado para reducir payload
GET /api/tools/ai-eval/history?id=NSELECT por PKIncluye results completos

Consideraciones de crecimiento

  • Cada run puede persistir hasta 25 celdas con respuestas completas. Con prompts MIB largos, cada fila puede pesar ~100-300 KB en results.
  • No hay TTL ni política de purga automática en v0. Si el volumen crece, considerar DELETE FROM ai_eval_runs WHERE created_at < datetime('now', '-90 days') vía cron Worker.
  • D1 tiene límite de 10 GB por base de datos en plan Workers Paid.

Véase también

  • [[feature—workspace—ai-eval]]
  • [[concept—general—que-paginas-wiki-existen-sobre-cloudflare-pages-fu]]