File size: 2,235 Bytes
e13590b
 
 
 
 
 
 
 
 
 
a26b99c
12d6af7
 
e13590b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5c1d1c7
 
 
 
e13590b
 
5c1d1c7
 
 
 
 
 
 
e13590b
 
 
5c1d1c7
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
"""Modèles pour l'enrichissement."""
from __future__ import annotations

from enum import Enum
from typing import List, Optional

from pydantic import BaseModel, Field


class GapType(str, Enum):
    MISSING         = "missing"          # aucune triplet pour (term, relation)
    LOW_COVERAGE    = "low_coverage"     # < N triplets positifs
    NEGATIVE_FILLED = "negative_filled"  # que des triplets négatifs (JDM a dit non)


class Gap(BaseModel):
    """Un trou identifié dans le graphe JDM."""
    term: str = Field(..., description="Le terme analysé")
    relation: str = Field(..., description="Relation JDM ciblée (r_xxx)")
    gap_type: GapType
    severity: float = Field(0.0, ge=0.0, le=1.0,
                            description="Force du signal (0=faible, 1=très forte)")
    detail: str = ""
    # Pour les asymétries : référence aux triplets en place côté inverse.
    related_triples: List[dict] = Field(default_factory=list)


class Candidate(BaseModel):
    """Un triplet candidat proposé pour combler un gap."""
    term: str
    relation: str
    target: str = Field(..., description="Terme cible proposé")
    confidence: float = Field(0.0, ge=0.0, le=1.0)
    rationale: str = ""
    source: str = Field("unknown", description="LLM | inference | external")
    annotation: str = Field(
        "", description="Annotation sémantique suggérée (constitutif, "
        "contrastif, ...) — vide si aucune")
    # Validation STRUCTURELLE (déterministe, contenance) :
    validation_status: Optional[str] = None  # "ok" | "duplicate" | "unknown_term" | "inconsistent"
    validation_note: str = ""
    # Consolidation SÉMANTIQUE par inférence (Phase 11) :
    #   "consolidated"     — l'inférence confirme le triplet (→ soumission)
    #   "not_consolidated" — silence de l'inférence (pas forcément faux)
    #   "rejected"         — l'inférence réfute le triplet
    consolidation_status: Optional[str] = None
    consolidation_schema: Optional[str] = None
    consolidation_explanation: str = ""

    def is_valid(self) -> bool:
        return self.validation_status in (None, "ok")

    def is_consolidated(self) -> bool:
        return self.consolidation_status == "consolidated"