Metadata-Version: 2.4
Name: llm-wf
Version: 0.1.1
Summary: Moteur de workflow LLM basé sur des graphes d'agents
Home-page: https://gitlab.univ-nantes.fr/desmontils-e/llm-workflow
Author: Emmanuel Desmontils
Author-email: emmanuel.desmontils@univ-nantes.fr
License: CeCILL-B
Project-URL: Source, https://gitlab.univ-nantes.fr/desmontils-e/llm-workflow
Project-URL: Bug Tracker, https://gitlab.univ-nantes.fr/desmontils-e/llm-workflow/-/issues
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.11.0
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pyyaml>=6.0
Requires-Dist: jinja2>=3.1.6
Requires-Dist: colorama>=0.4.6
Requires-Dist: openai>=2.9.0
Requires-Dist: anthropic>=0.84.0
Requires-Dist: ollama>=0.4.7
Requires-Dist: google-genai>=1.61.0
Requires-Dist: lmstudio>=1.5.0
Requires-Dist: requests>=2.31.0
Requires-Dist: pypdf>=4.0
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license
Dynamic: license-file
Dynamic: project-url
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# llm-workflow

Moteur de workflow LLM basé sur des graphes d'agents. Permet d'enchaîner des agents LLM connectés par leurs variables, avec parallélisation automatique des agents indépendants.

## Principe

Un workflow est un **graphe orienté acyclique (DAG)** d'agents LLM. Chaque agent :

- reçoit des **variables d'entrée** injectées dans son prompt (template Jinja2) ;
- appelle un service LLM ;
- produit une ou plusieurs **variables de sortie**.

Les connexions entre agents sont déduites automatiquement : si l'agent A produit `résumé` et que l'agent B consomme `résumé`, l'arête A → B est créée. Les agents sans dépendance commune s'exécutent **en parallèle**.

```
entrée: document
    │
    ▼
[agent_résumé]  ──────────────────────────────────┐
    │ résumé                                       │
    ▼                                              ▼
[agent_mots_clés]                        [agent_sentiment]
    │ mots_clés                                    │ sentiment
    └──────────────────────┬───────────────────────┘
                           ▼
                    [agent_rapport]
                           │ rapport_final
                           ▼
                         sortie
```

## Installation

```bash
pip install .
```

Ou en mode développement :

```bash
pip install -e .
```

## Usage CLI

```bash
llmwf -w workflow.yaml -v document="Mon texte à analyser"
llmwf -w workflow.yaml -f document=rapport.pdf --verbose
llmwf -w workflow.yaml -f doc=rapport.txt -v langue=français -o md
llmwf -w workflow.yaml --graph                  # diagramme seul
llmwf -w workflow.yaml --graph -f doc=texte.txt # diagramme + exécution
```

### Options

| Option | Description |
|--------|-------------|
| `-w`, `--workflow` | Fichier YAML du workflow (requis) |
| `-v var=valeur` | Variable directe (répétable) |
| `-f var=fichier` | Variable chargée depuis un fichier `.txt`, `.md` ou `.pdf` (répétable) |
| `-o text\|md\|html` | Format de sortie (défaut : `text`) |
| `-g [fichier]`, `--graph [fichier]` | Génère le diagramme PlantUML du workflow (voir ci-dessous) |
| `--verbose` | Affiche le détail de l'exécution |
| `--version` | Affiche la version |

### Génération de diagramme PlantUML

L'option `-g`/`--graph` produit une représentation visuelle du graphe d'agents au format PlantUML.

```bash
llmwf -w workflow.yaml --graph              # → <Nom_du_workflow>.puml
llmwf -w workflow.yaml --graph mon_flow.puml  # → mon_flow.puml
```

Le rendu en image (PNG) est tenté automatiquement selon la disponibilité :

1. **Binaire local** `plantuml` — rendu local si installé
2. **Serveur public** `plantuml.com` — via le package Python `plantuml` si le réseau est accessible
3. **Fichier `.puml` seul** — si aucune option de rendu n'est disponible

Utilisé sans variables d'entrée (`-v`/`-f`), le diagramme est généré puis la commande se termine (pas d'exécution du workflow).

## Format du fichier workflow YAML

```yaml
name: "Analyse de document"
system_prompt: prompts/system.md

agents:
  - id: résumé
    prompt: prompts/resume.md
    service: ollama
    model: gemma3:4b
    inputs: [document]
    outputs: [résumé]

  - id: mots_clés
    prompt: prompts/mots_cles.md
    service: anthropic
    model: claude-haiku-4-5-20251001
    api_key: "None"          # utilise QCANTHROPIC_API_KEY
    inputs: [résumé]
    outputs: [mots_clés]

  - id: rapport
    prompt: prompts/rapport.md
    service: ollama
    model: gemma3:4b
    inputs: [résumé, mots_clés]
    outputs: [rapport_final]
```

### Champs d'un agent

| Champ | Requis | Description |
|-------|--------|-------------|
| `id` | oui | Identifiant unique de l'agent |
| `prompt` | oui | Chemin vers le fichier de prompt (relatif au YAML) |
| `service` | oui | Service LLM (voir ci-dessous) |
| `model` | oui | Nom du modèle |
| `inputs` | non | Variables d'entrée consommées |
| `outputs` | oui | Variables de sortie produites |
| `url` | non | URL personnalisée du service |
| `api_key` | non | Clé API (sinon variable d'environnement) |

### Sorties multiples

Si un agent déclare **plusieurs outputs**, son prompt doit retourner un objet JSON :

```
{"var1": "valeur1", "var2": "valeur2"}
```

Le moteur extrait automatiquement un bloc ` ```json ``` ` ou le premier objet JSON nu dans la réponse.

## Services LLM supportés

| `service` | Description | Variable d'env. |
|-----------|-------------|-----------------|
| `ollama` | Ollama local (`localhost:11434`) ou distant si `url` fourni | — |
| `ollama_cloud` | Ollama Cloud | `OLLAMA_API_KEY` |
| `lms` | LM Studio (local) | — |
| `openai` | OpenAI API | `OPENAI_API_KEY` |
| `anthropic` | Anthropic Claude | `QCANTHROPIC_API_KEY` |
| `google` | Google Gemini | `GEMINI_API_KEY` |
| `albert` | Albert (DINUM — service public) | `ALBERT_API_KEY` |
| `ragarenn` | Ragarenn (Eskemm Numérique) | `RAG_API_KEY` |
| `poe` | POE API | `POE_API_KEY` |
| `generic` | API compatible OpenAI (nécessite `url` et `api_key`) | — |

## Format des prompts

Les prompts sont des templates **Jinja2**. Les variables d'entrée déclarées dans `inputs` sont injectées automatiquement.

```markdown
Voici le document à résumer :

{{ document }}

Produis un résumé en 3 phrases maximum.
```

> Les caractères spéciaux Markdown et les balises Jinja2 présents dans les variables sont échappés automatiquement pour éviter les injections de prompt.

## Usage programmatique

```python
from llm_workflow import WorkflowConfig, WorkflowGraph, WorkflowExecutor

config = WorkflowConfig.from_yaml("workflow.yaml")
graph = WorkflowGraph.from_agents(config.agents)

errors = graph.validate({"document": "Mon texte..."})
if errors:
    raise ValueError(errors)

executor = WorkflowExecutor(graph, config.load_system_prompt(), verbose=True)
results = executor.execute({"document": "Mon texte..."})
print(results["rapport_final"])
```

## Variables d'environnement

```bash
export OPENAI_API_KEY="sk-..."
export QCANTHROPIC_API_KEY="sk-ant-..."
export GEMINI_API_KEY="AIza..."
export ALBERT_API_KEY="..."
export RAG_API_KEY="..."
export OLLAMA_API_KEY="..."
export POE_API_KEY="..."
```

## Exemple complet

Le répertoire [`examples/analyse_document/`](examples/analyse_document/) contient un workflow fonctionnel à 4 agents (résumé → mots-clés + sentiment en parallèle → rapport).

Prérequis : Ollama installé et démarré avec le modèle `gemma3:4b`.

```bash
# Avec un texte direct
llmwf -w examples/analyse_document/workflow.yaml \
       -v document="L'intelligence artificielle transforme profondément nos sociétés." \
       --verbose

# Avec un fichier texte
llmwf -w examples/analyse_document/workflow.yaml \
       -f document=mon_document.txt \
       -o md
```

## Prérequis

- Python ≥ 3.11
- Dépendances : voir `requirements.txt`

## Auteur

Emmanuel Desmontils — [emmanuel.desmontils@univ-nantes.fr](mailto:emmanuel.desmontils@univ-nantes.fr)

avec l'aide de Claude Code  et POE/Sonnet-4.6

## Licence

[CeCILL-B](LICENSE) — Licence libre française élaborée par le CEA, le CNRS et l'INRIA, compatible avec le droit français. Permet la réutilisation et la modification libres sous condition d'attribution.
