2 points par GN⁺ 2025-06-29 | 1 commentaires | Partager sur WhatsApp
  • SymbolicAI est un framework neuro-symbolique qui combine la programmation Python classique avec la nature différentiable et programmable des LLM, avec pour objectif de s’utiliser naturellement dans Python
  • Ses concepts clés sont les primitives basées sur l’objet Symbol et les contrats (contracts) qui valident et corrigent les résultats des LLM ; le comportement par défaut démarre en mode syntaxique pour des raisons de sécurité et de vitesse
  • En mode syntaxique, Symbol se comporte comme une valeur Python ordinaire ; en mode sémantique, il manipule le contexte et le sens, avec un passage possible via semantic=True, .sem, .map() et d’autres appels de fonctions sémantiques
  • Le système de contrats applique le principe Design by Contract aux workflows LLM, en couvrant dans un flux à base de décorateur la validation des entrées, les changements d’état, la génération par LLM, la validation des sorties et les réponses de repli en cas d’échec
  • L’installation commence par pip install symbolicai ; l’usage réel nécessite une configuration avec symconfig et symai.config.json, et le moteur neuro-symbolique est indispensable pour utiliser le paquet symai

Le modèle visé par SymbolicAI

  • SymbolicAI est un framework neuro-symbolique (neuro-symbolic) qui traite à la fois du code Python ordinaire et du traitement sémantique basé sur les LLM
  • Sa conception modulaire permet de l’étendre et de le personnaliser selon les besoins
  • Il prend en charge l’intégration d’outils comme l’écriture de son propre moteur, l’hébergement d’un moteur local, la recherche web ou la génération d’images
  • Le nom du projet vise à créditer les travaux fondateurs d’Allen Newell et Herbert Simon

La primitive Symbol

  • Au cœur de SymbolicAI se trouve l’objet Symbol, qui permet d’utiliser de petites opérations composables comme une syntaxe Python native
  • Symbol possède deux modes de fonctionnement
    • Syntactic : se comporte comme une valeur Python ordinaire, par exemple une chaîne, une liste ou un entier transmis
    • Semantic : est connecté au moteur neuro-symbolique et traite le sens et le contexte
  • Le mode par défaut est le mode syntaxique
    • Les opérateurs Python comme ==, ~ et & sont surchargés dans symai
    • Appeler le moteur immédiatement à chaque comparaison ou décalage de bits pourrait ralentir l’exécution et provoquer des effets de bord inattendus
    • La sécurité et la vitesse sont préservées en n’activant le comportement sémantique qu’aux endroits nécessaires

Comment passer en mode sémantique

  • En spécifiant semantic=True à la création, l’objet se comporte dès le départ comme un Symbol sémantique
    • Dans l’exemple, Symbol("Cats are adorable", semantic=True) traite "feline" in S comme True
  • Il est possible de passer au comportement sémantique à la demande avec la projection .sem, puis de revenir au comportement syntaxique avec .syn
    • Pour la même valeur "Cats are adorable", "feline" in S.sem vaut True dans S.sem, tandis qu’il vaut False dans le S par défaut
  • Les opérations en notation pointée comme .map() ou les autres appels de fonctions sémantiques basculent automatiquement le Symbol en mode sémantique
    • Dans l’exemple, appliquer convert all fruits to vegetables à une liste de fruits transforme uniquement les fruits en légumes et conserve cat et dog
  • Les projections .sem et .syn ajoutent différentes couches de comportement au même objet de base, ce qui permet d’enchaîner des opérations syntaxiques et sémantiques sur un même Symbol

Exemples d’opérations fournies

  • SymbolicAI prend en charge diverses primitives, documentées dans primitives
  • En mode syntaxique, == vérifie une correspondance littérale ; en mode sémantique, il traite une équivalence floue ou conceptuelle comme entre "Hi" et "Hello"
  • En mode syntaxique, + correspond à l’addition de nombres ou à la concaténation de chaînes et de listes ; en mode sémantique, il effectue une combinaison signifiante, un mélange ou une fusion de concepts
  • En mode syntaxique, & correspond à un AND binaire ou logique ; en mode sémantique, il traite la conjonction logique, le raisonnement et la fusion de contextes
  • Les fonctionnalités propres au mode sémantique incluent notamment .choice(cases, default), .foreach(condition, apply), .cluster(**clustering_kwargs?), .similarity(other, metric?, normalize?)
    • .cluster() regroupe les données sémantiquement et utilise DBSCAN de sklearn
    • .similarity() calcule la similarité entre embeddings

Comment les contrats gèrent les sorties des LLM

  • Partant du constat qu’un LLM peut halluciner mais que le code, lui, ne le peut pas, SymbolicAI applique le principe Design by Contract au monde des LLM
  • Les contrats ne s’appuient pas uniquement sur des tests a posteriori : ils lient le modèle de données et les contraintes de validation à un décorateur pour traiter la correction dès la phase de conception
  • Le décorateur de contrat du code d’exemple utilise les options suivantes
    • pre_remedy=True : tente de corriger automatiquement les entrées invalides
    • post_remedy=True : tente de corriger automatiquement les sorties LLM invalides
    • accumulate_errors=True : transmet l’historique des erreurs à chaque nouvelle tentative
    • verbose=True : affiche la progression dans le terminal
    • remedy_retry_params : utilise tries=3, delay=0.4, max_delay=4.0, jitter=0.15, backoff=1.8, graceful=False
  • Le flux de haut niveau d’une classe Expression à laquelle un contrat est appliqué est le suivant
    • prompt : description statique qui définit ce que le LLM doit faire, obligatoire
    • pre : vérifie les entrées, optionnel
    • act : modifie l’état, optionnel
    • LLM : le moteur SymbolicAI génère la réponse attendue
    • post : vérifie que la réponse respecte les règles sémantiques, optionnel
    • forward : obligatoire ; en cas de succès du contrat, renvoie un objet LLM dont le type a été validé, et en cas d’échec, renvoie une réponse de repli graceful
  • La documentation sur les contrats se trouve dans contract validation system sur DeepWiki et features/contracts

Installation et fonctionnalités optionnelles

  • L’installation de base se fait avec pip
pip install symbolicai
  • Il est aussi possible de cloner le dépôt et de configurer un environnement virtuel Python avec uv >= 0.9.17
git clone git@github.com:ExtensityAI/symbolicai.git
cd symbolicai
uv sync --python x.xx
source ./.venv/bin/activate
  • SymbolicAI utilise plusieurs moteurs pour traiter le texte, la voix et les images, et inclut aussi l’accès à un moteur de recherche pour les informations web
  • Les dépendances optionnelles peuvent être installées par extra selon les fonctionnalités
    • bitsandbytes, hf, lean, llama_cpp, ocr, qdrant, scrape, search, serpapi, services, solver, whisper, wolframalpha
  • Toutes les dépendances optionnelles peuvent être installées en une seule fois
pip install "symbolicai[all]"
  • uv sync --frozen installe les dépendances figées dans le fichier lock fourni
  • Certaines dépendances optionnelles peuvent nécessiter des étapes d’installation supplémentaires, et certaines ne sont actuellement prises en charge qu’à titre expérimental, avec un comportement potentiellement différent de celui attendu

Gestion de la configuration et moteur obligatoire

  • SymbolicAI utilise un système de gestion de configuration basé sur des priorités
  • La configuration est chargée depuis trois emplacements, par ordre de priorité
    • Mode debug dans le répertoire de travail courant : priorité la plus élevée, s’applique uniquement à symai.config.json
    • Configuration propre à l’environnement Python : située dans {python_env}/.symai/, adaptée aux configurations par projet
    • Configuration globale du répertoire personnel : située dans ~/.symai/, sert de fallback par défaut
  • Trois fichiers de configuration sont gérés
    • symai.config.json : configuration principale de SymbolicAI
    • symsh.config.json : configuration du shell
    • symserver.config.json : configuration du serveur
  • symconfig affiche l’emplacement de configuration, le chemin de configuration actif et la configuration actuelle avec les informations sensibles masquées ; il lance aussi la mise en cache initiale du paquet et l’initialisation des fichiers de configuration
  • Pour utiliser le paquet symai, un moteur neuro-symbolique est obligatoire
  • Définir les propriétés du moteur dans symai.config.json au chemin du projet remplace les variables d’environnement
    • L’exemple de configuration inclut notamment claude-sonnet-4-6 comme valeur de NEUROSYMBOLIC_ENGINE_MODEL, text-embedding-3-small comme modèle d’embedding, tts-1 comme modèle TTS, mistral-ocr-latest comme modèle OCR et qdrant comme moteur d’indexation
  • Les avertissements utilisateur sont activés par défaut et peuvent être désactivés avec la variable d’environnement SYMAI_WARNINGS=0

Tests, documentation et licence

  • Voici des exemples d’exécution des tests
pytest tests
pytest -m mandatory
pytest --cov=symbolicai tests
  • La configuration doit être correctement définie avant les tests
  • Pour aller plus loin, on peut consulter la page DeepWiki de SymbolicAI, le papier et les tutoriels vidéo
  • Les informations de citation renvoient au preprint arXiv 2024 intitulé Symbolicai: A framework for logic-based approaches combining generative models and solvers
  • Le projet est sous BSD-3-Clause License

1 commentaires

 
GN⁺ 2025-06-29
Avis sur Hacker News
  • Ce sont ces fonctionnalités qui ressemblent à du vaudou qui sont les plus intéressantes
    Par exemple, avec un map sémantique, si l’on applique « remplace tous les fruits par des légumes » à ['apple', 'banana', 'cherry', 'cat', 'dog'], on obtient quelque chose comme ['carrot', 'broccoli', 'spinach', 'cat', 'dog'], et equals() donne des résultats différents selon le contexte, par exemple context='greeting context' ou context='politeness level'
    Les opérateurs bit à bit sont aussi utilisés comme des combinaisons logiques sémantiques, de sorte que horn_rule & observation mène à une inférence ; interpret() semble donc puissant
    Je serais curieux de savoir ce qui a motivé sa création, quels sont ses usages réels, et quel est jusqu’ici le cas d’utilisation préféré de son auteur

    • Lotus pourrait aussi être intéressant : https://github.com/lotus-data/lotus
      L’idée est de prendre les principaux opérateurs relationnels et d’en faire des versions sémantiques via une extension de bibliothèques Python de dataframes ; chaque appel devient ensuite un point de « modèle » pour des tâches plus complexes, comme des approches fondées sur l’apprentissage
      Côté SQL cloud, Snowflake semble aussi aller dans cette direction, et chez louie.ai nous avons utilisé une approche similaire avec des notebooks/tableaux de bord/API IA (MCP, etc.) : on parle à des données comme Splunk, Databricks ou des bases de graphes, et le système détermine selon le contexte les opérateurs symboliques + sémantiques appropriés ; en pratique, c’était assez utile
      Le principal cas d’usage à 80 % consiste à créer un dataframe enrichi par un map sémantique, du type « récupère toutes les alertes dans l’index Splunk xyz et ajoute une colonne qui signale les éléments suspects ainsi qu’une colonne qui en explique la raison », puis à obtenir une explication en langage naturel via un reduce sémantique, par exemple « résume ce que tu as trouvé »
    • Je me demande pourquoi transformer apple en légume donne carrot
    • La réponse risque d’être très longue
      Peu de choses ont fondamentalement changé depuis le lancement du projet fin 2022 ; les modèles se sont simplement améliorés, mais une bonne partie des opérations primitives existait déjà à l’époque de GPT-3
      Ce qui est devenu plus important récemment, c’est la contribution du DbC : le fait de pouvoir chaîner des contrats et de bien propager les garde-fous est particulier, car cela a résolu quasiment tous les problèmes que j’avais lancés autour des agents
      Perplexity est devenu moins utile avec la recherche web d’OpenAI, et la recherche web d’OpenAI n’était pas non plus suffisante comparée à une version personnalisée, donc j’ai créé mon propre agent de recherche approfondie : https://x.com/futurisold/status/1931751644233945216
      Au travail aussi, nous avons chaîné 3 contrats pour créer de la génération de documents de bout en bout, avec un exemple de sortie ici : https://drive.google.com/file/d/1Va7ALq_N-fTYeumKhH4jSxsTrWD...
      L’entrée demandait de comparer et d’analyser les prompts système des grands fournisseurs d’IA afin d’identifier les formats comme XML/Markdown/JSON, les instructions de flatterie et de manipulation, les contraintes d’utilisation des outils, les garde-fous éthiques et les différences de conception d’alignement, puis de synthétiser le tout dans un rapport technique ; les instructions générées ont été étendues en questions précises comparant la structure des prompts système, les cadres linguistiques et les contraintes opérationnelles d’OpenAI, Google, Anthropic, xAI, etc.
      Les contrats ont été présentés dans un billet de mars et ont beaucoup évolué depuis, mais les bases et la motivation restent les mêmes : https://futurisold.github.io/2025-03-01-dbc/
  • Lier à la fois l’article et le notebook d’exemples aiderait à comprendre
    https://github.com/ExtensityAI/symbolicai/blob/main/examples...
    https://arxiv.org/pdf/2402.00854

  • Super
    Pouvoir utiliser des opérateurs comme == ou + non pas comme syntaxe, mais comme opérateurs sémantiques, me semble être un terreau pour de nouvelles idées, un peu comme quand les word embeddings sont apparus et qu’une sorte d’algèbre conceptuelle approximative du type « King - Man + Woman = Queen » a émergé
    Cela dit, l’intégration neuronal + symbolique semble ici, comme dans la plupart des systèmes, assez superficielle et compartimentée ; dans la classification, elle ressemble plutôt au Type 3 / Neuro;Symbolic : https://harshakokel.com/posts/neurosymbolic-systems
    La vraie magie viendra sans doute d’une intégration plus fondamentale, et dans notre entreprise (https://onton.com) nous réfléchissons aussi à des systèmes post-LLM dotés d’une représentation unifiée qui ne soit ni purement symbolique ni une matrice dense en virgule flottante, capables d’apprendre progressivement à partir de petites quantités de données bruitées tout en évitant le catastrophic forgetting, avec une fiabilité solide pour les mathématiques et les opérations symboliques, et sans hallucinations
    Relier des systèmes existants au pistolet à colle est utile, mais je pense qu’une architecture unifiée changera tout

  • Il y a un bug dans la partie sur le contrat d’exactitude
    Après valid_opts = ['A', 'B', 'C'], on trouve if v not in valid_sizes:, mais valid_sizes n’est pas défini

    • C’était un reste de refactorisation, c’est corrigé maintenant
  • « Symbolic AI » est déjà un terme bien défini, donc c’est un peu dommage : https://en.m.wikipedia.org/wiki/Symbolic_artificial_intellig...

    • Je comprends ce point
      Le nom pourrait être changé, et l’article contient une note de bas de page sur ce choix
      L’intention était de créditer les travaux fondateurs de Newell et Simon, qui ont inspiré ce projet
  • Je m’interroge sur la structure des coûts
    J’aimerais savoir si l’on paie le coût d’inférence du LLM à chaque fois qu’on exécute une ligne impliquant du calcul en langage naturel, et si, avec une API externe, on est réellement facturé à chaque fois
    Par exemple, je me demande ce qui se passe si l’on appelle une fonction « symbolic » dans une boucle

    • Oui
      Par exemple, si l’on utilise OpenAI, toutes les opérations fondées sur le sens deviennent des appels à l’API OpenAI
      Si l’on héberge un LLM local avec llama.cpp, il n’y a pas de facturation à l’inférence en dehors du coût d’hébergement du modèle
    • Il me semble qu’il faudra une forme de cache, d’une manière ou d’une autre
  • Comme le code est souvent généré par des LLM ces temps-ci, je me demande en quoi une structure syntaxique spécifique comme Symbol, qui contient du contexte et peut être manipulée avec des opérateurs Python, aide davantage qu’un code Python ordinaire créé par un humain indiquant les conditions de vérification et d’équilibrage
    Par exemple, au lieu d’utiliser une grammaire qui transforme des fruits en légumes, on pourrait aussi demander au LLM, via un prompt, de créer un programme qui prend une liste de fruits et appelle en interne un LLM pour renvoyer les légumes correspondants
    J’aimerais comprendre la différence

    • Ce serait peut-être pour limiter les hallucinations
      Si l’on fait créer un système formel par le LLM, il est beaucoup plus facile à vérifier qu’un programme généraliste
  • Je me demande si vous avez aussi envisagé une IA neuro-symbolique capable d’évoluer
    https://deepwiki.com/dubprime/mythral/3.2-genome-system
    Ou encore la piste d’une IA qui ressentirait des émotions ?
    https://deepwiki.com/search/how-do-emotives-work_193cb616-54...
    Je me demande aussi si vous avez lu Society of Mind de Marvin Minsky

    • La réponse courte serait : oui, à tout cela
      J’ai aussi mené des expériences allant de la théorie de l’esprit jusqu’aux émotions, mais j’ai l’impression qu’à l’heure actuelle les modèles n’ont pas encore vraiment atteint ce niveau ; le rendement par rapport à l’effort diminuait, donc c’est en pause
      Je pourrais facilement relancer le sujet, mais Minsky n’est pas mon préféré ; dans cette génération, je suis davantage attiré par Newell/Simon
    • Reste que l’important est de savoir si c’est explicable, ou si c’est une boîte noire quasi magique
  • J’ai un peu bricolé avec de la régression symbolique où un LLM examine des documents pour créer des opérateurs primitifs, c’est-à-dire des opérateurs à mettre dans PySR sur GitHub (github.com/MilesCranmer/PySR)
    Je ne suis pas allé très loin parce qu’il était difficile de relier l’ensemble, mais avec ce genre d’outil, je pourrais peut-être réessayer

    • C’est clairement possible
      Je recommande d’utiliser des contrats
      J’ai déjà utilisé une approche similaire avec des contrats qui « recollaient » de manière itérative un graphe d’ontologie cassé
      Comme modèle de données pour inspirer le système, j’avais des structures comme Merge, Bridge, Prune, Operation, définissant chacune les index de clusters à fusionner, les relations classe parente-enfant et la liste des classes à élaguer, puis un validateur imposait les conditions d’opérations binaires/unaires
      De façon similaire, on peut créer un modèle pour les opérateurs, faire en sorte que le contrat résolve un opérateur à la fois, puis appliquer cet opérateur