Amélioration

This commit is contained in:
ocroguennec committed 2026-09-27 11:54:18 +02:00
1 parent e0145c8727
commit 1e3994f17f
3 files changed
+98 -12

No files matched your search

+44 -3
View File
@@ -332,14 +332,55 @@ router.post('/ai-lookup', async (req, res, next) => {
throw new HttpError(500, `Impossible de déchiffrer la clé API : ${e.message}`);
}
// Journalisation dans ai_usage_log (même table que le chat utilisateur, routes/ai.js) —
// demandé par Olivier le 27/09/26 : ces appels consomment de vrais tokens (recherche web
// incluse) et doivent remonter dans Admin > Assistant IA > Usage, pas seulement dans le
// journal d'audit. investisseur_id = null (route admin, pas de contexte investisseur) —
// best-effort comme dans routes/ai.js : un échec de log ne doit jamais faire échouer la
// réponse à l'utilisateur.
function logUsage({ usage, toolCalled, erreur }) {
try {
db.prepare(`
INSERT INTO ai_usage_log
(user_id, investisseur_id, provider_id, modele, tokens_entree, tokens_sortie, outils_appeles, erreur)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`).run(
req.user.id,
null,
provider.id,
provider.modele,
usage?.input_tokens ?? null,
usage?.output_tokens ?? null,
toolCalled ? JSON.stringify(['web_search']) : null,
erreur || null,
);
} catch (logErr) {
console.error("[institutions-referentiel/ai-lookup] échec du log d'usage (ignoré) :", logErr.message);
}
}
// Liste fermée des catégories existantes — transmise au modèle pour qu'il choisisse
// EXACTEMENT parmi des libellés déjà connus du référentiel (voir lookupInstitution()),
// remappables en id de façon fiable plutôt que du texte libre à recréer/dédupliquer.
const categories = db.prepare('SELECT id, nom FROM categories_institutions ORDER BY nom').all();
try {
const result = await lookupInstitution({ apiKey, model: provider.modele, nom, url: url || undefined });
const result = await lookupInstitution({ apiKey, model: provider.modele, nom, url: url || undefined, categories });
logUsage({ usage: result.usage, toolCalled: result.toolCalled, erreur: null });
audit(req, {
action: 'institution_ai_lookup', category: 'ai', actorId: req.user.id,
details: { nom, ok: true, dureeMs: result.durationMs, sourcesCount: result.sourcesCount },
details: { nom, ok: true, dureeMs: result.durationMs, sourcesCount: result.sourcesCount, categoriesCount: result.categoryIds.length },
});
res.json({
ok: true,
description: result.description,
domiciliation: result.domiciliation,
url: result.url,
categories_ids: result.categoryIds,
dureeMs: result.durationMs,
});
res.json({ ok: true, description: result.description, domiciliation: result.domiciliation, dureeMs: result.durationMs });
} catch (e) {
logUsage({ usage: e.usage, toolCalled: e.toolCalled, erreur: e.message });
audit(req, {
action: 'institution_ai_lookup', category: 'ai', actorId: req.user.id,
details: { nom, ok: false, error: e.message },