Files
nav-carte/scripts/test-citations.mjs
T
Jules NenyandClaude Opus 5.5 85cd31d201 feat(chatbot-pensees): garde-fou serveur des citations (guillemets retirés si introuvables)
La route demande include_references + include_chunk_content à LightRAG et vérifie
chaque segment >= 6 mots entre « » / "…" / “…” dans les chunks réellement
récupérés (normalisation accents, casse, apostrophes, ponctuation, élisions [...]).
Un segment introuvable perd ses guillemets (texte conservé) ; champ optionnel
citations: { gardees, retirees }. Fonction pure dans server/utils/citations.ts,
réutilisée par scripts/verif-citations.mjs (qui gagne --max-total-tokens) ;
scripts/test-citations.mjs couvre les cas limites.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015vcVGz8i4WpZm2dixKUiSD
2026-10-09 03:59:32 +02:00

36 lines
2.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
// Test du garde-fou des citations (server/utils/citations.ts). Usage : node scripts/test-citations.mjs
import assert from 'node:assert/strict'
import { verifierCitations, contenusChunks } from '../server/utils/citations.ts'
const ctx = ["La technique est devenue autonome, et forme un monde dévorant.\r\nIl n’y a plus de liberté de choix. Plus on parle d’une valeur, plus c'est le signe de son absence."]
const t = (rep, c = ctx) => verifierCitations(rep, c)
// retrouvée (apostrophes, casse, ponctuation de bord, retours chariot) : gardée
let r = t('Ellul écrit : « Il n\'y a plus de liberté de choix ! » donc.')
assert.equal(r.gardees, 1); assert.equal(r.retirees, 0); assert.ok(r.texte.includes('«'))
// introuvable : guillemets retirés, texte conservé
r = t('Il dit : « La technique est une machine à fabriquer du pouvoir social inévitable ». Fin.')
assert.equal(r.retirees, 1); assert.equal(r.texte, 'Il dit : La technique est une machine à fabriquer du pouvoir social inévitable. Fin.')
// guillemets droits et anglais
r = t('"Une phrase inventée qui ne figure nulle part dans le texte" et “Une autre phrase inventée qui ne figure nulle part ici”')
assert.equal(r.retirees, 2); assert.ok(!/["“”]/.test(r.texte))
// court (< 6 mots) : intact, non compté
r = t('Le « rift métabolique » et la « ville intelligente ».')
assert.equal(r.gardees + r.retirees, 0); assert.ok(r.texte.includes('« rift métabolique »'))
// élision [...] : chaque morceau doit exister
r = t('« Plus on parle d\'une valeur [...] le signe de son absence »')
assert.equal(r.gardees, 1)
r = t('« Plus on parle d\'une valeur [...] le signe de sa présence éclatante »')
assert.equal(r.retirees, 1)
// pas de correspondance en milieu de mot
r = t('« ormation autonome, et forme un monde dévorant »')
assert.equal(r.retirees, 1)
// aucun contexte : rien de long n'est gardé
r = t('« Il n\'y a plus de liberté de choix »', [])
assert.equal(r.retirees, 1)
// contenusChunks : tableau de chaînes ou chaîne
assert.deepEqual(contenusChunks([{ content: ['a', 'b'] }, { content: 'c' }, {}, null]), ['a', 'b', 'c'])
assert.deepEqual(contenusChunks(undefined), [])
console.log('citations : tous les cas passent')