festbench-web/database/migrations/2026_09_16_000001_create_benchmark_tables.php

95 lines
4 KiB
PHP

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('benchmark_runs', function (Blueprint $table) {
$table->id();
$table->string('run_id', 32)->unique()->comment('festbench run_id');
$table->dateTime('ran_at')->nullable()->comment('ts from festbench');
$table->string('suite', 32);
$table->string('run_key', 255)->nullable();
// model + server identity (sensitive fields nullable, redacted by default)
$table->string('model_id', 255)->nullable();
$table->string('model_quant', 64)->nullable();
$table->string('model_quant_raw', 128)->nullable();
$table->string('model_path', 512)->nullable();
$table->string('engine', 64)->nullable();
$table->string('engine_build', 128)->nullable();
$table->unsignedBigInteger('n_ctx')->nullable();
$table->unsignedInteger('slots')->nullable();
$table->string('gpu', 128)->nullable();
$table->unsignedInteger('gpu_count')->nullable();
$table->string('gpu_source', 64)->nullable();
$table->string('host', 255)->nullable();
$table->string('client', 255)->nullable();
$table->string('endpoint', 512)->nullable();
$table->string('label', 255)->nullable();
$table->string('config', 255)->nullable();
// provenance
$table->string('image_digest', 512)->nullable();
$table->json('validators')->nullable();
$table->json('suite_versions')->nullable();
$table->string('harness', 32)->nullable();
$table->string('harness_ver', 64)->nullable();
$table->string('harness_mode', 64)->nullable();
// user-owned overlay — the only mutable part
$table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
$table->string('visibility', 16)->default('public')->comment('public|private');
$table->text('notes')->nullable();
$table->timestamps();
$table->index('suite');
$table->index(['model_id', 'model_quant']);
$table->index(['visibility', 'user_id']);
});
Schema::create('run_results', function (Blueprint $table) {
$table->id();
$table->foreignId('benchmark_run_id')->constrained()->cascadeOnDelete();
$table->string('suite', 32);
$table->string('section', 64)->nullable();
$table->string('task', 128);
$table->string('level', 16)->nullable()->comment('off|low|medium|xhigh');
$table->boolean('ok')->nullable();
$table->double('decode')->nullable();
$table->double('user_tps')->nullable();
$table->double('ttft')->nullable();
$table->double('t_answer')->nullable();
$table->double('wall')->nullable();
$table->unsignedInteger('reasoning')->nullable();
$table->unsignedInteger('visible')->nullable();
$table->unsignedInteger('total')->nullable();
$table->unsignedInteger('tool_calls')->nullable();
$table->unsignedInteger('checks_passed')->nullable();
$table->unsignedInteger('checks_total')->nullable();
$table->string('finish', 32)->nullable();
$table->text('detail')->nullable();
// complete source row, so future festbench fields need no migration
$table->json('payload')->nullable();
$table->timestamps();
$table->index(['benchmark_run_id']);
$table->index(['suite', 'level']);
$table->index(['ok']);
});
}
public function down(): void
{
Schema::dropIfExists('run_results');
Schema::dropIfExists('benchmark_runs');
}
};