/** * Test manuel du filtre de pertinence IA * Vérifie que les articles hors périmètre médico-social sont bien rejetés */ import { createRequire } from "module"; const require = createRequire(import.meta.url); // Simuler les articles de test const testArticles = [ { titre: "Nouvelle réglementation sur la pêche en eau douce", resume: "Le ministère de l'Agriculture publie un arrêté modifiant les quotas de pêche dans les rivières françaises pour la saison 2025.", expected: false, label: "Pêche (hors périmètre)" }, { titre: "Résultats du championnat de football de Ligue 1", resume: "Le Paris Saint-Germain remporte le titre de champion de France pour la dixième fois consécutive.", expected: false, label: "Sport (hors périmètre)" }, { titre: "Hausse des taux d'intérêt de la BCE", resume: "La Banque centrale européenne relève ses taux directeurs de 0,25 point pour lutter contre l'inflation.", expected: false, label: "Économie (hors périmètre)" }, { titre: "Nouveau décret sur les EHPAD : réforme du financement", resume: "Un décret publié au Journal Officiel modifie les modalités de tarification des établissements d'hébergement pour personnes âgées dépendantes.", expected: true, label: "EHPAD (pertinent)" }, { titre: "MDPH : simplification des démarches pour les personnes handicapées", resume: "La CNSA annonce une simplification des formulaires de demande de PCH et AAH pour faciliter l'accès aux droits.", expected: true, label: "MDPH/Handicap (pertinent)" }, { titre: "Aide alimentaire : distribution dans les épiceries sociales", resume: "Les associations d'aide alimentaire font face à une hausse de 30% des demandes d'aide dans les épiceries sociales et les CHRS.", expected: true, label: "Précarité/CHRS (pertinent)" }, ]; // Appel direct à l'API LLM via fetch const API_URL = process.env.BUILT_IN_FORGE_API_URL; const API_KEY = process.env.BUILT_IN_FORGE_API_KEY; if (!API_URL || !API_KEY) { console.error("Variables d'environnement manquantes : BUILT_IN_FORGE_API_URL, BUILT_IN_FORGE_API_KEY"); process.exit(1); } const PROMPT_PERTINENCE = `Tu es un expert des établissements et services sociaux et médico-sociaux (ESMS) en France, spécialisé dans les secteurs : handicap, personnes âgées, protection de l'enfance, précarité/insertion, sanitaire. Ta mission est de déterminer si un article de presse ou une publication institutionnelle est DIRECTEMENT pertinent pour une association gestionnaire d'ESMS. Un article est pertinent UNIQUEMENT s'il traite explicitement de l'un des sujets suivants : - Réglementation, lois, décrets, circulaires concernant les ESMS, le secteur social ou médico-social - Financement, tarification, dotations des structures sociales et médico-sociales (CPOM, SERAFIN-PH, etc.) - Politiques publiques ciblant les personnes handicapées, âgées, enfants en danger, personnes précaires - Fonctionnement, organisation, ressources humaines des ESMS - Droits et accompagnement des usagers des ESMS - Institutions directement liées : ARS, MDPH, ASE, conseils départementaux (action sociale), CAF, CNSA - Santé publique avec impact direct sur les ESMS ou leurs usagers Un article est NON PERTINENT si : - Il traite de politique générale, économie, international, environnement, sport, culture, agriculture, pêche, tourisme, immobilier, technologie grand public, etc. - Il mentionne des personnes vulnérables de façon anecdotique sans lien avec les ESMS - Il concerne la santé uniquement sous l'angle hospitalier ou médical sans lien avec le médico-social - Le lien avec le secteur médico-social est vague, indirect ou nécessite plusieurs degrés de déduction Sois STRICT : en cas de doute, réponds pertinent: false. Réponds UNIQUEMENT avec un objet JSON valide, sans texte autour, sans balises markdown : {"pertinent": true/false, "raison": "explication courte en une phrase"}`; async function checkRelevance(titre, resume) { const response = await fetch(`${API_URL}/v1/chat/completions`, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": `Bearer ${API_KEY}`, }, body: JSON.stringify({ messages: [ { role: "system", content: PROMPT_PERTINENCE }, { role: "user", content: `Titre : ${titre}\n\nRésumé : ${resume}` }, ], response_format: { type: "json_schema", json_schema: { name: "pertinence_result", strict: true, schema: { type: "object", properties: { pertinent: { type: "boolean" }, raison: { type: "string" }, }, required: ["pertinent", "raison"], additionalProperties: false, }, }, }, }), }); const data = await response.json(); const content = data?.choices?.[0]?.message?.content; return JSON.parse(content); } console.log("=== Test du filtre de pertinence IA ===\n"); let passed = 0; let failed = 0; for (const article of testArticles) { try { const result = await checkRelevance(article.titre, article.resume); const ok = result.pertinent === article.expected; const icon = ok ? "✅" : "❌"; console.log(`${icon} [${article.label}]`); console.log(` Attendu: ${article.expected} | Obtenu: ${result.pertinent}`); console.log(` Raison: ${result.raison}\n`); if (ok) passed++; else failed++; } catch (e) { console.log(`⚠️ [${article.label}] Erreur: ${e.message}\n`); failed++; } } console.log(`\n=== Résultat: ${passed}/${testArticles.length} tests passés ===`); if (failed > 0) { console.log(`❌ ${failed} test(s) échoué(s)`); process.exit(1); } else { console.log("✅ Tous les tests passés !"); }