You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
senzapaura_es/scripts/db/sembrar-animos.mjs

120 lines
3.1 KiB

Los prompts, dentro de la ficha del género y con la forma que dice su modelo Estaban modelados desde la fase 1 y no existían en el panel: `modelo_ia`, `animo` y `prompt`, cero filas las tres y ni siquiera una línea en la portada. Y la primera versión no respetaba el modelo. `modelo_ia.esquema` dice esto: > JSON Schema con la forma que toman los prompts de este modelo. Se validan > contra él al guardar, y el panel puede pintar el formulario a partir de él sin > una pantalla por cada IA. Había puesto un `textarea` único guardando `{ texto }` y forzado `estado: 'publicado'` al crear, cuando el modelo dice borrador por defecto. Las dos cosas van ahora como estaban escritas: el formulario del prompt sale del esquema de su modelo —un campo por propiedad, con su etiqueta, su ayuda, su lista cerrada y su rango— y lo que se guarda se comprueba contra él. `$lib/esquema-prompt` es el lector, y dice en su cabecera qué subconjunto entiende: objeto en la raíz con `properties` y `required`; por campo string, number, integer o boolean, más `enum`, `maxLength`, `minimum`, `maximum`, `title` y `description`. Lo que no esté se ignora; un esquema roto se rechaza al guardarlo, no al usarlo. Un modelo sin esquema sigue funcionando con un bloque de texto. Y `x-order`, que no estaba previsto y hace falta: la base guarda el esquema como `jsonb` y ahí Postgres reordena las claves por longitud, así que el campo obligatorio salía el último del formulario. Se vio en la captura. Los prompts van **dentro de la ficha del género**, no en una pestaña aparte: un prompt es de ese género y escribir la ficha y sacar la música son la misma sesión. Fuera de su formulario, porque cada prompt se guarda por su cuenta. Los modelos se dan de alta a mano, con su versión: Suno v4 y v3.5 son dos modelos, y una lista sembrada en un script envejecería en un mes. Los nueve ánimos de la GEMS sí se siembran, con `npm run db:animos`. Comprobado contra el panel de verdad: esquema aceptado y esquema roto rechazado, formulario pintado desde el esquema —lista cerrada, número con rango, letra en bloque—, campo obligatorio reclamado, un solo preferido por combinación y el preferido el primero de la lista. Falta `prompt.ejemplo_id`, el audio del resultado: pide los medios, que todavía no se editan aquí. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
4 weeks ago
/**
* Siembra los ánimos.
*
* npm run db:animos
*
* Son los nueve factores de la **GEMS** (*Geneva Emotional Music Scale*), que es
* una escala hecha para emoción musical y no para emoción en general: por eso
* tiene «trascendencia» y «nostalgia» y no tiene «miedo» ni «asco».
*
* Cada uno lleva además los dos ejes del modelo circumplejo de Russell:
* valencia —si tira a agradable o a desagradable— y energía. Sirven para
* ordenar, para interpolar entre dos ánimos, y sobre todo porque son
* redactables: «alta energía, valencia baja» es una instrucción que una IA
* entiende; «tensión» a secas, no.
*
* Idempotente por código: volver a lanzarlo actualiza y no duplica.
*/
import pg from 'pg';
/** `valencia` va de −1 a 1 y `energia` de 0 a 100, como dice el esquema. */
const ANIMOS = [
{
codigo: 'asombro',
nombre: 'Asombro',
gems: 'wonder',
valencia: 1,
energia: 60,
descripcion: 'Lo que abre los ojos. Deslumbra sin arrollar.'
},
{
codigo: 'trascendencia',
nombre: 'Trascendencia',
gems: 'transcendence',
valencia: 1,
energia: 45,
descripcion: 'Sacar a alguien de sí mismo. Lo solemne sin lo grandilocuente.'
},
{
codigo: 'ternura',
nombre: 'Ternura',
gems: 'tenderness',
valencia: 1,
energia: 30,
descripcion: 'El cariño dicho de cerca y en voz baja.'
},
{
codigo: 'nostalgia',
nombre: 'Nostalgia',
gems: 'nostalgia',
valencia: 0,
energia: 30,
descripcion:
'Lo que se recuerda con gusto y duele un poco. La valencia va en medio a propósito.'
},
{
codigo: 'serenidad',
nombre: 'Serenidad',
gems: 'peacefulness',
valencia: 1,
energia: 20,
descripcion: 'Calma sin sueño. Nada que resolver.'
},
{
codigo: 'fuerza',
nombre: 'Fuerza',
gems: 'power',
valencia: 1,
energia: 85,
descripcion: 'Empuje, triunfo, ganas. Lo que se canta de pie.'
},
{
codigo: 'alegria-vital',
nombre: 'Alegría vital',
gems: 'joyful activation',
valencia: 1,
energia: 80,
descripcion: 'Alegría que mueve el cuerpo. Es la de bailar, no la de sonreír.'
},
{
codigo: 'tension',
nombre: 'Tensión',
gems: 'tension',
valencia: -1,
energia: 75,
descripcion: 'Nervio, inquietud, algo a punto de pasar.'
},
{
codigo: 'tristeza',
nombre: 'Tristeza',
gems: 'sadness',
valencia: -1,
energia: 20,
descripcion: 'La pena quieta. En un bolero, la de siempre.'
}
];
const c = new pg.Client({ connectionString: process.env.DATABASE_URL, query_timeout: 15_000 });
await c.connect();
let nuevos = 0;
for (const a of ANIMOS) {
const { rows } = await c.query(
`insert into animo (id, codigo, nombre, gems, valencia, energia, descripcion)
values (gen_random_uuid(), $1, $2, $3, $4, $5, $6)
on conflict (codigo) do update set
nombre = excluded.nombre,
gems = excluded.gems,
valencia = excluded.valencia,
energia = excluded.energia,
descripcion = excluded.descripcion
returning (xmax = 0) as insertado`,
[a.codigo, a.nombre, a.gems, a.valencia, a.energia, a.descripcion]
);
if (rows[0].insertado) nuevos++;
}
console.log(`${ANIMOS.length} ánimos: ${nuevos} nuevos, ${ANIMOS.length - nuevos} actualizados.`);
await c.end();

Powered by TurnKey Linux.