- Updated execution counts for code cells to reflect the correct order of execution. - Modified the structure of conversation-related database interactions to align with new naming conventions. - Enhanced the conversation creation process by including additional metadata and improving the response handling. - Implemented better error handling and logging for conversation archiving and message retrieval. - Adjusted the schema definitions for input and output to ensure compatibility with the latest API changes.
37 KiB
37 KiB
import { load } from "jsr:@std/dotenv";
import OpenAI from "jsr:@openai/openai";
const env = await load({
export: true,
});
const openai = new OpenAI();
import { createClient } from "@supabase/supabase-js";
const supabaseUrl = Deno.env.get("SUPABASE_URL") || env.SUPABASE_URL;
const supabaseKey = Deno.env.get("SUPABASE_ANON_KEY") || env.SUPABASE_ANON_KEY;
const supabase = createClient(supabaseUrl, supabaseKey);
const { data: input } = await supabase.from("planes_estudio")
.select("*, estructuras_plan (definicion)").limit(1).single();
input
// Create a conversation for a plan de estudio
const openaiConversation = await openai.conversations.create({
metadata: {
"tabla": "planes_estudio",
"id": input.id,
instanciador: "alex",
},
items: [
{ type: "message", role: "system", content: "En caso de que te pidan algo que no tiene nada que ver con planes de estudio o asignatura responde con un refusal." },
],
});
const {data: conversationPlane} = await supabase.from("conversaciones_plan").insert({
openai_conversation_id: openaiConversation.id,
plan_estudio_id: input.id,
}).select("id").single();
conversationPlane
console.log(input.id, conversationPlane.id, openaiConversation.id);
// Archivar una conversación
const items = await openai.conversations.items.list(conversation.openai_conversation_id);
await supabase.from("conversaciones_plan").update({
estado: "ARCHIVANDO",
conversacion_json: items,
}).eq("id", conversationPlane.id);
await openai.conversations.delete(conversation.openai_conversation_id);
// Listar mensajes dado una conversacion_plan.id
const { data: conversation } = await supabase.from("conversaciones_plan").select("openai_conversation_id").eq("id", conversationPlane.id).single();
const items = await openai.conversations.items.list(conversation.openai_conversation_id);
items.data.filter((item) => item.type === "message" && ["assistant", "user"].includes(item.role))
// Add a message to the conversation
const campos = ["programa_de_investigacion", "perfil_de_ingreso"];
const { data: conversationToUpdate } = await supabase.from(
"conversaciones_plan",
).select("openai_conversation_id").eq(
"id",
conversationPlane.id,
).single();
const definicion = input.estructuras_plan.definicion;
// Estructura que hace que la IA incluya mensaje, en la estructura le agregará otro campo llamado "ai-mensaje"
const estructura_complementaria_de_respuesta = {
properties: {
"ai-message": {
type: "string",
description:
"Un mensaje que la IA incluirá en su respuesta para el usuario final que le confirme que ha entendido la solicitud y que ha mejorado el plan de estudio",
examples: [
"Claro, aquí tienes una mejor redacción para el perfil de ingreso. Además, he sugerido el siguiente tema de investigación relevante para el plan de estudio.",
],
},
},
};
if (definicion?.type === "object" && definicion?.properties) {
const entries = Object.entries(definicion.properties).filter(([key]) =>
campos.includes(key)
);
input.estructuras_plan.definicion = {
...definicion,
properties: Object.fromEntries(entries),
required: Array.isArray(definicion.required)
? definicion.required.filter((key) => campos.includes(key))
: undefined,
};
}
if (definicion?.properties) {
definicion.properties = {
...definicion.properties,
...estructura_complementaria_de_respuesta.properties,
};
definicion.required = [
...(definicion.required || []),
...Object.keys(estructura_complementaria_de_respuesta.properties),
];
}
const plan_sin_estructura = { ...input, estructuras_plan: undefined };
const mejoras = await openai.responses.create({
conversation: conversationToUpdate.openai_conversation_id,
model: "gpt-5-nano",
text: {
format: { type: "json_schema", name: "definicion", schema: definicion },
},
metadata: {
usuario: "admin",
plan_estudio_id: input.id,
},
input: [{
role: "system",
content: `Eres un asistente que ayuda a mejorar este plan de estudio: ${
JSON.stringify(plan_sin_estructura)
}. Si te hacen una pregunta que no tiene nada que ver con el plan de estudio, responde con un refusal.`,
}, {
role: "user",
content:
"Dale una mejor redacción al perfil de ingreso y para el programa de investigación sugiere un tema de investigación relevante para el plan de estudio.",
}],
});
JSON.parse(mejoras.output_text);