agentic-api 1.0.6 → 2.0.31
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/README.md +336 -76
- package/dist/src/agents/agents.example.d.ts +3 -0
- package/dist/src/agents/agents.example.js +38 -0
- package/dist/src/agents/authentication.js +2 -0
- package/dist/src/agents/prompts.d.ts +2 -2
- package/dist/src/agents/prompts.js +112 -49
- package/dist/src/agents/reducer.core.d.ts +12 -0
- package/dist/src/agents/reducer.core.js +207 -0
- package/dist/src/agents/reducer.d.ts +3 -0
- package/dist/src/agents/reducer.example.d.ts +28 -0
- package/dist/src/agents/reducer.example.js +118 -0
- package/dist/src/agents/reducer.js +19 -0
- package/dist/src/agents/reducer.loaders.d.ts +34 -0
- package/dist/src/agents/reducer.loaders.js +122 -0
- package/dist/src/agents/reducer.process.d.ts +16 -0
- package/dist/src/agents/reducer.process.js +143 -0
- package/dist/src/agents/reducer.tools.d.ts +29 -0
- package/dist/src/agents/reducer.tools.js +157 -0
- package/dist/src/agents/reducer.types.d.ts +50 -0
- package/dist/src/agents/reducer.types.js +5 -0
- package/dist/src/agents/simulator.d.ts +47 -0
- package/dist/src/agents/simulator.executor.d.ts +26 -0
- package/dist/src/agents/simulator.executor.js +132 -0
- package/dist/src/agents/simulator.js +205 -0
- package/dist/src/agents/simulator.prompts.d.ts +16 -0
- package/dist/src/agents/simulator.prompts.js +108 -0
- package/dist/src/agents/simulator.types.d.ts +42 -0
- package/dist/src/agents/simulator.types.js +2 -0
- package/dist/src/agents/simulator.utils.d.ts +20 -0
- package/dist/src/agents/simulator.utils.js +87 -0
- package/dist/src/execute.d.ts +13 -6
- package/dist/src/execute.js +351 -85
- package/dist/src/index.d.ts +9 -0
- package/dist/src/index.js +14 -0
- package/dist/src/princing.openai.d.ts +9 -2
- package/dist/src/princing.openai.js +15 -11
- package/dist/src/prompts.d.ts +3 -2
- package/dist/src/prompts.js +159 -19
- package/dist/src/rag/embeddings.d.ts +103 -0
- package/dist/src/rag/embeddings.js +466 -0
- package/dist/src/rag/index.d.ts +12 -0
- package/dist/src/rag/index.js +40 -0
- package/dist/src/rag/lucene.d.ts +45 -0
- package/dist/src/rag/lucene.js +227 -0
- package/dist/src/rag/parser.d.ts +68 -0
- package/dist/src/rag/parser.js +192 -0
- package/dist/src/rag/tools.d.ts +76 -0
- package/dist/src/rag/tools.js +196 -0
- package/dist/src/rag/types.d.ts +178 -0
- package/dist/src/rag/types.js +21 -0
- package/dist/src/rag/usecase.d.ts +16 -0
- package/dist/src/rag/usecase.js +79 -0
- package/dist/src/rules/errors.d.ts +60 -0
- package/dist/src/rules/errors.js +97 -0
- package/dist/src/rules/git/git.e2e.helper.d.ts +104 -0
- package/dist/src/rules/git/git.e2e.helper.js +488 -0
- package/dist/src/rules/git/git.health.d.ts +66 -0
- package/dist/src/rules/git/git.health.js +354 -0
- package/dist/src/rules/git/git.helper.d.ts +129 -0
- package/dist/src/rules/git/git.helper.js +53 -0
- package/dist/src/rules/git/index.d.ts +6 -0
- package/dist/src/rules/git/index.js +76 -0
- package/dist/src/rules/git/repo.d.ts +128 -0
- package/dist/src/rules/git/repo.js +900 -0
- package/dist/src/rules/git/repo.pr.d.ts +137 -0
- package/dist/src/rules/git/repo.pr.js +589 -0
- package/dist/src/rules/git/repo.tools.d.ts +134 -0
- package/dist/src/rules/git/repo.tools.js +730 -0
- package/dist/src/rules/index.d.ts +8 -0
- package/dist/src/rules/index.js +25 -0
- package/dist/src/rules/messages.d.ts +17 -0
- package/dist/src/rules/messages.js +21 -0
- package/dist/src/rules/types.ctrl.d.ts +28 -0
- package/dist/src/rules/types.ctrl.js +2 -0
- package/dist/src/rules/types.d.ts +510 -0
- package/dist/src/rules/types.helpers.d.ts +132 -0
- package/dist/src/rules/types.helpers.js +2 -0
- package/dist/src/rules/types.js +33 -0
- package/dist/src/rules/user.mapper.d.ts +61 -0
- package/dist/src/rules/user.mapper.js +160 -0
- package/dist/src/rules/utils/slug.d.ts +22 -0
- package/dist/src/rules/utils/slug.js +35 -0
- package/dist/src/rules/utils.matter.d.ts +66 -0
- package/dist/src/rules/utils.matter.js +208 -0
- package/dist/src/rules/utils.slug.d.ts +22 -0
- package/dist/src/rules/utils.slug.js +35 -0
- package/dist/src/scrapper.d.ts +3 -2
- package/dist/src/scrapper.js +33 -37
- package/dist/src/stategraph/index.d.ts +8 -0
- package/dist/src/stategraph/index.js +21 -0
- package/dist/src/stategraph/stategraph.d.ts +91 -0
- package/dist/src/stategraph/stategraph.js +241 -0
- package/dist/src/stategraph/stategraph.storage.d.ts +41 -0
- package/dist/src/stategraph/stategraph.storage.js +166 -0
- package/dist/src/stategraph/types.d.ts +139 -0
- package/dist/src/stategraph/types.js +19 -0
- package/dist/src/types.d.ts +62 -39
- package/dist/src/types.js +53 -89
- package/dist/src/usecase.d.ts +4 -0
- package/dist/src/usecase.js +44 -0
- package/dist/src/utils.d.ts +12 -5
- package/dist/src/utils.js +30 -13
- package/package.json +9 -3
|
@@ -104,7 +104,7 @@ Sois précis, concis, hiérarchique, et logique.
|
|
|
104
104
|
`;
|
|
105
105
|
exports.promptMarkdown = `# RÔLE:
|
|
106
106
|
- Tu es un expert en développement de test unitaires avec nodejs et jtest.
|
|
107
|
-
- Tu as développé un RAG avec openai et "HNSW" qui contient toutes les Procédures de l'entreprise Pilet
|
|
107
|
+
- Tu as développé un RAG avec openai et "HNSW" qui contient toutes les Procédures de l'entreprise Pilet & Renaud SA.
|
|
108
108
|
- Ta mission est de créer une série de tests exhaustifs pour valider que le RAG couvre à 100% le contenu des procédures de l'entreprise.
|
|
109
109
|
- Produire des questions à un coût important, tu dois être efficace, tu dois capturer un maximum de détails (sujet, relation, objet) avec un minimum de questions (maximum 4).
|
|
110
110
|
- Toutes les questions que tu vas créer concernent précisément le INPUT fournit ci-dessous.
|
|
@@ -146,7 +146,7 @@ exports.promptMarkdown = `# RÔLE:
|
|
|
146
146
|
- MED: Mise en demeure.
|
|
147
147
|
- WC: Toilettes.
|
|
148
148
|
- M-Files: logiciel de gestion de documents
|
|
149
|
-
- PR ou PRSA: Pilet
|
|
149
|
+
- PR ou PRSA: Pilet & Renaud SA
|
|
150
150
|
- PPE: Service qui gère les copropriétés.
|
|
151
151
|
- GP: Garantie Bancaire
|
|
152
152
|
- BAL: Boite à Lettre
|
|
@@ -176,53 +176,116 @@ INPUT:
|
|
|
176
176
|
// 6. output (L’agent sait-il comment formuler sa réponse)
|
|
177
177
|
// 😩 Il lit la demande de haïku, voit qu’il doit "appeler un agent spécialisé" et pense que ce n’est pas lui.
|
|
178
178
|
exports.systemReviewPrompt = `
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
-
|
|
198
|
-
-
|
|
199
|
-
-
|
|
200
|
-
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
-
|
|
206
|
-
-
|
|
207
|
-
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
-
|
|
225
|
-
|
|
179
|
+
### Identity
|
|
180
|
+
Tu es “PromptVerifier”, un auditeur senior de prompts système spécialisé dans les agents structurés. Ta mission est de relire, diagnostiquer et annoter un prompt système ligne par ligne pour fiabiliser son exécution.
|
|
181
|
+
|
|
182
|
+
### Task context
|
|
183
|
+
- Tu reçois un prompt (principalement un prompt système) à auditer.
|
|
184
|
+
- Tu dois le comprendre précisément dans son ensemble.
|
|
185
|
+
- Tu dois le parcourir section par section, directive par directive (une directive = une ligne).
|
|
186
|
+
- Tu détectes les problèmes et proposes des remarques ultra-ciblées, minimales, directement au bout de la ligne concernée.
|
|
187
|
+
|
|
188
|
+
### Tone context
|
|
189
|
+
- Français, clair, concis, professionnel. Pas de langage fleuri. Zéro redondance.
|
|
190
|
+
|
|
191
|
+
### Background data
|
|
192
|
+
- Bonnes pratiques GPT‑5 sur la prédictibilité agentique, le contrôle d’eagerness, les “tool preambles”, l’exploration disciplinée, la vérification continue et l’efficacité.
|
|
193
|
+
- Utilises les ressources internet: GPT‑5 prompting guide.
|
|
194
|
+
|
|
195
|
+
### Task rules
|
|
196
|
+
- Analyse systématique “directive = une ligne” (section = groupe de directives), ligne par ligne. Pour chaque ligne, vérifier:
|
|
197
|
+
- Multiple interprétation / trop vague (risque de faux négatifs)
|
|
198
|
+
- Doublons
|
|
199
|
+
- Contradictions
|
|
200
|
+
- Redondances
|
|
201
|
+
- Alignement strict à la MISSION
|
|
202
|
+
- Neutralité, logique, applicabilité générale (les exemples sont spécifiques, les règles doivent rester générales)
|
|
203
|
+
- Appliques les bonnes pratique (ci-dessous) "Reasoning best practices" et "XML-like tags best practices"
|
|
204
|
+
- Séparation claire QUOI (règle/objectif) vs COMMENT (procédure/exemple)
|
|
205
|
+
- Ne corrige pas le texte dans la sortie. Tu n’ajoutes que des remarques en fin de ligne pour les éléments problématique “pas OK”.
|
|
206
|
+
- Une modification = une directive à la fois (discipline de changement). Pour la proposition de correction, tu la gardes implicite dans la remarque (succincte), sans réécrire la ligne.
|
|
207
|
+
- Pas d’appels d’outils externes. Aucune recherche additionnelle. Raisonne localement.
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
### Reasoning best practices
|
|
211
|
+
- **Objectif**: maximiser exactitude et fiabilité tout en contrôlant coût/latence.
|
|
212
|
+
- **Quand raisonner plus**: tâches ambiguës, mult-étapes, sécurité élevée; sinon rester minimal.
|
|
213
|
+
- **Budget de réflexion**: fixer un plafond clair (ex. étapes max, temps, outils); arrêter dès critères atteints.
|
|
214
|
+
- **Décomposition**: formuler le problème → lister sous‑tâches → ordonner → traiter séquentiellement.
|
|
215
|
+
- **Plan → Agir → Vérifier**: annoncer un plan bref, exécuter, valider la sortie vs critères de succès.
|
|
216
|
+
- **Checklist de vérification**: exactitude, complétude, cohérence règles, absence de contradictions.
|
|
217
|
+
- **Auto‑évaluation (reflection)**: demander “où mon raisonnement peut-il être faux ?” puis corriger si nécessaire.
|
|
218
|
+
- **Compare & critique (si utile)**: générer 2 pistes succinctes puis choisir via critères objectifs.
|
|
219
|
+
- **Preuves/sources**: exiger références cliquables pour faits non triviaux; sinon marquer incertitude.
|
|
220
|
+
- **Scratchpad privé**: ne pas exposer le raisonnement détaillé; n’afficher que le résultat et les annotations requises.
|
|
221
|
+
- **Erreurs programmées**: si échec à une vérification, corriger une chose à la fois et revérifier.
|
|
222
|
+
- **Sortie contractuelle**: respecter strictement le format demandé; ne jamais ajouter de texte hors contrat.
|
|
223
|
+
- **Efficience**: privilégier la simplicité; éviter re‑recherches si l’action est possible; paralléliser lectures.
|
|
224
|
+
- **Traçabilité**: noter hypothèses explicites; si non vérifiables, choisir l’option la moins risquée et poursuivre.
|
|
225
|
+
|
|
226
|
+
### XML-like tags best practices
|
|
227
|
+
Quand privilégier les XML‑tags: blocs opérationnels “machine‑actionables” (budgets, stop conditions, discipline d’édition, preambles/outils) :
|
|
228
|
+
- **\`<context_gathering>\` — objectif**: Calibrer l’exploration (profondeur, parallélisation, critères d’arrêt) pour réduire la latence.
|
|
229
|
+
|
|
230
|
+
- **\`<persistence>\` — objectif**: Encourager l’autonomie et la complétion sans rendre la main trop tôt.
|
|
231
|
+
|
|
232
|
+
- **\`<tool_preambles>\` — objectif**: Annoncer clairement but, plan et updates succinctes lors des appels d’outils.
|
|
233
|
+
|
|
234
|
+
- **\`<instructions>\` — objectif**: Établir les règles d’édition et de validation dans un contexte d’exécution (Terminal‑Bench).
|
|
235
|
+
|
|
236
|
+
- **\`<apply_patch>\` — objectif**: Définir le format V4A de diff/patch et la manière correcte d’appliquer les edits.
|
|
237
|
+
|
|
238
|
+
- **\`<exploration>\` — objectif**: Encadrer la découverte: décomposer, cartographier, cibler, puis agir rapidement.
|
|
239
|
+
|
|
240
|
+
- **\`<verification>\` — objectif**: Imposer des contrôles continus et la validation finale des livrables.
|
|
241
|
+
|
|
242
|
+
- **\`<efficiency>\` — objectif**: Contraindre coûts/latences via planification méticuleuse et exécution sobre.
|
|
243
|
+
|
|
244
|
+
- **\`<final_instructions>\` — objectif**: Fixer les contraintes finales (outils, formats) à respecter strictement.
|
|
245
|
+
|
|
246
|
+
Référence: [GPT‑5 prompting guide — OpenAI Cookbook](https://cookbook.openai.com/examples/gpt-5/gpt-5_prompting_guide)
|
|
247
|
+
|
|
248
|
+
### Issue taxonomy (types et émojis)
|
|
249
|
+
- Ambiguïté / Trop vague: 🤔
|
|
250
|
+
- Doublon: ❌
|
|
251
|
+
- Contradiction: ❌
|
|
252
|
+
- Redondance: ❌
|
|
253
|
+
- Hors mission / Non aligné: 🎯❌
|
|
254
|
+
- Non neutre / Non logique / Non universel: 🤔
|
|
255
|
+
- Mauvaise séparation QUOI/COMMENT: 🤔
|
|
256
|
+
|
|
257
|
+
### Output formatting (OBLIGATOIRE)
|
|
258
|
+
- Tu DOIS afficher uniquement le prompt original, intact, dans l’ordre et en entier.
|
|
259
|
+
- Pour chaque ligne avec un problème tu AJOUTES À LA FIN de la ligne tes remarque au format:
|
|
260
|
+
- **N️ EMOJI ** justification brève
|
|
261
|
+
- Exemple: — [**🌀 Ambiguïté:** “souvent”, préciser critère mesurable
|
|
262
|
+
- Numérotation N️: incrémente à chaque nouvelle remarque (1,2,3, …).
|
|
263
|
+
- Lignes sans problème: aucun ajout.
|
|
264
|
+
- Zéro préambule, zéro post‑scriptum, zéro résumé, zéro légende: sors UNIQUEMENT le prompt annoté (le texte d’entrée + remarques en fin de ligne).
|
|
265
|
+
- Les remarques doivent être concises (≤ 120 caractères par problème), actionnables et spécifiques.
|
|
266
|
+
|
|
267
|
+
### Persistence
|
|
268
|
+
- Va au bout de l’audit dans une seule passe. Ne demande pas de clarification: choisis l’hypothèse raisonnable minimale et continue.
|
|
269
|
+
|
|
270
|
+
### Context gathering (calibrage eagerness)
|
|
271
|
+
- Profondeur faible (pas d’outils ni relectures multiples). Early stop: dès que chaque ligne a été inspectée.
|
|
272
|
+
- Pas de reformulation du prompt source; conserve-le strictement, ajoute seulement les remarques finales par ligne.
|
|
273
|
+
|
|
274
|
+
### Efficiency
|
|
275
|
+
- Remarques courtes, ciblées, sans jargon. Évite les répétitions. Privilégie le signal.
|
|
276
|
+
|
|
277
|
+
### User request
|
|
278
|
+
- Input attendu: le prompt système à auditer (texte entier).
|
|
279
|
+
|
|
280
|
+
### Step-by-step reasoning CoT
|
|
281
|
+
- Interne. Ne jamais afficher le raisonnement.
|
|
282
|
+
|
|
283
|
+
### Final instructions
|
|
284
|
+
- Sors UNIQUEMENT le prompt original, ligne par ligne, avec remarques en fin de ligne pour ce qui n’est pas OK, numérotées en gras et avec l’émoji de type.
|
|
285
|
+
- Aucune autre sortie n’est permise.
|
|
286
|
+
|
|
287
|
+
### References
|
|
288
|
+
- GPT‑5 prompting guide — OpenAI Cookbook: https://cookbook.openai.com/examples/gpt-5/gpt-5_prompting_guide
|
|
226
289
|
|
|
227
290
|
`;
|
|
228
291
|
exports.systemReviewStructurePrompt = `
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MapLLM - Simple hierarchical reducer with native loaders
|
|
3
|
+
*/
|
|
4
|
+
import type { NativeLoader, StatefulReducerConfig, MapLLMReduceResult } from './reducer.types';
|
|
5
|
+
/**
|
|
6
|
+
* MapLLM - Orchestrateur principal pour le reduce hiérarchique
|
|
7
|
+
*/
|
|
8
|
+
export declare class MapLLM {
|
|
9
|
+
private loader;
|
|
10
|
+
constructor(loader: NativeLoader);
|
|
11
|
+
reduce(config: StatefulReducerConfig, callback: (result: MapLLMReduceResult, currentValue: string | object) => MapLLMReduceResult, init: MapLLMReduceResult): Promise<MapLLMReduceResult>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MapLLM - Simple hierarchical reducer with native loaders
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MapLLM = void 0;
|
|
7
|
+
const execute_1 = require("../execute");
|
|
8
|
+
const utils_1 = require("../utils");
|
|
9
|
+
/**
|
|
10
|
+
* MapLLM - Orchestrateur principal pour le reduce hiérarchique
|
|
11
|
+
*/
|
|
12
|
+
class MapLLM {
|
|
13
|
+
constructor(loader) {
|
|
14
|
+
this.loader = loader;
|
|
15
|
+
}
|
|
16
|
+
async reduce(config, callback, init) {
|
|
17
|
+
const startTime = Date.now();
|
|
18
|
+
// Merge init with defaults
|
|
19
|
+
let result = { ...init, ...{
|
|
20
|
+
continue: false,
|
|
21
|
+
model: init.model || (0, execute_1.modelConfig)("LOW-fast"),
|
|
22
|
+
metadata: {
|
|
23
|
+
iterations: 0,
|
|
24
|
+
averageChunkSize: 0,
|
|
25
|
+
processingTimeMs: 0
|
|
26
|
+
}
|
|
27
|
+
} };
|
|
28
|
+
const verbose = init.verbose || false;
|
|
29
|
+
if (verbose) {
|
|
30
|
+
console.log('🚀 MapLLM: Starting reduce process...');
|
|
31
|
+
}
|
|
32
|
+
let position = 0;
|
|
33
|
+
let totalChunkSize = 0;
|
|
34
|
+
let totalReduce = 0;
|
|
35
|
+
const openai = (0, utils_1.openaiInstance)();
|
|
36
|
+
const llm = Object.assign({}, result.model);
|
|
37
|
+
llm.stream = false;
|
|
38
|
+
delete llm.stream_options;
|
|
39
|
+
//
|
|
40
|
+
// maxIterations is set by the callback
|
|
41
|
+
while (!result.maxIterations) {
|
|
42
|
+
if (result.metadata) {
|
|
43
|
+
result.metadata.iterations++;
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
// 1. Load chunk
|
|
47
|
+
const chunk = await this.loader.loadNativeChunk(position);
|
|
48
|
+
if (verbose) {
|
|
49
|
+
console.log(`📦 Processing chunk ${result.metadata?.iterations} position ${position} is eof ${chunk.eof}`);
|
|
50
|
+
}
|
|
51
|
+
totalChunkSize += chunk.content.length;
|
|
52
|
+
// Update position immediately after loading (before any continue)
|
|
53
|
+
position = chunk.position;
|
|
54
|
+
// 2. Digest chunk
|
|
55
|
+
// Simple message array without memory manager - but preserve conversation
|
|
56
|
+
// Prepare messages based on acc type and content
|
|
57
|
+
const isFirstChunk = (typeof result.acc === 'string' && result.acc.length === 0) ||
|
|
58
|
+
(typeof result.acc === 'object' && Object.keys(result.acc).length === 0);
|
|
59
|
+
const accContent = typeof result.acc === 'string' ? result.acc : JSON.stringify(result.acc);
|
|
60
|
+
const messages = isFirstChunk ? [
|
|
61
|
+
{ role: "system", content: config.digestPrompt },
|
|
62
|
+
{ role: "user", content: chunk.content }
|
|
63
|
+
] : [
|
|
64
|
+
{ role: "system", content: config.digestPrompt },
|
|
65
|
+
{ role: "assistant", content: accContent },
|
|
66
|
+
{ role: "user", content: chunk.content }
|
|
67
|
+
];
|
|
68
|
+
llm.messages = messages;
|
|
69
|
+
// Configure structured output if format is specified
|
|
70
|
+
if (result.format) {
|
|
71
|
+
llm.response_format = {
|
|
72
|
+
type: "json_schema",
|
|
73
|
+
json_schema: {
|
|
74
|
+
name: result.format.name,
|
|
75
|
+
schema: result.format.schema,
|
|
76
|
+
strict: result.format.strict ?? true
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const chat = await openai.chat.completions.create(llm);
|
|
81
|
+
const digestMessage = chat.choices[0]?.message;
|
|
82
|
+
// Parse JSON if structured output is enabled
|
|
83
|
+
let digestContent = digestMessage.content;
|
|
84
|
+
if (result.format && digestContent) {
|
|
85
|
+
try {
|
|
86
|
+
digestContent = JSON.parse(digestContent);
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
console.warn('Failed to parse structured output as JSON:', digestContent);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//
|
|
93
|
+
// the reduce callback operates the process of digesting and accumulating
|
|
94
|
+
result = callback(result, digestContent);
|
|
95
|
+
if (result.maxIterations) {
|
|
96
|
+
throw new Error(`Maximum iterations (${result.metadata?.iterations}) reached without completion`);
|
|
97
|
+
}
|
|
98
|
+
// Check EOF BEFORE any continue to ensure we exit the loop
|
|
99
|
+
if (chunk.eof) {
|
|
100
|
+
if (verbose) {
|
|
101
|
+
console.log('🏁 End of document reached after processing final chunk');
|
|
102
|
+
}
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
// Décision de réduction basée sur callback
|
|
106
|
+
if (!result.continue) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const accForReduce = typeof result.acc === 'string' ? result.acc : JSON.stringify(result.acc);
|
|
110
|
+
llm.messages = [
|
|
111
|
+
{ role: "system", content: config.reducePrompt },
|
|
112
|
+
{ role: "user", content: accForReduce }
|
|
113
|
+
];
|
|
114
|
+
// Configure structured output if format is specified
|
|
115
|
+
if (result.format) {
|
|
116
|
+
llm.response_format = {
|
|
117
|
+
type: "json_schema",
|
|
118
|
+
json_schema: {
|
|
119
|
+
name: result.format.name,
|
|
120
|
+
schema: result.format.schema,
|
|
121
|
+
strict: result.format.strict ?? true
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
const reduce = await openai.chat.completions.create(llm);
|
|
126
|
+
const reduceMessage = reduce.choices[0]?.message;
|
|
127
|
+
//
|
|
128
|
+
// should not happen
|
|
129
|
+
if (!reduceMessage.content) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
// 3. Reduce with system - Update result.acc (replace)
|
|
133
|
+
totalReduce++;
|
|
134
|
+
// Parse JSON if structured output is enabled
|
|
135
|
+
if (result.format) {
|
|
136
|
+
try {
|
|
137
|
+
result.acc = JSON.parse(reduceMessage.content);
|
|
138
|
+
}
|
|
139
|
+
catch (e) {
|
|
140
|
+
console.warn('Failed to parse reduce result as JSON:', reduceMessage.content);
|
|
141
|
+
result.acc = reduceMessage.content;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
result.acc = reduceMessage.content;
|
|
146
|
+
}
|
|
147
|
+
if (verbose) {
|
|
148
|
+
console.log(`✅ Reduce ${result.metadata?.iterations} processed (${chunk.content.length} chars)`);
|
|
149
|
+
console.log("✅ Reduce result:", result.acc);
|
|
150
|
+
}
|
|
151
|
+
// EOF check is now handled earlier in the loop
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
if (verbose) {
|
|
155
|
+
console.log(`❌ Chunk ${result.metadata?.iterations} failed: ${error}`);
|
|
156
|
+
}
|
|
157
|
+
throw new Error(`Failed to process chunk ${result.metadata?.iterations}: ${error}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Final reduce
|
|
161
|
+
const finalAccContent = typeof result.acc === 'string' ? result.acc : JSON.stringify(result.acc);
|
|
162
|
+
const messages = [
|
|
163
|
+
{ role: "system", content: config.reducePrompt },
|
|
164
|
+
{ role: "user", content: finalAccContent }
|
|
165
|
+
];
|
|
166
|
+
llm.messages = messages;
|
|
167
|
+
// Configure structured output if format is specified
|
|
168
|
+
if (result.format) {
|
|
169
|
+
llm.response_format = {
|
|
170
|
+
type: "json_schema",
|
|
171
|
+
json_schema: {
|
|
172
|
+
name: result.format.name,
|
|
173
|
+
schema: result.format.schema,
|
|
174
|
+
strict: result.format.strict ?? true
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const reduce = await openai.chat.completions.create(llm);
|
|
179
|
+
const finalContent = reduce.choices[0]?.message.content || '';
|
|
180
|
+
// Parse JSON if structured output is enabled
|
|
181
|
+
if (result.format && finalContent) {
|
|
182
|
+
try {
|
|
183
|
+
result.acc = JSON.parse(finalContent);
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
console.warn('Failed to parse final result as JSON:', finalContent);
|
|
187
|
+
result.acc = finalContent;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
result.acc = finalContent;
|
|
192
|
+
}
|
|
193
|
+
const endTime = Date.now();
|
|
194
|
+
const processingTimeMs = endTime - startTime;
|
|
195
|
+
if (verbose) {
|
|
196
|
+
console.log(`🎉 MapLLM completed: ${result.metadata?.iterations} chunks in ${processingTimeMs}ms`);
|
|
197
|
+
}
|
|
198
|
+
// Update final metadata
|
|
199
|
+
result.continue = false; // Terminé
|
|
200
|
+
if (result.metadata) {
|
|
201
|
+
result.metadata.processingTimeMs = processingTimeMs;
|
|
202
|
+
result.metadata.averageChunkSize = Math.round(totalChunkSize / result.metadata.iterations);
|
|
203
|
+
}
|
|
204
|
+
return result;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
exports.MapLLM = MapLLM;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MapLLM Reducer - Simple hierarchical reducer
|
|
3
|
+
*
|
|
4
|
+
* Main export file for the MapLLM reducer functionality
|
|
5
|
+
*/
|
|
6
|
+
export { MapLLM } from './reducer.core';
|
|
7
|
+
export { FileNativeLoader, StringNativeLoader } from './reducer.loaders';
|
|
8
|
+
export type { NativeLoader, StatefulReducerConfig, MapLLMOptions, ReduceResult, ChunkStrategy } from './reducer.types';
|
|
9
|
+
export declare const exampleConfigs: {
|
|
10
|
+
weather: {
|
|
11
|
+
digestPrompt: string;
|
|
12
|
+
reducePrompt: string;
|
|
13
|
+
};
|
|
14
|
+
foods: {
|
|
15
|
+
digestPrompt: string;
|
|
16
|
+
reducePrompt: string;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export declare const examples: {
|
|
20
|
+
/**
|
|
21
|
+
* Example: Weather data analysis
|
|
22
|
+
*/
|
|
23
|
+
weatherAnalysis(weatherFilePath: string): Promise<import("./reducer.types").ReduceResult>;
|
|
24
|
+
/**
|
|
25
|
+
* Example: Food selection from string content
|
|
26
|
+
*/
|
|
27
|
+
foodSelection(foodListContent: string): Promise<import("./reducer.types").ReduceResult>;
|
|
28
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MapLLM Reducer - Simple hierarchical reducer
|
|
4
|
+
*
|
|
5
|
+
* Main export file for the MapLLM reducer functionality
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.examples = exports.exampleConfigs = exports.StringNativeLoader = exports.FileNativeLoader = exports.MapLLM = void 0;
|
|
42
|
+
// Core classes
|
|
43
|
+
var reducer_core_1 = require("./reducer.core");
|
|
44
|
+
Object.defineProperty(exports, "MapLLM", { enumerable: true, get: function () { return reducer_core_1.MapLLM; } });
|
|
45
|
+
var reducer_loaders_1 = require("./reducer.loaders");
|
|
46
|
+
Object.defineProperty(exports, "FileNativeLoader", { enumerable: true, get: function () { return reducer_loaders_1.FileNativeLoader; } });
|
|
47
|
+
Object.defineProperty(exports, "StringNativeLoader", { enumerable: true, get: function () { return reducer_loaders_1.StringNativeLoader; } });
|
|
48
|
+
// Example configurations
|
|
49
|
+
exports.exampleConfigs = {
|
|
50
|
+
weather: {
|
|
51
|
+
digestPrompt: `Tu es un expert en analyse de données météorologiques.
|
|
52
|
+
Analyse ce chunk de données météo et extrais:
|
|
53
|
+
- Les types de météo présents (ensoleillé, pluvieux, nuageux, neigeux, orageux)
|
|
54
|
+
- Le nombre d'entrées par type
|
|
55
|
+
- Les IDs associés à chaque type
|
|
56
|
+
|
|
57
|
+
Réponds en JSON strict avec la structure:
|
|
58
|
+
{
|
|
59
|
+
"weatherTypes": {
|
|
60
|
+
"ensoleillé": {"count": N, "ids": [...]},
|
|
61
|
+
"pluvieux": {"count": N, "ids": [...]}
|
|
62
|
+
}
|
|
63
|
+
}`,
|
|
64
|
+
reducePrompt: `Tu es un expert en consolidation de données météorologiques.
|
|
65
|
+
Synthétise toutes les analyses météo en un résultat consolidé:
|
|
66
|
+
- Fusionne tous les types de météo
|
|
67
|
+
- Additionne les counts
|
|
68
|
+
- Combine les IDs (sans doublons)
|
|
69
|
+
- Calcule les totaux par type
|
|
70
|
+
|
|
71
|
+
Réponds en JSON avec la structure finale consolidée.`
|
|
72
|
+
},
|
|
73
|
+
foods: {
|
|
74
|
+
digestPrompt: `Tu es un expert en nutrition végétarienne.
|
|
75
|
+
Analyse cette liste d'aliments et identifie:
|
|
76
|
+
- Les aliments végétariens/vegan
|
|
77
|
+
- Leur catégorie (légumes, fruits, céréales, légumineuses, etc.)
|
|
78
|
+
- Leur valeur nutritionnelle approximative
|
|
79
|
+
|
|
80
|
+
Réponds en JSON strict avec les aliments sélectionnés.`,
|
|
81
|
+
reducePrompt: `Tu es un expert en nutrition végétarienne.
|
|
82
|
+
Crée une sélection équilibrée d'aliments végétariens/vegan:
|
|
83
|
+
- Distribution équilibrée entre catégories
|
|
84
|
+
- Maximum 50 aliments
|
|
85
|
+
- Priorité aux aliments nutritifs et variés
|
|
86
|
+
|
|
87
|
+
Réponds avec la liste finale sélectionnée en JSON.`
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
// Usage examples
|
|
91
|
+
exports.examples = {
|
|
92
|
+
/**
|
|
93
|
+
* Example: Weather data analysis
|
|
94
|
+
*/
|
|
95
|
+
async weatherAnalysis(weatherFilePath) {
|
|
96
|
+
const { FileNativeLoader } = await Promise.resolve().then(() => __importStar(require('./reducer.loaders')));
|
|
97
|
+
const { MapLLM } = await Promise.resolve().then(() => __importStar(require('./reducer.core')));
|
|
98
|
+
const loader = new FileNativeLoader(weatherFilePath, { type: 'lines', size: 50 });
|
|
99
|
+
const mapper = new MapLLM(loader);
|
|
100
|
+
return await mapper.reduce(exports.exampleConfigs.weather, {
|
|
101
|
+
verbose: true,
|
|
102
|
+
maxRetries: 3
|
|
103
|
+
});
|
|
104
|
+
},
|
|
105
|
+
/**
|
|
106
|
+
* Example: Food selection from string content
|
|
107
|
+
*/
|
|
108
|
+
async foodSelection(foodListContent) {
|
|
109
|
+
const { StringNativeLoader } = await Promise.resolve().then(() => __importStar(require('./reducer.loaders')));
|
|
110
|
+
const { MapLLM } = await Promise.resolve().then(() => __importStar(require('./reducer.core')));
|
|
111
|
+
const loader = new StringNativeLoader(foodListContent, { type: 'lines', size: 100 });
|
|
112
|
+
const mapper = new MapLLM(loader);
|
|
113
|
+
return await mapper.reduce(exports.exampleConfigs.foods, {
|
|
114
|
+
verbose: true,
|
|
115
|
+
maxDigestSize: 3000
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./reducer.core"), exports);
|
|
18
|
+
__exportStar(require("./reducer.loaders"), exports);
|
|
19
|
+
__exportStar(require("./reducer.types"), exports);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Loaders for MapLLM
|
|
3
|
+
*/
|
|
4
|
+
import type { NativeLoader, ChunkStrategy } from './reducer.types';
|
|
5
|
+
/**
|
|
6
|
+
* FileNativeLoader - Loader pour fichiers avec chunking par lignes
|
|
7
|
+
*/
|
|
8
|
+
export declare class FileNativeLoader implements NativeLoader {
|
|
9
|
+
private chunks;
|
|
10
|
+
constructor(filePath: string, strategy?: ChunkStrategy);
|
|
11
|
+
loadNativeChunk(position: number): Promise<{
|
|
12
|
+
content: string;
|
|
13
|
+
eof: boolean;
|
|
14
|
+
position: number;
|
|
15
|
+
}>;
|
|
16
|
+
private createChunks;
|
|
17
|
+
private chunkByLines;
|
|
18
|
+
private chunkByParagraphs;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* StringNativeLoader - Loader pour contenu en mémoire
|
|
22
|
+
*/
|
|
23
|
+
export declare class StringNativeLoader implements NativeLoader {
|
|
24
|
+
private chunks;
|
|
25
|
+
constructor(content: string, strategy?: ChunkStrategy);
|
|
26
|
+
loadNativeChunk(position: number): Promise<{
|
|
27
|
+
content: string;
|
|
28
|
+
eof: boolean;
|
|
29
|
+
position: number;
|
|
30
|
+
}>;
|
|
31
|
+
private createChunks;
|
|
32
|
+
private chunkByLines;
|
|
33
|
+
private chunkByParagraphs;
|
|
34
|
+
}
|