sourcefinder/docs/SYSTEME_SCORING.md
Alexis Trouvé a7bd6115b7
Some checks failed
SourceFinder CI/CD Pipeline / Code Quality & Linting (push) Has been cancelled
SourceFinder CI/CD Pipeline / Unit Tests (push) Has been cancelled
SourceFinder CI/CD Pipeline / Security Tests (push) Has been cancelled
SourceFinder CI/CD Pipeline / Integration Tests (push) Has been cancelled
SourceFinder CI/CD Pipeline / Performance Tests (push) Has been cancelled
SourceFinder CI/CD Pipeline / Code Coverage Report (push) Has been cancelled
SourceFinder CI/CD Pipeline / Build & Deployment Validation (16.x) (push) Has been cancelled
SourceFinder CI/CD Pipeline / Build & Deployment Validation (18.x) (push) Has been cancelled
SourceFinder CI/CD Pipeline / Build & Deployment Validation (20.x) (push) Has been cancelled
SourceFinder CI/CD Pipeline / Regression Tests (push) Has been cancelled
SourceFinder CI/CD Pipeline / Security Audit (push) Has been cancelled
SourceFinder CI/CD Pipeline / Notify Results (push) Has been cancelled
feat: Implémentation complète du système SourceFinder avec tests
- Architecture modulaire avec injection de dépendances
- Système de scoring intelligent multi-facteurs (spécificité, fraîcheur, qualité, réutilisation)
- Moteur anti-injection 4 couches (preprocessing, patterns, sémantique, pénalités)
- API REST complète avec validation et rate limiting
- Repository JSON avec index mémoire et backup automatique
- Provider LLM modulaire pour génération de contenu
- Suite de tests complète (Jest) :
  * Tests unitaires pour sécurité et scoring
  * Tests d'intégration API end-to-end
  * Tests de sécurité avec simulation d'attaques
  * Tests de performance et charge
- Pipeline CI/CD avec GitHub Actions
- Logging structuré et monitoring
- Configuration ESLint et environnement de test

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-15 23:06:10 +08:00

818 lines
23 KiB
Markdown
Raw Permalink 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.

# Système de Scoring Intelligent SourceFinder
## Vue d'Ensemble
Le système de scoring de SourceFinder évalue intelligemment la pertinence des articles d'actualités canines selon quatre critères pondérés, conformément aux spécifications du CDC (Cahier des Charges). Chaque article reçoit un score final de 0 à 100 points selon la formule :
```
Score Final = (Spécificité × 0.4) + (Fraîcheur × 0.3) + (Qualité × 0.2) + (Réutilisabilité × 0.1)
```
Cette approche multi-critères garantit une sélection équilibrée entre pertinence thématique, actualité, fiabilité des sources et optimisation de la réutilisation du contenu.
## Architecture Modulaire
### Organisation des Composants
```
BasicScoringEngine (Orchestrateur principal)
├── SpecificityCalculator (40% du score)
├── FreshnessCalculator (30% du score)
├── QualityCalculator (20% du score)
└── ReuseCalculator (10% du score)
```
Chaque calculateur est indépendant et interchangeable, respectant le principe d'architecture modulaire du système.
### Interface IScoringEngine
Tous les moteurs de scoring implémentent cette interface standardisée :
```javascript
interface IScoringEngine {
async scoreArticle(newsItem, context): Promise<ScoringResult>
async batchScore(newsItems, context): Promise<Array<ScoredArticle>>
explainScore(scoredArticle): Object
}
```
## 1. Calculateur de Spécificité (40% du Score)
### Principe
La spécificité évalue la pertinence du contenu par rapport à la race de chien recherchée. C'est le critère le plus important car il détermine directement l'utilité de l'article pour le client final.
### Hiérarchie de Scoring
| Niveau | Score | Critère | Exemple |
|--------|--------|---------|---------|
| **Mention Exacte** | 100 pts | Nom exact de la race trouvé | "Berger Allemand", "Golden Retriever" |
| **Groupe/Famille** | 70 pts | Famille de race mentionnée | "Chiens de berger", "Retrievers" |
| **Taille Similaire** | 50 pts | Catégorie de taille | "Grands chiens", "Petite race" |
| **Usage Similaire** | 40 pts | Usage/fonction similaire | "Chien de garde", "Chien de famille" |
| **Générique Chiens** | 25 pts | Mention générale canine | "Chiens", "Compagnons" |
| **Animaux Domestiques** | 10 pts | Contexte animal général | "Animaux de compagnie" |
### Base de Données des Races
Le système intègre une base de données des races FCI avec :
```javascript
// Exemple : Berger Allemand (352-1)
{
name: 'berger allemand',
variants: ['german shepherd', 'berger d\'allemagne'],
group: 'chiens de berger',
families: ['bergers', 'chiens de troupeau'],
size: 'grands chiens',
usages: ['chien de garde', 'chien de travail', 'chien policier']
}
```
### Algorithme de Détection
1. **Normalisation du contenu** : Conversion en minuscules, suppression de la ponctuation
2. **Recherche par regex** : Détection des mots-clés avec délimiteurs (`\b`)
3. **Scoring hiérarchique** : Attribution du score le plus élevé trouvé
4. **Traçabilité** : Enregistrement des termes correspondants pour audit
### Cas Spéciaux
- **Races composées** : "Berger Allemand à poil long" → Détection du nom principal
- **Synonymes multiples** : "Labrador" → "Labrador Retriever"
- **Variantes linguistiques** : "German Shepherd" → "Berger Allemand"
## 2. Calculateur de Fraîcheur (30% du Score)
### Principe
La fraîcheur évalue la récence de l'article. Plus un article est récent, plus il est susceptible d'être pertinent pour la génération de contenu actualisé.
### Seuils d'Évaluation
| Catégorie | Âge | Score | Usage Recommandé |
|-----------|-----|--------|------------------|
| **Excellent** | < 7 jours | 100 pts | Actualités urgentes |
| **Bon** | 7-30 jours | 70 pts | Contenu récent |
| **Correct** | 30-90 jours | 40 pts | Informations générales |
| **Ancien** | 90-180 jours | 20 pts | Contenu de référence |
| **Obsolète** | > 180 jours | 5 pts | Archives uniquement |
### Gestion des Dates
#### Formats Supportés
- **ISO 8601** : `2024-01-15T10:30:00Z`
- **Français** : `15/01/2024`, `15-01-2024`, `15.01.2024`
- **Timestamps** : Unix timestamp (secondes ou millisecondes)
- **Objets Date** : Instances JavaScript Date
#### Validation et Sécurité
```javascript
// Plage de dates valides : 1990 à (année actuelle + 5)
isValidDate(date) {
const year = date.getFullYear();
const currentYear = new Date().getFullYear();
return year >= 1990 && year <= currentYear + 5;
}
```
### Ajustements Contextuels
#### Bonus Contenu "Evergreen" (+20 pts max)
Articles à valeur permanente identifiés par mots-clés :
- Guides : "guide", "comment", "conseils"
- Éducation : "dressage", "formation", "méthode"
- Santé générale : "prévention", "bien-être"
#### Malus Actualités Périmées (-30% du score)
Articles d'actualité urgente devenus obsolètes :
- Mots-clés : "actualité", "urgent", "breaking", "annonce"
- Appliqué si score de base < 40 points
#### Bonus Recherche d'Archives (+15 pts max)
Si `context.allowOldContent = true`, améliore la valorisation du contenu ancien.
### Calcul de l'Âge
```javascript
calculateAgeInDays(publishDate, searchDate) {
const diffMs = searchDate.getTime() - publishDate.getTime();
return Math.floor(diffMs / (1000 * 60 * 60 * 24));
}
```
#### Gestion des Cas d'Erreur
- **Date future** : Score = 0 (erreur de publication)
- **Date manquante** : Score = 0 (non fiable)
- **Date invalide** : Score = 0 (format incorrect)
## 3. Calculateur de Qualité (20% du Score)
### Principe
La qualité évalue la fiabilité et l'autorité de la source de publication. Ce critère garantit la crédibilité du contenu généré.
### Classification des Sources
#### Sources Premium (90-100 pts)
**Organismes Officiels et Institutions**
- `centrale-canine.fr` (Société Centrale Canine) : 100 pts
- `fci.be` (Fédération Cynologique Internationale) : 100 pts
- `veterinaire.fr` (Ordre des Vétérinaires) : 95 pts
- Sites universitaires vétérinaires : 95 pts
**Critères d'identification :**
- Extension `.edu` ou `.fr` officielle
- Mentions légales complètes
- Références scientifiques
- Autorité reconnue dans le domaine
#### Sources Spécialisées (70-85 pts)
**Médias Spécialisés Canins**
- `30millionsdamis.fr` : 85 pts
- `wamiz.com` : 80 pts
- `woopets.fr` : 80 pts
- Clubs de race officiels : 85 pts
**Caractéristiques :**
- Spécialisation exclusive dans le domaine canin
- Équipe éditoriale identifiée
- Historique de publication
- Partenariats avec organismes officiels
#### Sources Standard (50-70 pts)
**Médias Généralistes de Qualité**
- `lefigaro.fr/animaux` : 65 pts
- `ouest-france.fr/animaux` : 60 pts
- Magazines lifestyle avec section animaux : 55 pts
**Évaluation :**
- Réputation générale du média
- Qualité éditoriale
- Processus de vérification
- Expertise occasionnelle sur les animaux
#### Sources Fallback (20-50 pts)
**Contenu Généraliste ou Non-Vérifié**
- Blogs personnels : 30 pts
- Forums : 25 pts
- Réseaux sociaux : 20 pts
- Sources inconnues : 25 pts
### Indicateurs de Qualité
#### Indicateurs Positifs (+5 à +15 pts)
```javascript
qualityIndicators = {
hasAuthor: +10, // Auteur identifié
hasPublishDate: +10, // Date de publication
hasReferences: +15, // Références citées
hasVetReview: +15, // Validation vétérinaire
hasCitations: +10, // Citations scientifiques
isRecent: +5, // Publication récente
hasImages: +5, // Illustrations présentes
hasStructure: +5 // Contenu bien structuré
}
```
#### Indicateurs Négatifs (-5 à -20 pts)
```javascript
qualityPenalties = {
hasAds: -5, // Publicités excessives
poorWriting: -10, // Qualité rédactionnelle
noContact: -10, // Pas de contact
noLegal: -15, // Pas de mentions légales
anonymousContent: -10, // Contenu anonyme
clickbait: -15, // Titre aguicheur
outdatedInfo: -20 // Informations obsolètes
}
```
### Détection Automatique
#### Analyse du Contenu
```javascript
// Détection de qualité par analyse textuelle
analyzeContentQuality(content) {
const wordCount = content.split(/\s+/).length;
const sentenceCount = content.split(/[.!?]+/).length;
const avgSentenceLength = wordCount / sentenceCount;
return {
isSubstantial: wordCount > 200,
isWellStructured: avgSentenceLength > 8 && avgSentenceLength < 25,
hasVariety: this.calculateLexicalDiversity(content) > 0.6
};
}
```
#### Analyse des Métadonnées
- Présence d'auteur et date
- Structure HTML appropriée
- Balises meta descriptions
- Schema.org markup
### Pondération Contextuelle
Le score de qualité peut être ajusté selon le contexte :
```javascript
// Bonus pour recherche spécialisée
if (context.requireHighQuality) {
// Réduction des scores sources non-premium
if (baseScore < 70) baseScore *= 0.8;
}
// Malus cumul sources faibles
if (context.lowQualityCount > 3) {
baseScore *= 0.9;
}
```
## 4. Calculateur de Réutilisabilité (10% du Score)
### Principe
La réutilisabilité optimise l'usage du stock d'articles en évitant la sur-utilisation et en respectant les périodes de rotation. Ce critère assure la diversité du contenu généré.
### Scoring par Usage
| Catégorie | Utilisations | Score | Statut |
|-----------|--------------|--------|---------|
| **Neuf** | 0 | 100 pts | Priorité maximale |
| **Peu utilisé** | 1-2 | 80 pts | Recommandé |
| **Modérément utilisé** | 3-5 | 60 pts | Acceptable |
| **Très utilisé** | 6-10 | 40 pts | Limité |
| **Saturé** | > 10 | 20 pts | À éviter |
### Périodes de Rotation
Le système respecte des périodes de rotation selon le type de source :
```javascript
rotationPeriods = {
premium: 90, // 3 mois - Sources premium (coût élevé, qualité maximale)
standard: 60, // 2 mois - Sources standard (équilibre qualité/coût)
fallback: 30 // 1 mois - Sources fallback (renouvellement rapide)
}
```
### Ajustements Temporels
#### Bonus Période de Rotation Respectée (+10 à +20 pts)
```javascript
// Calcul du bonus temporel
if (daysSinceLastUse >= rotationPeriod) {
const bonus = Math.min(20, daysSinceLastUse - rotationPeriod + 10);
return bonus;
}
```
#### Malus Utilisation Récente (-10 à -20 pts)
Articles utilisés dans les 7 derniers jours subissent une pénalité pour favoriser la diversité.
```javascript
// Malus utilisation récente
if (daysSinceLastUse < 7) {
const penalty = -Math.max(10, 20 - daysSinceLastUse * 2);
return penalty;
}
```
### Ajustements Contextuels
#### Bonus Client Différent (+10 pts)
Si l'article est utilisé par un client différent du précédent :
```javascript
if (context.clientId && article.lastClientId &&
context.clientId !== article.lastClientId) {
adjustment += 10;
}
```
#### Bonus Contexte Différent (+15 pts max)
Évaluation de la similarité avec le contexte précédent :
```javascript
calculateContextSimilarity(context1, context2) {
const ctx1Words = context1.toLowerCase().split(/\s+/);
const ctx2Words = context2.toLowerCase().split(/\s+/);
const intersection = ctx1Words.filter(word => ctx2Words.includes(word));
const union = [...new Set([...ctx1Words, ...ctx2Words])];
return intersection.length / union.length;
}
```
#### Bonus Contenu Evergreen (+5 pts)
Articles à valeur permanente (guides, conseils) bénéficient d'un bonus de réutilisabilité.
#### Malus Sur-utilisation Race (-10 pts)
Pénalité si l'article a été trop utilisé pour la même race (≥ 5 utilisations).
### Statuts de Rotation
```javascript
getRotationStatus(lastUsed, sourceType, now) {
const daysSinceLastUse = calculateDaysDifference(lastUsed, now);
const rotationPeriod = this.rotationPeriods[sourceType];
if (daysSinceLastUse >= rotationPeriod) return 'available';
if (daysSinceLastUse >= rotationPeriod * 0.7) return 'soon_available';
return 'in_rotation';
}
```
### Statistiques de Collection
Le calculateur fournit des statistiques globales sur l'état de réutilisation du stock :
```javascript
getCollectionReuseStats(articles) {
return {
totalArticles: articles.length,
byUsageCategory: { fresh: X, low: Y, ... },
byRotationStatus: { available: A, in_rotation: B, ... },
averageUsage: averageUsageCount,
reuseEfficiency: percentageAvailable,
recommendations: ['action1', 'action2', ...]
};
}
```
## Orchestration par BasicScoringEngine
### Calcul Principal
Le `BasicScoringEngine` coordonne les quatre calculateurs :
```javascript
async scoreArticle(newsItem, context) {
// Exécution en parallèle pour optimiser les performances
const [specificityResult, freshnessResult, qualityResult, reuseResult] =
await Promise.all([
this.specificityCalculator.calculateSpecificity(newsItem, context),
this.freshnessCalculator.calculateFreshness(newsItem, context),
this.qualityCalculator.calculateQuality(newsItem, context),
this.reuseCalculator.calculateReuse(newsItem, context)
]);
// Application de la formule CDC
const finalScore = Math.round(
(specificityResult.score * 0.4) + // 40%
(freshnessResult.score * 0.3) + // 30%
(qualityResult.score * 0.2) + // 20%
(reuseResult.score * 0.1) // 10%
);
return {
finalScore,
specificityScore: specificityResult.score,
freshnessScore: freshnessResult.score,
qualityScore: qualityResult.score,
reuseScore: reuseResult.score,
scoringDetails: { /* détails complets */ },
scoreCategory: this.categorizeScore(finalScore),
usageRecommendation: this.generateUsageRecommendation(...)
};
}
```
### Catégorisation des Scores
| Catégorie | Plage | Recommandation | Usage |
|-----------|-------|----------------|--------|
| **Excellent** | 80-100 | `priority_use` | Utilisation prioritaire |
| **Bon** | 65-79 | `recommended` | Recommandé |
| **Correct** | 50-64 | `conditional_use` | Usage conditionnel |
| **Faible** | 30-49 | `limited_use` | Usage limité |
| **Rejeté** | 0-29 | `avoid` | À éviter |
### Scoring par Lot
Pour optimiser les performances, le système support le scoring en lot avec limitation de concurrence :
```javascript
async batchScore(newsItems, context) {
const batchSize = 10; // Limitation pour éviter la surcharge
const results = [];
for (let i = 0; i < newsItems.length; i += batchSize) {
const batch = newsItems.slice(i, i + batchSize);
const batchResults = await Promise.all(
batch.map(item => this.scoreArticle(item, context))
);
results.push(...batchResults);
}
// Tri par score décroissant
return results.sort((a, b) => (b.finalScore || 0) - (a.finalScore || 0));
}
```
### Explication des Scores
Le moteur peut expliquer en détail comment un score a été calculé :
```javascript
explainScore(scoredArticle) {
return {
scoreBreakdown: {
finalScore: scoredArticle.finalScore,
components: {
specificity: {
score: scoredArticle.specificityScore,
weight: 0.4,
contribution: Math.round(scoredArticle.specificityScore * 0.4),
reason: scoredArticle.scoringDetails.specificity.reason,
details: scoredArticle.scoringDetails.specificity.details
},
// ... autres composants
}
},
strengths: this.identifyStrengths(scoredArticle),
weaknesses: this.identifyWeaknesses(scoredArticle),
improvementSuggestions: this.generateImprovementSuggestions(scoredArticle),
usageGuideline: {
category: scoredArticle.scoreCategory,
recommendation: scoredArticle.usageRecommendation,
confidence: this.calculateConfidence(scoredArticle)
}
};
}
```
## Performance et Optimisation
### Exécution Parallèle
Les quatre calculateurs s'exécutent en parallèle pour minimiser la latence :
```javascript
// ✅ Optimal : 4 calculs en parallèle
const results = await Promise.all([calc1, calc2, calc3, calc4]);
// ❌ Suboptimal : 4 calculs séquentiels
const result1 = await calc1;
const result2 = await calc2;
const result3 = await calc3;
const result4 = await calc4;
```
### Cache et Mémorisation
- **Base de données des races** : Chargée en mémoire au démarrage
- **Sources quality** : Index en mémoire pour accès O(1)
- **Calculs récents** : Cache des scores pour éviter les recalculs
### Métriques de Performance
Le système collecte des métriques de performance :
```javascript
{
totalScored: 1250,
averageScore: 67.3,
scoreDistribution: {
excellent: 156,
good: 234,
fair: 345,
poor: 289,
reject: 226
},
calculationTime: {
total: 45678, // ms
average: 36.5 // ms par article
}
}
```
## Cas d'Usage et Exemples
### Exemple 1 : Article Premium Spécialisé
```json
{
"title": "Nouvelle étude génétique sur la dysplasie chez les Bergers Allemands",
"content": "Une équipe de chercheurs de l'École Vétérinaire de Maisons-Alfort...",
"url": "https://centrale-canine.fr/etudes/dysplasie-berger-allemand-2024",
"publishDate": "2024-01-10T08:00:00Z",
"sourceType": "premium",
"sourceDomain": "centrale-canine.fr"
}
// Contexte
{
"raceCode": "352-1", // Berger Allemand
"clientId": "client-123",
"searchDate": "2024-01-12T10:00:00Z"
}
// Résultat de scoring
{
"finalScore": 91,
"specificityScore": 100, // Mention exacte "Bergers Allemands"
"freshnessScore": 95, // 2 jours, très récent
"qualityScore": 100, // centrale-canine.fr = source premium
"reuseScore": 80, // Article neuf, jamais utilisé
"scoreCategory": "excellent",
"usageRecommendation": "priority_use"
}
```
### Exemple 2 : Article Standard Généraliste
```json
{
"title": "5 conseils pour l'alimentation des grands chiens",
"content": "Les chiens de grande taille ont des besoins nutritionnels spécifiques...",
"url": "https://wamiz.com/conseils-alimentation-grands-chiens",
"publishDate": "2023-12-15T14:30:00Z",
"sourceType": "standard",
"sourceDomain": "wamiz.com",
"usageCount": 3,
"lastUsed": "2024-01-05T10:00:00Z"
}
// Contexte
{
"raceCode": "352-1", // Berger Allemand (grand chien)
"clientId": "client-456",
"searchDate": "2024-01-12T10:00:00Z"
}
// Résultat de scoring
{
"finalScore": 64,
"specificityScore": 50, // "grands chiens" = taille similaire
"freshnessScore": 40, // 28 jours, dans la catégorie "fair"
"qualityScore": 80, // wamiz.com = source spécialisée
"reuseScore": 60, // 3 utilisations = modérément utilisé
"scoreCategory": "fair",
"usageRecommendation": "conditional_use"
}
```
### Exemple 3 : Article Fallback Sur-utilisé
```json
{
"title": "Les animaux de compagnie et la famille",
"content": "Avoir un animal de compagnie apporte de nombreux bénéfices...",
"url": "https://blog-perso.com/animaux-famille",
"publishDate": "2023-10-20T16:00:00Z",
"sourceType": "fallback",
"sourceDomain": "blog-perso.com",
"usageCount": 12,
"lastUsed": "2024-01-10T08:00:00Z"
}
// Résultat de scoring
{
"finalScore": 23,
"specificityScore": 10, // "animaux de compagnie" = très généraliste
"freshnessScore": 20, // 84 jours = ancien
"qualityScore": 30, // Blog personnel = faible qualité
"reuseScore": 20, // > 10 utilisations = saturé
"scoreCategory": "reject",
"usageRecommendation": "avoid"
}
```
## Extensibilité et Personnalisation
### Ajout de Nouveaux Calculateurs
L'architecture modulaire permet d'ajouter facilement de nouveaux critères :
```javascript
// Exemple : Calculateur de sentiment
class SentimentCalculator {
async calculateSentiment(article, context) {
// Logique d'analyse de sentiment
return {
score: sentimentScore,
reason: 'positive_sentiment',
details: 'Contenu majoritairement positif'
};
}
}
// Intégration dans BasicScoringEngine
constructor() {
this.sentimentCalculator = new SentimentCalculator();
this.weights = {
specificity: 0.35, // Réduction pour faire place au sentiment
freshness: 0.25,
quality: 0.2,
reuse: 0.1,
sentiment: 0.1 // Nouveau critère
};
}
```
### Personnalisation des Poids
Les poids peuvent être ajustés selon le contexte d'usage :
```javascript
// Profil "News" : Privilégier fraîcheur et spécificité
const newsWeights = {
specificity: 0.5,
freshness: 0.4,
quality: 0.1,
reuse: 0.0
};
// Profil "Evergreen" : Équilibrer qualité et réutilisabilité
const evergreenWeights = {
specificity: 0.3,
freshness: 0.1,
quality: 0.4,
reuse: 0.2
};
```
### Configuration Dynamique
Le système support la configuration dynamique via le contexte :
```javascript
const context = {
raceCode: "352-1",
scoringProfile: "premium", // news, evergreen, premium, balanced
qualityThreshold: 70,
freshnessBonus: 1.2,
customWeights: { /* poids spécifiques */ }
};
```
## Monitoring et Observabilité
### Logs Structurés
Chaque opération de scoring génère des logs détaillés :
```javascript
logger.info('Article scored successfully', {
articleId: 'art-123',
finalScore: 85,
breakdown: {
specificity: 90,
freshness: 95,
quality: 80,
reuse: 70
},
calculationTime: 45,
raceCode: '352-1',
category: 'excellent'
});
```
### Métriques Business
- **Distribution des scores** : Répartition par catégorie
- **Performance moyenne** : Score moyen par race/source
- **Efficacité de réutilisation** : Taux d'articles disponibles
- **Qualité des sources** : Évolution de la qualité du stock
### Alertes Automatiques
Le système peut déclencher des alertes :
```javascript
// Alerte qualité dégradée
if (averageQualityScore < threshold) {
alerting.trigger('quality_degradation', {
currentScore: averageQualityScore,
threshold: threshold,
recommendation: 'Renouveler sources premium'
});
}
```
## Évolutions Futures
### Machine Learning
Integration future d'un modèle ML pour affiner les scores :
```javascript
class MLScoringEngine extends BasicScoringEngine {
constructor() {
super();
this.mlModel = new ContentQualityModel();
}
async scoreArticle(newsItem, context) {
const baseScore = await super.scoreArticle(newsItem, context);
const mlAdjustment = await this.mlModel.predict(newsItem, context);
return {
...baseScore,
finalScore: this.adjustWithML(baseScore.finalScore, mlAdjustment),
mlConfidence: mlAdjustment.confidence
};
}
}
```
### Scoring Adaptatif
Ajustement automatique des poids selon les performances :
```javascript
class AdaptiveScoringEngine extends BasicScoringEngine {
updateWeights(feedbackData) {
// Apprentissage des poids optimaux selon feedback utilisateur
this.weights = this.optimizeWeights(feedbackData);
}
}
```
### Intégration Multi-langues
Support de scoring multi-langues avec détection automatique :
```javascript
const languageSpecificCalculators = {
'fr': new FrenchSpecificityCalculator(),
'en': new EnglishSpecificityCalculator(),
'de': new GermanSpecificityCalculator()
};
```
## Conclusion
Le système de scoring SourceFinder offre une évaluation sophistiquée et équilibrée du contenu canin, combinant pertinence thématique, actualité, qualité des sources et optimisation de la réutilisation.
Son architecture modulaire garantit :
- **Flexibilité** : Ajout facile de nouveaux critères
- **Performance** : Calculs parallèles et optimisations
- **Transparence** : Explication détaillée des scores
- **Fiabilité** : Gestion d'erreurs et logging complet
- **Évolutivité** : Support de personnalisations avancées
Cette approche multi-critères assure une sélection de contenu optimale pour tous les cas d'usage, de la génération d'actualités urgentes aux guides permanents de référence.