Merge pull request 'Agregar contexto de la asignatura al chat y se agrega estructura de contenido tematico y de criterios de evaluación para la respuesta estructurada fix #55' (#62) from issue/55-agregar-contexto-de-la-asignatura-al-chat into main
Reviewed-on: AlexRG/genesis-2#62
This commit was merged in pull request #62.
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
export const definicionesDeEstructurasDeColumnas = {
|
||||
contenido_tematico: {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"x-column": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"contenido_tematico",
|
||||
],
|
||||
},
|
||||
"x-definicion": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"unidad": {
|
||||
"type": "integer",
|
||||
},
|
||||
"titulo": {
|
||||
"type": "string",
|
||||
},
|
||||
"temas": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"nombre": {
|
||||
"type": "string",
|
||||
},
|
||||
"horasEstimadas": {
|
||||
"type": "integer",
|
||||
"description":
|
||||
"Horas del tema. La suma de todas las horasEstimadas debe ser igual a las horas académicas del prompt.",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"nombre",
|
||||
"horasEstimadas",
|
||||
],
|
||||
"additionalProperties": false,
|
||||
},
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"unidad",
|
||||
"titulo",
|
||||
"temas",
|
||||
],
|
||||
"additionalProperties": false,
|
||||
},
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"x-column",
|
||||
"x-definicion",
|
||||
],
|
||||
"additionalProperties": false,
|
||||
},
|
||||
criterios_de_evaluacion: {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"x-column": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"criterios_de_evaluacion",
|
||||
],
|
||||
},
|
||||
"x-definicion": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"criterio": {
|
||||
"type": "string",
|
||||
},
|
||||
"porcentaje": {
|
||||
"type": "integer",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"criterio",
|
||||
"porcentaje",
|
||||
],
|
||||
"additionalProperties": false,
|
||||
},
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"x-column",
|
||||
"x-definicion",
|
||||
],
|
||||
"additionalProperties": false,
|
||||
},
|
||||
} as const;
|
||||
@@ -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)
|
||||
);
|
||||
campos.forEach((key) => {
|
||||
|
||||
out.properties = Object.fromEntries(entries);
|
||||
// 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];
|
||||
|
||||
if (Array.isArray(out.required)) {
|
||||
out.required = out.required.filter((k: string) => campos.includes(k));
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user