OrkaJS
Orka.JS

Chaînes

Des chaînes pré-construites pour les patterns LLM courants : question-réponse sur documents, récupération conversationnelle avec mémoire, et résumé multi-stratégie. Chaque chaîne orchestre la récupération, la construction de contexte et la génération en un seul appel.

Pourquoi des Chaînes ?

Construire un pipeline RAG from scratch nécessite plusieurs étapes : récupérer les documents, construire le contexte, formater les prompts, appeler le LLM et gérer les erreurs. Les chaînes encapsulent ces patterns dans des composants réutilisables et testés avec une observabilité intégrée via les étapes intermédiaires.

RetrievalQA

RetrievalQA

Synchro Sans État

"Flux direct requête-réponse pour bases de connaissances."

Conversational

Conversational

Gestion du Contexte

"Maintient l'état du dialogue via un historique persistant."

Summarization

Summarization

Optimiseur de Tokens

"Traite de gros volumes via logique Stuff ou Map-Reduce."

QA Chain

QA Chain

Logique Avancée

"Prompts personnalisés et stratégies de retrieval multi-étapes."

# RetrievalQAChain

La chaîne la plus simple pour le question-réponse sur documents. Elle récupère les documents pertinents, construit une fenêtre de contexte et génère une réponse en un seul appel. Parfaite pour les requêtes simples sur une base de connaissances.

import { RetrievalQAChain, VectorRetriever } from '@orka-js/tools';
import { OpenAIAdapter } from '@orka-js/openai';
 
const llm = new OpenAIAdapter({ apiKey: process.env.OPENAI_API_KEY! });
 
const retriever = new VectorRetriever({
llm,
vectorDB: myVectorDB,
topK: 5
});
 
const chain = new RetrievalQAChain({
llm,
retriever,
collection: 'documentation',
returnSources: true, // Inclut les documents sources dans le résultat
maxSourceTokens: 3000, // Max de tokens pour la fenêtre de contexte
systemPrompt: 'Tu es un assistant utile. Réponds uniquement sur la base du contexte fourni.'
});
 
const result = await chain.call('How do I configure authentication?');
 
console.log(result.answer);
// "Pour configurer l'authentification, vous devez..."
 
console.log(result.sources);
// [{ id: 'doc-1', score: 0.92, content: '...' }, ...]
 
console.log(result.intermediateSteps);
// [
// { name: 'retrieve', input: '...', output: 'Found 5 relevant documents', latencyMs: 120 },
// { name: 'generate', input: '...', output: '...', latencyMs: 850 }
// ]
 
console.log(result.usage);
// { promptTokens: 1200, completionTokens: 350, totalTokens: 1550 }

Intermediate StepsÉtapes Intermédiaires

Chaque chaîne retourne intermediateSteps avec le nom, l'entrée, la sortie et la latence de chaque étape. Cela vous donne une observabilité complète de l'exécution de la chaîne — utile pour le débogage, le monitoring et l'optimisation.

# ConversationalRetrievalChain

Étend RetrievalQA avec la mémoire conversationnelle. Elle condense automatiquement les questions de suivi en utilisant l'historique du chat, pour que le retriever reçoive une requête autonome même quand l'utilisateur demande "Et le deuxième ?" ou "Peux-tu expliquer plus ?". La chaîne maintient son propre historique de chat en interne.

import { ConversationalRetrievalChain } from '@orka-js/tools';
 
const chain = new ConversationalRetrievalChain({
llm,
retriever,
collection: 'documentation',
returnSources: true,
maxHistoryLength: 10, // Garde les 10 derniers messages en contexte
// Optionnel: personnalisez la condensation des questions de suivi
condenseQuestionPrompt: `Given the following conversation and a follow-up question,
rephrase the follow-up as a standalone question.
 
Chat History:
{{history}}
 
Follow-up: {{question}}
 
Standalone Question:`
});
 
// Première question — récupération normale
const result1 = await chain.call('What authentication methods are supported?');
console.log(result1.answer);
// "Orka JS supporte JWT, OAuth2 et API key authentication..."
 
// Suivi — automatiquement condensé avec l'historique
const result2 = await chain.call('How do I configure the second one?');
// Internally condensed to: "How do I configure OAuth2 authentication?"
console.log(result2.answer);
// "Pour configurer OAuth2, vous devez configurer..."
 
// Un autre suivi
const result3 = await chain.call('What are the required scopes?');
// Condensed to: "What are the required OAuth2 scopes?"
console.log(result3.answer);
// "Les scopes requis sont: openid, profile, email..."
 
// Vérifiez les étapes intermédiaires pour voir la question condensée
console.log(result2.intermediateSteps);
// [
// { name: 'condense_question', input: 'How do I configure the second one?',
// output: 'How do I configure OAuth2 authentication?' },
// { name: 'retrieve', ... },
// { name: 'generate', ... }
// ]
 
// Gérer l'historique
console.log(chain.getChatHistory());
// [{ role: 'user', content: '...' }, { role: 'assistant', content: '...' }, ...]
 
// Réinitialiser la conversation
chain.clearHistory();

Requête Contextuelle

L'utilisateur pose une question de suivi (ex: 'Et le deuxième ?') qui dépend des échanges précédents.

Step 1: InputAmbiguous User Input

Condensation Sémantique

Le LLM analyse l'historique pour réécrire la requête en version autonome : 'Comment configurer OAuth2 ?'

Step 2: CondenseLLM Pre-processing

Recherche de Connaissances

Le retriever utilise la question autonome condensée pour récupérer les documents les plus pertinents.

Step 3: RetrievalVector Lookup

Génération Finale

Le LLM synthétise le contexte récupéré et l'historique complet pour fournir une réponse précise.

Step 4: ResponseContextual Answer

# SummarizationChain

Résume un ou plusieurs documents en utilisant trois stratégies différentes, chacune avec des compromis différents pour la qualité, la vitesse et le coût.

Injection Linéaire

Stuffing Stuffing

Regroupe tous les chunks dans un seul contexte. Exécution instantanée mais se heurte aux limites de tokens.

LatenceUltra-Low
Docs Atomiques
Traitement Parallèle

Map-Reduce Map-Reduce

Résume les chunks en parallèle, puis les distille. Idéal pour les datasets massifs et l'extensibilité infinie.

ScalabilitéInfinite
Gros Volumes
Polissage Itératif

Refine Refine

Parcourt les chunks pour affiner le résultat. Meilleure rétention des nuances mais plus lent (séquentiel).

CohérenceMax
Haute Précision

- Stratégie Stuff

import { SummarizationChain } from '@orka-js/tools';
 
// Stuff: tous les documents dans une seule prompt
const stuffChain = new SummarizationChain({
llm,
strategy: 'stuff',
systemPrompt: 'Provide a clear and concise summary.'
});
 
const result = await stuffChain.call([
'Document 1 content here...',
'Document 2 content here...',
'Document 3 content here...'
]);
 
console.log(result.answer); // Résumé combiné
console.log(result.usage); // Utilisation des tokens (1 appel LLM)

- Stratégie Map-Reduce

// Map-Reduce: résume les chunks indépendamment, puis combine
const mapReduceChain = new SummarizationChain({
llm,
strategy: 'map-reduce',
maxChunkSize: 3000, // Divise les gros documents en chunks de 3000 caractères
combinePrompt: Combine les résumés suivants en un résumé cohérent:\n\n{{summaries}}\n\nRésumé Combiné:
});
 
const result = await mapReduceChain.call([
veryLongDocument1, // 50 000 caractères
veryLongDocument2 // 30 000 caractères
]);
 
console.log(result.answer);// Résumé combiné final
console.log(result.intermediateSteps);
// [
// { name: 'map_chunk_0', ... }, // Résumé du chunk 1
// { name: 'map_chunk_1', ... }, // Résumé du chunk 2
// ...
// { name: 'reduce_combine', ... } // Final combined summary
// ]

- Stratégie Refine

// Refine: améliore itérativement le résumé avec chaque chunk
const refineChain = new SummarizationChain({
llm,
strategy: 'refine',
maxChunkSize: 3000,
refinePrompt: `Voici un résumé existant:
{{existingSummary}}
 
Affine ce résumé avec le contexte supplémentaire suivant:
{{context}}
 
Résumé Affiné:`
});
 
const result = await refineChain.call([longDocument]);
 
console.log(result.answer);// Résumé final affiné
console.log(result.intermediateSteps);
// [
// { name: 'initial_summary', ... }, // Résumé du premier chunk
// { name: 'refine_1', ... }, // Affiné avec le chunk 2
// { name: 'refine_2', ... }, // Affiné avec le chunk 3
// ...
// ]

# QAChain — Question-Réponse Avancé

QAChain combine la récupération avec le question-réponse multi-stratégie. Contrairement à RetrievalQAChain qui utilise toujours l'approche "stuff", QAChain supporte les stratégies stuff, map-reduce et refine pour répondre aux questions sur de grands ensembles de documents.

import { QAChain } from '@orka-js/tools';
 
// Stratégie Stuff (par défaut) — rapide, pour petits ensembles de documents
const stuffQA = new QAChain({
llm,
retriever,
collection: 'docs',
strategy: 'stuff',
returnSources: true
});
 
const result1 = await stuffQA.call(Quel est le taux de limitation?);
 
// Stratégie Map-Reduce — pour de nombreux documents récupérés
const mapReduceQA = new QAChain({
llm,
retriever,
collection: 'docs',
strategy: 'map-reduce',
returnSources: true,
systemPrompt: Réponds précisément basé sur les documents. Cite les sources quand c'est possible.
});
 
const result2 = await mapReduceQA.call(Compare toutes les méthodes d'authentification);
// Map : extrait les informations pertinentes de chaque document
// Reduce : combine en une réponse complète
 
// Stratégie Refine — meilleure qualité pour questions complexes
const refineQA = new QAChain({
llm,
retriever,
collection: 'docs',
strategy: 'refine',
returnSources: true
});
 
const result3 = await refineQA.call(Explique le processus de déploiement complet étape par étape);
// Commence avec la réponse du premier doc, affine avec chaque doc supplémentaire

Exemple Complet — Pipeline RAG Production

import { createOrka } from '@orka-js/core';
import { OpenAIAdapter } from '@orka-js/openai';
import {
EnsembleRetriever,
VectorRetriever,
BM25Retriever,
ConversationalRetrievalChain,
SummarizationChain
} from '@orka-js/tools';
import { MemoryCache, CachedLLM } from '@orka-js/cache';
 
// Configuration avec mise en cache
const baseLLM = new OpenAIAdapter({ apiKey: process.env.OPENAI_API_KEY! });
const llm = new CachedLLM(baseLLM, new MemoryCache({ maxSize: 500 }));
 
const orka = createOrka({ llm, vectorDB: myVectorDB });
 
// Récupérateur hybride (BM25 + Vector)
const hybrid = new EnsembleRetriever({
retrievers: [
new BM25Retriever({ documents: myDocs, topK: 10 }),
new VectorRetriever({ llm, vectorDB: myVectorDB, topK: 10 })
],
weights: [0.3, 0.7],
topK: 5
});
 
// Chaîne conversationnelle avec récupérateur hybride
const chatChain = new ConversationalRetrievalChain({
llm,
retriever: hybrid,
collection: 'documentation',
returnSources: true,
maxHistoryLength: 10
});
 
// Gérer la conversation utilisateur
async function handleMessage(userMessage: string) {
const result = await chatChain.call(userMessage);
 
return {
answer: result.answer,
sources: result.sources?.map(s => ({
id: s.id,
score: s.score,
preview: s.content?.slice(0, 100)
})),
steps: result.intermediateSteps
};
}
 
// Résumer de longs documents
const summarizer = new SummarizationChain({
llm,
strategy: 'map-reduce',
maxChunkSize: 3000
});
 
async function summarizeDocuments(texts: string[]) {
const result = await summarizer.call(texts);
return result.answer;
}

Comparaison

Moteur de ChaineUsage CibleÉtat / MémoireLogiques Disponibles
RetrievalQAQ&R unitaire sur documentsStateless
stuff
ConversationalAgents de support contextuels
Stateful
stuff
SummarizationDistillation de contenus massifsStateless
stuffmap-reducerefine
QAChainAnalyse haute-fidélitéStateless
stuffmap-reducerefine

Comparaison des Stratégies de Résumé

Stratégie d'AgrégationCoût de CalculFidélité de SortieCapacité
Stuffing
1LLM Calls
Baseline
Lié au contexte
Map-Reduce
N + 1LLM Calls
Parallelized
Unlimited
Refine
N (Sequential)LLM Calls
State-of-the-Art
Unlimited

💡 Bonnes Pratiques

1. Commencez avec RetrievalQA

Pour la plupart des cas d'usage, RetrievalQAChain suffit. Passez à ConversationalRetrievalChain uniquement quand vous avez besoin de conversations multi-tours.

2. Utilisez la Récupération Hybride

Combinez BM25 + VectorRetriever dans un EnsembleRetriever pour les meilleurs résultats. La correspondance de mots-clés capture les termes exacts que la recherche sémantique pourrait manquer.

3. Surveillez les Étapes Intermédiaires

Utilisez intermediateSteps pour déboguer la qualité de récupération, identifier les étapes lentes et optimiser votre pipeline.

4. Choisissez la Bonne Stratégie de Résumé

Utilisez 'stuff' pour les documents courts (<4K tokens), 'map-reduce' pour le traitement parallèle de gros docs, et 'refine' quand la qualité du résumé est critique.

Imports Tree-shakeable

// ✅ Importez uniquement ce dont vous avez besoin
import { RetrievalQAChain } from '@orka-js/tools';
import { ConversationalRetrievalChain } from '@orka-js/tools';
import { SummarizationChain } from '@orka-js/tools';
import { QAChain } from '@orka-js/tools';
 
// ✅ Ou importez depuis l'index
import { RetrievalQAChain, ConversationalRetrievalChain, SummarizationChain, QAChain } from '@orka-js/tools';