societyai 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +111 -0
- package/LICENSE +21 -0
- package/README.md +879 -0
- package/dist/builder.d.ts +181 -0
- package/dist/builder.d.ts.map +1 -0
- package/dist/builder.js +667 -0
- package/dist/builder.js.map +1 -0
- package/dist/config.d.ts +43 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +11 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +107 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +319 -0
- package/dist/context.js.map +1 -0
- package/dist/errors.d.ts +31 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +85 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +219 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +395 -0
- package/dist/events.js.map +1 -0
- package/dist/graph.d.ts +104 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +366 -0
- package/dist/graph.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +113 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +13 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +78 -0
- package/dist/logger.js.map +1 -0
- package/dist/memory.d.ts +146 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +353 -0
- package/dist/memory.js.map +1 -0
- package/dist/metrics.d.ts +143 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +271 -0
- package/dist/metrics.js.map +1 -0
- package/dist/middleware.d.ts +147 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +484 -0
- package/dist/middleware.js.map +1 -0
- package/dist/models.d.ts +32 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +211 -0
- package/dist/models.js.map +1 -0
- package/dist/patterns.d.ts +6 -0
- package/dist/patterns.d.ts.map +1 -0
- package/dist/patterns.js +68 -0
- package/dist/patterns.js.map +1 -0
- package/dist/pipeline.d.ts +84 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +569 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/retry.d.ts +5 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +70 -0
- package/dist/retry.js.map +1 -0
- package/dist/society.d.ts +94 -0
- package/dist/society.d.ts.map +1 -0
- package/dist/society.js +721 -0
- package/dist/society.js.map +1 -0
- package/dist/strategies.d.ts +55 -0
- package/dist/strategies.d.ts.map +1 -0
- package/dist/strategies.js +678 -0
- package/dist/strategies.js.map +1 -0
- package/dist/tools.d.ts +88 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +366 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +213 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/dist/validation.d.ts +64 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +334 -0
- package/dist/validation.js.map +1 -0
- package/dist/worker-pool.d.ts +17 -0
- package/dist/worker-pool.d.ts.map +1 -0
- package/dist/worker-pool.js +80 -0
- package/dist/worker-pool.js.map +1 -0
- package/docs/README.md +468 -0
- package/docs/advanced.md +616 -0
- package/docs/aggregation-strategies.md +926 -0
- package/docs/api-reference.md +771 -0
- package/docs/architecture.md +648 -0
- package/docs/context-system.md +642 -0
- package/docs/event-system.md +1047 -0
- package/docs/examples.md +576 -0
- package/docs/getting-started.md +564 -0
- package/docs/graph-execution.md +389 -0
- package/docs/memory-system.md +497 -0
- package/docs/metrics-observability.md +560 -0
- package/docs/middleware-system.md +1038 -0
- package/docs/migration.md +296 -0
- package/docs/pipeline-patterns.md +761 -0
- package/docs/structured-output.md +612 -0
- package/docs/tool-calling.md +491 -0
- package/docs/workflows.md +740 -0
- package/examples/README.md +234 -0
- package/examples/advanced-patterns.ts +115 -0
- package/examples/complete-integration.ts +327 -0
- package/examples/graph-workflow.ts +161 -0
- package/examples/memory-system.ts +155 -0
- package/examples/metrics-tracking.ts +243 -0
- package/examples/structured-output.ts +231 -0
- package/examples/tool-calling.ts +163 -0
- package/package.json +94 -0
|
@@ -0,0 +1,926 @@
|
|
|
1
|
+
# Aggregation Strategies
|
|
2
|
+
|
|
3
|
+
Les stratégies d'agrégation de SocietyAI permettent de combiner les résultats de plusieurs agents de manière flexible et personnalisable.
|
|
4
|
+
|
|
5
|
+
## Table des Matières
|
|
6
|
+
|
|
7
|
+
- [Vue d'ensemble](#vue-densemble)
|
|
8
|
+
- [Built-in Strategies](#built-in-strategies)
|
|
9
|
+
- [Custom Strategies](#custom-strategies)
|
|
10
|
+
- [Strategy Composition](#strategy-composition)
|
|
11
|
+
- [Exemples Complets](#exemples-complets)
|
|
12
|
+
|
|
13
|
+
## Vue d'ensemble
|
|
14
|
+
|
|
15
|
+
Les stratégies d'agrégation définissent comment combiner les résultats de plusieurs agents. Elles permettent de:
|
|
16
|
+
|
|
17
|
+
- **Fusionner** plusieurs réponses en une seule
|
|
18
|
+
- **Voter** pour sélectionner la meilleure réponse
|
|
19
|
+
- **Atteindre un consensus** basé sur la similarité
|
|
20
|
+
- **Pondérer** les contributions selon l'expertise
|
|
21
|
+
- **Filtrer** et sélectionner les meilleurs résultats
|
|
22
|
+
- **Composer** des stratégies complexes
|
|
23
|
+
|
|
24
|
+
### Principes de Design
|
|
25
|
+
|
|
26
|
+
- **Composable**: Les stratégies peuvent être combinées
|
|
27
|
+
- **Type-safe**: Support complet TypeScript
|
|
28
|
+
- **Model-agnostic**: Fonctionne avec n'importe quel format de résultat
|
|
29
|
+
- **Extensible**: Facile de créer des stratégies personnalisées
|
|
30
|
+
|
|
31
|
+
## Built-in Strategies
|
|
32
|
+
|
|
33
|
+
### Concat Strategy
|
|
34
|
+
|
|
35
|
+
Concatène tous les résultats réussis.
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { Strategies } from 'societyai';
|
|
39
|
+
|
|
40
|
+
// Concat avec séparateur par défaut (\n\n)
|
|
41
|
+
const merged = Strategies.concat().aggregate(results);
|
|
42
|
+
|
|
43
|
+
// Concat avec séparateur personnalisé
|
|
44
|
+
const merged = Strategies.concat('\n---\n').aggregate(results);
|
|
45
|
+
|
|
46
|
+
// Avec métadonnées complètes
|
|
47
|
+
const result = Strategies.concat().aggregateFull(results);
|
|
48
|
+
console.log(result.output);
|
|
49
|
+
console.log(result.metadata.successCount);
|
|
50
|
+
console.log(result.contributions);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Cas d'usage:**
|
|
54
|
+
|
|
55
|
+
- Combiner des perspectives multiples
|
|
56
|
+
- Rassembler des analyses différentes
|
|
57
|
+
- Fusion de rapports
|
|
58
|
+
|
|
59
|
+
### Merge Strategy
|
|
60
|
+
|
|
61
|
+
Alias pour concat, fusionne les résultats.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
const merged = Strategies.merge().aggregate(results);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### First Strategy
|
|
68
|
+
|
|
69
|
+
Retourne seulement le premier résultat réussi.
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
const first = Strategies.first().aggregate(results);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Cas d'usage:**
|
|
76
|
+
|
|
77
|
+
- Première réponse valide suffit
|
|
78
|
+
- Optimisation de performance
|
|
79
|
+
- Fallback en cascade
|
|
80
|
+
|
|
81
|
+
### Last Strategy
|
|
82
|
+
|
|
83
|
+
Retourne seulement le dernier résultat réussi.
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
const last = Strategies.last().aggregate(results);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Best Of Strategy
|
|
90
|
+
|
|
91
|
+
Sélectionne le meilleur résultat selon un critère.
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
// Meilleur par longueur (plus long)
|
|
95
|
+
const best = Strategies.bestOf((r) => r.content.length).aggregate(results);
|
|
96
|
+
|
|
97
|
+
// Meilleur par score personnalisé
|
|
98
|
+
const best = Strategies.bestOf((r) => {
|
|
99
|
+
const quality = calculateQuality(r.content);
|
|
100
|
+
const relevance = calculateRelevance(r.content);
|
|
101
|
+
return quality * 0.6 + relevance * 0.4;
|
|
102
|
+
}).aggregate(results);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Cas d'usage:**
|
|
106
|
+
|
|
107
|
+
- Sélection par qualité
|
|
108
|
+
- Optimisation de pertinence
|
|
109
|
+
- Métriques personnalisées
|
|
110
|
+
|
|
111
|
+
### Voting Strategy
|
|
112
|
+
|
|
113
|
+
Vote majoritaire simple - sélectionne la réponse la plus fréquente.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
const winner = Strategies.voting().aggregate(results);
|
|
117
|
+
|
|
118
|
+
// Avec option pour gérer les égalités
|
|
119
|
+
const winner = Strategies.voting({
|
|
120
|
+
tieBreaker: 'first', // ou 'last', 'random', 'all'
|
|
121
|
+
}).aggregate(results);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Cas d'usage:**
|
|
125
|
+
|
|
126
|
+
- Décisions démocratiques
|
|
127
|
+
- Validation par consensus
|
|
128
|
+
- Détection d'anomalies
|
|
129
|
+
|
|
130
|
+
### Weighted Vote Strategy
|
|
131
|
+
|
|
132
|
+
Vote avec pondérations par agent.
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// Pondérations égales au nombre d'agents
|
|
136
|
+
const weights = [0.5, 0.3, 0.2]; // Total = 1.0
|
|
137
|
+
const winner = Strategies.weightedVote(weights).aggregate(results);
|
|
138
|
+
|
|
139
|
+
// Pondérations par expertise
|
|
140
|
+
const weights = {
|
|
141
|
+
'expert-agent': 0.5,
|
|
142
|
+
'senior-agent': 0.3,
|
|
143
|
+
'junior-agent': 0.2,
|
|
144
|
+
};
|
|
145
|
+
const winner = Strategies.weightedVote(weights).aggregate(results);
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Cas d'usage:**
|
|
149
|
+
|
|
150
|
+
- Expertise variable
|
|
151
|
+
- Priorisation par rôle
|
|
152
|
+
- Hiérarchies de confiance
|
|
153
|
+
|
|
154
|
+
### Consensus Strategy
|
|
155
|
+
|
|
156
|
+
Atteint un consensus basé sur la similarité des réponses.
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
// Consensus avec seuil de 70%
|
|
160
|
+
const consensus = Strategies.consensus(0.7).aggregate(results);
|
|
161
|
+
|
|
162
|
+
// Avec fonction de similarité personnalisée
|
|
163
|
+
const consensus = Strategies.consensus(0.8, {
|
|
164
|
+
similarity: (a, b) => {
|
|
165
|
+
// Calcul de similarité personnalisé
|
|
166
|
+
return calculateSimilarity(a, b);
|
|
167
|
+
},
|
|
168
|
+
}).aggregate(results);
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**Comment ça marche:**
|
|
172
|
+
|
|
173
|
+
1. Compare toutes les paires de résultats
|
|
174
|
+
2. Calcule la similarité moyenne
|
|
175
|
+
3. Si similarité ≥ seuil, fusion des résultats
|
|
176
|
+
4. Sinon, retourne indication de désaccord
|
|
177
|
+
|
|
178
|
+
**Cas d'usage:**
|
|
179
|
+
|
|
180
|
+
- Validation croisée
|
|
181
|
+
- Détection de consensus
|
|
182
|
+
- Assurance qualité
|
|
183
|
+
|
|
184
|
+
### Majority Strategy
|
|
185
|
+
|
|
186
|
+
Sélectionne les résultats approuvés par la majorité.
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
// Majorité simple (>50%)
|
|
190
|
+
const majority = Strategies.majority().aggregate(results);
|
|
191
|
+
|
|
192
|
+
// Majorité qualifiée (≥66%)
|
|
193
|
+
const majority = Strategies.majority(0.66).aggregate(results);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Average Strategy
|
|
197
|
+
|
|
198
|
+
Moyenne des résultats numériques.
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
// Pour résultats numériques
|
|
202
|
+
const avg = Strategies.average().aggregate(numericResults);
|
|
203
|
+
|
|
204
|
+
// Avec extraction personnalisée
|
|
205
|
+
const avg = Strategies.average({
|
|
206
|
+
extract: (result) => parseFloat(result.content),
|
|
207
|
+
}).aggregate(results);
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Cas d'usage:**
|
|
211
|
+
|
|
212
|
+
- Estimations numériques
|
|
213
|
+
- Scores moyens
|
|
214
|
+
- Agrégation de métriques
|
|
215
|
+
|
|
216
|
+
### Filter Strategy
|
|
217
|
+
|
|
218
|
+
Filtre les résultats avant agrégation.
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
// Filtrer par condition
|
|
222
|
+
const filtered = Strategies.filter((r) => r.success && r.content.length > 10).aggregate(results);
|
|
223
|
+
|
|
224
|
+
// Combiner avec autre stratégie
|
|
225
|
+
const filtered = Strategies.compose(
|
|
226
|
+
Strategies.filter((r) => r.success),
|
|
227
|
+
Strategies.bestOf((r) => r.content.length)
|
|
228
|
+
);
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Transform Strategy
|
|
232
|
+
|
|
233
|
+
Transforme les résultats avant agrégation.
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
// Transformer le contenu
|
|
237
|
+
const transformed = Strategies.transform((r) => r.content.toUpperCase()).aggregate(results);
|
|
238
|
+
|
|
239
|
+
// Extraction de données
|
|
240
|
+
const transformed = Strategies.transform((r) => {
|
|
241
|
+
const data = JSON.parse(r.content);
|
|
242
|
+
return data.summary;
|
|
243
|
+
}).aggregate(results);
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Ranking Strategy
|
|
247
|
+
|
|
248
|
+
Classe les résultats selon un critère.
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
// Classement par score
|
|
252
|
+
const ranked = Strategies.ranking((r) => calculateScore(r.content), {
|
|
253
|
+
top: 3, // Garder top 3
|
|
254
|
+
order: 'desc', // Ordre décroissant
|
|
255
|
+
}).aggregate(results);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### Unanimous Strategy
|
|
259
|
+
|
|
260
|
+
Requiert l'unanimité de tous les agents.
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
// Tous doivent être d'accord
|
|
264
|
+
const unanimous = Strategies.unanimous().aggregate(results);
|
|
265
|
+
|
|
266
|
+
// Avec fonction de comparaison personnalisée
|
|
267
|
+
const unanimous = Strategies.unanimous({
|
|
268
|
+
compare: (a, b) => normalizeText(a) === normalizeText(b),
|
|
269
|
+
}).aggregate(results);
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Custom Strategies
|
|
273
|
+
|
|
274
|
+
### Strategy Builder
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
import { StrategyBuilder } from 'societyai';
|
|
278
|
+
|
|
279
|
+
const customStrategy = StrategyBuilder.create()
|
|
280
|
+
.withName('custom-merge')
|
|
281
|
+
.withDescription('Merges results with custom logic')
|
|
282
|
+
.withAggregator((results) => {
|
|
283
|
+
// Logique personnalisée
|
|
284
|
+
const successful = results.filter((r) => r.success);
|
|
285
|
+
|
|
286
|
+
// Traiter les résultats
|
|
287
|
+
const processed = successful.map((r) => processResult(r.content));
|
|
288
|
+
|
|
289
|
+
// Combiner
|
|
290
|
+
return processed.join('\n\n');
|
|
291
|
+
})
|
|
292
|
+
.build();
|
|
293
|
+
|
|
294
|
+
// Utiliser
|
|
295
|
+
const result = customStrategy.aggregate(results);
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
### Function Strategy
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
import { createStrategy } from 'societyai';
|
|
302
|
+
|
|
303
|
+
// Créer une stratégie depuis une fonction
|
|
304
|
+
const myStrategy = createStrategy('my-strategy', (results) => {
|
|
305
|
+
// Implémentation
|
|
306
|
+
return results
|
|
307
|
+
.filter((r) => r.success)
|
|
308
|
+
.map((r) => r.content)
|
|
309
|
+
.join(' | ');
|
|
310
|
+
});
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Class-Based Strategy
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
import { AggregationStrategy, StepResult, AggregationResult } from 'societyai';
|
|
317
|
+
|
|
318
|
+
class SmartMergeStrategy implements AggregationStrategy {
|
|
319
|
+
name = 'smart-merge';
|
|
320
|
+
description = 'Intelligently merges results';
|
|
321
|
+
|
|
322
|
+
constructor(
|
|
323
|
+
private options: {
|
|
324
|
+
minLength?: number;
|
|
325
|
+
maxResults?: number;
|
|
326
|
+
} = {}
|
|
327
|
+
) {}
|
|
328
|
+
|
|
329
|
+
aggregate(results: StepResult[]): string {
|
|
330
|
+
let successful = results.filter((r) => r.success);
|
|
331
|
+
|
|
332
|
+
// Filtrer par longueur minimum
|
|
333
|
+
if (this.options.minLength) {
|
|
334
|
+
successful = successful.filter((r) => r.content.length >= this.options.minLength!);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Limiter le nombre
|
|
338
|
+
if (this.options.maxResults) {
|
|
339
|
+
successful = successful.slice(0, this.options.maxResults);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Fusionner
|
|
343
|
+
return successful.map((r) => r.content).join('\n\n');
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
aggregateFull(results: StepResult[]): AggregationResult {
|
|
347
|
+
const output = this.aggregate(results);
|
|
348
|
+
const successful = results.filter((r) => r.success);
|
|
349
|
+
|
|
350
|
+
return {
|
|
351
|
+
output,
|
|
352
|
+
metadata: {
|
|
353
|
+
successCount: successful.length,
|
|
354
|
+
failedCount: results.length - successful.length,
|
|
355
|
+
strategy: this.name,
|
|
356
|
+
avgLength: successful.reduce((sum, r) => sum + r.content.length, 0) / successful.length,
|
|
357
|
+
},
|
|
358
|
+
contributions: results.map((r) => ({
|
|
359
|
+
agentId: r.agentId,
|
|
360
|
+
included: r.success,
|
|
361
|
+
weight: 1.0 / successful.length,
|
|
362
|
+
})),
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Utilisation
|
|
368
|
+
const strategy = new SmartMergeStrategy({ minLength: 50, maxResults: 5 });
|
|
369
|
+
const result = strategy.aggregate(results);
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## Strategy Composition
|
|
373
|
+
|
|
374
|
+
### Chaîner des Stratégies
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
import { chainStrategies } from 'societyai';
|
|
378
|
+
|
|
379
|
+
// Exécuter des stratégies en séquence
|
|
380
|
+
const chained = chainStrategies([
|
|
381
|
+
Strategies.filter((r) => r.success),
|
|
382
|
+
Strategies.transform((r) => r.content.trim()),
|
|
383
|
+
Strategies.bestOf((r) => r.content.length),
|
|
384
|
+
]);
|
|
385
|
+
|
|
386
|
+
const result = chained.aggregate(results);
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Stratégies Parallèles
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
import { parallelStrategies } from 'societyai';
|
|
393
|
+
|
|
394
|
+
// Exécuter plusieurs stratégies et combiner
|
|
395
|
+
const parallel = parallelStrategies(
|
|
396
|
+
[Strategies.bestOf((r) => r.content.length), Strategies.consensus(0.7), Strategies.voting()],
|
|
397
|
+
Strategies.voting()
|
|
398
|
+
); // Stratégie finale pour combiner
|
|
399
|
+
|
|
400
|
+
const result = parallel.aggregate(results);
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Compose Helper
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
import { Strategies } from 'societyai';
|
|
407
|
+
|
|
408
|
+
// Composer plusieurs stratégies
|
|
409
|
+
const composed = Strategies.compose(
|
|
410
|
+
// 1. Filtrer les succès
|
|
411
|
+
Strategies.filter((r) => r.success),
|
|
412
|
+
|
|
413
|
+
// 2. Garder ceux avec contenu substantiel
|
|
414
|
+
Strategies.filter((r) => r.content.length > 100),
|
|
415
|
+
|
|
416
|
+
// 3. Voter pour le meilleur
|
|
417
|
+
Strategies.weightedVote([0.5, 0.3, 0.2])
|
|
418
|
+
);
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### Conditional Strategy
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
function conditionalStrategy(
|
|
425
|
+
condition: (results: StepResult[]) => boolean,
|
|
426
|
+
strategyA: AggregationStrategy,
|
|
427
|
+
strategyB: AggregationStrategy
|
|
428
|
+
): AggregationStrategy {
|
|
429
|
+
return {
|
|
430
|
+
name: 'conditional',
|
|
431
|
+
aggregate: (results) => {
|
|
432
|
+
if (condition(results)) {
|
|
433
|
+
return strategyA.aggregate(results);
|
|
434
|
+
} else {
|
|
435
|
+
return strategyB.aggregate(results);
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
aggregateFull: (results) => {
|
|
439
|
+
const strategy = condition(results) ? strategyA : strategyB;
|
|
440
|
+
return strategy.aggregateFull(results);
|
|
441
|
+
},
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Utilisation
|
|
446
|
+
const strategy = conditionalStrategy(
|
|
447
|
+
(results) => results.length > 5,
|
|
448
|
+
Strategies.voting(), // Beaucoup de résultats -> vote
|
|
449
|
+
Strategies.consensus(0.8) // Peu de résultats -> consensus
|
|
450
|
+
);
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
## Exemples Complets
|
|
454
|
+
|
|
455
|
+
### Exemple 1: Stratégie de Review Multi-Niveau
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
class MultiLevelReviewStrategy implements AggregationStrategy {
|
|
459
|
+
name = 'multi-level-review';
|
|
460
|
+
|
|
461
|
+
constructor(
|
|
462
|
+
private levels: Array<{
|
|
463
|
+
threshold: number;
|
|
464
|
+
strategy: AggregationStrategy;
|
|
465
|
+
}>
|
|
466
|
+
) {
|
|
467
|
+
// Trier par threshold décroissant
|
|
468
|
+
this.levels.sort((a, b) => b.threshold - a.threshold);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
aggregate(results: StepResult[]): string {
|
|
472
|
+
const successRate = results.filter((r) => r.success).length / results.length;
|
|
473
|
+
|
|
474
|
+
// Sélectionner la stratégie selon le taux de succès
|
|
475
|
+
for (const level of this.levels) {
|
|
476
|
+
if (successRate >= level.threshold) {
|
|
477
|
+
return level.strategy.aggregate(results);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Fallback - premier résultat réussi
|
|
482
|
+
return Strategies.first().aggregate(results);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
aggregateFull(results: StepResult[]): AggregationResult {
|
|
486
|
+
const output = this.aggregate(results);
|
|
487
|
+
const successRate = results.filter((r) => r.success).length / results.length;
|
|
488
|
+
|
|
489
|
+
return {
|
|
490
|
+
output,
|
|
491
|
+
metadata: {
|
|
492
|
+
successCount: results.filter((r) => r.success).length,
|
|
493
|
+
failedCount: results.filter((r) => !r.success).length,
|
|
494
|
+
strategy: this.name,
|
|
495
|
+
successRate,
|
|
496
|
+
levelUsed: this.getLevelUsed(successRate),
|
|
497
|
+
},
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
private getLevelUsed(successRate: number): string {
|
|
502
|
+
for (const level of this.levels) {
|
|
503
|
+
if (successRate >= level.threshold) {
|
|
504
|
+
return level.strategy.name;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return 'fallback';
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// Utilisation
|
|
512
|
+
const strategy = new MultiLevelReviewStrategy([
|
|
513
|
+
{ threshold: 0.9, strategy: Strategies.consensus(0.9) }, // Excellent
|
|
514
|
+
{ threshold: 0.7, strategy: Strategies.consensus(0.7) }, // Bon
|
|
515
|
+
{ threshold: 0.5, strategy: Strategies.voting() }, // Moyen
|
|
516
|
+
{ threshold: 0.3, strategy: Strategies.bestOf(scoreFunc) }, // Faible
|
|
517
|
+
]);
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### Exemple 2: Stratégie avec Validation
|
|
521
|
+
|
|
522
|
+
```typescript
|
|
523
|
+
class ValidatedMergeStrategy implements AggregationStrategy {
|
|
524
|
+
name = 'validated-merge';
|
|
525
|
+
|
|
526
|
+
constructor(
|
|
527
|
+
private validator: (content: string) => boolean,
|
|
528
|
+
private minValidResults: number = 2
|
|
529
|
+
) {}
|
|
530
|
+
|
|
531
|
+
aggregate(results: StepResult[]): string {
|
|
532
|
+
// Filtrer les résultats valides
|
|
533
|
+
const validResults = results.filter((r) => r.success).filter((r) => this.validator(r.content));
|
|
534
|
+
|
|
535
|
+
if (validResults.length < this.minValidResults) {
|
|
536
|
+
throw new Error(
|
|
537
|
+
`Insufficient valid results: ${validResults.length} < ${this.minValidResults}`
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// Fusionner les résultats valides
|
|
542
|
+
return validResults.map((r) => r.content).join('\n\n');
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
aggregateFull(results: StepResult[]): AggregationResult {
|
|
546
|
+
const validResults = results.filter((r) => r.success).filter((r) => this.validator(r.content));
|
|
547
|
+
|
|
548
|
+
const output = this.aggregate(results);
|
|
549
|
+
|
|
550
|
+
return {
|
|
551
|
+
output,
|
|
552
|
+
metadata: {
|
|
553
|
+
successCount: results.filter((r) => r.success).length,
|
|
554
|
+
failedCount: results.filter((r) => !r.success).length,
|
|
555
|
+
strategy: this.name,
|
|
556
|
+
validCount: validResults.length,
|
|
557
|
+
invalidCount: results.filter((r) => r.success).length - validResults.length,
|
|
558
|
+
},
|
|
559
|
+
contributions: results.map((r) => {
|
|
560
|
+
const isValid = r.success && this.validator(r.content);
|
|
561
|
+
return {
|
|
562
|
+
agentId: r.agentId,
|
|
563
|
+
included: isValid,
|
|
564
|
+
weight: isValid ? 1.0 / validResults.length : 0,
|
|
565
|
+
};
|
|
566
|
+
}),
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// Utilisation
|
|
572
|
+
const strategy = new ValidatedMergeStrategy(
|
|
573
|
+
(content) => {
|
|
574
|
+
// Valider le contenu
|
|
575
|
+
return content.length > 50 && !content.includes('error') && isValidJSON(content);
|
|
576
|
+
},
|
|
577
|
+
3 // Au moins 3 résultats valides requis
|
|
578
|
+
);
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### Exemple 3: Stratégie de Scoring Avancée
|
|
582
|
+
|
|
583
|
+
```typescript
|
|
584
|
+
interface ScoringCriteria {
|
|
585
|
+
name: string;
|
|
586
|
+
weight: number;
|
|
587
|
+
score: (content: string) => number;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
class ScoringStrategy implements AggregationStrategy {
|
|
591
|
+
name = 'advanced-scoring';
|
|
592
|
+
|
|
593
|
+
constructor(
|
|
594
|
+
private criteria: ScoringCriteria[],
|
|
595
|
+
private threshold?: number
|
|
596
|
+
) {
|
|
597
|
+
// Normaliser les poids
|
|
598
|
+
const totalWeight = criteria.reduce((sum, c) => sum + c.weight, 0);
|
|
599
|
+
this.criteria = criteria.map((c) => ({
|
|
600
|
+
...c,
|
|
601
|
+
weight: c.weight / totalWeight,
|
|
602
|
+
}));
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
private calculateScore(content: string): number {
|
|
606
|
+
return this.criteria.reduce((total, criterion) => {
|
|
607
|
+
const score = criterion.score(content);
|
|
608
|
+
return total + score * criterion.weight;
|
|
609
|
+
}, 0);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
aggregate(results: StepResult[]): string {
|
|
613
|
+
const scored = results
|
|
614
|
+
.filter((r) => r.success)
|
|
615
|
+
.map((r) => ({
|
|
616
|
+
content: r.content,
|
|
617
|
+
agentId: r.agentId,
|
|
618
|
+
score: this.calculateScore(r.content),
|
|
619
|
+
}))
|
|
620
|
+
.sort((a, b) => b.score - a.score);
|
|
621
|
+
|
|
622
|
+
if (this.threshold !== undefined) {
|
|
623
|
+
// Filtrer par threshold
|
|
624
|
+
const qualified = scored.filter((s) => s.score >= this.threshold!);
|
|
625
|
+
if (qualified.length === 0) {
|
|
626
|
+
throw new Error('No results meet the quality threshold');
|
|
627
|
+
}
|
|
628
|
+
return qualified.map((s) => s.content).join('\n\n');
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// Retourner le meilleur
|
|
632
|
+
return scored[0]?.content || '';
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
aggregateFull(results: StepResult[]): AggregationResult {
|
|
636
|
+
const scored = results
|
|
637
|
+
.filter((r) => r.success)
|
|
638
|
+
.map((r) => ({
|
|
639
|
+
result: r,
|
|
640
|
+
score: this.calculateScore(r.content),
|
|
641
|
+
}))
|
|
642
|
+
.sort((a, b) => b.score - a.score);
|
|
643
|
+
|
|
644
|
+
const output = this.aggregate(results);
|
|
645
|
+
|
|
646
|
+
return {
|
|
647
|
+
output,
|
|
648
|
+
metadata: {
|
|
649
|
+
successCount: scored.length,
|
|
650
|
+
failedCount: results.length - scored.length,
|
|
651
|
+
strategy: this.name,
|
|
652
|
+
topScore: scored[0]?.score,
|
|
653
|
+
avgScore: scored.reduce((sum, s) => sum + s.score, 0) / scored.length,
|
|
654
|
+
scores: scored.map((s) => ({
|
|
655
|
+
agentId: s.result.agentId,
|
|
656
|
+
score: s.score,
|
|
657
|
+
})),
|
|
658
|
+
},
|
|
659
|
+
contributions: results.map((r) => {
|
|
660
|
+
const scoredResult = scored.find((s) => s.result.agentId === r.agentId);
|
|
661
|
+
return {
|
|
662
|
+
agentId: r.agentId,
|
|
663
|
+
included: scoredResult !== undefined,
|
|
664
|
+
weight: scoredResult?.score,
|
|
665
|
+
};
|
|
666
|
+
}),
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
// Utilisation
|
|
672
|
+
const strategy = new ScoringStrategy(
|
|
673
|
+
[
|
|
674
|
+
{
|
|
675
|
+
name: 'length',
|
|
676
|
+
weight: 0.3,
|
|
677
|
+
score: (content) => Math.min(content.length / 1000, 1),
|
|
678
|
+
},
|
|
679
|
+
{
|
|
680
|
+
name: 'keywords',
|
|
681
|
+
weight: 0.4,
|
|
682
|
+
score: (content) => {
|
|
683
|
+
const keywords = ['important', 'relevant', 'accurate'];
|
|
684
|
+
return keywords.filter((k) => content.toLowerCase().includes(k)).length / keywords.length;
|
|
685
|
+
},
|
|
686
|
+
},
|
|
687
|
+
{
|
|
688
|
+
name: 'structure',
|
|
689
|
+
weight: 0.3,
|
|
690
|
+
score: (content) => {
|
|
691
|
+
const hasIntro = content.includes('Introduction');
|
|
692
|
+
const hasConclusion = content.includes('Conclusion');
|
|
693
|
+
const hasSections = (content.match(/\n## /g) || []).length >= 3;
|
|
694
|
+
return (hasIntro ? 0.33 : 0) + (hasConclusion ? 0.33 : 0) + (hasSections ? 0.34 : 0);
|
|
695
|
+
},
|
|
696
|
+
},
|
|
697
|
+
],
|
|
698
|
+
0.6
|
|
699
|
+
); // Threshold: 60%
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
### Exemple 4: Stratégie ML-Based
|
|
703
|
+
|
|
704
|
+
```typescript
|
|
705
|
+
class MLBasedStrategy implements AggregationStrategy {
|
|
706
|
+
name = 'ml-based';
|
|
707
|
+
|
|
708
|
+
constructor(
|
|
709
|
+
private model: PredictionModel,
|
|
710
|
+
private features: FeatureExtractor
|
|
711
|
+
) {}
|
|
712
|
+
|
|
713
|
+
aggregate(results: StepResult[]): string {
|
|
714
|
+
// Extraire les features
|
|
715
|
+
const candidates = results
|
|
716
|
+
.filter((r) => r.success)
|
|
717
|
+
.map((r) => ({
|
|
718
|
+
content: r.content,
|
|
719
|
+
features: this.features.extract(r.content),
|
|
720
|
+
}));
|
|
721
|
+
|
|
722
|
+
// Prédire les scores
|
|
723
|
+
const scored = candidates.map((c) => ({
|
|
724
|
+
content: c.content,
|
|
725
|
+
score: this.model.predict(c.features),
|
|
726
|
+
}));
|
|
727
|
+
|
|
728
|
+
// Sélectionner le meilleur
|
|
729
|
+
const best = scored.sort((a, b) => b.score - a.score)[0];
|
|
730
|
+
|
|
731
|
+
return best?.content || '';
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
aggregateFull(results: StepResult[]): AggregationResult {
|
|
735
|
+
const output = this.aggregate(results);
|
|
736
|
+
|
|
737
|
+
return {
|
|
738
|
+
output,
|
|
739
|
+
metadata: {
|
|
740
|
+
successCount: results.filter((r) => r.success).length,
|
|
741
|
+
failedCount: results.filter((r) => !r.success).length,
|
|
742
|
+
strategy: this.name,
|
|
743
|
+
modelUsed: this.model.name,
|
|
744
|
+
},
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// Utilisation avec un modèle de qualité
|
|
750
|
+
const qualityModel = loadQualityModel();
|
|
751
|
+
const featureExtractor = new TextFeatureExtractor();
|
|
752
|
+
|
|
753
|
+
const strategy = new MLBasedStrategy(qualityModel, featureExtractor);
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
## Bonnes Pratiques
|
|
757
|
+
|
|
758
|
+
### 1. Choisir la Bonne Stratégie
|
|
759
|
+
|
|
760
|
+
```typescript
|
|
761
|
+
// ✅ Bon - stratégie adaptée au cas d'usage
|
|
762
|
+
|
|
763
|
+
// Pour validation factuelle
|
|
764
|
+
Strategies.consensus(0.8); // Forte similarité requise
|
|
765
|
+
|
|
766
|
+
// Pour opinions diverses
|
|
767
|
+
Strategies.concat('\n\n'); // Garder toutes les perspectives
|
|
768
|
+
|
|
769
|
+
// Pour décision binaire
|
|
770
|
+
Strategies.voting(); // Majorité simple
|
|
771
|
+
|
|
772
|
+
// Pour expertise variable
|
|
773
|
+
Strategies.weightedVote(weights); // Pondération par expertise
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
### 2. Gestion des Échecs
|
|
777
|
+
|
|
778
|
+
```typescript
|
|
779
|
+
// ✅ Bon - gérer les cas où tous échouent
|
|
780
|
+
const safeStrategy = Strategies.compose(
|
|
781
|
+
Strategies.filter((r) => r.success),
|
|
782
|
+
Strategies.bestOf((r) => r.content.length),
|
|
783
|
+
// Fallback si aucun succès
|
|
784
|
+
{
|
|
785
|
+
name: 'fallback',
|
|
786
|
+
aggregate: (results) => {
|
|
787
|
+
if (results.length === 0) {
|
|
788
|
+
return 'No results available';
|
|
789
|
+
}
|
|
790
|
+
return Strategies.first().aggregate(results);
|
|
791
|
+
},
|
|
792
|
+
}
|
|
793
|
+
);
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
### 3. Validation des Résultats
|
|
797
|
+
|
|
798
|
+
```typescript
|
|
799
|
+
// ✅ Bon - valider avant agrégation
|
|
800
|
+
const validatedStrategy = StrategyBuilder.create()
|
|
801
|
+
.withName('validated')
|
|
802
|
+
.withAggregator((results) => {
|
|
803
|
+
const valid = results.filter(
|
|
804
|
+
(r) => r.success && r.content.length > 0 && isValidFormat(r.content)
|
|
805
|
+
);
|
|
806
|
+
|
|
807
|
+
if (valid.length === 0) {
|
|
808
|
+
throw new Error('No valid results to aggregate');
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
return valid.map((r) => r.content).join('\n\n');
|
|
812
|
+
})
|
|
813
|
+
.build();
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
### 4. Métadonnées Riches
|
|
817
|
+
|
|
818
|
+
```typescript
|
|
819
|
+
// ✅ Bon - inclure métadonnées utiles
|
|
820
|
+
const strategy: AggregationStrategy = {
|
|
821
|
+
name: 'rich-metadata',
|
|
822
|
+
aggregate: (results) => {
|
|
823
|
+
// ... logique d'agrégation
|
|
824
|
+
},
|
|
825
|
+
aggregateFull: (results) => {
|
|
826
|
+
const output = this.aggregate(results);
|
|
827
|
+
const successful = results.filter((r) => r.success);
|
|
828
|
+
|
|
829
|
+
return {
|
|
830
|
+
output,
|
|
831
|
+
metadata: {
|
|
832
|
+
successCount: successful.length,
|
|
833
|
+
failedCount: results.length - successful.length,
|
|
834
|
+
strategy: 'rich-metadata',
|
|
835
|
+
// Métadonnées additionnelles
|
|
836
|
+
totalLength: successful.reduce((sum, r) => sum + r.content.length, 0),
|
|
837
|
+
avgLength: successful.reduce((sum, r) => sum + r.content.length, 0) / successful.length,
|
|
838
|
+
timestamp: Date.now(),
|
|
839
|
+
agents: successful.map((r) => r.agentId),
|
|
840
|
+
},
|
|
841
|
+
contributions: results.map((r) => ({
|
|
842
|
+
agentId: r.agentId,
|
|
843
|
+
included: r.success,
|
|
844
|
+
weight: r.success ? 1.0 / successful.length : 0,
|
|
845
|
+
})),
|
|
846
|
+
};
|
|
847
|
+
},
|
|
848
|
+
};
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
### 5. Performance
|
|
852
|
+
|
|
853
|
+
```typescript
|
|
854
|
+
// ✅ Bon - optimiser pour performance
|
|
855
|
+
const efficientStrategy = Strategies.filter((r) => r.success && r.content.length > 50).aggregate(
|
|
856
|
+
results
|
|
857
|
+
);
|
|
858
|
+
|
|
859
|
+
// ❌ Mauvais - opérations coûteuses répétées
|
|
860
|
+
results.forEach((r) => {
|
|
861
|
+
if (expensiveValidation(r)) {
|
|
862
|
+
// Appelé N fois
|
|
863
|
+
// ...
|
|
864
|
+
}
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
// ✅ Mieux - valider une fois
|
|
868
|
+
const validated = results.filter((r) => expensiveValidation(r));
|
|
869
|
+
const result = Strategies.concat().aggregate(validated);
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
## API Reference
|
|
873
|
+
|
|
874
|
+
### `Strategies`
|
|
875
|
+
|
|
876
|
+
**Méthodes statiques:**
|
|
877
|
+
|
|
878
|
+
- `concat(separator?: string): AggregationStrategy`
|
|
879
|
+
- `merge(): AggregationStrategy`
|
|
880
|
+
- `first(): AggregationStrategy`
|
|
881
|
+
- `last(): AggregationStrategy`
|
|
882
|
+
- `bestOf(scorer: Function): AggregationStrategy`
|
|
883
|
+
- `voting(options?: VotingOptions): AggregationStrategy`
|
|
884
|
+
- `weightedVote(weights: number[] | Record<string, number>): AggregationStrategy`
|
|
885
|
+
- `consensus(threshold: number, options?: ConsensusOptions): AggregationStrategy`
|
|
886
|
+
- `majority(threshold?: number): AggregationStrategy`
|
|
887
|
+
- `average(options?: AverageOptions): AggregationStrategy`
|
|
888
|
+
- `filter(predicate: Function): AggregationStrategy`
|
|
889
|
+
- `transform(transformer: Function): AggregationStrategy`
|
|
890
|
+
- `ranking(scorer: Function, options?: RankingOptions): AggregationStrategy`
|
|
891
|
+
- `unanimous(options?: UnanimousOptions): AggregationStrategy`
|
|
892
|
+
- `compose(...strategies: AggregationStrategy[]): AggregationStrategy`
|
|
893
|
+
|
|
894
|
+
### `StrategyBuilder`
|
|
895
|
+
|
|
896
|
+
**Méthodes:**
|
|
897
|
+
|
|
898
|
+
- `static create(): StrategyBuilder`
|
|
899
|
+
- `withName(name: string): this`
|
|
900
|
+
- `withDescription(description: string): this`
|
|
901
|
+
- `withAggregator(fn: (results: StepResult[]) => string): this`
|
|
902
|
+
- `build(): AggregationStrategy`
|
|
903
|
+
|
|
904
|
+
### `AggregationStrategy` Interface
|
|
905
|
+
|
|
906
|
+
```typescript
|
|
907
|
+
interface AggregationStrategy {
|
|
908
|
+
name: string;
|
|
909
|
+
description?: string;
|
|
910
|
+
aggregate: (results: StepResult[]) => string;
|
|
911
|
+
aggregateFull: (results: StepResult[]) => AggregationResult;
|
|
912
|
+
}
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
### Helper Functions
|
|
916
|
+
|
|
917
|
+
- `createStrategy(name: string, fn: Function): AggregationStrategy`
|
|
918
|
+
- `chainStrategies(strategies: AggregationStrategy[]): AggregationStrategy`
|
|
919
|
+
- `parallelStrategies(strategies: AggregationStrategy[], final: AggregationStrategy): AggregationStrategy`
|
|
920
|
+
|
|
921
|
+
## Voir Aussi
|
|
922
|
+
|
|
923
|
+
- [Workflows](./workflows.md) - Utilisation dans les workflows
|
|
924
|
+
- [Pipeline Patterns](./pipeline-patterns.md) - Patterns de pipeline
|
|
925
|
+
- [Graph Execution](./graph-execution.md) - Utilisation dans les graphes
|
|
926
|
+
- [Advanced Patterns](./advanced.md) - Patterns avancés
|