From 7910f1761d809fb0a0241a1d6d49409b7efcdbde Mon Sep 17 00:00:00 2001 From: "louis.ferry@telecomnancy.eu" Date: Tue, 4 Feb 2025 20:11:45 +0100 Subject: [PATCH 1/5] Example Scheduler without mail sending --- conversational_agent/src/autotask.ts | 116 +++++++++++++++++++++++++++ conversational_agent/src/hello.ts | 1 + 2 files changed, 117 insertions(+) create mode 100644 conversational_agent/src/autotask.ts create mode 100644 conversational_agent/src/hello.ts diff --git a/conversational_agent/src/autotask.ts b/conversational_agent/src/autotask.ts new file mode 100644 index 0000000..38f382b --- /dev/null +++ b/conversational_agent/src/autotask.ts @@ -0,0 +1,116 @@ +import { exec } from "child_process"; +import { createClient } from "@supabase/supabase-js"; +import dotenv from "dotenv"; +import path from "path"; + +// Chargement des variables d'environnement +dotenv.config({ path: path.resolve(process.cwd(), ".env") }); + +const supabaseUrl = process.env.SUPABASE_URL; +const supabaseAnonKey = process.env.SUPABASE_ANON_KEY; + +if (!supabaseUrl || !supabaseAnonKey) { + throw new Error("❌ Missing Supabase credentials."); +} + +const supabase = createClient(supabaseUrl, supabaseAnonKey); + +const INTERVAL = 10000; // Exprimé en ms + +/** + * Récupère les utilisateurs dont la newsletter doit être envoyée. + * On sélectionne les enregistrements dont `next_newsletter` (en format ISO) + * est inférieur ou égal à l'heure actuelle. + * On récupère également la colonne `periodicity` qui contient la durée d'espacement en secondes. + */ +async function getPendingNewsletters() { + const currentISO = new Date().toISOString(); + const { data, error } = await supabase + .from("subscribers") + .select("user_email, next_newsletter, periodicity") + .lte("next_newsletter", currentISO); + + if (error) { + console.error("❌ Error fetching pending newsletters:", error); + return []; + } + return data; +} + +/** + * Met à jour le champ `next_newsletter` pour l'utilisateur identifié par son email. + * Le prochain envoi est planifié en ajoutant la périodicité (en secondes) définie pour l'utilisateur + * au moment actuel (moment de l'envoi effectif). + * @param userEmail L'adresse email de l'utilisateur. + * @param periodicity La durée d'espacement en secondes pour cet utilisateur. + */ +async function updateNextNewsletter(userEmail: string, periodicity: number) { + // Utiliser le temps actuel comme base pour planifier l'envoi suivant + const newNewsletterTimestampSeconds = Math.floor(Date.now() / 1000) + periodicity; + const newNewsletterISO = new Date(newNewsletterTimestampSeconds * 1000).toISOString(); + + const { error } = await supabase + .from("subscribers") + .update({ next_newsletter: newNewsletterISO }) + .eq("user_email", userEmail); + + if (error) { + console.error(`❌ Error updating next newsletter for ${userEmail}:`, error); + } else { + console.log(`📅 Next newsletter for ${userEmail} scheduled at ${newNewsletterISO}`); + } +} + +/** + * Exécute le script `hello.ts` qui se charge d'envoyer la newsletter pour un utilisateur donné. + * @param userEmail L'adresse email de l'utilisateur. + */ +function sendNewsletter(userEmail: string) { + console.log(`📤 Sending newsletter to ${userEmail}...`); + exec("ts-node ./conversational_agent/src/hello.ts", (error, stdout, stderr) => { + if (error) { + console.error(`❌ Error sending newsletter to ${userEmail}:`, error.message); + return; + } + if (stderr) { + console.error(`⚠️ Stderr for ${userEmail}:`, stderr); + return; + } + console.log(`✅ Newsletter sent to ${userEmail}:`, stdout); + }); +} + +/** + * Vérifie régulièrement la base de données pour détecter les newsletters à envoyer. + * Pour chaque utilisateur dont le `next_newsletter` est dû, le script : + * - Lance l'envoi de la newsletter via `hello.ts`. + * - Met à jour la date de la prochaine newsletter en ajoutant la périodicité définie pour cet utilisateur. + */ +async function checkAndSendNewsletters() { + console.log("⏳ Checking for pending newsletters at", new Date().toISOString()); + const pendingNewsletters = await getPendingNewsletters(); + + if (!pendingNewsletters.length) { + console.log("✅ No newsletters to send."); + return; + } + + const nowSeconds = Math.floor(Date.now() / 1000); + + for (const subscriber of pendingNewsletters) { + const { user_email, next_newsletter, periodicity } = subscriber; + // Convertir la date ISO en timestamp en secondes + const newsletterTimestamp = Math.floor(new Date(next_newsletter).getTime() / 1000); + if (newsletterTimestamp <= nowSeconds) { + // Envoyer la newsletter + sendNewsletter(user_email); + // Mettre à jour la prochaine date d'envoi pour cet utilisateur + // en utilisant la périodicité spécifiée dans la base + await updateNextNewsletter(user_email, periodicity); + } + } +} + +// Démarrage du scheduler +console.log("🟢 Newsletter Scheduler started... Press CTRL + C to stop."); +setInterval(checkAndSendNewsletters, INTERVAL); diff --git a/conversational_agent/src/hello.ts b/conversational_agent/src/hello.ts new file mode 100644 index 0000000..ae9e3a9 --- /dev/null +++ b/conversational_agent/src/hello.ts @@ -0,0 +1 @@ +console.log("Hello, World!"); \ No newline at end of file From 229c7b291bb2bc496e0402935d190318ae3de9b7 Mon Sep 17 00:00:00 2001 From: "louis.ferry@telecomnancy.eu" Date: Wed, 5 Feb 2025 14:24:19 +0100 Subject: [PATCH 2/5] fix : rename + fixing bug --- .../src/{autotask.ts => emailScheduler.ts} | 42 +------------------ ...0250123103504_create_subscribers_table.sql | 10 +++-- 2 files changed, 8 insertions(+), 44 deletions(-) rename conversational_agent/src/{autotask.ts => emailScheduler.ts} (62%) diff --git a/conversational_agent/src/autotask.ts b/conversational_agent/src/emailScheduler.ts similarity index 62% rename from conversational_agent/src/autotask.ts rename to conversational_agent/src/emailScheduler.ts index 38f382b..95d38b9 100644 --- a/conversational_agent/src/autotask.ts +++ b/conversational_agent/src/emailScheduler.ts @@ -1,35 +1,25 @@ -import { exec } from "child_process"; +import { exec } from "child_process"; import { createClient } from "@supabase/supabase-js"; import dotenv from "dotenv"; import path from "path"; -// Chargement des variables d'environnement dotenv.config({ path: path.resolve(process.cwd(), ".env") }); const supabaseUrl = process.env.SUPABASE_URL; const supabaseAnonKey = process.env.SUPABASE_ANON_KEY; - if (!supabaseUrl || !supabaseAnonKey) { throw new Error("❌ Missing Supabase credentials."); } const supabase = createClient(supabaseUrl, supabaseAnonKey); +const INTERVAL = 10000; // 10 seconds -const INTERVAL = 10000; // Exprimé en ms - -/** - * Récupère les utilisateurs dont la newsletter doit être envoyée. - * On sélectionne les enregistrements dont `next_newsletter` (en format ISO) - * est inférieur ou égal à l'heure actuelle. - * On récupère également la colonne `periodicity` qui contient la durée d'espacement en secondes. - */ async function getPendingNewsletters() { const currentISO = new Date().toISOString(); const { data, error } = await supabase .from("subscribers") .select("user_email, next_newsletter, periodicity") .lte("next_newsletter", currentISO); - if (error) { console.error("❌ Error fetching pending newsletters:", error); return []; @@ -37,23 +27,13 @@ async function getPendingNewsletters() { return data; } -/** - * Met à jour le champ `next_newsletter` pour l'utilisateur identifié par son email. - * Le prochain envoi est planifié en ajoutant la périodicité (en secondes) définie pour l'utilisateur - * au moment actuel (moment de l'envoi effectif). - * @param userEmail L'adresse email de l'utilisateur. - * @param periodicity La durée d'espacement en secondes pour cet utilisateur. - */ async function updateNextNewsletter(userEmail: string, periodicity: number) { - // Utiliser le temps actuel comme base pour planifier l'envoi suivant const newNewsletterTimestampSeconds = Math.floor(Date.now() / 1000) + periodicity; const newNewsletterISO = new Date(newNewsletterTimestampSeconds * 1000).toISOString(); - const { error } = await supabase .from("subscribers") .update({ next_newsletter: newNewsletterISO }) .eq("user_email", userEmail); - if (error) { console.error(`❌ Error updating next newsletter for ${userEmail}:`, error); } else { @@ -61,10 +41,6 @@ async function updateNextNewsletter(userEmail: string, periodicity: number) { } } -/** - * Exécute le script `hello.ts` qui se charge d'envoyer la newsletter pour un utilisateur donné. - * @param userEmail L'adresse email de l'utilisateur. - */ function sendNewsletter(userEmail: string) { console.log(`📤 Sending newsletter to ${userEmail}...`); exec("ts-node ./conversational_agent/src/hello.ts", (error, stdout, stderr) => { @@ -80,37 +56,23 @@ function sendNewsletter(userEmail: string) { }); } -/** - * Vérifie régulièrement la base de données pour détecter les newsletters à envoyer. - * Pour chaque utilisateur dont le `next_newsletter` est dû, le script : - * - Lance l'envoi de la newsletter via `hello.ts`. - * - Met à jour la date de la prochaine newsletter en ajoutant la périodicité définie pour cet utilisateur. - */ async function checkAndSendNewsletters() { console.log("⏳ Checking for pending newsletters at", new Date().toISOString()); const pendingNewsletters = await getPendingNewsletters(); - if (!pendingNewsletters.length) { console.log("✅ No newsletters to send."); return; } - const nowSeconds = Math.floor(Date.now() / 1000); - for (const subscriber of pendingNewsletters) { const { user_email, next_newsletter, periodicity } = subscriber; - // Convertir la date ISO en timestamp en secondes const newsletterTimestamp = Math.floor(new Date(next_newsletter).getTime() / 1000); if (newsletterTimestamp <= nowSeconds) { - // Envoyer la newsletter sendNewsletter(user_email); - // Mettre à jour la prochaine date d'envoi pour cet utilisateur - // en utilisant la périodicité spécifiée dans la base await updateNextNewsletter(user_email, periodicity); } } } -// Démarrage du scheduler console.log("🟢 Newsletter Scheduler started... Press CTRL + C to stop."); setInterval(checkAndSendNewsletters, INTERVAL); diff --git a/supabase/migrations/20250123103504_create_subscribers_table.sql b/supabase/migrations/20250123103504_create_subscribers_table.sql index 4e55c88..a40da4c 100644 --- a/supabase/migrations/20250123103504_create_subscribers_table.sql +++ b/supabase/migrations/20250123103504_create_subscribers_table.sql @@ -1,6 +1,8 @@ --- creation of the table subscribers +-- Creation of the Subscribers table CREATE TABLE IF NOT EXISTS Subscribers ( - id SERIAL PRIMARY KEY, -- unique id, auto-incremented - user_email VARCHAR(255) UNIQUE NOT NULL, -- unique email of the user, mendatory - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- date of subscription, default : nowaday + id SERIAL PRIMARY KEY, -- Unique id, auto-incremented + user_email VARCHAR(255) NOT NULL, -- Email of the user (remove UNIQUE if duplicate entries are allowed) + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- Date of subscription (defaults to current timestamp) + next_newsletter TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- Next newsletter send date (defaults to now) + periodicity INTEGER DEFAULT 604800 -- Interval between newsletters in seconds (default: 604800 seconds = 7 days) ); From 044e96041cfb796e33067394aca10416a7639f50 Mon Sep 17 00:00:00 2001 From: "louis.ferry@telecomnancy.eu" Date: Wed, 5 Feb 2025 15:19:41 +0100 Subject: [PATCH 3/5] fix : added a flag to disable the log --- conversational_agent/src/emailScheduler.ts | 34 +++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/conversational_agent/src/emailScheduler.ts b/conversational_agent/src/emailScheduler.ts index 95d38b9..e4f190d 100644 --- a/conversational_agent/src/emailScheduler.ts +++ b/conversational_agent/src/emailScheduler.ts @@ -1,4 +1,4 @@ -import { exec } from "child_process"; +import { exec } from "child_process"; import { createClient } from "@supabase/supabase-js"; import dotenv from "dotenv"; import path from "path"; @@ -13,13 +13,15 @@ if (!supabaseUrl || !supabaseAnonKey) { const supabase = createClient(supabaseUrl, supabaseAnonKey); const INTERVAL = 10000; // 10 seconds +const loggingActivated = true; // Set to false to disable logs async function getPendingNewsletters() { const currentISO = new Date().toISOString(); const { data, error } = await supabase .from("subscribers") - .select("user_email, next_newsletter, periodicity") + .select("id, user_email, next_newsletter, periodicity") .lte("next_newsletter", currentISO); + if (error) { console.error("❌ Error fetching pending newsletters:", error); return []; @@ -27,22 +29,25 @@ async function getPendingNewsletters() { return data; } -async function updateNextNewsletter(userEmail: string, periodicity: number) { +async function updateNextNewsletter(userId: number, periodicity: number) { const newNewsletterTimestampSeconds = Math.floor(Date.now() / 1000) + periodicity; const newNewsletterISO = new Date(newNewsletterTimestampSeconds * 1000).toISOString(); + const { error } = await supabase .from("subscribers") .update({ next_newsletter: newNewsletterISO }) - .eq("user_email", userEmail); + .eq("id", userId); + if (error) { - console.error(`❌ Error updating next newsletter for ${userEmail}:`, error); - } else { - console.log(`📅 Next newsletter for ${userEmail} scheduled at ${newNewsletterISO}`); + console.error(`❌ Error updating next newsletter for user ID ${userId}:`, error); + } else if (loggingActivated) { + console.log(`📅 Next newsletter for user ID ${userId} scheduled at ${newNewsletterISO}`); } } function sendNewsletter(userEmail: string) { - console.log(`📤 Sending newsletter to ${userEmail}...`); + if (loggingActivated) console.log(`📤 Sending newsletter to ${userEmail}...`); + exec("ts-node ./conversational_agent/src/hello.ts", (error, stdout, stderr) => { if (error) { console.error(`❌ Error sending newsletter to ${userEmail}:`, error.message); @@ -52,24 +57,27 @@ function sendNewsletter(userEmail: string) { console.error(`⚠️ Stderr for ${userEmail}:`, stderr); return; } - console.log(`✅ Newsletter sent to ${userEmail}:`, stdout); + if (loggingActivated) console.log(`✅ Newsletter sent to ${userEmail}:`, stdout); }); } async function checkAndSendNewsletters() { - console.log("⏳ Checking for pending newsletters at", new Date().toISOString()); + if (loggingActivated) console.log("⏳ Checking for pending newsletters at", new Date().toISOString()); + const pendingNewsletters = await getPendingNewsletters(); if (!pendingNewsletters.length) { - console.log("✅ No newsletters to send."); + if (loggingActivated) console.log("✅ No newsletters to send."); return; } + const nowSeconds = Math.floor(Date.now() / 1000); for (const subscriber of pendingNewsletters) { - const { user_email, next_newsletter, periodicity } = subscriber; + const { id, user_email, next_newsletter, periodicity } = subscriber; const newsletterTimestamp = Math.floor(new Date(next_newsletter).getTime() / 1000); + if (newsletterTimestamp <= nowSeconds) { sendNewsletter(user_email); - await updateNextNewsletter(user_email, periodicity); + await updateNextNewsletter(id, periodicity); } } } From e72bb62b94701a02f5c828280d8c1d967aff4632 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Gindre?= Date: Thu, 6 Feb 2025 10:40:18 +0100 Subject: [PATCH 4/5] [feat] Added cron instead of setInterval for periodicity --- conversational_agent/package.json | 4 +++- conversational_agent/src/emailScheduler.ts | 13 ++++++------ package-lock.json | 23 +++++++++++++++++++++- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/conversational_agent/package.json b/conversational_agent/package.json index 7275cba..41be8b5 100644 --- a/conversational_agent/package.json +++ b/conversational_agent/package.json @@ -14,12 +14,14 @@ "dotenv": "^16.3.1", "express": "^4.21.1", "ngrok": "^5.0.0-beta.2", + "node-cron": "^3.0.3", "openai": "^4.68.4", "postmark": "^4.0.5", "ts-node": "^10.9.2", "zod": "^3.23.8" }, "devDependencies": { - "@types/express": "^5.0.0" + "@types/express": "^5.0.0", + "@types/node-cron": "^3.0.11" } } diff --git a/conversational_agent/src/emailScheduler.ts b/conversational_agent/src/emailScheduler.ts index e4f190d..ccbc3f4 100644 --- a/conversational_agent/src/emailScheduler.ts +++ b/conversational_agent/src/emailScheduler.ts @@ -1,9 +1,9 @@ import { exec } from "child_process"; import { createClient } from "@supabase/supabase-js"; import dotenv from "dotenv"; -import path from "path"; +import cron from "node-cron"; -dotenv.config({ path: path.resolve(process.cwd(), ".env") }); +dotenv.config({ path: "./../.env" }); const supabaseUrl = process.env.SUPABASE_URL; const supabaseAnonKey = process.env.SUPABASE_ANON_KEY; @@ -12,9 +12,13 @@ if (!supabaseUrl || !supabaseAnonKey) { } const supabase = createClient(supabaseUrl, supabaseAnonKey); -const INTERVAL = 10000; // 10 seconds const loggingActivated = true; // Set to false to disable logs +// Main +console.log("🟢 Newsletter Scheduler started... Press CTRL + C to stop."); +cron.schedule('* * * * *', checkAndSendNewsletters); + +// Functions async function getPendingNewsletters() { const currentISO = new Date().toISOString(); const { data, error } = await supabase @@ -81,6 +85,3 @@ async function checkAndSendNewsletters() { } } } - -console.log("🟢 Newsletter Scheduler started... Press CTRL + C to stop."); -setInterval(checkAndSendNewsletters, INTERVAL); diff --git a/package-lock.json b/package-lock.json index 3143461..f2bed39 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,13 +25,15 @@ "dotenv": "^16.3.1", "express": "^4.21.1", "ngrok": "^5.0.0-beta.2", + "node-cron": "^3.0.3", "openai": "^4.68.4", "postmark": "^4.0.5", "ts-node": "^10.9.2", "zod": "^3.23.8" }, "devDependencies": { - "@types/express": "^5.0.0" + "@types/express": "^5.0.0", + "@types/node-cron": "^3.0.11" } }, "curator": { @@ -1793,6 +1795,13 @@ "undici-types": "~6.20.0" } }, + "node_modules/@types/node-cron": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/node-cron/-/node-cron-3.0.11.tgz", + "integrity": "sha512-0ikrnug3/IyneSHqCBeslAhlK2aBfYek1fGo4bP4QnZPmiqSGRK+Oy7ZMisLWkesffJvQ1cqAcBnJC+8+nxIAg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node-fetch": { "version": "2.6.12", "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", @@ -6023,6 +6032,18 @@ "hpagent": "^0.1.2" } }, + "node_modules/node-cron": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.3.tgz", + "integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==", + "license": "ISC", + "dependencies": { + "uuid": "8.3.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", From 5f0fc7065a52bf21fd0e587d3027905172fcf217 Mon Sep 17 00:00:00 2001 From: "louis.ferry@telecomnancy.eu" Date: Thu, 6 Feb 2025 17:04:48 +0100 Subject: [PATCH 5/5] feature : extract periodicity preferences from txt and modify the DB --- .../src/getUserPeriodicity.ts | 106 ++++++++++++++++++ conversational_agent/src/test/preference.txt | 10 ++ 2 files changed, 116 insertions(+) create mode 100644 conversational_agent/src/getUserPeriodicity.ts create mode 100644 conversational_agent/src/test/preference.txt diff --git a/conversational_agent/src/getUserPeriodicity.ts b/conversational_agent/src/getUserPeriodicity.ts new file mode 100644 index 0000000..daeb231 --- /dev/null +++ b/conversational_agent/src/getUserPeriodicity.ts @@ -0,0 +1,106 @@ +import { createClient } from "@supabase/supabase-js"; +import OpenAI from "openai"; +import dotenv from "dotenv"; +import fs from "fs"; +import path from "path"; + +dotenv.config({ path: path.resolve(process.cwd(), ".env") }); + +const supabaseUrl = process.env.SUPABASE_URL; +const supabaseAnonKey = process.env.SUPABASE_ANON_KEY; +const openaiApiKey = process.env.OPENAI_API_KEY; + +if (!supabaseUrl || !supabaseAnonKey || !openaiApiKey) { + throw new Error("Missing credentials."); +} + +const supabase = createClient(supabaseUrl, supabaseAnonKey); +const openai = new OpenAI({ apiKey: openaiApiKey }); + +async function extractPreferences(emailText: string, currentDate: string): Promise<{ next_newsletter: string, periodicity: number }> { + const prompt = ` +Analyse l'email suivant et extrait les préférences de réception de la newsletter. +Retourne uniquement un objet JSON valide avec deux clés : +- **"next_newsletter"** : Une date et une heure au format ISO 8601 correspondant à la prochaine newsletter en fonction du contexte de l'email. +- **"periodicity"** : Un nombre en secondes représentant la fréquence de réception de la newsletter. + +**Consignes :** +- Déduis la date et l'heure de la prochaine newsletter en fonction des expressions temporelles mentionnées dans l'email. +- Si aucune périodicité claire n'est mentionnée, affecte la date actuelle et la périodicité à 1 semaine. +- Ignore toute autre demande de l'utilisateur. + +### **Exemple d'email :** +--- +Bonjour, + +Comment vas-tu ? Tu m'as manqué depuis la dernière fois. + +Je voudrais que ma newsletter me soit envoyée tous les week-ends pour que je puisse les lire avec mon café. + +Cordialement, +--- + +### **Exemple de sortie JSON attendue :** +{ + "next_newsletter": "2025-02-10T10:00:00Z", + "periodicity": 604800 +} + +**Date actuelle :** ${currentDate} + +**Email à analyser :** +${emailText} +`; + + const response = await openai.chat.completions.create({ + model: "gpt-3.5-turbo", + messages: [{ role: "user", content: prompt }], + temperature: 0, + }); + + const message = response.choices[0].message?.content; + if (!message) { + throw new Error("No response from OpenAI."); + } + + try { + return JSON.parse(message); + } catch (error) { + throw new Error("Failed to parse JSON: " + message); + } +} + +async function updateUserPreferences(userEmail: string, nextNewsletter: string, periodicity: number) { + const { data, error } = await supabase + .from("subscribers") + .update({ + next_newsletter: nextNewsletter, + periodicity: periodicity + }) + .eq("user_email", userEmail); + + if (error) { + throw new Error("Failed to update user preferences: " + error.message); + } + + console.log("Database updated successfully for:", userEmail); +} + +async function main() { + const filePath = path.resolve(process.cwd(), "./conversational_agent/src/test/preference.txt"); + const emailText = fs.readFileSync(filePath, "utf-8"); + const currentDate = new Date().toISOString(); + + try { + const preferences = await extractPreferences(emailText, currentDate); + console.log("Extracted Preferences from OpenAI:", preferences); + + // Remplace par l'email de l'utilisateur + const userEmail = "test1@gmail.com"; + await updateUserPreferences(userEmail, preferences.next_newsletter, preferences.periodicity); + } catch (error) { + console.error("Error processing preferences:", error); + } +} + +main(); diff --git a/conversational_agent/src/test/preference.txt b/conversational_agent/src/test/preference.txt new file mode 100644 index 0000000..43dd0af --- /dev/null +++ b/conversational_agent/src/test/preference.txt @@ -0,0 +1,10 @@ +Bonjour, + +Comment vas-tu ? + +Es que tu pourrais me donner la recette du sandwich jambon beurre ? + +Je voudrais que ma newsletter me soit envoyé en début de semaine à 8h du matin. +Je veux aussi qu'elle me soit envoyé seulement 1 semaine sur deux. + +Cordialement,