Modèle / jeu de données
lotus-data/lotus avatar
lotus-data/lotus

LOTUS : des opérateurs sémantiques pour traiter un corpus avec des LLM

Optimized Agentic and LLM Bulk Processing Over Your Data

1 678 étoiles154 forksPythonApache-2.0

En bref

De quoi s’agit-il ?
LOTUS, publié sous licence Apache-2.0 par des chercheurs de Stanford et de Berkeley, transforme un DataFrame ou une liste de documents en pipeline d'opérateurs LLM (map, filter, reduce, join) que l'optimiseur se charge de planifier. Le projet vise les traitements par lots, pas les démos interactives.
À qui s’adresse-t-il ?
LOTUS convient aux équipes qui doivent passer un volume important de documents ou de lignes de DataFrame dans un LLM et qui acceptent d'écrire leurs traitements comme des opérateurs sémantiques. Il faut passer son chemin si le besoin se limite à quelques appels interactifs, ou si l'on ne veut pas dépendre d'une clé API externe.
Puis-je l’utiliser commercialement ?
Oui. Apache-2.0 est une licence permissive : vous pouvez utiliser, modifier et vendre un logiciel qui en dépend, à condition de conserver les mentions de droit d’auteur et de licence.
Est-il encore maintenu ?
Oui. Les derniers commits datent d’il y a 74 jours.
En quel langage est-il écrit ?
Principalement Python, d’après les statistiques de langage de GitHub.

Ces réponses reposent sur les données GitHub du projet (dernière synchronisation le 15 septembre 2026) et sur notre analyse. Elles ne constituent pas un avis juridique.

ANALYSE OPEN SOURCE APPROFONDIE

Le problème : appliquer une instruction en langage naturel à chaque ligne d'un jeu de données

Le cas d'usage de départ est simple à énoncer et pénible à coder. On dispose d'un DataFrame, d'un dossier de fichiers ou d'une liste de documents, et l'on veut appliquer la même consigne à chaque élément : extraire un champ, juger une réponse, filtrer selon un critère flou, résumer. Écrire soi-même la boucle, la gestion des erreurs, la mise en lots et le parallélisme représente beaucoup de code pour un résultat qui varie d'une exécution à l'autre.

LOTUS répond à ce problème en exposant des opérateurs sémantiques, c'est-à-dire des primitives de type map, filter, reduce et join dont l'argument est une instruction en langage naturel plutôt qu'une fonction Python. Le README cite comme publics visés l'analyse de bases de code, les évaluations de type LLM-juge, l'extraction de champs dans des documents et la synthèse sur un corpus. Ce sont des tâches où l'on traite des milliers d'éléments, pas une question posée à un chatbot. Le nom du projet, LOTUS, signifie LLMs Over Text, Unstructured and Structured Data, ce qui résume la cible : données structurées et non structurées traitées par un modèle de langue.

Deux familles d'opérateurs, deux façons d'exécuter la même consigne

La documentation distingue deux classes d'opérateurs, et ce choix structure tout le reste.

Les opérateurs LLM (sem_map, sem_filter, sem_agg, sem_join, sem_extract) envoient chaque élément, ou chaque paire d'éléments pour le join, au modèle avec l'instruction fournie. C'est l'équivalent d'un appel unique par ligne, avec la mise en lots gérée par la bibliothèque.

Les opérateurs agentiques passent par corpus.agent(...) et acceptent une liste d'opérations à composer, par exemple ops=["map", "reduce"]. Chaque agent dispose d'un REPL Python sandboxé, ce qui lui permet de calculer des valeurs exactes au lieu de les estimer. L'exemple du README porte sur quatre petites fonctions Python dont certaines sont boguées : la consigne demande à l'agent de tester chaque fonction sur des entrées d'exemple et de signaler celles qui échouent, avec un contre-exemple. Sans le REPL, le modèle devrait deviner le résultat de l'exécution. Avec, il l'obtient.

La distinction a une conséquence pratique : un filtre qui demande « est-ce que ce texte parle de X » se traite avec sem_filter, alors qu'une vérification qui exige d'exécuter du code ou d'enchaîner plusieurs appels d'outils relève des opérateurs agentiques. Le coût par élément n'est pas le même, puisque l'agent peut consommer plusieurs appels de modèle là où l'opérateur LLM en fait un.

L'optimiseur : ce que LOTUS prend en charge à votre place

Le README décrit une séparation nette entre la déclaration et l'exécution. L'utilisateur exprime ce qu'il veut avec les opérateurs, et l'optimiseur décide comment l'exécuter : regroupement des appels en lots, recours à des cascades de modèles et à des proxies, planification paresseuse de l'ensemble du pipeline. Le schéma du dépôt résume le flux en quatre étapes : Corpus, programmation déclarative, optimiseur LOTUS, résultats.

C'est le point le plus intéressant du projet et aussi celui sur lequel la documentation fournie reste la plus discrète. Le README affirme que les pipelines optimisés atteignent ou dépassent l'exactitude de bonnes références tout en allant plus vite et en coûtant moins, et renvoie à un article arXiv ainsi qu'à un blog pour les chiffres. Aucun détail n'est donné ici sur la façon dont les cascades sont configurées, sur les seuils qui déclenchent le passage d'un petit modèle à un grand, ni sur la manière de forcer un modèle précis pour un opérateur donné. Pour un projet dont l'argument central est l'optimisation, c'est une lacune de la page d'accueil : il faut aller lire la documentation et l'article avant de se faire une idée du gain réel sur son propre jeu de données.

Installation et première exécution

L'installation tient en une commande, avec une variante pour uv :

pip install lotus-ai

ou uv add lotus-ai. Pour suivre la branche principale : pip install git+https://github.com/lotus-data/lotus.git@main. Le paquet s'appelle lotus-ai sur PyPI, tandis que le module s'importe sous le nom lotus.

La configuration passe par lotus.settings.configure(lm=LM(model="gpt-5", reasoning_effort="low")). Deux points méritent l'attention. D'abord, la clé API doit être exportée dans l'environnement avant l'exécution, par exemple export OPENAI_API_KEY=sk-.... Ensuite, le paramètre reasoning_effort est propre au modèle cité dans l'exemple ; le README ne précise pas quels autres modèles acceptent ce réglage, ni comment configurer un fournisseur différent d'OpenAI.

Le corpus se construit avec lotus.Corpus.from_documents(snippets), à partir de documents en ligne, d'un DataFrame, de fichiers ou d'un seul grand texte. L'appel corpus.agent(...) prend la tâche en langage naturel, la liste d'opérations et les outils, ici tools=[PythonREPLTool()]. Le résultat s'affiche via result.output.

Un point pratique : l'exemple du README est présenté comme entièrement autonome, mais il suppose une clé API valide et un accès réseau. Rien dans le matériel fourni ne décrit un mode hors ligne ou un modèle local, ce qui limite l'usage dans un environnement isolé.

Les cas où LOTUS n'est pas le bon outil

Le premier cas est le traitement d'un seul document ou de quelques lignes. Si vous voulez résumer un fichier, un appel direct à une API de modèle sera plus court à écrire et plus facile à déboguer que la mise en place d'un corpus et d'opérateurs. LOTUS prend sa valeur à l'échelle du lot.

Le deuxième cas est le besoin de reproductibilité stricte. Les opérateurs sémantiques reposent sur des modèles de langue, dont les sorties varient. Le README ne décrit aucun mécanisme de graine aléatoire, de cache de réponses ou de rejeu déterministe. Pour un pipeline de conformité qui doit produire le même résultat à chaque exécution, c'est un obstacle de fond, pas un détail de configuration.

Le troisième cas concerne les tâches où le calcul exact est la seule chose qui compte. Les opérateurs agentiques atténuent le problème grâce au REPL sandboxé, mais le recours à un modèle pour décider quoi exécuter introduit une couche d'incertitude là où une fonction Python ordinaire suffirait. Si votre transformation s'exprime en pandas sans ambiguïté, écrivez-la en pandas.

Enfin, le coût : chaque élément du corpus déclenche au moins un appel de modèle, et un agent peut en déclencher plusieurs. Sur un million de lignes, la facture se calcule avant de lancer le traitement, pas après.

Face à un pipeline maison ou à un framework d'orchestration

L'alternative la plus directe n'est pas un autre projet mais du code que vous écrivez : une boucle sur les lignes du DataFrame, un appel au modèle par ligne, un ThreadPoolExecutor pour le parallélisme, et un fichier de cache pour ne pas repayer les appels déjà effectués. Cette approche a un avantage réel : vous contrôlez chaque étape, vous savez exactement combien d'appels partent, et le débogage se fait avec les outils habituels. Elle a un coût tout aussi réel : la mise en lots, la reprise après erreur et la composition d'opérations comme le reduce restent à votre charge, et c'est précisément ce que LOTUS annonce prendre en charge.

Un framework d'orchestration de type DAG, où chaque étape est un nœud, représente une autre voie. La différence tient à l'unité de base : dans un orchestrateur, vous décrivez des étapes et leurs dépendances ; dans LOTUS, vous décrivez une instruction en langage naturel appliquée à un corpus, et la bibliothèque décide du découpage. Le second modèle est plus concis quand la tâche est floue, le premier est plus lisible quand la tâche est parfaitement spécifiée. Le choix dépend donc moins de la taille du jeu de données que de la nature de la consigne.

Licence, maintenance et coût de mise à jour

Le dépôt est publié sous Apache-2.0, une licence permissive qui autorise l'usage commercial, la modification et la redistribution, avec conservation du fichier de licence et des mentions de copyright. Elle comporte une clause de brevets. Ce paragraphe décrit la licence, il ne constitue pas un avis juridique : pour un usage en entreprise, faites vérifier les obligations de mention par votre service compétent.

Le rythme de publication est soutenu. Les données fournies montrent trois versions en un peu plus d'un mois, v1.2.2 le 13 juin 2026, v1.2.3 le 2 juillet, v1.2.4 le 3 juillet, et une dernière poussée sur main le 3 juillet 2026. Le dépôt n'est pas archivé. Pour un utilisateur, cela signifie deux choses : les correctifs arrivent vite, et une version figée dans un requirements.txt peut devenir ancienne en quelques semaines. Un épinglage précis de lotus-ai est donc prudent en production, avec une revue des notes de version avant chaque montée.

Le coût de mise à jour ne se limite pas au paquet. Les opérateurs sémantiques dépendent de modèles externes, dont les versions évoluent indépendamment de LOTUS. Un changement de modèle côté fournisseur peut modifier les sorties de vos opérateurs sans qu'aucune ligne de votre code n'ait bougé. C'est le principal coût caché de ce type de bibliothèque.

Conclusion éditoriale

LOTUS convient aux équipes qui doivent passer un volume important de documents ou de lignes de DataFrame dans un LLM et qui acceptent d'écrire leurs traitements comme des opérateurs sémantiques. Il faut passer son chemin si le besoin se limite à quelques appels interactifs, ou si l'on ne veut pas dépendre d'une clé API externe. Avant d'adopter, vérifier deux points précis dans la documentation : la liste des modèles acceptés par lotus.models.LM et le comportement de l'optimiseur quand le budget de jetons est dépassé.

Sources officielles

  1. License: Apache-2.0
  2. lotus-data/lotus on GitHub
  3. Project website
  4. README
  5. Releases
Notes de la communauté

Notes de la communauté