Agregar notebook para integración con OpenAI y Supabase
Deploy Function / deploy (push) Has been cancelled
Deploy Migrations to Production / deploy (push) Has been cancelled

This commit is contained in:
2026-02-20 11:53:50 -06:00
parent f816e31b63
commit d029fa23e7
+398
View File
@@ -0,0 +1,398 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "bb61ec88",
"metadata": {},
"outputs": [],
"source": [
"import { load } from \"jsr:@std/dotenv\";\n",
"import OpenAI from \"jsr:@openai/openai\";\n",
"\n",
"const env = await load({\n",
" export: true,\n",
"});\n",
"\n",
"const openai = new OpenAI();"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8baca5f2",
"metadata": {},
"outputs": [],
"source": [
"import { createClient } from \"@supabase/supabase-js\";\n",
"const supabaseUrl = Deno.env.get(\"SUPABASE_URL\") || env.SUPABASE_URL;\n",
"const supabaseKey = Deno.env.get(\"SUPABASE_ANON_KEY\") || env.SUPABASE_ANON_KEY;\n",
"const supabase = createClient(supabaseUrl, supabaseKey);"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "26b3bb36",
"metadata": {},
"outputs": [],
"source": [
"// plan Crear un plan en la base (sin datos) estado generando\n",
"const { data: plan, error } = await supabase.from(\"planes_estudio\").insert({\n",
" \"carrera_id\": \"8208da08-d549-4359-8865-9d806bc54f19\",\n",
" \"estructura_id\": \"69fb2b77-5a95-47e0-bf1f-389d384200e4\",\n",
" \"estado_actual_id\": \"18f49b67-8077-4371-be6e-2019a3be3562\",\n",
" \"nombre\": \"Ingeniearía en Cifbernética y Ciberseguridad (2025)\",\n",
" \"nivel\": \"Doctorado\",\n",
" \"tipo_ciclo\": \"Semestre\",\n",
" \"numero_ciclos\": 8,\n",
" \"activo\": true,\n",
" \"tipo_origen\": \"IA\",\n",
" \"creado_por\": \"11111111-1111-1111-1111-111111111111\",\n",
" \"actualizado_por\": \"11111111-1111-1111-1111-111111111111\",\n",
"}).select(\"*\").single();\n"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "8abb080e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\u001b[32m\"e39952c1-a53b-43bf-8033-feda493a0651\"\u001b[39m"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"plan.id"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "a382bdc6",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{\n",
" id: \u001b[32m\"resp_0f1906be7e83879e00699895d7f1cc8193a960e6ccdab1d377\"\u001b[39m,\n",
" object: \u001b[32m\"response\"\u001b[39m,\n",
" created_at: \u001b[33m1771607511\u001b[39m,\n",
" status: \u001b[32m\"queued\"\u001b[39m,\n",
" background: \u001b[33mtrue\u001b[39m,\n",
" completed_at: \u001b[1mnull\u001b[22m,\n",
" error: \u001b[1mnull\u001b[22m,\n",
" frequency_penalty: \u001b[33m0\u001b[39m,\n",
" incomplete_details: \u001b[1mnull\u001b[22m,\n",
" instructions: \u001b[1mnull\u001b[22m,\n",
" max_output_tokens: \u001b[1mnull\u001b[22m,\n",
" max_tool_calls: \u001b[1mnull\u001b[22m,\n",
" model: \u001b[32m\"gpt-5-mini-2025-08-07\"\u001b[39m,\n",
" output: [],\n",
" parallel_tool_calls: \u001b[33mtrue\u001b[39m,\n",
" presence_penalty: \u001b[33m0\u001b[39m,\n",
" previous_response_id: \u001b[1mnull\u001b[22m,\n",
" prompt_cache_key: \u001b[1mnull\u001b[22m,\n",
" prompt_cache_retention: \u001b[1mnull\u001b[22m,\n",
" reasoning: { effort: \u001b[32m\"medium\"\u001b[39m, summary: \u001b[1mnull\u001b[22m },\n",
" safety_identifier: \u001b[1mnull\u001b[22m,\n",
" service_tier: \u001b[32m\"auto\"\u001b[39m,\n",
" store: \u001b[33mtrue\u001b[39m,\n",
" temperature: \u001b[33m1\u001b[39m,\n",
" text: {\n",
" format: {\n",
" type: \u001b[32m\"json_schema\"\u001b[39m,\n",
" description: \u001b[1mnull\u001b[22m,\n",
" name: \u001b[32m\"response_schema\"\u001b[39m,\n",
" schema: {\n",
" type: \u001b[32m\"object\"\u001b[39m,\n",
" properties: { \u001b[32m\"ai-message\"\u001b[39m: \u001b[36m[Object]\u001b[39m, \u001b[32m\"suggested-topic\"\u001b[39m: \u001b[36m[Object]\u001b[39m },\n",
" required: [ \u001b[32m\"ai-message\"\u001b[39m, \u001b[32m\"suggested-topic\"\u001b[39m ],\n",
" additionalProperties: \u001b[33mfalse\u001b[39m\n",
" },\n",
" strict: \u001b[33mtrue\u001b[39m\n",
" },\n",
" verbosity: \u001b[32m\"medium\"\u001b[39m\n",
" },\n",
" tool_choice: \u001b[32m\"auto\"\u001b[39m,\n",
" tools: [],\n",
" top_logprobs: \u001b[33m0\u001b[39m,\n",
" top_p: \u001b[33m1\u001b[39m,\n",
" truncation: \u001b[32m\"disabled\"\u001b[39m,\n",
" usage: \u001b[1mnull\u001b[22m,\n",
" user: \u001b[1mnull\u001b[22m,\n",
" metadata: {\n",
" tabla: \u001b[32m\"planes_estudio\"\u001b[39m,\n",
" id: \u001b[32m\"e39952c1-a53b-43bf-8033-feda493a0651\"\u001b[39m\n",
" },\n",
" output_text: \u001b[32m\"\"\u001b[39m\n",
"}"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\n",
"let response = await openai.responses.create({\n",
" model: \"gpt-5-mini\",\n",
" input: \"Hola mundo\",\n",
" metadata: {\n",
" tabla: \"planes_estudio\",\n",
" id: plan.id,\n",
" },\n",
" text: {\n",
" format: {\n",
" type: \"json_schema\",\n",
" name: \"response_schema\",\n",
" schema: {\n",
" type: \"object\",\n",
" properties: {\n",
" \"ai-message\": {\n",
" type: \"string\",\n",
" description:\n",
" \"Un mensaje de texto que la IA generará para el usuario final. Este mensaje debe ser claro y directo, proporcionando la información solicitada por el usuario o indicando que no se puede procesar la solicitud si no está relacionada con planes de estudio o asignaturas.\",\n",
" },\n",
" \"suggested-topic\": {\n",
" type: \"string\",\n",
" description:\n",
" \"Un tema de investigación sugerido por la IA que sea relevante para el plan de estudio o asignatura mencionada en la solicitud del usuario. Este tema debe ser específico y relacionado con el área de estudio correspondiente.\",\n",
" },\n",
" },\n",
" required: [\"ai-message\", \"suggested-topic\"],\n",
" additionalProperties: false,\n",
" },\n",
" },\n",
" },\n",
" background: true,\n",
"});\n",
"\n",
"response;\n"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "6b2470ed",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Current status: queued\n",
"Current status: in_progress\n",
"Current status: in_progress\n"
]
},
{
"data": {
"text/plain": [
"{\n",
" id: \u001b[32m\"resp_0f1906be7e83879e00699895d7f1cc8193a960e6ccdab1d377\"\u001b[39m,\n",
" object: \u001b[32m\"response\"\u001b[39m,\n",
" created_at: \u001b[33m1771607511\u001b[39m,\n",
" status: \u001b[32m\"completed\"\u001b[39m,\n",
" background: \u001b[33mtrue\u001b[39m,\n",
" billing: { payer: \u001b[32m\"developer\"\u001b[39m },\n",
" completed_at: \u001b[33m1771607519\u001b[39m,\n",
" error: \u001b[1mnull\u001b[22m,\n",
" frequency_penalty: \u001b[33m0\u001b[39m,\n",
" incomplete_details: \u001b[1mnull\u001b[22m,\n",
" instructions: \u001b[1mnull\u001b[22m,\n",
" max_output_tokens: \u001b[1mnull\u001b[22m,\n",
" max_tool_calls: \u001b[1mnull\u001b[22m,\n",
" model: \u001b[32m\"gpt-5-mini-2025-08-07\"\u001b[39m,\n",
" output: [\n",
" {\n",
" id: \u001b[32m\"rs_0f1906be7e83879e00699895d976548193ad40e9aae0b1b4f2\"\u001b[39m,\n",
" type: \u001b[32m\"reasoning\"\u001b[39m,\n",
" summary: []\n",
" },\n",
" {\n",
" id: \u001b[32m\"msg_0f1906be7e83879e00699895ddf62881938811097ba62e8724\"\u001b[39m,\n",
" type: \u001b[32m\"message\"\u001b[39m,\n",
" status: \u001b[32m\"completed\"\u001b[39m,\n",
" content: [\n",
" {\n",
" type: \u001b[32m\"output_text\"\u001b[39m,\n",
" annotations: [],\n",
" logprobs: [],\n",
" text: \u001b[32m'{\"ai-message\":\"¡Hola! ¿Cómo puedo ayudarte hoy? Si te refieres al clásico “Hola mundo” en programación, puedo mostrarte ejemplos en varios lenguajes, explicar su historia o ayudarte a crear tu primer programa. ¿Qué prefieres?\",\"suggested-topic\":\"El uso del programa “Hola mundo” como herramienta pedagógica en la enseñanza de la programación: impacto en la comprensión inicial, variaciones por lenguaje y mejores prácticas didácticas.\"}'\u001b[39m\n",
" }\n",
" ],\n",
" role: \u001b[32m\"assistant\"\u001b[39m\n",
" }\n",
" ],\n",
" parallel_tool_calls: \u001b[33mtrue\u001b[39m,\n",
" presence_penalty: \u001b[33m0\u001b[39m,\n",
" previous_response_id: \u001b[1mnull\u001b[22m,\n",
" prompt_cache_key: \u001b[1mnull\u001b[22m,\n",
" prompt_cache_retention: \u001b[1mnull\u001b[22m,\n",
" reasoning: { effort: \u001b[32m\"medium\"\u001b[39m, summary: \u001b[1mnull\u001b[22m },\n",
" safety_identifier: \u001b[1mnull\u001b[22m,\n",
" service_tier: \u001b[32m\"default\"\u001b[39m,\n",
" store: \u001b[33mtrue\u001b[39m,\n",
" temperature: \u001b[33m1\u001b[39m,\n",
" text: {\n",
" format: {\n",
" type: \u001b[32m\"json_schema\"\u001b[39m,\n",
" description: \u001b[1mnull\u001b[22m,\n",
" name: \u001b[32m\"response_schema\"\u001b[39m,\n",
" schema: {\n",
" type: \u001b[32m\"object\"\u001b[39m,\n",
" properties: { \u001b[32m\"ai-message\"\u001b[39m: \u001b[36m[Object]\u001b[39m, \u001b[32m\"suggested-topic\"\u001b[39m: \u001b[36m[Object]\u001b[39m },\n",
" required: [ \u001b[32m\"ai-message\"\u001b[39m, \u001b[32m\"suggested-topic\"\u001b[39m ],\n",
" additionalProperties: \u001b[33mfalse\u001b[39m\n",
" },\n",
" strict: \u001b[33mtrue\u001b[39m\n",
" },\n",
" verbosity: \u001b[32m\"medium\"\u001b[39m\n",
" },\n",
" tool_choice: \u001b[32m\"auto\"\u001b[39m,\n",
" tools: [],\n",
" top_logprobs: \u001b[33m0\u001b[39m,\n",
" top_p: \u001b[33m1\u001b[39m,\n",
" truncation: \u001b[32m\"disabled\"\u001b[39m,\n",
" usage: {\n",
" input_tokens: \u001b[33m167\u001b[39m,\n",
" input_tokens_details: { cached_tokens: \u001b[33m0\u001b[39m },\n",
" output_tokens: \u001b[33m437\u001b[39m,\n",
" output_tokens_details: { reasoning_tokens: \u001b[33m320\u001b[39m },\n",
" total_tokens: \u001b[33m604\u001b[39m\n",
" },\n",
" user: \u001b[1mnull\u001b[22m,\n",
" metadata: {\n",
" tabla: \u001b[32m\"planes_estudio\"\u001b[39m,\n",
" id: \u001b[32m\"e39952c1-a53b-43bf-8033-feda493a0651\"\u001b[39m\n",
" },\n",
" output_text: \u001b[32m'{\"ai-message\":\"¡Hola! ¿Cómo puedo ayudarte hoy? Si te refieres al clásico “Hola mundo” en programación, puedo mostrarte ejemplos en varios lenguajes, explicar su historia o ayudarte a crear tu primer programa. ¿Qué prefieres?\",\"suggested-topic\":\"El uso del programa “Hola mundo” como herramienta pedagógica en la enseñanza de la programación: impacto en la comprensión inicial, variaciones por lenguaje y mejores prácticas didácticas.\"}'\u001b[39m\n",
"}"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"while (response.status === \"queued\" || response.status === \"in_progress\") {\n",
" console.log(\"Current status: \" + response.status);\n",
" await new Promise((resolve) => setTimeout(resolve, 2000)); // wait 2 seconds\n",
" response = await openai.responses.retrieve(response.id);\n",
"}\n",
"\n",
"response;"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "ebb67bd8",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{ tabla: \u001b[32m\"planes_estudio\"\u001b[39m, id: \u001b[32m\"e39952c1-a53b-43bf-8033-feda493a0651\"\u001b[39m }"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"response.metadata"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "cd18fc2d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{\n",
" error: \u001b[1mnull\u001b[22m,\n",
" data: {\n",
" id: \u001b[32m\"e39952c1-a53b-43bf-8033-feda493a0651\"\u001b[39m,\n",
" carrera_id: \u001b[32m\"8208da08-d549-4359-8865-9d806bc54f19\"\u001b[39m,\n",
" estructura_id: \u001b[32m\"69fb2b77-5a95-47e0-bf1f-389d384200e4\"\u001b[39m,\n",
" nombre: \u001b[32m\"Ingeniearía en Cifbernética y Ciberseguridad (2025)\"\u001b[39m,\n",
" nivel: \u001b[32m\"Doctorado\"\u001b[39m,\n",
" tipo_ciclo: \u001b[32m\"Semestre\"\u001b[39m,\n",
" numero_ciclos: \u001b[33m8\u001b[39m,\n",
" datos: {\n",
" \u001b[32m\"ai-message\"\u001b[39m: \u001b[32m\"¡Hola! ¿Cómo puedo ayudarte hoy? Si te refieres al clásico “Hola mundo” en programación, puedo mostrarte ejemplos en varios lenguajes, explicar su historia o ayudarte a crear tu primer programa. ¿Qué prefieres?\"\u001b[39m,\n",
" \u001b[32m\"suggested-topic\"\u001b[39m: \u001b[32m\"El uso del programa “Hola mundo” como herramienta pedagógica en la enseñanza de la programación: impacto en la comprensión inicial, variaciones por lenguaje y mejores prácticas didácticas.\"\u001b[39m\n",
" },\n",
" estado_actual_id: \u001b[32m\"18f49b67-8077-4371-be6e-2019a3be3562\"\u001b[39m,\n",
" activo: \u001b[33mtrue\u001b[39m,\n",
" tipo_origen: \u001b[32m\"IA\"\u001b[39m,\n",
" meta_origen: {},\n",
" creado_por: \u001b[32m\"11111111-1111-1111-1111-111111111111\"\u001b[39m,\n",
" actualizado_por: \u001b[32m\"11111111-1111-1111-1111-111111111111\"\u001b[39m,\n",
" creado_en: \u001b[32m\"2026-02-20T17:11:28.995222+00:00\"\u001b[39m,\n",
" actualizado_en: \u001b[32m\"2026-02-20T17:12:40.170995+00:00\"\u001b[39m,\n",
" nombre_search: \u001b[32m\"ingeniearia en cifbernetica y ciberseguridad (2025)\"\u001b[39m,\n",
" plan_hash: \u001b[32m\"70d28457bbddfe4f5cde0574\"\u001b[39m\n",
" },\n",
" count: \u001b[1mnull\u001b[22m,\n",
" status: \u001b[33m200\u001b[39m,\n",
" statusText: \u001b[32m\"OK\"\u001b[39m\n",
"}"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"await supabase.from(response.metadata.tabla).update({\n",
" datos: JSON.parse(response.output_text),\n",
"}).eq(\"id\", response.metadata.id).select(\"*\").single();"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cbbfd8c0",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Deno",
"language": "typescript",
"name": "deno"
},
"language_info": {
"codemirror_mode": "typescript",
"file_extension": ".ts",
"mimetype": "text/x.typescript",
"name": "typescript",
"nbconvert_exporter": "script",
"pygments_lexer": "typescript",
"version": "5.9.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}