Merge pull request 'Agregar conversaciones a la tabla como respaldo #33' (#34) from issue/33-agregar-conversaciones-a-la-tabla-como-respaldo into main
Deploy Function / deploy (push) Successful in 25s
Deploy Migrations to Production / deploy (push) Successful in 10s

Reviewed-on: AlexRG/genesis-2#34
This commit was merged in pull request #34.
This commit is contained in:
2026-02-24 21:21:18 +00:00
8 changed files with 216 additions and 112 deletions
Generated
+6 -2
View File
@@ -20,6 +20,7 @@
"jsr:@zod/zod@^4.3.5": "4.3.5", "jsr:@zod/zod@^4.3.5": "4.3.5",
"npm:@supabase/supabase-js@2": "2.90.1", "npm:@supabase/supabase-js@2": "2.90.1",
"npm:@supabase/supabase-js@^2.90.1": "2.90.1", "npm:@supabase/supabase-js@^2.90.1": "2.90.1",
"npm:@toon-format/toon@^2.1.0": "2.1.0",
"npm:@types/bun@^1.3.5": "1.3.5", "npm:@types/bun@^1.3.5": "1.3.5",
"npm:deno@^2.6.4": "2.6.4", "npm:deno@^2.6.4": "2.6.4",
"npm:openai@6.16.0": "6.16.0_zod@3.25.76", "npm:openai@6.16.0": "6.16.0_zod@3.25.76",
@@ -182,6 +183,9 @@
"@supabase/storage-js" "@supabase/storage-js"
] ]
}, },
"@toon-format/toon@2.1.0": {
"integrity": "sha512-JwWptdF5eOA0HaQxbKAzkpQtR4wSWTEfDlEy/y3/4okmOAX1qwnpLZMmtEWr+ncAhTTY1raCKH0kteHhSXnQqg=="
},
"@types/bun@1.3.5": { "@types/bun@1.3.5": {
"integrity": "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w==", "integrity": "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w==",
"dependencies": [ "dependencies": [
@@ -515,8 +519,7 @@
"minipass", "minipass",
"minizlib", "minizlib",
"yallist" "yallist"
], ]
"deprecated": true
}, },
"tr46@0.0.3": { "tr46@0.0.3": {
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
@@ -587,6 +590,7 @@
"packageJson": { "packageJson": {
"dependencies": [ "dependencies": [
"npm:@supabase/supabase-js@^2.90.1", "npm:@supabase/supabase-js@^2.90.1",
"npm:@toon-format/toon@^2.1.0",
"npm:@types/bun@^1.3.5", "npm:@types/bun@^1.3.5",
"npm:deno@^2.6.4", "npm:deno@^2.6.4",
"npm:openai@^6.16.0", "npm:openai@^6.16.0",
+33 -31
View File
@@ -2,7 +2,7 @@
"cells": [ "cells": [
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 1,
"id": "bb61ec88", "id": "bb61ec88",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
@@ -19,7 +19,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 2,
"id": "8baca5f2", "id": "8baca5f2",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
@@ -32,7 +32,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 19, "execution_count": 7,
"id": "26b3bb36", "id": "26b3bb36",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
@@ -55,28 +55,36 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 21, "execution_count": 9,
"id": "8abb080e", "id": "8abb080e",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"data": { "data": {
"text/plain": [ "text/plain": [
"\u001b[32m\"e39952c1-a53b-43bf-8033-feda493a0651\"\u001b[39m" "{\n",
" message: \u001b[32m\"TypeError: error sending request for url (http://127.0.0.1:54321/rest/v1/planes_estudio?select=*): client error (Connect): tcp connect error: No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión. (os error 10061)\"\u001b[39m,\n",
" details: \u001b[32m\"TypeError: error sending request for url (http://127.0.0.1:54321/rest/v1/planes_estudio?select=*): client error (Connect): tcp connect error: No se puede establecer una conexión ya que el equipo de destino denegó expresamente dicha conexión. (os error 10061)\\n\"\u001b[39m +\n",
" \u001b[32m\" at async mainFetch (ext:deno_fetch/26_fetch.js:192:12)\\n\"\u001b[39m +\n",
" \u001b[32m\" at async fetch (ext:deno_fetch/26_fetch.js:475:11)\\n\"\u001b[39m +\n",
" \u001b[32m\" at async <anonymous>:2:31\"\u001b[39m,\n",
" hint: \u001b[32m\"\"\u001b[39m,\n",
" code: \u001b[32m\"\"\u001b[39m\n",
"}"
] ]
}, },
"execution_count": 21, "execution_count": 9,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
], ],
"source": [ "source": [
"plan.id" "error"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 22, "execution_count": 12,
"id": "a382bdc6", "id": "a382bdc6",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -84,9 +92,9 @@
"data": { "data": {
"text/plain": [ "text/plain": [
"{\n", "{\n",
" id: \u001b[32m\"resp_0f1906be7e83879e00699895d7f1cc8193a960e6ccdab1d377\"\u001b[39m,\n", " id: \u001b[32m\"resp_0ae72cbd0894279200699c8e42941c8192ba4a09e280b21a17\"\u001b[39m,\n",
" object: \u001b[32m\"response\"\u001b[39m,\n", " object: \u001b[32m\"response\"\u001b[39m,\n",
" created_at: \u001b[33m1771607511\u001b[39m,\n", " created_at: \u001b[33m1771867714\u001b[39m,\n",
" status: \u001b[32m\"queued\"\u001b[39m,\n", " status: \u001b[32m\"queued\"\u001b[39m,\n",
" background: \u001b[33mtrue\u001b[39m,\n", " background: \u001b[33mtrue\u001b[39m,\n",
" completed_at: \u001b[1mnull\u001b[22m,\n", " completed_at: \u001b[1mnull\u001b[22m,\n",
@@ -130,15 +138,12 @@
" truncation: \u001b[32m\"disabled\"\u001b[39m,\n", " truncation: \u001b[32m\"disabled\"\u001b[39m,\n",
" usage: \u001b[1mnull\u001b[22m,\n", " usage: \u001b[1mnull\u001b[22m,\n",
" user: \u001b[1mnull\u001b[22m,\n", " user: \u001b[1mnull\u001b[22m,\n",
" metadata: {\n", " metadata: { tabla: \u001b[32m\"planes_estudio\"\u001b[39m, id: \u001b[32m\"2\"\u001b[39m },\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", " output_text: \u001b[32m\"\"\u001b[39m\n",
"}" "}"
] ]
}, },
"execution_count": 22, "execution_count": 12,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
@@ -150,7 +155,7 @@
" input: \"Hola mundo\",\n", " input: \"Hola mundo\",\n",
" metadata: {\n", " metadata: {\n",
" tabla: \"planes_estudio\",\n", " tabla: \"planes_estudio\",\n",
" id: plan.id,\n", " id: '2',\n",
" },\n", " },\n",
" text: {\n", " text: {\n",
" format: {\n", " format: {\n",
@@ -183,7 +188,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 23, "execution_count": 13,
"id": "6b2470ed", "id": "6b2470ed",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -200,13 +205,13 @@
"data": { "data": {
"text/plain": [ "text/plain": [
"{\n", "{\n",
" id: \u001b[32m\"resp_0f1906be7e83879e00699895d7f1cc8193a960e6ccdab1d377\"\u001b[39m,\n", " id: \u001b[32m\"resp_0ae72cbd0894279200699c8e42941c8192ba4a09e280b21a17\"\u001b[39m,\n",
" object: \u001b[32m\"response\"\u001b[39m,\n", " object: \u001b[32m\"response\"\u001b[39m,\n",
" created_at: \u001b[33m1771607511\u001b[39m,\n", " created_at: \u001b[33m1771867714\u001b[39m,\n",
" status: \u001b[32m\"completed\"\u001b[39m,\n", " status: \u001b[32m\"completed\"\u001b[39m,\n",
" background: \u001b[33mtrue\u001b[39m,\n", " background: \u001b[33mtrue\u001b[39m,\n",
" billing: { payer: \u001b[32m\"developer\"\u001b[39m },\n", " billing: { payer: \u001b[32m\"developer\"\u001b[39m },\n",
" completed_at: \u001b[33m1771607519\u001b[39m,\n", " completed_at: \u001b[33m1771867721\u001b[39m,\n",
" error: \u001b[1mnull\u001b[22m,\n", " error: \u001b[1mnull\u001b[22m,\n",
" frequency_penalty: \u001b[33m0\u001b[39m,\n", " frequency_penalty: \u001b[33m0\u001b[39m,\n",
" incomplete_details: \u001b[1mnull\u001b[22m,\n", " incomplete_details: \u001b[1mnull\u001b[22m,\n",
@@ -216,12 +221,12 @@
" model: \u001b[32m\"gpt-5-mini-2025-08-07\"\u001b[39m,\n", " model: \u001b[32m\"gpt-5-mini-2025-08-07\"\u001b[39m,\n",
" output: [\n", " output: [\n",
" {\n", " {\n",
" id: \u001b[32m\"rs_0f1906be7e83879e00699895d976548193ad40e9aae0b1b4f2\"\u001b[39m,\n", " id: \u001b[32m\"rs_0ae72cbd0894279200699c8e43cd4c8192bcbc70792b6aa621\"\u001b[39m,\n",
" type: \u001b[32m\"reasoning\"\u001b[39m,\n", " type: \u001b[32m\"reasoning\"\u001b[39m,\n",
" summary: []\n", " summary: []\n",
" },\n", " },\n",
" {\n", " {\n",
" id: \u001b[32m\"msg_0f1906be7e83879e00699895ddf62881938811097ba62e8724\"\u001b[39m,\n", " id: \u001b[32m\"msg_0ae72cbd0894279200699c8e48976481928e1f205210636717\"\u001b[39m,\n",
" type: \u001b[32m\"message\"\u001b[39m,\n", " type: \u001b[32m\"message\"\u001b[39m,\n",
" status: \u001b[32m\"completed\"\u001b[39m,\n", " status: \u001b[32m\"completed\"\u001b[39m,\n",
" content: [\n", " content: [\n",
@@ -229,7 +234,7 @@
" type: \u001b[32m\"output_text\"\u001b[39m,\n", " type: \u001b[32m\"output_text\"\u001b[39m,\n",
" annotations: [],\n", " annotations: [],\n",
" logprobs: [],\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", " text: \u001b[32m'{\"ai-message\":\"¡Hola! ¿En qué puedo ayudarte hoy? Puedo mostrar ejemplos de \\\\\"Hola mundo\\\\\" en distintos lenguajes, explicar conceptos de programación, ayudar con una tarea o sugerir recursos. Dime qué prefieres.\",\"suggested-topic\":\"El papel del programa \\\\\"Hola Mundo\\\\\" en la enseñanza de la programación: comparación práctica entre Python, Java y C (sintaxis, tiempo de arranque, facilidad de aprendizaje y percepción del estudiante).\"}'\u001b[39m\n",
" }\n", " }\n",
" ],\n", " ],\n",
" role: \u001b[32m\"assistant\"\u001b[39m\n", " role: \u001b[32m\"assistant\"\u001b[39m\n",
@@ -268,20 +273,17 @@
" usage: {\n", " usage: {\n",
" input_tokens: \u001b[33m167\u001b[39m,\n", " input_tokens: \u001b[33m167\u001b[39m,\n",
" input_tokens_details: { cached_tokens: \u001b[33m0\u001b[39m },\n", " input_tokens_details: { cached_tokens: \u001b[33m0\u001b[39m },\n",
" output_tokens: \u001b[33m437\u001b[39m,\n", " output_tokens: \u001b[33m482\u001b[39m,\n",
" output_tokens_details: { reasoning_tokens: \u001b[33m320\u001b[39m },\n", " output_tokens_details: { reasoning_tokens: \u001b[33m320\u001b[39m },\n",
" total_tokens: \u001b[33m604\u001b[39m\n", " total_tokens: \u001b[33m649\u001b[39m\n",
" },\n", " },\n",
" user: \u001b[1mnull\u001b[22m,\n", " user: \u001b[1mnull\u001b[22m,\n",
" metadata: {\n", " metadata: { tabla: \u001b[32m\"planes_estudio\"\u001b[39m, id: \u001b[32m\"2\"\u001b[39m },\n",
" tabla: \u001b[32m\"planes_estudio\"\u001b[39m,\n", " output_text: \u001b[32m'{\"ai-message\":\"¡Hola! ¿En qué puedo ayudarte hoy? Puedo mostrar ejemplos de \\\\\"Hola mundo\\\\\" en distintos lenguajes, explicar conceptos de programación, ayudar con una tarea o sugerir recursos. Dime qué prefieres.\",\"suggested-topic\":\"El papel del programa \\\\\"Hola Mundo\\\\\" en la enseñanza de la programación: comparación práctica entre Python, Java y C (sintaxis, tiempo de arranque, facilidad de aprendizaje y percepción del estudiante).\"}'\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, "execution_count": 13,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
+8 -4
View File
@@ -83,11 +83,13 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 26, "execution_count": null,
"id": "1403c789", "id": "1403c789",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"import { title } from \"node:process\";\n",
"\n",
"const combinedSchema = {\n", "const combinedSchema = {\n",
" type: \"object\",\n", " type: \"object\",\n",
" $defs: {\n", " $defs: {\n",
@@ -126,10 +128,12 @@
" fabricante: { type: \"string\", maxLength: 100 },\n", " fabricante: { type: \"string\", maxLength: 100 },\n",
"\n", "\n",
" // Agregar campo del preset\n", " // Agregar campo del preset\n",
" perishables: { $ref: \"#/$defs/perishables\" },\n", " perishables: {\n",
" origen: { $ref: \"#/$defs/origen\" },\n", " $ref: \"#/$defs/perishables\",\n",
" \"x-column\": \"perishables\",\n",
" },\n",
"\n", "\n",
" perecedero: { type: \"null\", \"x-column\": \"perishable\", const: null },\n", " origen: { $ref: \"#/$defs/origen\" },\n",
" },\n", " },\n",
" required: [\"nombre\", \"fabricante\", \"perishables\", \"origen\", \"perecedero\"],\n", " required: [\"nombre\", \"fabricante\", \"perishables\", \"origen\", \"perecedero\"],\n",
" additionalProperties: false,\n", " additionalProperties: false,\n",
+54 -73
View File
@@ -2,7 +2,7 @@
"cells": [ "cells": [
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 2,
"id": "902bff53", "id": "902bff53",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
@@ -19,7 +19,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 3,
"id": "3b0acbc3", "id": "3b0acbc3",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
@@ -32,63 +32,18 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": 1,
"id": "dae842ad", "id": "dae842ad",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"name": "stdout", "ename": "ReferenceError",
"output_type": "stream", "evalue": "openai is not defined",
"text": [ "output_type": "error",
"{\n", "traceback": [
" object: \"list\",\n", "Stack trace:",
" data: [\n", "ReferenceError: openai is not defined",
" {\n", " at <anonymous>:5:15"
" object: \"embedding\",\n",
" index: 0,\n",
" embedding: [\n",
" 0.017360063269734383, 0.022553985938429832, 0.025286488234996796,\n",
" -0.009742671623826027, -0.016438385471701622, -0.014725150540471077,\n",
" -0.020840751007199287, 0.02215278521180153, -0.02024437114596367,\n",
" 0.007834257557988167, 0.0029981620609760284, -0.04109596461057663,\n",
" 0.030165957286953926, -0.03402615711092949, 0.0008369643473997712,\n",
" 0.00044016868923790753, -0.027129843831062317, -0.04248390346765518,\n",
" -0.058683738112449646, 0.034655068069696426, 0.013738414272665977,\n",
" 0.02060219831764698, 0.016687780618667603, 0.0059637944214046,\n",
" -0.010306521318852901, 0.014898642897605896, -0.008826415985822678,\n",
" 0.042136918753385544, 0.009477011859416962, -0.03953453525900841,\n",
" -0.012198670767247677, -0.040055014193058014, -0.019409440457820892,\n",
" -0.0210576169192791, -0.0392959825694561, -0.005996324121952057,\n",
" -0.0022486215457320213, 0.05209103599190712, 0.0009325206046923995,\n",
" 0.013163721188902855, 0.0505296029150486, 0.014540815725922585,\n",
" 0.0027921402361243963, 0.03190087899565697, 0.00004917589103570208,\n",
" 0.03209605813026428, -0.038363464176654816, -0.02424553595483303,\n",
" 0.014096241444349289, 0.02559009939432144, -0.06089576333761215,\n",
" -0.011016755364835262, -0.026696112006902695, 0.050659723579883575,\n",
" 0.019561246037483215, 0.050833214074373245, 0.014529972337186337,\n",
" -0.023204581812024117, -0.014399852603673935, -0.009292676113545895,\n",
" 0.003149967873468995, 0.02007087878882885, 0.025503354147076607,\n",
" 0.0230094026774168, 0.04471761733293533, 0.01479020994156599,\n",
" -0.06692461669445038, 0.03591288626194, -0.037127330899238586,\n",
" 0.029558734968304634, -0.017576929181814194, 0.01953955926001072,\n",
" -0.027888871729373932, -0.0041095963679254055, 0.0004940461367368698,\n",
" -0.011266149580478668, -0.04200679808855057, 0.03537072241306305,\n",
" -0.0015058581484481692, -0.05551750585436821, -0.05287174880504608,\n",
" 0.016373327001929283, 0.005573437083512545, -0.01235047634691,\n",
" -0.009005329571664333, -0.034047845751047134, -0.018368486315011978,\n",
" -0.00271217105910182, 0.007731246296316385, -0.020981714129447937,\n",
" -0.040900785475969315, -0.03727913647890091, -0.059030722826719284,\n",
" -0.04536821320652962, 0.02257567271590233, 0.08579189330339432,\n",
" 0.014605875127017498, -0.030686434358358383, -0.0019084142986685038,\n",
" 0.02216362953186035,\n",
" ... 1436 more items\n",
" ]\n",
" }\n",
" ],\n",
" model: \"text-embedding-3-small\",\n",
" usage: { prompt_tokens: 13, total_tokens: 13 }\n",
"}\n",
"✅ Insertados textos con embeddings\n"
] ]
} }
], ],
@@ -120,7 +75,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 13, "execution_count": 12,
"id": "2d8fa9a9", "id": "2d8fa9a9",
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
@@ -129,20 +84,26 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"🔎 Consulta: ¿Cómo son buscados vectores?\n", "🔎 Consulta: ¿Cómo son buscados vectores?\n",
"\n",
"- Los vectores se usan con el cliente de OPENAI embeddings\n",
" Similaridad: 0.5639\n",
"\n",
"- Supabase permite almacenar vectores usando pgvector.\n",
" Similaridad: 0.4758\n",
"\n",
"- Los embeddings convierten texto en representaciones numéricas.\n",
" Similaridad: 0.3645\n",
"\n" "\n"
] ]
},
{
"data": {
"text/plain": [
"\u001b[32m\"code: PGRST202\\n\"\u001b[39m +\n",
" \u001b[32m'details: \"Searched for the function public.buscar_documentos with parameters match_count, query_embedding or with a single unnamed json/jsonb parameter, but no matches were found in the schema cache.\"\\n'\u001b[39m +\n",
" \u001b[32m\"hint: Perhaps you meant to call the function public.unaccent\\n\"\u001b[39m +\n",
" \u001b[32m'message: \"Could not find the function public.buscar_documentos(match_count, query_embedding) in the schema cache\"'\u001b[39m"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
} }
], ],
"source": [ "source": [
"import { encode } from \"@toon-format/toon\";\n",
"\n",
"const consulta = \"¿Cómo son buscados vectores?\";\n", "const consulta = \"¿Cómo son buscados vectores?\";\n",
"\n", "\n",
"const emb = await openai.embeddings.create({\n", "const emb = await openai.embeddings.create({\n",
@@ -157,22 +118,42 @@
" match_count: 3,\n", " match_count: 3,\n",
"});\n", "});\n",
"\n", "\n",
"if (error) throw error;\n", "/* if (error) throw error; */\n",
"\n", "\n",
"console.log(`🔎 Consulta: ${consulta}\\n`);\n", "console.log(`🔎 Consulta: ${consulta}\\n`);\n",
"for (const r of data ?? []) {\n", "encode(error, {\n",
" console.log(`- ${r.contenido}`);\n", " indent: 2,\n",
" console.log(` Similaridad: ${Number(r.similarity).toFixed(4)}\\n`);\n", " delimiter: \",\",\n",
"}\n" " keyFolding: \"off\",\n",
" flattenDepth: Infinity,\n",
"});\n"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 10,
"id": "791a94d8", "id": "791a94d8",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
"source": [] {
"data": {
"text/plain": [
"{\n",
" code: \u001b[32m\"PGRST202\"\u001b[39m,\n",
" details: \u001b[32m\"Searched for the function public.buscar_documentos with parameters match_count, query_embedding or with a single unnamed json/jsonb parameter, but no matches were found in the schema cache.\"\u001b[39m,\n",
" hint: \u001b[32m\"Perhaps you meant to call the function public.unaccent\"\u001b[39m,\n",
" message: \u001b[32m\"Could not find the function public.buscar_documentos(match_count, query_embedding) in the schema cache\"\u001b[39m\n",
"}"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"error"
]
} }
], ],
"metadata": { "metadata": {
+1
View File
@@ -1,6 +1,7 @@
{ {
"dependencies": { "dependencies": {
"@supabase/supabase-js": "^2.90.1", "@supabase/supabase-js": "^2.90.1",
"@toon-format/toon": "^2.1.0",
"deno": "^2.6.4", "deno": "^2.6.4",
"openai": "^6.16.0", "openai": "^6.16.0",
"supabase": "^2.72.6" "supabase": "^2.72.6"
@@ -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.", "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 model = CREATE_CHAT_CONVERSATION_STRUCTURED_MODELO;
const prompt = body.user_prompt ?? body.content; 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({ const resp = await openai.responses.create({
conversation: row.openai_conversation_id, conversation: row.openai_conversation_id,
model, 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({ return withCors(jsonResponse({
ok: true, ok: true,
openai_response_id: resp.id, openai_response_id: resp.id,
@@ -1,5 +1,3 @@
alter table "public"."conversaciones_plan" add column "nombre" text default ('Chat '::text || CURRENT_DATE); alter table "public"."conversaciones_plan" add column "nombre" text default ('Chat '::text || CURRENT_DATE);
alter table "public"."conversaciones_plan" alter column "conversacion_json" set default '[]'::jsonb; alter table "public"."conversaciones_plan" alter column "conversacion_json" set default '[]'::jsonb;
@@ -0,0 +1,21 @@
CREATE OR REPLACE FUNCTION public.append_conversacion_asignatura(p_id uuid, p_append jsonb)
RETURNS void
LANGUAGE sql
AS $function$
update conversaciones_asignatura
set conversacion_json = coalesce(conversacion_json, '[]'::jsonb) || p_append
where id = p_id;
$function$
;
CREATE OR REPLACE FUNCTION public.append_conversacion_plan(p_id uuid, p_append jsonb)
RETURNS void
LANGUAGE sql
AS $function$
update conversaciones_plan
set conversacion_json = coalesce(conversacion_json, '[]'::jsonb) || p_append
where id = p_id;
$function$
;