Generación de asignaturas con sugerencias #22

Merged
Guillermo.Arrieta merged 7 commits from acad-ia-2/issue/89-sugerencias-asignaturas into main 2026-02-12 23:30:01 +00:00
3 changed files with 19 additions and 13 deletions
Showing only changes of commit b1d431a683 - Show all commits
@@ -1,8 +1,5 @@
{ {
"imports": { "imports": {
"zod": "https://deno.land/x/zod@v3.22.4/mod.ts", "zod": "https://deno.land/x/zod@v3.22.4/mod.ts"
"openai": "npm:openai@6.16.0",
"@supabase/supabase-js": "npm:@supabase/supabase-js@2",
"@supabase/functions-js/edge-runtime.d.ts": "jsr:@supabase/functions-js@^2/edge-runtime.d.ts"
} }
} }
@@ -1,6 +1,6 @@
{ {
"imports": { "imports": {
"zod": "https://deno.land/x/zod@v3.22.4/mod.ts", "zod": "npm:zod@4.3.5",
"openai": "npm:openai@6.16.0", "openai": "npm:openai@6.16.0",
"openai/helpers/zod": "npm:openai@6.16.0/helpers/zod", "openai/helpers/zod": "npm:openai@6.16.0/helpers/zod",
"@supabase/supabase-js": "npm:@supabase/supabase-js@2", "@supabase/supabase-js": "npm:@supabase/supabase-js@2",
@@ -16,26 +16,30 @@ export type DataAsignaturaSugerida = {
creditos: Tables<"asignaturas">["creditos"] | null; creditos: Tables<"asignaturas">["creditos"] | null;
horasAcademicas?: number | null; horasAcademicas?: number | null;
horasIndependientes?: number | null; horasIndependientes?: number | null;
descripcion?: string; descripcion: string;
}; };
const AsignaturaSugeridaItemSchema: z.ZodType<DataAsignaturaSugerida> = z const AsignaturaSugeridaItemSchema: z.ZodType<DataAsignaturaSugerida> = z
.object({ .object({
nombre: z.string().describe("Nombre de la asignatura a crear"), nombre: z.string().describe("Nombre de la asignatura a crear"),
codigo: z.string().optional().describe( codigo: z.string().optional().nullable().describe(
"Código o clave de la asignatura. Un string único que la identifique, como 'MAT101' o 'FIS202'. Opcional, pero recomendado para evitar confusiones.", "Código o clave de la asignatura. Un string único que la identifique, como 'MAT101' o 'FIS202'. Opcional, pero recomendado para evitar confusiones.",
), ),
tipo: z.enum(["TRONCAL", "OBLIGATORIA", "OPTATIVA", "OTRA"]).nullable(), tipo: z.enum(["TRONCAL", "OBLIGATORIA", "OPTATIVA", "OTRA"]).nullable(),
creditos: z.number().nullable(), creditos: z.number().nullable(),
horasAcademicas: z.number().optional().nullable(), horasAcademicas: z.number().optional().nullable(),
horasIndependientes: z.number().optional().nullable(), horasIndependientes: z.number().optional().nullable(),
descripcion: z.string().optional(), descripcion: z.string(),
}); });
const AsignaturaSugeridaSchema = z const AsignaturaSugeridaSchema = z
.array(AsignaturaSugeridaItemSchema) .object({
.length(6) sugerencias: z
.describe("Arreglo de 6 sugerencias de asignatura"); .array(AsignaturaSugeridaItemSchema)
.length(6)
.describe("Arreglo de 6 sugerencias de asignatura"),
})
.describe("Respuesta estructurada con 6 sugerencias de asignatura");
Deno.serve(async (req: Request): Promise<Response> => { Deno.serve(async (req: Request): Promise<Response> => {
const url = new URL(req.url); const url = new URL(req.url);
@@ -81,7 +85,7 @@ Deno.serve(async (req: Request): Promise<Response> => {
} }
const options: StructuredResponseOptions = { const options: StructuredResponseOptions = {
model: "gpt-4o-mini", model: "gpt-5-mini",
input: [ input: [
{ {
role: "user", role: "user",
@@ -149,7 +153,12 @@ Deno.serve(async (req: Request): Promise<Response> => {
); );
} }
return sendSuccess(parsed.data); console.log(
`[${
new Date().toISOString()
}][${functionName}]: Request processed successfully`,
);
return sendSuccess(parsed.data.sugerencias);
} catch (error) { } catch (error) {
if (error instanceof HttpError) { if (error instanceof HttpError) {
console.error( console.error(