feat: add @toon-format/toon dependency and integrate into OpenAI notebooks

- Updated deno.lock and package.json to include @toon-format/toon@^2.1.0.
- Modified background-openai.ipynb to handle error responses and adjust execution counts.
- Enhanced definitions-openai.ipynb to include additional metadata for perishables and origen schemas.
- Refactored embeddings-openai.ipynb to improve error handling and output formatting.
- Updated create-chat-conversation function to append messages and responses to conversations.
- Added SQL functions for appending conversation data to the database.
This commit is contained in:
2026-02-24 15:20:19 -06:00
parent dcaeeb72dd
commit 7ee9944ab5
8 changed files with 234 additions and 110 deletions
@@ -285,6 +285,11 @@ app.post(`${prefix}/conversations/:id/messages`, async (c) => {
"Excelente, actualmente tu plan de estudio tiene una redacción clara, pero podrías mejorar el perfil de ingreso para hacerlo más atractivo.",
],
},
"is_refusal": {
type: "boolean",
description:
"Indica si la respuesta es un refusal (es decir, la pregunta no tiene que ver con el plan de estudio)",
},
},
},
},
@@ -301,6 +306,56 @@ app.post(`${prefix}/conversations/:id/messages`, async (c) => {
const model = CREATE_CHAT_CONVERSATION_STRUCTURED_MODELO;
const prompt = body.user_prompt ?? body.content;
// append message of the user to conversacion_json (which guarantees a JSONB default to '[]')
/**
* appended includes timestamp, user, prompt and fields (if any)
*/
type AppendedMessage = {
timestamp: string;
user: string;
prompt: string;
fields?: string[];
};
type AppendedResponse = {
timestamp: string;
user: "assistant";
refusal: boolean;
message: string;
recommendations?: {
texto_mejora: string;
campo_afectado: string;
aplicada: false;
};
};
type AppendedItem = AppendedMessage | AppendedResponse;
let appended: AppendedItem = {
timestamp: new Date().toISOString(),
user: /* user.email ?? user.id ??*/ "unknown",
prompt,
fields: body.campos,
};
const { error: appendErr } = await supabase.rpc(
"append_conversacion_plan",
{
p_id: conversation_plan_id,
p_appended: JSON.stringify(appended),
},
);
if (appendErr) {
throw new HttpError(
500,
"append_conversation_failed",
"No se pudo agregar el mensaje a la conversación",
appendErr,
);
}
const resp = await openai.responses.create({
conversation: row.openai_conversation_id,
model,
@@ -322,6 +377,44 @@ app.post(`${prefix}/conversations/:id/messages`, async (c) => {
],
});
const respuestaJSON = JSON.parse(resp.output_text ?? "{}");
// Now an item with the assistant response and the structured data (if any) should be
appended = {
timestamp: new Date().toISOString(),
user: "assistant",
refusal: resp.output_text === "refusal",
// the ai-message field is the response
message: respuestaJSON?.["ai-message"] ?? "",
recommendations: resp.output_text
? Object.entries(respuestaJSON).filter(([k]) => k !== "ai-message")
.map(
([campo_afectado, texto_mejora]) => ({
campo_afectado,
texto_mejora,
aplicada: false,
}),
)
: undefined,
} as AppendedResponse;
const { error: appendRespErr } = await supabase.rpc(
"append_conversacion_plan",
{
p_id: conversation_plan_id,
p_appended: JSON.stringify(appended),
},
);
if (appendRespErr) {
throw new HttpError(
500,
"append_response_failed",
"No se pudo agregar la respuesta a la conversación",
appendRespErr,
);
}
return withCors(jsonResponse({
ok: true,
openai_response_id: resp.id,