Skip to main content

Surround any LLM with verifiable capability networks (exact math, knowledge, web) and say each result back in its own voice.

Project description

CybNodes

On n'alourdit pas le cerveau par force brute. On l'entoure de circuits structurés et vérifiables.

Une petite librairie Python qui entoure ton LLM de réseaux de capacités (calcul exact, savoir, recherche web), et qui redit chaque résultat dans la voix de ton modèle.

PyPI

cybnodes.pages.dev / GitHub / PyPI / MIT


C'est quoi, concrètement ?

CybNodes est une librairie Python (pip install cybnodes, puis import cybnodes). Pas une app, pas un service, pas un script à lancer : une brique que tu branches autour de ton propre modèle.

L'idée : un LLM est génial pour parler, mauvais pour garantir. Il invente un calcul, hallucine une date, n'a pas l'actu. Plutôt que de grossir le modèle, CybNodes met devant lui des réseaux, chacun sait répondre de façon exacte et vérifiable à un type de question. Un routeur choisit le bon réseau ; un tisseur redit le résultat brut dans la voix de ton modèle pour garder son âme.

Conséquence : un petit modèle (qui tient sur ta machine) peut alimenter un système qui "pèse" bien plus lourd.

Pour le dire autrement : CybNodes n'est pas un mini-LangChain. C'est une petite couche de fiabilité pour les petits modèles locaux. Les petits modèles sont attachants ; la fiabilité vient de savoir quand le modèle doit arrêter de deviner et passer la main à un outil précis.


Pourquoi

Sans CybNodes Avec CybNodes
"47 × 38 ?" → le LLM tente, parfois faux calcul exact (AST sûr), toujours juste
"c'est quoi un X ?" → le LLM hallucine réponse depuis ton graphe de connaissances
"quoi de neuf sur Y ?" → données périmées recherche web avec la source citée
corriger un fait → ré-entraîner le modèle éditer un fichier, zéro entraînement

Le savoir et les capacités vivent hors du modèle. Tu les corriges, tu les étends, sans toucher aux poids.


Installation

pip install cybnodes
# ou, depuis les sources :
git clone https://github.com/Alex-Lou/cybnodes.git
cd cybnodes && pip install -e .

Python ≥ 3.9. Aucune dépendance obligatoire (stdlib uniquement, le réseau web utilise urllib).


Démarrage (60 secondes)

from cybnodes import CybNodes, Persona
from cybnodes.networks import CalculNetwork, SavoirNetwork

# 1. Tu apportes TON modèle : n'importe quel callable (ollama, API, local…)
def mon_llm(question, context):
    return appelle_mon_modele(question, context)   # -> str

# 2. Tu l'entoures de réseaux
cyb = CybNodes(
    conductor=mon_llm,
    networks=[
        CalculNetwork(),                              # calcul exact
        SavoirNetwork(graph_path="mon_graphe.json"),  # GraphRAG sur tes triplets
    ],
    persona=Persona(name="Aria", templates={
        "calcul": ["Voilà : {value} ✦", "{value}, et c'est exact !"],
        "savoir": ["{value}"],
    }),
)

# 3. Tu demandes
cyb.ask("combien font 47 x 38 ?")   # → "Voilà : 47 x 38 = 1786 ✦"   (exact, jamais faux)
cyb.ask("c'est quoi un chat ?")     # → depuis ton graphe, dans la voix d'Aria
cyb.ask("écris-moi un haïku")       # → aucun réseau ne prend la main → ton modèle répond

C'est tout. Le routeur essaie les réseaux ; si aucun ne répond, ton modèle reprend la main, comme avant.


L'architecture en 5 couches

        question
           │
   ┌───────▼────────┐
   │   ROUTEUR      │  essaie les réseaux dans l'ordre (règles d'abord, fiable)
   └───────┬────────┘
     hit?  │  no hit
   ┌───────▼──┐   └──────────────┐
   │ RÉSEAU   │                  │
   │ (calcul, │            ┌─────▼──────┐
   │  savoir, │            │ CONDUCTEUR │  ton LLM (sa voix)
   │  web…)   │            └─────┬──────┘
   └───────┬──┘                  │
   ┌───────▼────────┐            │
   │   TISSEUR      │ redit dans │
   │  + PERSONA     │ la voix    │
   └───────┬────────┘            │
           └──────────┬──────────┘
                   réponse
Couche Classe Rôle
Conducteur conductor= (ton callable) ton modèle, sa voix/personnalité
Réseaux Network une capacité chacun, indépendants
Routeur Router choisit le réseau ; un réseau qui plante n'écroule rien
Tisseur Weaver + Persona redit le résultat brut dans la voix
Mémoire Memory capte des faits sûrs sur l'utilisateur (backend pluggable)

Les réseaux livrés

Réseau Ce qu'il fait Vérifiable par
CalculNetwork arithmétique exacte (+ - × ÷ ^ %, mots "fois / plus / puissance"…), AST sûr, zéro eval le calcul lui-même
SavoirNetwork GraphRAG : répond depuis un graphe de triplets sujet-relation-objet le nœud du graphe
WebNetwork recherche d'actu via l'API Brave Search (clé BRAVE_API_KEY), cite la source l'URL renvoyée

Chaque réseau ne se déclenche que quand il est sûr de lui ; sinon il rend la main (renvoie None).


Écrire ton propre réseau

from cybnodes import Network, Result

class MeteoNetwork(Network):
    name = "meteo"

    def match(self, question):
        if "météo" not in question.lower():
            return None                       # pas mon rayon → je rends la main
        data = appel_api_meteo(...)           # un résultat VÉRIFIABLE (source réelle)
        return Result(kind="meteo", text=f"Il fait {data}°", source="api-météo")

cyb.add_network(MeteoNetwork())               # branché. C'est tout.

Fiabilité : évidence, manifeste, evals

La source dans la réponse. Chaque Result porte une source (le calcul exact, le node du graphe, l'URL). Par défaut elle reste disponible mais discrète ; avec Weaver(cite=True) (ou un gabarit qui place {source}), elle remonte dans la réponse finale. C'est ce qui rend un petit modèle fiable et pas seulement charmant.

from cybnodes import CybNodes, Weaver, Persona
cyb = CybNodes(conductor=mon_llm, networks=[...], weaver=Weaver(Persona(name="Aria"), cite=True))
cyb.ask("c'est quoi un chat ?")   # -> "... (source : graphe de connaissances : chat)"

Le manifeste. Chaque réseau peut déclarer ce qu'il sait faire : utile pour la doc, le debug, et un routeur futur. Purement déclaratif (ça ne change pas match()).

from cybnodes import Manifest

class MeteoNetwork(Network):
    name = "meteo"
    manifest = Manifest(answers="la meteo d'une ville", deterministic=False, needs_source=True)
    ...

cyb.skills()   # -> [{'name': 'calcul', 'deterministic': True, 'needs_source': False, ...}, ...]

Évaluer le routeur. Le routeur EST le produit : ce qui compte, c'est qu'il choisisse la bonne capacité, et que la réponse reste dans ce que la capacité a prouvé. route_only(question) renvoie la décision brute (sans modèle ni tissage) ; tests/test_router.py mesure ça sur des cas francs (calcul simple, calcul caché dans une phrase, info récente, fait connu, fait inconnu, conversation). Comme le routeur est à base de règles, son point faible est le rappel : un match() qui rate un cas le laisse filer au modèle (ainsi le mot "aujourd'hui" peut encore sur-déclencher le web). D'où les evals.


Quand l'utiliser (et quand non)

Utilise CybNodes quand tu veux qu'un LLM réponde de façon exacte / vérifiable / à jour sur certains types de questions, tout en gardant sa voix, sans ré-entraîner.

Ne l'utilise pas pour du pur génératif libre (écriture, brainstorming) : là, ton modèle seul suffit, CybNodes lui laisse simplement la main.


Les 4 questions (les invariants)

  • Où vit l'état ? Personnalité → conducteur ; savoir → graphe (hors modèle) ; faits utilisateur → Mémoire.
  • Où vit le feedback ? Chaque réseau renvoie un résultat vérifiable (calcul exact, nœud du graphe, source web).
  • Qu'est-ce qui casse si on retire X ? Réseaux indépendants → on en retire un sans casser les autres.
  • Timing / ordre ? Routeur synchrone : 1 question → routeur → réseau(x) → tisseur → réponse.

État du projet

Ce qui marche aujourd'hui, testé (python tests/test_cybnodes.py et python tests/test_router.py) :

  • ✅ Cœur (routeur, tisseur/persona, mémoire, conducteur model-agnostic)
  • CalculNetwork, SavoirNetwork (GraphRAG), WebNetwork (Brave)
  • Évidence : la source remonte dans la réponse (Weaver(cite=True) / {source})
  • Manifeste : chaque réseau déclare sa capacité (Manifest, cyb.skills())
  • Router evals : route_only() + un fichier de tests par catégorie

Pistes ouvertes (design posé, pas encore livré, pas de promesse vide) :

  • Routeur d'intention par classifieur (plutôt qu'ordre fixe), arbitré par Result.confidence et le manifeste
  • Précision du routeur : resserrer les intentions trop larges (ex. "aujourd'hui")
  • Réseaux code / langues / traduction
  • Backends de recherche additionnels

Licence

MIT, fais-en ce que tu veux.

Conçu par CybWu. Né autour d'une petite IA, pensé pour entourer n'importe quel modèle.

🐺

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cybnodes-0.2.1.tar.gz (23.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cybnodes-0.2.1-py3-none-any.whl (19.2 kB view details)

Uploaded Python 3

File details

Details for the file cybnodes-0.2.1.tar.gz.

File metadata

  • Download URL: cybnodes-0.2.1.tar.gz
  • Upload date:
  • Size: 23.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for cybnodes-0.2.1.tar.gz
Algorithm Hash digest
SHA256 0308d0c3dfb68a89a355dc5f2bba8a5119aa7cdd5f91bdf898debfbf9c4dc9da
MD5 538cd43d8350ef97ec445568f513b040
BLAKE2b-256 47a30e001fa460c9dbc7088851c9fe5fb5c2e579d4d7bd852a10891f62d82d0b

See more details on using hashes here.

File details

Details for the file cybnodes-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: cybnodes-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 19.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for cybnodes-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1f8bf4e4212511fa271a6f18587eaae3f219778920e7ba34439283a59819d5e1
MD5 d8e832d6d6dc9bd9fe44e30c260de9a1
BLAKE2b-256 977e2be86c9700849df42a946534e94d00ccf5028093773a3fd8e2cb77f93abb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page