Agregar contexto de la asignatura al chat y se agrega estructura de contenido tematico y de criterios de evaluación para la respuesta estructurada
Supa-backup / run_db_backup (pull_request) Successful in 38s
CI / test (pull_request) Successful in 44s
Deploy Function / deploy (pull_request) Successful in 25s
Deploy Migrations to Production / deploy (pull_request) Successful in 9s

fix #55
This commit is contained in:
2026-03-12 16:02:38 -06:00
parent 0a1f61f587
commit 631e85b3d6
2 changed files with 120 additions and 25 deletions
@@ -1,5 +1,5 @@
import { definicionesDeEstructurasDeColumnas } from "../../_shared/estructuras.ts";
import { HttpError } from "./errors.ts";
export function pickSchemaFields(
definicion: any,
campos: string[],
@@ -45,17 +45,15 @@ export function pickSchemaFields(
return out;
}
export function pickSchemaAsignaturaFields(
definicion: any,
campos: string[],
) {
console.log(campos);
console.log(definicion);
if (!definicion || definicion.type !== "object" || !definicion.properties) {
return definicion;
}
// Campos extra de control
const extra = {
properties: {
"ai-message": {
@@ -70,33 +68,36 @@ export function pickSchemaAsignaturaFields(
};
const out = structuredClone(definicion);
const finalProperties: Record<string, any> = {};
const finalRequired: string[] = [];
// FILTRADO: Si el usuario pidió campos específicos, filtramos.
// Si campos está vacío, la lógica de Planes devolvería todo,
// pero aquí asumimos que siempre vienen campos si isStructured es true.
const entries = Object.entries(out.properties).filter(([k]) =>
campos.includes(k)
);
out.properties = Object.fromEntries(entries);
if (Array.isArray(out.required)) {
out.required = out.required.filter((k: string) => campos.includes(k));
}
campos.forEach((key) => {
// REVISIÓN DE ESTRUCTURA ESPECIAL
if (key in definicionesDeEstructurasDeColumnas) {
// Extraemos solo el esquema del array que vive en 'x-definicion'
// Esto hace que la IA reciba el esquema del array directamente
const especial = (definicionesDeEstructurasDeColumnas as any)[key];
finalProperties[key] = especial.properties["x-definicion"];
finalRequired.push(key);
}
// CAMPOS NORMALES (los que están en 'datos')
else if (out.properties[key]) {
finalProperties[key] = out.properties[key];
if (out.required?.includes(key)) {
finalRequired.push(key);
}
}
});
// SIEMPRE agregamos los campos de control (ai-message, is_refusal)
out.properties = { ...out.properties, ...extra.properties };
// Reconstruimos los requeridos para que OpenAI sepa que DEBE llenar los campos solicitados
out.required = Array.isArray(out.required)
? [...new Set([...out.required, ...Object.keys(extra.properties)])]
: Object.keys(extra.properties);
// Forzamos que no invente campos
out.properties = { ...finalProperties, ...extra.properties };
out.required = [...new Set([...finalRequired, ...Object.keys(extra.properties)])];
out.additionalProperties = false;
return out;
}
export function safePlanForPrompt(plan: any) {
const copy = structuredClone(plan);
if (copy?.estructuras_plan) delete copy.estructuras_plan;