expAge
refactor(inference): retire le schéma assoc_bridge
d9a76ab
"""Modèles Pydantic du moteur d'inférence JDM (Phase 11)."""
from __future__ import annotations
from enum import Enum
from typing import List
from pydantic import BaseModel, ConfigDict, Field
class FiredSchema(str, Enum):
"""Schéma d'inférence ayant produit le résultat.
L'énumération est complète dès le départ (sérialisation stable) même si
certains schémas ne sont activés qu'à l'effort 2.
"""
NONE = "none" # aucun schéma — silence
TAUTOLOGY = "tautology" # subject == object, relation réflexive
CONTRADICTION = "contradiction" # subject == object, relation antonymique
INVERSE = "inverse" # (object, R⁻¹, subject)
IMPLICATION = "implication" # R impliquée par une R' plus spécifique
SYNONYM_EQUIV = "synonym_equiv" # via un synonyme de l'object
ISA_INCOMPATIBLE = "isa_incompatible" # réfutation via r_isa-incompatible
CLASS_ELIM = "class_elimination" # réfutation : la classe de A nie R B
DEDUCTION_ISA = "deduction_isa" # A r_isa/r_syn G, G R B
TRANSITIVITY = "transitivity" # A R X, X R B (relation transitive)
TARGET_GENERIC = "target_generic" # A R G, G générique de l'object
DOUBLE_ISA = "double_isa" # A r_isa X, B r_isa Y, X R Y
COMPOSITION = "composition" # A R2 C, C R3 B ⟹ A R B
PREFIX = "prefix" # préfixe lexical (saucisse de Toulouse)
HYPONYM_PROP = "hyponym_propagation" # A R H, H r_isa B ⟹ A R B
ANTONYM_CONTRAST = "antonym_contrast" # réfutation : A R X, X r_anto B
COHYPONYM = "cohyponym" # réfutation : A et B cohyponymes
GEO_PROPAGATION = "geo_propagation" # A r_lieu L, L r_holo B ⟹ A r_lieu B
class ProofStep(BaseModel):
"""Un triplet JDM élémentaire dans la chaîne de preuve d'une inférence."""
source: str
relation: str
target: str
w: float
note: str = ""
class InferenceResult(BaseModel):
"""Résultat d'une inférence sur le triplet (subject, relation, object).
`signed_weight` porte le verdict :
* > 0 → le triplet est jugé VRAI par inférence
* < 0 → le triplet est jugé FAUX / réfuté
* = 0 → silence (aucun schéma n'a conclu)
"""
model_config = ConfigDict(extra="ignore")
subject: str
relation: str
object: str
signed_weight: float = 0.0
fired_schema: FiredSchema = FiredSchema.NONE
proof: List[ProofStep] = Field(default_factory=list)
confidence: float = Field(0.0, ge=0.0, le=1.0)
lookups_used: int = 0
explanation: str = ""
@property
def is_true(self) -> bool:
return self.signed_weight > 0
@property
def is_false(self) -> bool:
return self.signed_weight < 0
@property
def is_silent(self) -> bool:
return self.signed_weight == 0