diff --git a/deno.lock b/deno.lock index 1ea3a90..c3819bf 100644 --- a/deno.lock +++ b/deno.lock @@ -5,8 +5,10 @@ "jsr:@david/dax@~0.44.2": "0.44.2", "jsr:@david/path@0.2": "0.2.0", "jsr:@david/which@~0.4.1": "0.4.1", + "jsr:@openai/openai@*": "6.16.0", "jsr:@openai/openai@^6.16.0": "6.16.0", "jsr:@std/bytes@^1.0.6": "1.0.6", + "jsr:@std/dotenv@*": "0.225.6", "jsr:@std/fmt@1": "1.0.9", "jsr:@std/fs@1": "1.0.22", "jsr:@std/fs@^1.0.20": "1.0.22", @@ -57,6 +59,9 @@ "@std/bytes@1.0.6": { "integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a" }, + "@std/dotenv@0.225.6": { + "integrity": "1d6f9db72f565bd26790fa034c26e45ecb260b5245417be76c2279e5734c421b" + }, "@std/fmt@1.0.9": { "integrity": "2487343e8899fb2be5d0e3d35013e54477ada198854e52dd05ed0422eddcabe0" }, @@ -89,57 +94,33 @@ "npm": { "@deno/darwin-arm64@2.6.4": { "integrity": "sha512-5pocuV2IVWYUzomXze+bDSO86uX1WPxUn82BS7BrLI3ix8Eq7l8DhvYgz064w7rwCM4CiLLSc6MAQpAI+0gUag==", - "os": [ - "darwin" - ], - "cpu": [ - "arm64" - ] + "os": ["darwin"], + "cpu": ["arm64"] }, "@deno/darwin-x64@2.6.4": { "integrity": "sha512-tX7Fz47HcoXTYR4wN2WzXjqJtEPTftzjEknCYkZa8D4BzvpN7Zo1ra3Jd6bWPN9+T6mgTL6YMPMMSigXddIUcA==", - "os": [ - "darwin" - ], - "cpu": [ - "x64" - ] + "os": ["darwin"], + "cpu": ["x64"] }, "@deno/linux-arm64-glibc@2.6.4": { "integrity": "sha512-wY4hjjVLq5idClWj6e1de9IUZ0QZ1rxo16o0dwCJpMi+w1lolxtYxGF4y7pkcxAdZOpMGsXZuYMPq1Z2n51esA==", - "os": [ - "linux" - ], - "cpu": [ - "arm64" - ] + "os": ["linux"], + "cpu": ["arm64"] }, "@deno/linux-x64-glibc@2.6.4": { "integrity": "sha512-H9b0WJw+eWyC6GcMGCXxC/3lz2kVveyWyUrzGyQ8hJmtDJpWiDnCU2iPqEpEcwXHgAUFFyjnRaFwedwwv5ApdA==", - "os": [ - "linux" - ], - "cpu": [ - "x64" - ] + "os": ["linux"], + "cpu": ["x64"] }, "@deno/win32-arm64@2.6.4": { "integrity": "sha512-fMH1dx54ORbCTpMorGjDshwonIu6KfgfPC+Pq+14jeq/8604EIFXiA484p3Ov+ViZycndNHEPe8ZKPNd8xLjJA==", - "os": [ - "win32" - ], - "cpu": [ - "arm64" - ] + "os": ["win32"], + "cpu": ["arm64"] }, "@deno/win32-x64@2.6.4": { "integrity": "sha512-hAxqNrBLHCINtqDgKcRiu8QtMbtdnHOVW3OFQjzA3gZEcpnGUK3JiF5ql++83SjuQH8ViZKGcdqkioLR7Bf14A==", - "os": [ - "win32" - ], - "cpu": [ - "x64" - ] + "os": ["win32"], + "cpu": ["x64"] }, "@isaacs/fs-minipass@4.0.1": { "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", @@ -376,8 +357,10 @@ "dependencies": [ "jsr:@david/dax@~0.44.2", "jsr:@openai/openai@^6.16.0", + "jsr:@supabase/functions-js@2", "jsr:@zod/zod@^4.3.5", - "jsr:@david/dax@~0.44.2" + "npm:@supabase/supabase-js@2", + "npm:openai@6.16.0" ], "packageJson": { "dependencies": [ diff --git a/notebooks/conversations-openai.ipynb b/notebooks/conversations-openai.ipynb new file mode 100644 index 0000000..4cd1380 --- /dev/null +++ b/notebooks/conversations-openai.ipynb @@ -0,0 +1,126 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 8, + "id": "a9a99d9d", + "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": 9, + "id": "89b3fffb", + "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": null, + "id": "33290880", + "metadata": {}, + "outputs": [], + "source": [ + "// Create a conversation for a plan de estudio\n", + "\n", + "const { data: input } = await supabase.from(\"planes_estudio\").limit(1).select(\"id\").single();\n", + "const openaiConversation = await openai.conversations.create({\n", + " metadata: {\n", + " \"tabla\": \"planes_estudio\",\n", + " \"id\": input.id,\n", + "\n", + " instanciador: \"alex\",\n", + " },\n", + "\n", + " items: [\n", + " { 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.\" },\n", + " ],\n", + "});\n", + "\n", + "const conversationPlane = await supabase.from(\"conversation_planes_estudio\").insert({\n", + " conversation_id: openaiConversation.id,\n", + " plan_estudio_id: input.id,\n", + "}).select(\"id\").single();" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f726b80e", + "metadata": {}, + "outputs": [], + "source": [ + "// Archivar una conversación\n", + "const { data: conversation } = await supabase.from(\"conversation_planes_estudio\").limit(1).select(\"conversation_id\").single();\n", + "\n", + "const items = await openai.conversations.items(conversation.conversation_id);\n", + "await supabase.from(\"conversation_planes_estudio\").update({\n", + " estado: \"ARCHIVANDO\",\n", + " conversation_json: items,\n", + "}).eq(\"id\", conversationPlane.id);\n", + "\n", + "await openai.conversations.delete(conversation.conversation_id);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cfae6e48", + "metadata": {}, + "outputs": [], + "source": [ + "// Listar conversaciones dadas de un plan de estudio\n", + "const { data: conversations } = await supabase.from(\"conversation_planes_estudio\").select(\"*\").eq(\"plan_estudio_id\", input.id);\n", + "conversations" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "83e060ae", + "metadata": {}, + "outputs": [], + "source": [ + "// Add a message to the conversation\n", + "const { data: conversationToUpdate } = await supabase.from(\n", + " \"conversation_planes_estudio\",\n", + ").eq(\"id\", conversationPlane.id)\n", + " .select(\"conversation_id\").single();\n" + ] + } + ], + "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 +} diff --git a/supabase/functions/create-chat-conversation/.npmrc b/supabase/functions/create-chat-conversation/.npmrc new file mode 100644 index 0000000..48c6388 --- /dev/null +++ b/supabase/functions/create-chat-conversation/.npmrc @@ -0,0 +1,3 @@ +# Configuration for private npm package dependencies +# For more information on using private registries with Edge Functions, see: +# https://supabase.com/docs/guides/functions/import-maps#importing-from-private-registries diff --git a/supabase/functions/create-chat-conversation/deno.json b/supabase/functions/create-chat-conversation/deno.json new file mode 100644 index 0000000..758d070 --- /dev/null +++ b/supabase/functions/create-chat-conversation/deno.json @@ -0,0 +1,5 @@ +{ + "imports": { + "@supabase/functions-js": "jsr:@supabase/functions-js@^2" + } +} diff --git a/supabase/functions/create-chat-conversation/index.ts b/supabase/functions/create-chat-conversation/index.ts new file mode 100644 index 0000000..3da0253 --- /dev/null +++ b/supabase/functions/create-chat-conversation/index.ts @@ -0,0 +1,32 @@ +// Follow this setup guide to integrate the Deno language server with your editor: +// https://deno.land/manual/getting_started/setup_your_environment +// This enables autocomplete, go to definition, etc. + +// Setup type definitions for built-in Supabase Runtime APIs +import "@supabase/functions-js/edge-runtime.d.ts" + +console.log("Hello from Functions!") + +Deno.serve(async (req) => { + const { name } = await req.json() + const data = { + message: `Hello ${name}!`, + } + + return new Response( + JSON.stringify(data), + { headers: { "Content-Type": "application/json" } }, + ) +}) + +/* To invoke locally: + + 1. Run `supabase start` (see: https://supabase.com/docs/reference/cli/supabase-start) + 2. Make an HTTP request: + + curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/create-chat-conversation' \ + --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0' \ + --header 'Content-Type: application/json' \ + --data '{"name":"Functions"}' + +*/