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 timeoutsconst 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 automatiqueconst 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-fournisseurconst 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 à Orkaif (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émarrageconst 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 conversationsconst 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 tokensconst 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'agentagent.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 APIconst 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 chevauchementawait 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 chevauchementawait 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ésultatsconsole.log('Average relevance:', results.summary.relevance.mean);console.log('Average faithfulness:', results.summary.faithfulness.mean); // Échouer la CI si la qualité descend sous le seuilif (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 → Fallbackimport { 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'erreurs | Intercepter OrkaError par code | Try/catch générique avec console.log |
| Timeouts | Définir timeoutMs sur chaque adaptateur | Se fier au timeout infini par défaut |
| Agents SQL | readOnly: true + fournir le schéma | readOnly: false en production |
| Cache | RedisCache avec TTL en production | Pas de cache pour les requêtes répétées |
| Traçage | Définir maxTraces + traceTtlMs | Traces illimitées dans les apps longue durée |
| Imports | Imports par sous-chemin pour le tree-shaking | Import * depuis la racine |
| Clés API | Variables d'environnement | Codées en dur dans le code source |
| Mémoire | Choisir la stratégie par cas d'utilisation | Historique de messages illimité |