tasq/node_modules/agentic-flow/dist/reasoningbank/HybridBackend.js

306 lines
12 KiB
JavaScript

/**
* Hybrid ReasoningBank Backend - Full Implementation for v1.7.1
*
* Combines Rust WASM (compute) + AgentDB TypeScript (storage) for optimal performance:
* - WASM: 10x faster similarity computation
* - AgentDB: Persistent SQLite storage with frontier memory
* - CausalRecall: Utility-based reranking with causal uplift
* - Automatic backend selection based on task requirements
*
* @example
* ```typescript
* import { HybridReasoningBank } from 'agentic-flow/reasoningbank';
*
* const rb = new HybridReasoningBank({ preferWasm: true });
* await rb.storePattern({ task: '...', success: true, reward: 0.95 });
* const patterns = await rb.retrievePatterns('similar task', { k: 5 });
* const strategy = await rb.learnStrategy('API optimization');
* ```
*/
import { SharedMemoryPool } from '../memory/SharedMemoryPool.js';
import { ReflexionMemory } from 'agentdb/controllers/ReflexionMemory';
import { SkillLibrary } from 'agentdb/controllers/SkillLibrary';
import { CausalRecall } from 'agentdb/controllers/CausalRecall';
import { CausalMemoryGraph } from 'agentdb/controllers/CausalMemoryGraph';
export class HybridReasoningBank {
memory;
reflexion;
skills;
causalRecall;
causalGraph;
useWasm;
wasmModule;
constructor(options = {}) {
this.memory = SharedMemoryPool.getInstance();
const db = this.memory.getDatabase();
const embedder = this.memory.getEmbedder();
this.reflexion = new ReflexionMemory(db, embedder);
this.skills = new SkillLibrary(db, embedder);
this.causalGraph = new CausalMemoryGraph(db);
// CausalRecall with optimized rerank config
this.causalRecall = new CausalRecall(db, embedder, {
alpha: 0.6, // 60% weight on similarity
beta: 0.3, // 30% weight on causal uplift
gamma: 0.1, // 10% penalty for latency
minConfidence: 0.7
});
this.useWasm = options.preferWasm ?? true;
this.wasmModule = null;
// Try to load WASM module
if (this.useWasm) {
this.loadWasmModule().catch(err => {
console.warn('[HybridReasoningBank] WASM unavailable, using TypeScript:', err.message);
this.useWasm = false;
});
}
}
async loadWasmModule() {
try {
// Dynamic import for WASM module
const wasm = await import('../../wasm/reasoningbank/reasoningbank_wasm.js');
this.wasmModule = wasm;
console.log('[HybridReasoningBank] WASM module loaded successfully');
}
catch (error) {
throw new Error(`WASM load failed: ${error}`);
}
}
/**
* Store a reasoning pattern
*/
async storePattern(pattern) {
const episodeId = await this.reflexion.storeEpisode(pattern);
// Store causal edge if action led to outcome
if (pattern.input && pattern.output && pattern.success) {
try {
this.causalGraph.addCausalEdge({
fromMemoryId: episodeId,
fromMemoryType: 'episode',
toMemoryId: episodeId + 1, // Next episode
toMemoryType: 'episode',
similarity: pattern.reward,
uplift: pattern.success ? pattern.reward : -pattern.reward,
confidence: 0.8,
sampleSize: 1,
metadata: {
sessionId: pattern.sessionId,
task: pattern.task
}
});
}
catch (error) {
console.warn('[HybridReasoningBank] Failed to record causal edge:', error);
}
}
return episodeId;
}
/**
* Retrieve similar patterns with optional WASM acceleration
*/
async retrievePatterns(query, options = {}) {
const { k = 5, minReward, onlySuccesses, onlyFailures } = options;
// Check cache first
const cacheKey = `retrieve:${query}:${k}:${onlySuccesses}:${onlyFailures}`;
const cached = this.memory.getCachedQuery(cacheKey);
if (cached)
return cached;
// Use CausalRecall for intelligent retrieval with utility-based ranking
try {
const result = await this.causalRecall.recall(`query-${Date.now()}`, query, k, undefined, // requirements
'public' // accessLevel
);
// Convert candidates to pattern format and filter
let patterns = result.candidates.map(c => ({
task: c.content,
similarity: c.similarity,
uplift: c.uplift || 0,
utilityScore: c.utilityScore,
type: c.type,
id: c.id
}));
// Apply filters
if (minReward !== undefined) {
patterns = patterns.filter(p => (p.uplift || 0) >= minReward);
}
// Cache and return
this.memory.cacheQuery(cacheKey, patterns, 60000);
return patterns;
}
catch (error) {
console.warn('[HybridReasoningBank] CausalRecall failed, falling back to ReflexionMemory:', error);
// Fallback to basic ReflexionMemory
const results = await this.reflexion.retrieveRelevant({
task: query,
k,
minReward,
onlySuccesses,
onlyFailures
});
this.memory.cacheQuery(cacheKey, results, 60000);
return results;
}
}
/**
* Learn optimal strategy for a task
*
* Combines pattern retrieval with causal analysis to provide evidence-based recommendations
*/
async learnStrategy(task) {
// Get successful patterns
const patterns = await this.retrievePatterns(task, { k: 10, onlySuccesses: true });
// Get causal effects for this task type
let causalData;
try {
// Note: queryCausalEffects requires specific memory IDs
// For task-level analysis, we'll use pattern success rates instead
const stats = await this.reflexion.getTaskStats(task, 30);
if (stats.totalAttempts > 0) {
causalData = {
action: task,
avgReward: stats.avgReward || 0,
avgUplift: stats.improvementTrend || 0,
confidence: Math.min(stats.totalAttempts / 10, 1.0),
evidenceCount: stats.totalAttempts,
recommendation: (stats.improvementTrend || 0) > 0.1 ? 'DO_IT' :
(stats.improvementTrend || 0) < -0.1 ? 'AVOID' : 'NEUTRAL'
};
}
}
catch (error) {
console.warn('[HybridReasoningBank] Causal analysis failed:', error);
}
// Fallback if no causal data
if (!causalData) {
causalData = {
action: task,
avgReward: patterns.length > 0 ? (patterns[0].reward || 0) : 0,
avgUplift: 0,
confidence: patterns.length > 0 ? 0.6 : 0.3,
evidenceCount: patterns.length,
recommendation: patterns.length > 0 ? 'DO_IT' : 'NEUTRAL'
};
}
// Calculate overall confidence
const patternConf = Math.min(patterns.length / 10, 1.0); // 10+ patterns = full confidence
const causalConf = causalData.confidence;
const confidence = 0.6 * patternConf + 0.4 * causalConf;
// Generate recommendation
let recommendation = '';
if (confidence > 0.8 && causalData.avgUplift > 0.1) {
recommendation = `Strong evidence for success (${patterns.length} patterns, +${(causalData.avgUplift * 100).toFixed(1)}% uplift)`;
}
else if (confidence > 0.5) {
recommendation = `Moderate evidence (${patterns.length} patterns available)`;
}
else {
recommendation = `Limited evidence - proceed with caution`;
}
return {
patterns,
causality: causalData,
confidence,
recommendation
};
}
/**
* Auto-consolidate patterns into skills
*/
async autoConsolidate(minUses = 3, minSuccessRate = 0.7, lookbackDays = 30) {
// Get task statistics
const stats = await this.reflexion.getTaskStats('', lookbackDays);
if (stats.totalAttempts < minUses || stats.successRate < minSuccessRate) {
return { skillsCreated: 0 };
}
// Get successful episodes for consolidation
const episodes = await this.reflexion.retrieveRelevant({
task: '',
k: 50,
onlySuccesses: true,
timeWindowDays: lookbackDays
});
// Group by task type and consolidate
const taskGroups = new Map();
episodes.forEach(ep => {
const group = taskGroups.get(ep.task) || [];
group.push(ep);
taskGroups.set(ep.task, group);
});
let skillsCreated = 0;
for (const [task, group] of taskGroups) {
if (group.length >= minUses) {
const successRate = group.filter(e => e.success).length / group.length;
if (successRate >= minSuccessRate) {
await this.skills.createSkill({
name: `skill_${task.replace(/\s+/g, '_').toLowerCase()}`,
description: `Consolidated from ${group.length} successful episodes`,
signature: { inputs: {}, outputs: {} },
successRate,
uses: group.length,
avgReward: group.reduce((sum, e) => sum + e.reward, 0) / group.length,
avgLatencyMs: group.reduce((sum, e) => sum + (e.latencyMs || 0), 0) / group.length,
metadata: { consolidatedAt: Date.now(), taskType: task }
});
skillsCreated++;
}
}
}
return { skillsCreated };
}
/**
* What-if causal analysis
*/
async whatIfAnalysis(action) {
try {
// Use task statistics for what-if analysis
const stats = await this.reflexion.getTaskStats(action, 30);
if (stats.totalAttempts === 0) {
return {
action,
avgReward: 0,
avgUplift: 0,
confidence: 0,
evidenceCount: 0,
recommendation: 'NEUTRAL'
};
}
const avgUplift = stats.improvementTrend || 0;
const confidence = Math.min(stats.totalAttempts / 10, 1.0);
return {
action,
avgReward: stats.avgReward || 0,
avgUplift,
confidence,
evidenceCount: stats.totalAttempts,
recommendation: avgUplift > 0.1 ? 'DO_IT' : avgUplift < -0.1 ? 'AVOID' : 'NEUTRAL'
};
}
catch (error) {
console.error('[HybridReasoningBank] What-if analysis failed:', error);
return {
action,
avgReward: 0,
avgUplift: 0,
confidence: 0,
evidenceCount: 0,
recommendation: 'NEUTRAL'
};
}
}
/**
* Search for relevant skills
*/
async searchSkills(taskType, k = 5) {
return this.skills.searchSkills({ task: taskType, k, minSuccessRate: 0.5 });
}
/**
* Get statistics
*/
getStats() {
return {
causalRecall: this.causalRecall.getStats(),
reflexion: {}, // ReflexionMemory doesn't expose global stats
skills: 0 // Would need to query database
};
}
}
//# sourceMappingURL=HybridBackend.js.map