Skip to main content

gcn-python — GCN Causal Engine

PyPI version Version Python License: Apache 2.0 Tests


Ce qu'est GCN

GCN est un moteur d'extraction et de raisonnement causal vérifiable.

Il prend du texte brut, extrait la structure causale, et répond à des questions sur cette structure — avec traçabilité jusqu'aux sources.

Texte brut (FR, EN, code — autres langues : frontend Rust + connector_lemmas à fournir)
          │
          ▼  GCN Causal Engine
          │
          ▼
CausalIR — graphe causal structuré
  ├── Nœuds typés  (7 types : etat, action, processus…)
  ├── Relations typées  (11 types : cause, enable, prevent…)
  ├── Confiance par arête
  └── Source exacte par relation
          │
          ├── Interrogeable : "what causes X ?"
          ├── Traceable    : "selon quel document ?"
          ├── Analyse contrefactuelle structurelle : "sans X, que se passe-t-il ?" (do-calculus complet dans gcn-backend Rust)
          └── Contradiction detection entre sources

Ce que GCN fait qu'un LLM ne garantit pas :

LLM GCN
Réponse causale Plausible, non vérifiable Tracée jusqu'à la source
Requêtes formelles sur le graphe ❌ ✅
Détection de contradictions entre sources ❌ ✅ (heuristique : co-occurrence prevent/filter+negated)
Raisonnement Pearl (do-calculus, gcn-backend Rust) ❌ ✅
Entraînable sur corpus spécifique Coûteux ✅ léger (NumPy)

Pour qui :

  • Analystes CTI / SOC — chaînes d'attaque depuis des rapports de menace
  • Auditeurs — obligations causales dans des référentiels réglementaires
  • Investigateurs — chaînes de responsabilité depuis des dossiers
  • Chercheurs — extraction de claims causaux depuis la littérature
  • Ingénieurs — dépendances causales dans le code source

Installation

pip install gcn-python

# Avec support PyTorch (RGCNLayerGAT) :
pip install "gcn-python[torch]"

Usage

1. Session interactive — analyser des fichiers et poser des questions

gcn-discuss --checkpoint model.npz
  GCN Causal Engine
  ─────────────────────────────────────────────────────
  Corpus : vide  —  utilisez /analyze pour charger des documents

  > /analyze incident_report.txt
    incident_report.txt : 47 relation(s) extraite(s)

  > /analyze threat_reports/
    APT28_2024.txt   : 23 relation(s)
    Mandiant_Q3.txt  : 31 relation(s)
    Total session : 101 relation(s)

  > What causes data exfiltration?
    causes_of: 'data exfiltration'
    ────────────────────────────────────────────────────
    1. [action] authentication_bypass  --[enable]-->  (conf=~0.72)
       source: APT28_2024.txt
    2. [processus] credential_theft  --[cause]-->  (conf=~0.65)
       source: Mandiant_Q3.txt
    ⚠ CONTRADICTION : firewall_rule --[prevent]--> (SecPolicy.txt)
    Note : les scores de confiance sont des softmax non calibrés — préférence relative, pas probabilité absolue.
    ────────────────────────────────────────────────────

  > /save session.json
    Graphe sauvegardé : 101 relations

  > /quit

# Reprendre la session précédente
gcn-discuss --checkpoint model.npz --graph session.json

Commandes disponibles :

Commande Description
/analyze <fichier_ou_répertoire> Analyser du texte brut, enrichir le graphe
/save <path.json> Persister le graphe de session
/load <path.json> Charger un graphe existant
/summarize Résumé du corpus courant
/help Aide
/quit Quitter

Questions causales (sans préfixe) :

What causes X?           explain: X
Effects of X?            effects: X
Chain from A to B?       chain: A B
Without X?               counterfactual: X

2. Indexer un corpus en batch

gcn-index --corpus rapports/ --checkpoint model.npz --output graph.json

Construit le graphe causal depuis un répertoire entier sans interaction. Utile pour pré-indexer avant une session gcn-discuss --graph graph.json.

3. Entraîner sur votre corpus

# Configuration de référence (v2.4.0) — val_edge_macro_f1 = 0.468
gcn-train \
  --data-dir gcn-datasets/real/train_c1_oversampled/ \
  --val-dir  gcn-datasets/real/val/ \
  --epochs 100 --lr 0.0005 \
  --weighted-loss --use-attention --bidirectional \
  --output model.npz

Voir gcn-train --help pour toutes les options (label smoothing, dropout R-GCN, etc.).

3b. Charger un checkpoint

from gcn_python import GCNEngine

# Chargement automatique — l'architecture est encodée dans le .npz
engine = GCNEngine.from_pretrained("model.npz", trusted=True)

# Ou charger manuellement dans un pipeline existant
from gcn_python.training.checkpoint import load_checkpoint
from gcn_python.pipeline.cgnp import CGNPipeline
# (pipeline déjà construit avec la même architecture)
load_checkpoint(pipeline, "model.npz")

Le checkpoint .npz contient :

  • Tous les poids (encoder_*, graph_0, graph_extra_*)
  • Les métadonnées d'architecture (_arch_json) : dimensions, bidirectionnel, n_relations
  • Le vocabulaire de features (_vocab_json) pour reconstruire FeatureVocabulary

Compatibilité : GCNEngine.from_pretrained() reconstruit l'architecture depuis _arch_json — aucun paramètre à passer manuellement. Requiert gcn-python >= 2.1.0.

3c. Inférence sur texte brut (sans annotation UD)

from gcn_python import GCNEngine

engine = GCNEngine.from_pretrained("model.npz", trusted=True, gcn_bin="gcn")
# gcn_bin="gcn" : chemin vers le binaire gcn-cli Rust (doit être dans le PATH)
# Sans gcn_bin : passe en mode heuristique GCNBridgeParser (~80-85% qualité)

cir = engine.analyze("Le gel détruit les cultures, provoquant des pénuries.")
print(cir)  # dict CausalIR JSON-serializable

Note : pour la qualité maximale, utiliser des données pré-annotées via GCNDataLoader plutôt que le bridge heuristique. Voir section Limitations connues.

4. API Python

from gcn_python import GCNEngine
from gcn_python.verbalizer.instructions import CausalGraph
from gcn_python.verbalizer.query_report import QueryVerbalizer

# Charger le moteur
engine = GCNEngine.from_pretrained("model.npz", trusted=True)

# Analyser un corpus
cirs  = engine.analyze_batch(open("corpus.txt").readlines())
graph = CausalGraph.from_cirs(cirs)
graph.save("graph.json")

# Interroger
vb = QueryVerbalizer(graph)
print(vb.causes("data_exfiltration"))
print(vb.path("phishing", "ransomware"))
print(vb.contradictions())

# Reprendre une session
graph2 = CausalGraph.load("graph.json")

5. Substituer votre propre encodeur

from gcn_python.layer2.interface import CausalEncoder

class MyEncoder(CausalEncoder):
    def forward_node(self, x): ...
    def forward_edge(self, x): ...
    def parameters(self): ...

from gcn_python.pipeline.cgnp import CGNPipeline
pipeline = CGNPipeline(encoder=MyEncoder(), graph=graph, vocabulary=vocab)

Format de données (gcn-nl)

Vos données d'entraînement : fichiers JSON avec tokens UD et CIR gold.

{
  "document": {
    "sentences": [{
      "id": "s001",
      "text": "The auth bypass enables data exfiltration.",
      "tokens": [
        {"id": 1, "form": "The",   "lemma": "the",    "pos": "DET",  "dep_rel": "det",   "dep_head": 3, "morph": {}},
        {"id": 2, "form": "auth",  "lemma": "auth",   "pos": "NOUN", "dep_rel": "compound","dep_head": 3,"morph": {}},
        {"id": 3, "form": "bypass","lemma": "bypass", "pos": "NOUN", "dep_rel": "nsubj", "dep_head": 4, "morph": {}}
      ],
      "cir": {
        "nodes": [
          {"id": "n001", "type": "entite",   "label": "auth_bypass",        "token_span": [1, 3]},
          {"id": "n002", "type": "processus","label": "data_exfiltration",   "token_span": [5, 7]}
        ],
        "edges": [{
          "source": "n001", "target": "n002", "relation": "enable",
          "attributes": {"confidence": 1.0, "explicit": true, "negated": false}
        }]
      }
    }]
  }
}

7 types de nœuds : etat · action · transition · processus · condition · entite · etat_systemique

11 relations : cause · enable · prevent · condition · concession · sequence · motivation · filter · opposition · data_dependency · control_dependency


Architecture

Texte brut (fr/en/code)
     │
     ▼  [gcn-frontend-fr / gcn-frontend-en / gcn-frontend-code — Rust]
UD tokens (pos, dep_rel, morph, lemma)
     │
     ▼  Layer 1 — FeatureVocabulary  (gcn-python)
80-dim vector par clause (sans embeddings — voir FeatureVocabulary.d_clause)
     │
     ▼  Layer 2 — MLPEncoder  (remplaçable)
node_logits (N×7) + edge_logits (E×11)
     │
     ▼  Layer 3 — RGCNLayer / RGCNLayerGAT  (remplaçable)
message passing — enrichissement des représentations
     │
     ▼  CGNPipeline.forward() → CausalIR

Précisions architecturales :

  • Traitement phrase par phrase : le ML traite une phrase à la fois. Le graphe document est la réunion des CIR individuels — aucune coréférence inter-phrase, aucun raisonnement cross-sentence.
  • Classification, pas prédiction : le moteur classifie les nœuds (7 types) et les arêtes (11 relations) depuis le texte complet déjà disponible. Il ne prédit pas d'événements futurs.
  • Features syntaxiques : le vecteur clause contient POS, dep_rel, morphologie UD. Le moteur ne voit pas le sens des mots. Ajouter --fasttext pour les cas sans connecteur explicite.
  • Teacher forcing : en entraînement, le R-GCN reçoit les vrais types de relations pour stabiliser les premières epochs. À l'inférence, le two-pass prédit les types sans or. Utiliser --scheduled-sampling pour réduire progressivement cette asymétrie.
  • Moteur vs checkpoint : le moteur est le pipeline (chassis). Le checkpoint .npz contient les poids du classifieur embarqué. Charger uniquement des checkpoints de sources fiables (contient du JSON sérialisé, risque équivalent à un pickle).

CLI

Commande Description
gcn-discuss Session interactive — /analyze, Q&A causale
gcn-index Indexation batch d'un corpus → graphe JSON
gcn-train Entraîner sur un corpus annoté
gcn-eval Évaluer un checkpoint
gcn-bootstrap Générer des données d'entraînement depuis texte brut
gcn-verbalize CIR → texte (ReferenceDecoder, templates)

Métriques d'évaluation

from gcn_python.evaluation.metrics import (
    node_macro_f1,      # F1 macro sur les 7 types de nœuds
    edge_macro_f1,      # F1 macro sur les 11 relations
    graph_exact_match,  # fraction de phrases avec graphe complet correct
    confusion_matrix,
    per_class_report,
)

Limitations connues — Classifieur ML

Limitation Impact Contournement
Features syntaxiques uniquement Le classifieur ne voit pas le sens des mots. Deux phrases avec le même patron UD reçoivent le même vecteur, même si leur causalité est différente. Ajouter --fasttext wiki.fr.bin pour injecter des embeddings sémantiques.
Causalité implicite (sans connecteur) Difficile à classifier — les features UD ne portent pas l'information implicite. Annoter des exemples explicitement sans connecteur dans le dataset.
Traitement phrase par phrase Aucune coréférence inter-phrase. Une chaîne causale sur 3 phrases ne sera pas résolue automatiquement. Réunion manuelle des CIR via CausalGraph.from_cirs().
Scores de confiance non calibrés Les probabilités softmax ne sont pas des probabilités épistémiques. conf=0.7 ≠ 70% de chance d'être correct. Ne pas utiliser les scores comme seuils de décision absolus.
Langues non FR/EN ES, DE, etc. n'ont ni frontend Rust ni connector_lemmas. Nœuds extraits, arêtes absentes. Implémenter un frontend Rust pour la langue cible + fournir connector_lemmas.

Limitations connues — GCNBridgeParser

GCNBridgeParser (dans gcn_python.frontend.bridge) permet d'utiliser le pipeline sans données pré-annotées en appelant le binaire Rust gcn via subprocess. Cette approche est heuristique et présente les limitations suivantes :

Limitation Impact Contournement
root_morph toujours {} Tense, Aspect, Mood, Polarity absents (14 dims à zéro) Utiliser GCNDataLoader avec des données annotées UD
root_pos / dep_rel heuristiques Approximation depuis le type de nœud CIR Idem
is_negative toujours False Négations non détectées Idem
Qualité globale ~80-85% Représentation appauvrie vs annotations manuelles Annoter des données via gcn-train
Requiert le binaire gcn dans le PATH GCNBridgeError si absent Installer gcn-core (Rust) et l'ajouter au PATH
Binding PyO3 direct non implémenté Appel subprocess (latence) Prévu hors scope v2.x

Utilisation recommandée :

# Qualité maximale — données annotées
from gcn_python.data.loader import GCNDataLoader
loader = GCNDataLoader("gcn-datasets/real/train/")

# Qualité réduite (~80-85%) — texte brut sans annotation
from gcn_python.frontend.bridge import GCNBridgeParser
parser = GCNBridgeParser(gcn_bin="gcn")  # gcn doit être dans le PATH
reps, connectors = parser.parse("Le gel détruit les cultures, provoquant des pénuries.")

Pour la production, privilégier les données annotées via gcn-train avec GCNDataLoader.


Stack complète

Package Rôle Langage
gcn-python Couches ML, entraînement, évaluation, gcn-discuss Python
gcn-ir Types fondamentaux CausalIR Rust
gcn-knowledge Taxonomies, lexique causal Rust
gcn-frontend-fr Parser causal français Rust
gcn-frontend-en Parser causal anglais Rust
gcn-frontend-code Parser code (Python/Rust/JS) Rust
gcn-middleend Graphe causal, cycles, validation Rust
gcn-backend Pearl niveaux 1-2-3, GCN-QL Rust
gcn-verbalizer CausalIR → texte Rust/Python

Licence

MIT — © Michel Tendeng

Release files for gcn-python 2.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gcn-python 2.5.0
File Size Uploaded
gcn_python-2.5.0.tar.gz 21.6 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for gcn-python 2.5.0
File Interpreter ABI Platform
gcn_python-2.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 21.8 MB

Release files / gcn_python-2.5.0.tar.gz

Download URL gcn_python-2.5.0.tar.gz
Size 21.6 MB
Tags Source
SHA-256 checksum
How to use checksums
0e521741d36a02c158891d9a5f9925a3913c85106228b0175b37cbe2a411afee
BLAKE2b-256 checksum
How to use checksums
f9c6a850a0a50de4584ed7804f27cabd6987c0e78733862e8b21ea82c01d664e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Release files / gcn_python-2.5.0-py3-none-any.whl

Download URL gcn_python-2.5.0-py3-none-any.whl
Size 156.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
23421e4e807f874879ff9b50003204eabaf8573314477e2ee98b10547758db44
BLAKE2b-256 checksum
How to use checksums
42a50d3172618cd3247578f83a12f0e14cfc33d7e827ad4c1a1082f848284af4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Release history Release notifications | RSS feed

This release

2.5.0 This release

2 release files

2.1.1

1 release file

2.1.0

1 release file

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page