OrkaJS
Orka.JS

Bonnes Pratiques

Patterns essentiels et recommandations pour construire des applications IA robustes, sécurisées et maintenables avec Orka.

1. Gestion Structurée des Erreurs

Orka fournit une hiérarchie d'erreurs personnalisée (OrkaError) avec des codes d'erreur et un contexte de module. Interceptez toujours les erreurs par type pour gérer les différents modes de défaillance de manière appropriée — les timeouts réseau, les limites de débit et les erreurs de validation nécessitent chacun des stratégies de récupération différentes.

import { OrkaError, OrkaErrorCode } from 'orkajs/errors';
 
try {
const result = await orka.ask({
knowledge: 'docs',
question: 'What is Orka?',
});
} catch (error) {
if (OrkaError.isOrkaError(error)) {
switch (error.code) {
case OrkaErrorCode.LLM_TIMEOUT:
// Réessayer avec un timeout plus long ou un fournisseur de secours
console.warn(`Timeout on ${error.module}: ${error.message}`);
break;
case OrkaErrorCode.LLM_RATE_LIMIT:
// Attendre et réessayer après un délai
await delay(5000);
break;
case OrkaErrorCode.KNOWLEDGE_SEARCH_ERROR:
// Se rabattre sur un appel LLM direct sans RAG
break;
default:
// Logger et propager
console.error(error.toJSON());
throw error;
}
}
}

Conseil : Utilisez OrkaError.isRetryable(error) pour déterminer rapidement si une erreur est transitoire et peut être réessayée automatiquement.

2. Résilience : Retry + Fallback + Timeout

Les applications LLM en production doivent gérer les défaillances transitoires avec élégance. Orka fournit trois mécanismes de résilience complémentaires qui peuvent être composés ensemble : ResilientLLM (retry automatique avec backoff exponentiel), FallbackLLM (basculement multi-fournisseur) et timeouts par adaptateur.

import { OpenAIAdapter } from 'orkajs/adapters/openai';
import { AnthropicAdapter } from 'orkajs/adapters/anthropic';
import { ResilientLLM } from 'orkajs/resilience';
import { FallbackLLM } from 'orkajs/resilience';
 
// Étape 1 : Configurer les adaptateurs avec des timeouts
const openai = new OpenAIAdapter({
apiKey: process.env.OPENAI_API_KEY!,
timeoutMs: 30_000, // 30s timeout
});
 
const anthropic = new AnthropicAdapter({
apiKey: process.env.ANTHROPIC_API_KEY!,
timeoutMs: 45_000,
});
 
// Étape 2 : Envelopper avec retry automatique
const resilientOpenAI = new ResilientLLM({
llm: openai,
retry: {
maxRetries: 3,
initialDelayMs: 1000,
backoffMultiplier: 2,
},
onRetry: (error, attempt) => {
console.warn(`Retry #${attempt}: ${error.message}`);
},
});
 
// Étape 3 : Ajouter un fallback multi-fournisseur
const llm = new FallbackLLM({
adapters: [resilientOpenAI, anthropic],
onFallback: (error, adapterName) => {
console.warn(`Falling back from ${adapterName}: ${error.message}`);
},
});

Cette approche en couches garantit : (1) les erreurs transitoires sont réessayées automatiquement, (2) les défaillances persistantes déclenchent un basculement vers un fournisseur alternatif, et (3) aucune requête ne reste bloquée indéfiniment grâce aux timeouts.

3. Bonnes Pratiques de Sécurité

- Prévention des Injections SQL

Lors de l'utilisation de SQLToolkit, activez toujours le mode readOnly en production. Le SQLToolkit d'Orka valide automatiquement les noms de tables (alphanumériques + underscores uniquement), bloque les mots-clés SQL dangereux (DROP, DELETE, ALTER, etc.) et empêche les attaques par injection multi-instructions.

import { SQLToolkit } from 'orkajs/agent/toolkits/sql';
 
const sqlToolkit = new SQLToolkit({
execute: (query) => db.query(query),
readOnly: true, // TOUJOURS activer en production
maxRows: 50, // Limiter la taille des résultats
schema: schemaString, // Fournir le schéma pour éviter les requêtes dynamiques
});

- Validation d'URL (Protection SSRF)

Lors de l'ingestion de connaissances depuis des URLs, Orka valide automatiquement que seuls les protocoles http/https sont utilisés, impose un timeout de 30 secondes et limite la taille de la réponse à 50 Mo. Ne passez jamais d'URLs contrôlées par l'utilisateur directement sans validation supplémentaire dans votre couche applicative.

// Orka gère cela en interne, mais ajoutez votre propre liste blanche pour les apps utilisateur :
const ALLOWED_DOMAINS = ['docs.example.com', 'wiki.internal.com'];
 
function validateUserUrl(url: string): boolean {
try {
const parsed = new URL(url);
return ALLOWED_DOMAINS.includes(parsed.hostname);
} catch {
return false;
}
}
 
// Puis utilisez-la avant de passer à Orka
if (validateUserUrl(userProvidedUrl)) {
await orka.knowledge.add('docs', { url: userProvidedUrl });
}

- Gestion des Clés API

Ne codez jamais les clés API en dur. Utilisez des variables d'environnement et validez leur présence au démarrage.

// Valider au démarrage
const requiredEnvVars = ['OPENAI_API_KEY', 'PINECONE_API_KEY'];
for (const envVar of requiredEnvVars) {
if (!process.env[envVar]) {
throw new Error(`Missing required environment variable: ${envVar}`);
}
}

4. Gestion de la Mémoire

Choisissez la bonne stratégie de mémoire selon votre cas d'utilisation. Orka fournit trois stratégies : sliding_window (garde les N messages les plus récents), buffer (garde les messages jusqu'à une limite de tokens) et summary (compresse les anciens messages en un résumé pour préserver le contexte tout en réduisant la taille).

import { Memory } from 'orkajs/memory';
 
// Pour les chatbots : utiliser summary pour préserver le contexte des longues conversations
const chatMemory = new Memory({
strategy: 'summary',
maxMessages: 20,
summaryThreshold: 8, // Résumer quand 8+ messages débordent
});
 
// Pour les tâches courtes : utiliser sliding_window pour la simplicité
const taskMemory = new Memory({
strategy: 'sliding_window',
maxMessages: 10,
});
 
// Pour les apps sensibles aux tokens : utiliser buffer avec estimation de tokens
const tokenMemory = new Memory({
strategy: 'buffer',
maxTokensEstimate: 2000,
});

Multi-session : Utilisez SessionMemory pour les applications multi-utilisateurs. Il gère des instances Memory séparées par session avec un nettoyage automatique basé sur le TTL.

5. Observabilité & Traçage

Configurez toujours le Tracer avec des limites en production pour éviter les fuites mémoire. Définissez maxTraces pour plafonner les traces stockées et traceTtlMs pour expirer automatiquement les anciennes. Utilisez les hooks pour exporter les traces vers votre système de monitoring.

import { Tracer } from 'orkajs/observability';
 
const tracer = new Tracer({
logLevel: 'info',
maxTraces: 500, // Garder au maximum 500 traces en mémoire
traceTtlMs: 3600_000, // Expirer automatiquement les traces après 1 heure
hooks: [{
onTraceEnd: (trace) => {
// Exporter vers votre système de monitoring
metrics.recordLatency(trace.name, trace.totalLatencyMs);
metrics.recordTokens(trace.name, trace.totalTokens);
},
onError: (error, context) => {
errorTracker.capture(error, context);
},
}],
});

6. Écouteurs d'Événements d'Agent

Tous les agents (ReActAgent, OpenAIFunctionsAgent, StructuredChatAgent) étendent BaseAgent et supportent les écouteurs d'événements. Utilisez-les pour le logging, les métriques ou les mises à jour UI en temps réel.

import { ReActAgent } from 'orkajs/agent/react';
 
const agent = new ReActAgent(config, llm, memory);
 
// Écouter les événements du cycle de vie de l'agent
agent.on('step:start', (event) => {
console.log(`[Agent] Starting step for: ${event.agentType}`);
});
 
agent.on('tool:start', (event) => {
console.log(`[Agent] Calling tool: ${event.toolName}`);
});
 
agent.on('tool:error', (event) => {
console.error(`[Agent] Tool ${event.toolName} failed:`, event.error);
});
 
agent.on('complete', (event) => {
console.log(`[Agent] Completed:`, event.output);
});
 
const result = await agent.run('Analyze the sales data');

7. Stratégie de Cache

Mettre en cache les réponses LLM réduit considérablement les coûts et la latence. Utilisez MemoryCache pour le développement et RedisCache pour la production. Orka utilise le hachage SHA-256 pour les clés de cache, garantissant des recherches sans collision.

import { CachedLLM } from 'orkajs/cache';
import { RedisCache } from 'orkajs/cache';
 
// Production : utiliser Redis pour un cache persistant et partagé
const cache = new RedisCache({
url: process.env.REDIS_URL!,
keyPrefix: 'orka:llm:',
ttlMs: 3600_000, // TTL de 1 heure
});
 
const cachedLLM = new CachedLLM({
llm: openai,
cache,
ttlMs: 3600_000,
});
 
// Même prompt + options = cache hit (clé SHA-256)
const result1 = await cachedLLM.generate('What is TypeScript?'); // Appel API
const result2 = await cachedLLM.generate('What is TypeScript?'); // Cache hit !

8. Ingestion de Connaissances à Grande Échelle

Lors de l'ingestion de grandes collections de documents, configurez soigneusement la taille des chunks et le chevauchement. Des chunks plus petits améliorent la précision de la recherche mais augmentent le stockage. Des chunks plus grands préservent plus de contexte mais peuvent réduire le scoring de pertinence.

// Paramètres recommandés par cas d'utilisation :
 
// FAQ / Réponses courtes : petits chunks, faible chevauchement
await orka.knowledge.create({
name: 'faq',
source: { path: './faq-docs' },
chunkSize: 256,
chunkOverlap: 32,
});
 
// Docs techniques : chunks moyens, chevauchement modéré
await orka.knowledge.create({
name: 'technical',
source: { path: './technical-docs' },
chunkSize: 512,
chunkOverlap: 64,
});
 
// Juridique / Long format : grands chunks, fort chevauchement
await orka.knowledge.create({
name: 'legal',
source: { path: './contracts' },
chunkSize: 1024,
chunkOverlap: 128,
});

9. Tests & Évaluation

Utilisez le framework d'évaluation intégré d'Orka pour mesurer la qualité avant le déploiement. Définissez des jeux de données de test avec les sorties attendues et exécutez des évaluations automatisées avec plusieurs métriques.

const results = await orka.evaluate({
dataset: [
{ input: 'What is Orka?', expected: 'Orka is a TypeScript AI framework' },
{ input: 'How to install?', expected: 'npm install orkajs' },
],
metrics: ['relevance', 'faithfulness', 'completeness'],
concurrency: 3,
});
 
// Vérifier les résultats
console.log('Average relevance:', results.summary.relevance.mean);
console.log('Average faithfulness:', results.summary.faithfulness.mean);
 
// Échouer la CI si la qualité descend sous le seuil
if (results.summary.relevance.mean < 0.8) {
process.exit(1);
}

10. Recommandations d'Architecture

- Tree-Shaking : Importez Seulement Ce Dont Vous Avez Besoin

Orka supporte les exports par sous-chemin pour une taille de bundle optimale. Importez toujours depuis des modules spécifiques plutôt que depuis le package racine.

// Bien : imports spécifiques (tree-shakeable)
import { ReActAgent } from 'orkajs/agent/react';
import { OpenAIAdapter } from 'orkajs/adapters/openai';
import { JSONParser } from 'orkajs/parsers/json';
 
// Éviter : tout importer
// import { ReActAgent, OpenAIAdapter, JSONParser } from 'orkajs';

- Pattern de Composition d'Adaptateurs

Composez les adaptateurs comme des blocs de construction. Chaque wrapper ajoute une capacité sans modifier l'adaptateur sous-jacent.

// Composition : Timeout → Retry → Cache → Fallback
import { OpenAIAdapter } from 'orkajs/adapters/openai';
import { ResilientLLM, FallbackLLM } from 'orkajs/resilience';
import { CachedLLM, RedisCache } from 'orkajs/cache';
 
// OpenAI (with 30s timeout)
// → ResilientLLM (3 retries)
// → CachedLLM (Redis, 1h TTL)
// → FallbackLLM (+ Anthropic backup)
 
const openai = new OpenAIAdapter({ apiKey: '...', timeoutMs: 30_000 });
const resilient = new ResilientLLM({ llm: openai });
const cached = new CachedLLM({
llm: resilient,
cache: new RedisCache({ url: 'redis://...' }),
ttlMs: 3600_000,
});
const llm = new FallbackLLM({
adapters: [cached, new AnthropicAdapter({ apiKey: '...' })],
});

Référence Rapide

PratiqueÀ faireÀ éviter
Gestion d'erreursIntercepter OrkaError par codeTry/catch générique avec console.log
TimeoutsDéfinir timeoutMs sur chaque adaptateurSe fier au timeout infini par défaut
Agents SQLreadOnly: true + fournir le schémareadOnly: false en production
CacheRedisCache avec TTL en productionPas de cache pour les requêtes répétées
TraçageDéfinir maxTraces + traceTtlMsTraces illimitées dans les apps longue durée
ImportsImports par sous-chemin pour le tree-shakingImport * depuis la racine
Clés APIVariables d'environnementCodées en dur dans le code source
MémoireChoisir la stratégie par cas d'utilisationHistorique de messages illimité