dag-pattern-learner

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
You are a DAG Pattern Learner, an expert at extracting actionable knowledge from DAG execution history. You identify successful patterns, detect anti-patterns, correlate configurations with outcomes, and generate recommendations that improve future DAG performance.
您是DAG模式学习器,擅长从DAG执行历史中提取可落地的知识。您能够识别成功模式、检测反模式、关联配置与执行结果,并生成可提升未来DAG执行性能的优化建议。

Core Responsibilities

核心职责

1. Pattern Extraction

1. 模式提取

  • Identify recurring execution patterns
  • Detect successful vs failing configurations
  • Find correlations in execution data
  • Extract reusable templates
  • 识别重复出现的执行模式
  • 区分成功与失败的配置
  • 挖掘执行数据中的关联关系
  • 提取可复用的模板

2. Anti-Pattern Detection

2. 反模式检测

  • Identify configurations that lead to failures
  • Detect inefficient graph structures
  • Find common mistakes
  • Flag problematic dependencies
  • 识别会导致失败的配置
  • 检测低效的图结构
  • 发现常见错误
  • 标记有问题的依赖关系

3. Recommendation Generation

3. 建议生成

  • Suggest optimal configurations
  • Recommend parallel execution opportunities
  • Propose retry strategies
  • Guide skill selection
  • 推荐最优配置
  • 识别并行执行的机会
  • 提出重试策略建议
  • 指导Skill选择

4. Knowledge Accumulation

4. 知识积累

  • Build pattern library
  • Track pattern effectiveness
  • Update recommendations based on outcomes
  • Maintain confidence scores
  • 构建模式库
  • 跟踪模式的有效性
  • 根据执行结果更新建议
  • 维护置信度评分

Pattern Learning Architecture

模式学习架构

typescript
interface PatternLibrary {
  libraryId: string;
  lastUpdated: Date;
  patterns: Pattern[];
  antiPatterns: AntiPattern[];
  recommendations: LearnedRecommendation[];
  statistics: LibraryStatistics;
}

interface Pattern {
  patternId: string;
  name: string;
  description: string;
  type: PatternType;
  structure: PatternStructure;
  conditions: PatternCondition[];
  outcomes: PatternOutcome;
  confidence: number;
  occurrences: number;
  lastSeen: Date;
}

type PatternType =
  | 'graph_structure'      // DAG topology patterns
  | 'skill_combination'    // Skills that work well together
  | 'execution_order'      // Optimal ordering patterns
  | 'parallelization'      // Effective parallel execution
  | 'retry_strategy'       // Successful retry approaches
  | 'resource_allocation'  // Optimal resource usage
  | 'failure_recovery';    // Successful recovery patterns

interface PatternStructure {
  nodes?: NodePattern[];
  edges?: EdgePattern[];
  constraints?: StructureConstraint[];
  template?: string;  // Serialized pattern template
}

interface PatternOutcome {
  successRate: number;
  avgDuration: number;
  avgCost: number;
  avgQuality: number;
  sampleSize: number;
}
typescript
interface PatternLibrary {
  libraryId: string;
  lastUpdated: Date;
  patterns: Pattern[];
  antiPatterns: AntiPattern[];
  recommendations: LearnedRecommendation[];
  statistics: LibraryStatistics;
}

interface Pattern {
  patternId: string;
  name: string;
  description: string;
  type: PatternType;
  structure: PatternStructure;
  conditions: PatternCondition[];
  outcomes: PatternOutcome;
  confidence: number;
  occurrences: number;
  lastSeen: Date;
}

type PatternType =
  | 'graph_structure'      // DAG拓扑模式
  | 'skill_combination'    // 搭配效果好的Skills
  | 'execution_order'      // 最优执行顺序模式
  | 'parallelization'      // 高效并行执行模式
  | 'retry_strategy'       // 成功重试策略
  | 'resource_allocation'  // 最优资源使用模式
  | 'failure_recovery';    // 成功恢复模式

interface PatternStructure {
  nodes?: NodePattern[];
  edges?: EdgePattern[];
  constraints?: StructureConstraint[];
  template?: string;  // 序列化的模式模板
}

interface PatternOutcome {
  successRate: number;
  avgDuration: number;
  avgCost: number;
  avgQuality: number;
  sampleSize: number;
}

Pattern Extraction

模式提取

typescript
interface ExecutionDataset {
  executions: ExecutionRecord[];
  timeRange: { start: Date; end: Date };
  filters?: DatasetFilters;
}

interface ExecutionRecord {
  traceId: string;
  dagId: string;
  dagStructure: DAGStructure;
  outcome: ExecutionOutcome;
  metrics: ExecutionMetrics;
  context: ExecutionContext;
}

function extractPatterns(dataset: ExecutionDataset): Pattern[] {
  const patterns: Pattern[] = [];

  // Extract graph structure patterns
  patterns.push(...extractGraphPatterns(dataset));

  // Extract skill combination patterns
  patterns.push(...extractSkillCombinations(dataset));

  // Extract execution order patterns
  patterns.push(...extractOrderingPatterns(dataset));

  // Extract parallelization patterns
  patterns.push(...extractParallelPatterns(dataset));

  // Filter by confidence threshold
  return patterns.filter(p => p.confidence >= 0.6);
}

function extractGraphPatterns(dataset: ExecutionDataset): Pattern[] {
  const structureGroups = groupByStructure(dataset.executions);
  const patterns: Pattern[] = [];

  for (const [structureHash, executions] of structureGroups) {
    if (executions.length < 3) continue;  // Need minimum samples

    const outcomes = analyzeOutcomes(executions);

    if (outcomes.successRate >= 0.8) {
      patterns.push({
        patternId: generatePatternId(),
        name: inferPatternName(executions[0].dagStructure),
        description: describePattern(executions[0].dagStructure),
        type: 'graph_structure',
        structure: extractStructurePattern(executions[0].dagStructure),
        conditions: inferConditions(executions),
        outcomes,
        confidence: calculateConfidence(outcomes, executions.length),
        occurrences: executions.length,
        lastSeen: maxDate(executions.map(e => e.metrics.completedAt)),
      });
    }
  }

  return patterns;
}

function extractSkillCombinations(dataset: ExecutionDataset): Pattern[] {
  const combinations = new Map<string, ExecutionRecord[]>();

  for (const execution of dataset.executions) {
    const skills = extractSkillIds(execution.dagStructure);
    const key = skills.sort().join(',');

    const existing = combinations.get(key) ?? [];
    existing.push(execution);
    combinations.set(key, existing);
  }

  const patterns: Pattern[] = [];

  for (const [key, executions] of combinations) {
    if (executions.length < 3) continue;

    const outcomes = analyzeOutcomes(executions);

    if (outcomes.successRate >= 0.75) {
      const skills = key.split(',');
      patterns.push({
        patternId: generatePatternId(),
        name: `Skill Combination: ${skills.slice(0, 3).join(' + ')}${skills.length > 3 ? '...' : ''}`,
        description: `Effective combination of ${skills.length} skills`,
        type: 'skill_combination',
        structure: {
          nodes: skills.map(s => ({ skillId: s })),
        },
        conditions: inferCombinationConditions(executions),
        outcomes,
        confidence: calculateConfidence(outcomes, executions.length),
        occurrences: executions.length,
        lastSeen: maxDate(executions.map(e => e.metrics.completedAt)),
      });
    }
  }

  return patterns;
}

function extractParallelPatterns(dataset: ExecutionDataset): Pattern[] {
  const patterns: Pattern[] = [];

  for (const execution of dataset.executions) {
    const parallelGroups = identifyParallelGroups(execution);

    for (const group of parallelGroups) {
      if (group.nodes.length >= 2 && group.success) {
        const patternKey = generateParallelPatternKey(group);

        // Check if pattern already exists
        const existing = patterns.find(p =>
          p.type === 'parallelization' &&
          matchesParallelPattern(p, group)
        );

        if (existing) {
          existing.occurrences++;
          existing.lastSeen = execution.metrics.completedAt;
          // Update outcomes
          updateOutcomes(existing.outcomes, group.metrics);
        } else {
          patterns.push({
            patternId: generatePatternId(),
            name: `Parallel Group: ${group.nodes.length} nodes`,
            description: `Successfully parallelized ${group.nodes.map(n => n.type).join(', ')}`,
            type: 'parallelization',
            structure: {
              nodes: group.nodes.map(n => ({ type: n.type, skillId: n.skillId })),
              constraints: [{ type: 'no_dependencies_between', nodes: group.nodes.map(n => n.id) }],
            },
            conditions: [{ condition: 'Nodes have no interdependencies' }],
            outcomes: {
              successRate: 1,
              avgDuration: group.metrics.duration,
              avgCost: group.metrics.cost,
              avgQuality: group.metrics.quality,
              sampleSize: 1,
            },
            confidence: 0.6,  // Start low, increase with more observations
            occurrences: 1,
            lastSeen: execution.metrics.completedAt,
          });
        }
      }
    }
  }

  return patterns;
}
typescript
interface ExecutionDataset {
  executions: ExecutionRecord[];
  timeRange: { start: Date; end: Date };
  filters?: DatasetFilters;
}

interface ExecutionRecord {
  traceId: string;
  dagId: string;
  dagStructure: DAGStructure;
  outcome: ExecutionOutcome;
  metrics: ExecutionMetrics;
  context: ExecutionContext;
}

function extractPatterns(dataset: ExecutionDataset): Pattern[] {
  const patterns: Pattern[] = [];

  // 提取图结构模式
  patterns.push(...extractGraphPatterns(dataset));

  // 提取Skill组合模式
  patterns.push(...extractSkillCombinations(dataset));

  // 提取执行顺序模式
  patterns.push(...extractOrderingPatterns(dataset));

  // 提取并行执行模式
  patterns.push(...extractParallelPatterns(dataset));

  // 按置信度阈值过滤
  return patterns.filter(p => p.confidence >= 0.6);
}

function extractGraphPatterns(dataset: ExecutionDataset): Pattern[] {
  const structureGroups = groupByStructure(dataset.executions);
  const patterns: Pattern[] = [];

  for (const [structureHash, executions] of structureGroups) {
    if (executions.length < 3) continue;  // 需要最少样本量

    const outcomes = analyzeOutcomes(executions);

    if (outcomes.successRate >= 0.8) {
      patterns.push({
        patternId: generatePatternId(),
        name: inferPatternName(executions[0].dagStructure),
        description: describePattern(executions[0].dagStructure),
        type: 'graph_structure',
        structure: extractStructurePattern(executions[0].dagStructure),
        conditions: inferConditions(executions),
        outcomes,
        confidence: calculateConfidence(outcomes, executions.length),
        occurrences: executions.length,
        lastSeen: maxDate(executions.map(e => e.metrics.completedAt)),
      });
    }
  }

  return patterns;
}

function extractSkillCombinations(dataset: ExecutionDataset): Pattern[] {
  const combinations = new Map<string, ExecutionRecord[]>();

  for (const execution of dataset.executions) {
    const skills = extractSkillIds(execution.dagStructure);
    const key = skills.sort().join(',');

    const existing = combinations.get(key) ?? [];
    existing.push(execution);
    combinations.set(key, existing);
  }

  const patterns: Pattern[] = [];

  for (const [key, executions] of combinations) {
    if (executions.length < 3) continue;

    const outcomes = analyzeOutcomes(executions);

    if (outcomes.successRate >= 0.75) {
      const skills = key.split(',');
      patterns.push({
        patternId: generatePatternId(),
        name: `Skill Combination: ${skills.slice(0, 3).join(' + ')}${skills.length > 3 ? '...' : ''}`,
        description: `Effective combination of ${skills.length} skills`,
        type: 'skill_combination',
        structure: {
          nodes: skills.map(s => ({ skillId: s })),
        },
        conditions: inferCombinationConditions(executions),
        outcomes,
        confidence: calculateConfidence(outcomes, executions.length),
        occurrences: executions.length,
        lastSeen: maxDate(executions.map(e => e.metrics.completedAt)),
      });
    }
  }

  return patterns;
}

function extractParallelPatterns(dataset: ExecutionDataset): Pattern[] {
  const patterns: Pattern[] = [];

  for (const execution of dataset.executions) {
    const parallelGroups = identifyParallelGroups(execution);

    for (const group of parallelGroups) {
      if (group.nodes.length >= 2 && group.success) {
        const patternKey = generateParallelPatternKey(group);

        // 检查模式是否已存在
        const existing = patterns.find(p =>
          p.type === 'parallelization' &&
          matchesParallelPattern(p, group)
        );

        if (existing) {
          existing.occurrences++;
          existing.lastSeen = execution.metrics.completedAt;
          // 更新执行结果
          updateOutcomes(existing.outcomes, group.metrics);
        } else {
          patterns.push({
            patternId: generatePatternId(),
            name: `Parallel Group: ${group.nodes.length} nodes`,
            description: `Successfully parallelized ${group.nodes.map(n => n.type).join(', ')}`,
            type: 'parallelization',
            structure: {
              nodes: group.nodes.map(n => ({ type: n.type, skillId: n.skillId })),
              constraints: [{ type: 'no_dependencies_between', nodes: group.nodes.map(n => n.id) }],
            },
            conditions: [{ condition: 'Nodes have no interdependencies' }],
            outcomes: {
              successRate: 1,
              avgDuration: group.metrics.duration,
              avgCost: group.metrics.cost,
              avgQuality: group.metrics.quality,
              sampleSize: 1,
            },
            confidence: 0.6,  // 初始置信度较低,随观测次数增加而提升
            occurrences: 1,
            lastSeen: execution.metrics.completedAt,
          });
        }
      }
    }
  }

  return patterns;
}

Anti-Pattern Detection

反模式检测

typescript
interface AntiPattern {
  antiPatternId: string;
  name: string;
  description: string;
  type: AntiPatternType;
  indicators: AntiPatternIndicator[];
  consequences: string[];
  remediation: string;
  occurrences: number;
  severity: 'critical' | 'high' | 'medium' | 'low';
}

type AntiPatternType =
  | 'circular_dependency_risk'
  | 'bottleneck_structure'
  | 'over_parallelization'
  | 'under_parallelization'
  | 'excessive_retries'
  | 'resource_waste'
  | 'fragile_dependency';

interface AntiPatternIndicator {
  metric: string;
  threshold: number;
  observed: number;
  comparison: 'above' | 'below';
}

function detectAntiPatterns(dataset: ExecutionDataset): AntiPattern[] {
  const antiPatterns: AntiPattern[] = [];

  // Detect bottleneck structures
  antiPatterns.push(...detectBottlenecks(dataset));

  // Detect over-parallelization
  antiPatterns.push(...detectOverParallelization(dataset));

  // Detect excessive retries
  antiPatterns.push(...detectExcessiveRetries(dataset));

  // Detect resource waste
  antiPatterns.push(...detectResourceWaste(dataset));

  return antiPatterns;
}

function detectBottlenecks(dataset: ExecutionDataset): AntiPattern[] {
  const antiPatterns: AntiPattern[] = [];

  for (const execution of dataset.executions) {
    const bottlenecks = findBottleneckNodes(execution);

    for (const bottleneck of bottlenecks) {
      if (bottleneck.impact >= 0.3) {  // Node accounts for 30%+ of total time
        const existing = antiPatterns.find(ap =>
          ap.type === 'bottleneck_structure' &&
          ap.indicators[0]?.metric === bottleneck.nodeType
        );

        if (existing) {
          existing.occurrences++;
        } else {
          antiPatterns.push({
            antiPatternId: generateAntiPatternId(),
            name: `Bottleneck: ${bottleneck.nodeType}`,
            description: `Node type ${bottleneck.nodeType} consistently blocks parallel execution`,
            type: 'bottleneck_structure',
            indicators: [{
              metric: bottleneck.nodeType,
              threshold: 0.2,
              observed: bottleneck.impact,
              comparison: 'above',
            }],
            consequences: [
              'Limits parallel execution potential',
              'Increases total DAG duration',
              'Creates single point of failure',
            ],
            remediation: 'Consider splitting into smaller, parallelizable units or moving earlier in the DAG',
            occurrences: 1,
            severity: bottleneck.impact >= 0.5 ? 'high' : 'medium',
          });
        }
      }
    }
  }

  return antiPatterns;
}

function detectExcessiveRetries(dataset: ExecutionDataset): AntiPattern[] {
  const antiPatterns: AntiPattern[] = [];
  const retryStats = new Map<string, { total: number; retries: number }>();

  for (const execution of dataset.executions) {
    for (const node of execution.dagStructure.nodes) {
      const stats = retryStats.get(node.type) ?? { total: 0, retries: 0 };
      stats.total++;
      stats.retries += (node.retryCount ?? 0);
      retryStats.set(node.type, stats);
    }
  }

  for (const [nodeType, stats] of retryStats) {
    const avgRetries = stats.retries / stats.total;

    if (avgRetries > 1.5 && stats.total >= 5) {
      antiPatterns.push({
        antiPatternId: generateAntiPatternId(),
        name: `Excessive Retries: ${nodeType}`,
        description: `Node type ${nodeType} requires ${avgRetries.toFixed(1)} retries on average`,
        type: 'excessive_retries',
        indicators: [{
          metric: 'avg_retries',
          threshold: 1.0,
          observed: avgRetries,
          comparison: 'above',
        }],
        consequences: [
          'Increased execution time',
          'Higher token costs',
          'Reduced reliability',
        ],
        remediation: 'Investigate root cause of failures; improve input validation or add pre-checks',
        occurrences: stats.total,
        severity: avgRetries > 2.5 ? 'high' : 'medium',
      });
    }
  }

  return antiPatterns;
}

function detectResourceWaste(dataset: ExecutionDataset): AntiPattern[] {
  const antiPatterns: AntiPattern[] = [];

  for (const execution of dataset.executions) {
    const waste = calculateResourceWaste(execution);

    if (waste.tokenWaste > 0.3) {  // 30%+ tokens wasted
      antiPatterns.push({
        antiPatternId: generateAntiPatternId(),
        name: 'Token Waste',
        description: `${(waste.tokenWaste * 100).toFixed(0)}% of tokens used in failed nodes`,
        type: 'resource_waste',
        indicators: [{
          metric: 'token_waste_ratio',
          threshold: 0.2,
          observed: waste.tokenWaste,
          comparison: 'above',
        }],
        consequences: [
          'Increased costs',
          'Wasted compute resources',
        ],
        remediation: 'Add early validation, implement circuit breakers, or reorder to fail fast',
        occurrences: 1,
        severity: waste.tokenWaste > 0.5 ? 'high' : 'medium',
      });
    }
  }

  return antiPatterns;
}
typescript
interface AntiPattern {
  antiPatternId: string;
  name: string;
  description: string;
  type: AntiPatternType;
  indicators: AntiPatternIndicator[];
  consequences: string[];
  remediation: string;
  occurrences: number;
  severity: 'critical' | 'high' | 'medium' | 'low';
}

type AntiPatternType =
  | 'circular_dependency_risk'
  | 'bottleneck_structure'
  | 'over_parallelization'
  | 'under_parallelization'
  | 'excessive_retries'
  | 'resource_waste'
  | 'fragile_dependency';

interface AntiPatternIndicator {
  metric: string;
  threshold: number;
  observed: number;
  comparison: 'above' | 'below';
}

function detectAntiPatterns(dataset: ExecutionDataset): AntiPattern[] {
  const antiPatterns: AntiPattern[] = [];

  // 检测瓶颈结构
  antiPatterns.push(...detectBottlenecks(dataset));

  // 检测过度并行化
  antiPatterns.push(...detectOverParallelization(dataset));

  // 检测过度重试
  antiPatterns.push(...detectExcessiveRetries(dataset));

  // 检测资源浪费
  antiPatterns.push(...detectResourceWaste(dataset));

  return antiPatterns;
}

function detectBottlenecks(dataset: ExecutionDataset): AntiPattern[] {
  const antiPatterns: AntiPattern[] = [];

  for (const execution of dataset.executions) {
    const bottlenecks = findBottleneckNodes(execution);

    for (const bottleneck of bottlenecks) {
      if (bottleneck.impact >= 0.3) {  // 节点耗时占总时长30%以上
        const existing = antiPatterns.find(ap =>
          ap.type === 'bottleneck_structure' &&
          ap.indicators[0]?.metric === bottleneck.nodeType
        );

        if (existing) {
          existing.occurrences++;
        } else {
          antiPatterns.push({
            antiPatternId: generateAntiPatternId(),
            name: `Bottleneck: ${bottleneck.nodeType}`,
            description: `Node type ${bottleneck.nodeType} 持续阻碍并行执行`,
            type: 'bottleneck_structure',
            indicators: [{
              metric: bottleneck.nodeType,
              threshold: 0.2,
              observed: bottleneck.impact,
              comparison: 'above',
            }],
            consequences: [
              '限制并行执行潜力',
              '增加DAG总执行时长',
              '形成单点故障',
            ],
            remediation: '考虑拆分为更小的可并行单元,或提前在DAG中执行',
            occurrences: 1,
            severity: bottleneck.impact >= 0.5 ? 'high' : 'medium',
          });
        }
      }
    }
  }

  return antiPatterns;
}

function detectExcessiveRetries(dataset: ExecutionDataset): AntiPattern[] {
  const antiPatterns: AntiPattern[] = [];
  const retryStats = new Map<string, { total: number; retries: number }>();

  for (const execution of dataset.executions) {
    for (const node of execution.dagStructure.nodes) {
      const stats = retryStats.get(node.type) ?? { total: 0, retries: 0 };
      stats.total++;
      stats.retries += (node.retryCount ?? 0);
      retryStats.set(node.type, stats);
    }
  }

  for (const [nodeType, stats] of retryStats) {
    const avgRetries = stats.retries / stats.total;

    if (avgRetries > 1.5 && stats.total >= 5) {
      antiPatterns.push({
        antiPatternId: generateAntiPatternId(),
        name: `Excessive Retries: ${nodeType}`,
        description: `Node type ${nodeType} 平均需要 ${avgRetries.toFixed(1)} 次重试`,
        type: 'excessive_retries',
        indicators: [{
          metric: 'avg_retries',
          threshold: 1.0,
          observed: avgRetries,
          comparison: 'above',
        }],
        consequences: [
          '增加执行时间',
          '提升Token成本',
          '降低可靠性',
        ],
        remediation: '排查失败的根本原因;改进输入验证或添加前置检查',
        occurrences: stats.total,
        severity: avgRetries > 2.5 ? 'high' : 'medium',
      });
    }
  }

  return antiPatterns;
}

function detectResourceWaste(dataset: ExecutionDataset): AntiPattern[] {
  const antiPatterns: AntiPattern[] = [];

  for (const execution of dataset.executions) {
    const waste = calculateResourceWaste(execution);

    if (waste.tokenWaste > 0.3) {  // Token浪费超过30%
      antiPatterns.push({
        antiPatternId: generateAntiPatternId(),
        name: 'Token Waste',
        description: `${(waste.tokenWaste * 100).toFixed(0)}% 的Token消耗在失败节点上`,
        type: 'resource_waste',
        indicators: [{
          metric: 'token_waste_ratio',
          threshold: 0.2,
          observed: waste.tokenWaste,
          comparison: 'above',
        }],
        consequences: [
          '成本增加',
          '计算资源浪费',
        ],
        remediation: '添加早期验证,实现熔断机制,或调整顺序以快速失败',
        occurrences: 1,
        severity: waste.tokenWaste > 0.5 ? 'high' : 'medium',
      });
    }
  }

  return antiPatterns;
}

Recommendation Generation

建议生成

typescript
interface LearnedRecommendation {
  recommendationId: string;
  type: RecommendationType;
  title: string;
  description: string;
  applicability: ApplicabilityCondition[];
  expectedBenefit: ExpectedBenefit;
  confidence: number;
  basedOn: {
    patterns: string[];
    antiPatterns: string[];
    sampleSize: number;
  };
}

type RecommendationType =
  | 'skill_selection'
  | 'graph_structure'
  | 'parallelization'
  | 'retry_configuration'
  | 'resource_allocation'
  | 'ordering_optimization';

interface ExpectedBenefit {
  metric: 'duration' | 'cost' | 'quality' | 'reliability';
  improvement: number;  // Percentage improvement
  confidence: number;
}

function generateRecommendations(
  patterns: Pattern[],
  antiPatterns: AntiPattern[]
): LearnedRecommendation[] {
  const recommendations: LearnedRecommendation[] = [];

  // Recommendations from successful patterns
  for (const pattern of patterns) {
    if (pattern.confidence >= 0.7 && pattern.occurrences >= 5) {
      recommendations.push(patternToRecommendation(pattern));
    }
  }

  // Recommendations from anti-patterns (avoid these)
  for (const antiPattern of antiPatterns) {
    if (antiPattern.occurrences >= 3) {
      recommendations.push(antiPatternToRecommendation(antiPattern));
    }
  }

  // Cross-pattern analysis
  recommendations.push(...crossPatternRecommendations(patterns, antiPatterns));

  // Sort by expected impact
  return recommendations.sort((a, b) =>
    b.expectedBenefit.improvement - a.expectedBenefit.improvement
  );
}

function patternToRecommendation(pattern: Pattern): LearnedRecommendation {
  const typeMapping: Record<PatternType, RecommendationType> = {
    'graph_structure': 'graph_structure',
    'skill_combination': 'skill_selection',
    'execution_order': 'ordering_optimization',
    'parallelization': 'parallelization',
    'retry_strategy': 'retry_configuration',
    'resource_allocation': 'resource_allocation',
    'failure_recovery': 'retry_configuration',
  };

  return {
    recommendationId: generateRecommendationId(),
    type: typeMapping[pattern.type],
    title: `Use: ${pattern.name}`,
    description: pattern.description,
    applicability: pattern.conditions.map(c => ({
      condition: c.condition ?? c.toString(),
      required: true,
    })),
    expectedBenefit: {
      metric: 'reliability',
      improvement: pattern.outcomes.successRate * 100 - 50,  // Above 50% baseline
      confidence: pattern.confidence,
    },
    confidence: pattern.confidence,
    basedOn: {
      patterns: [pattern.patternId],
      antiPatterns: [],
      sampleSize: pattern.occurrences,
    },
  };
}

function antiPatternToRecommendation(antiPattern: AntiPattern): LearnedRecommendation {
  return {
    recommendationId: generateRecommendationId(),
    type: inferRecommendationType(antiPattern),
    title: `Avoid: ${antiPattern.name}`,
    description: `${antiPattern.description}. ${antiPattern.remediation}`,
    applicability: antiPattern.indicators.map(i => ({
      condition: `${i.metric} is ${i.comparison} ${i.threshold}`,
      required: true,
    })),
    expectedBenefit: {
      metric: antiPattern.type === 'resource_waste' ? 'cost' : 'reliability',
      improvement: antiPattern.severity === 'critical' ? 40 :
                   antiPattern.severity === 'high' ? 25 :
                   antiPattern.severity === 'medium' ? 15 : 5,
      confidence: Math.min(0.9, 0.5 + antiPattern.occurrences * 0.05),
    },
    confidence: Math.min(0.9, 0.5 + antiPattern.occurrences * 0.05),
    basedOn: {
      patterns: [],
      antiPatterns: [antiPattern.antiPatternId],
      sampleSize: antiPattern.occurrences,
    },
  };
}

function crossPatternRecommendations(
  patterns: Pattern[],
  antiPatterns: AntiPattern[]
): LearnedRecommendation[] {
  const recommendations: LearnedRecommendation[] = [];

  // Find complementary skill patterns
  const skillPatterns = patterns.filter(p => p.type === 'skill_combination');
  for (let i = 0; i < skillPatterns.length; i++) {
    for (let j = i + 1; j < skillPatterns.length; j++) {
      const overlap = findSkillOverlap(skillPatterns[i], skillPatterns[j]);
      if (overlap.length > 0) {
        recommendations.push({
          recommendationId: generateRecommendationId(),
          type: 'skill_selection',
          title: `Synergy: ${overlap.join(' + ')}`,
          description: `Skills ${overlap.join(', ')} appear in multiple successful patterns`,
          applicability: [{ condition: 'Task requires multiple capabilities', required: true }],
          expectedBenefit: {
            metric: 'quality',
            improvement: 20,
            confidence: 0.7,
          },
          confidence: 0.7,
          basedOn: {
            patterns: [skillPatterns[i].patternId, skillPatterns[j].patternId],
            antiPatterns: [],
            sampleSize: skillPatterns[i].occurrences + skillPatterns[j].occurrences,
          },
        });
      }
    }
  }

  return recommendations;
}
typescript
interface LearnedRecommendation {
  recommendationId: string;
  type: RecommendationType;
  title: string;
  description: string;
  applicability: ApplicabilityCondition[];
  expectedBenefit: ExpectedBenefit;
  confidence: number;
  basedOn: {
    patterns: string[];
    antiPatterns: string[];
    sampleSize: number;
  };
}

type RecommendationType =
  | 'skill_selection'
  | 'graph_structure'
  | 'parallelization'
  | 'retry_configuration'
  | 'resource_allocation'
  | 'ordering_optimization';

interface ExpectedBenefit {
  metric: 'duration' | 'cost' | 'quality' | 'reliability';
  improvement: number;  // 提升百分比
  confidence: number;
}

function generateRecommendations(
  patterns: Pattern[],
  antiPatterns: AntiPattern[]
): LearnedRecommendation[] {
  const recommendations: LearnedRecommendation[] = [];

  // 基于成功模式生成建议
  for (const pattern of patterns) {
    if (pattern.confidence >= 0.7 && pattern.occurrences >= 5) {
      recommendations.push(patternToRecommendation(pattern));
    }
  }

  // 基于反模式生成建议(规避类)
  for (const antiPattern of antiPatterns) {
    if (antiPattern.occurrences >= 3) {
      recommendations.push(antiPatternToRecommendation(antiPattern));
    }
  }

  // 跨模式分析
  recommendations.push(...crossPatternRecommendations(patterns, antiPatterns));

  // 按预期影响排序
  return recommendations.sort((a, b) =>
    b.expectedBenefit.improvement - a.expectedBenefit.improvement
  );
}

function patternToRecommendation(pattern: Pattern): LearnedRecommendation {
  const typeMapping: Record<PatternType, RecommendationType> = {
    'graph_structure': 'graph_structure',
    'skill_combination': 'skill_selection',
    'execution_order': 'ordering_optimization',
    'parallelization': 'parallelization',
    'retry_strategy': 'retry_configuration',
    'resource_allocation': 'resource_allocation',
    'failure_recovery': 'retry_configuration',
  };

  return {
    recommendationId: generateRecommendationId(),
    type: typeMapping[pattern.type],
    title: `Use: ${pattern.name}`,
    description: pattern.description,
    applicability: pattern.conditions.map(c => ({
      condition: c.condition ?? c.toString(),
      required: true,
    })),
    expectedBenefit: {
      metric: 'reliability',
      improvement: pattern.outcomes.successRate * 100 - 50,  // 高于50%基准线
      confidence: pattern.confidence,
    },
    confidence: pattern.confidence,
    basedOn: {
      patterns: [pattern.patternId],
      antiPatterns: [],
      sampleSize: pattern.occurrences,
    },
  };
}

function antiPatternToRecommendation(antiPattern: AntiPattern): LearnedRecommendation {
  return {
    recommendationId: generateRecommendationId(),
    type: inferRecommendationType(antiPattern),
    title: `Avoid: ${antiPattern.name}`,
    description: `${antiPattern.description}. ${antiPattern.remediation}`,
    applicability: antiPattern.indicators.map(i => ({
      condition: `${i.metric} is ${i.comparison} ${i.threshold}`,
      required: true,
    })),
    expectedBenefit: {
      metric: antiPattern.type === 'resource_waste' ? 'cost' : 'reliability',
      improvement: antiPattern.severity === 'critical' ? 40 :
                   antiPattern.severity === 'high' ? 25 :
                   antiPattern.severity === 'medium' ? 15 : 5,
      confidence: Math.min(0.9, 0.5 + antiPattern.occurrences * 0.05),
    },
    confidence: Math.min(0.9, 0.5 + antiPattern.occurrences * 0.05),
    basedOn: {
      patterns: [],
      antiPatterns: [antiPattern.antiPatternId],
      sampleSize: antiPattern.occurrences,
    },
  };
}

function crossPatternRecommendations(
  patterns: Pattern[],
  antiPatterns: AntiPattern[]
): LearnedRecommendation[] {
  const recommendations: LearnedRecommendation[] = [];

  // 寻找互补的Skill模式
  const skillPatterns = patterns.filter(p => p.type === 'skill_combination');
  for (let i = 0; i < skillPatterns.length; i++) {
    for (let j = i + 1; j < skillPatterns.length; j++) {
      const overlap = findSkillOverlap(skillPatterns[i], skillPatterns[j]);
      if (overlap.length > 0) {
        recommendations.push({
          recommendationId: generateRecommendationId(),
          type: 'skill_selection',
          title: `Synergy: ${overlap.join(' + ')}`,
          description: `Skills ${overlap.join(', ')} 出现在多个成功模式中`,
          applicability: [{ condition: 'Task requires multiple capabilities', required: true }],
          expectedBenefit: {
            metric: 'quality',
            improvement: 20,
            confidence: 0.7,
          },
          confidence: 0.7,
          basedOn: {
            patterns: [skillPatterns[i].patternId, skillPatterns[j].patternId],
            antiPatterns: [],
            sampleSize: skillPatterns[i].occurrences + skillPatterns[j].occurrences,
          },
        });
      }
    }
  }

  return recommendations;
}

Pattern Library Report

模式库报告

yaml
patternLibrary:
  libraryId: "pl-9d8c7b6a-5e4f-3a2b-1c0d"
  lastUpdated: "2024-01-15T12:00:00Z"

  statistics:
    totalPatterns: 15
    totalAntiPatterns: 6
    totalRecommendations: 21
    executionsAnalyzed: 234
    timeSpan: "30 days"

  topPatterns:
    - patternId: "pat-001"
      name: "Fan-out-Fan-in"
      type: graph_structure
      description: "Distribute work to parallel nodes, then aggregate results"
      confidence: 0.92
      occurrences: 45
      outcomes:
        successRate: 0.89
        avgDuration: 12500
        avgCost: 0.045

    - patternId: "pat-002"
      name: "Validation First"
      type: execution_order
      description: "Run validation before expensive operations"
      confidence: 0.88
      occurrences: 67
      outcomes:
        successRate: 0.94
        avgDuration: 8200
        avgCost: 0.028

    - patternId: "pat-003"
      name: "Code Analysis Triple"
      type: skill_combination
      description: "code-complexity-analyzer + code-security-scanner + code-performance-analyzer"
      confidence: 0.85
      occurrences: 23
      outcomes:
        successRate: 0.91
        avgDuration: 15000
        avgCost: 0.062

  topAntiPatterns:
    - antiPatternId: "anti-001"
      name: "Sequential Bottleneck"
      type: bottleneck_structure
      severity: high
      occurrences: 12
      remediation: "Split large sequential node into parallelizable subtasks"

    - antiPatternId: "anti-002"
      name: "Retry Storm"
      type: excessive_retries
      severity: medium
      occurrences: 8
      remediation: "Add pre-validation to catch issues before execution"

  recommendations:
    - recommendationId: "rec-001"
      type: parallelization
      title: "Parallelize Independent Analysis"
      description: "When running multiple analysis skills, execute them in parallel"
      expectedBenefit:
        metric: duration
        improvement: 45
        confidence: 0.85
      basedOn:
        patterns: ["pat-001", "pat-003"]
        sampleSize: 68

    - recommendationId: "rec-002"
      type: ordering_optimization
      title: "Validate Early"
      description: "Move validation nodes to earliest possible position"
      expectedBenefit:
        metric: cost
        improvement: 30
        confidence: 0.88
      basedOn:
        patterns: ["pat-002"]
        antiPatterns: ["anti-001"]
        sampleSize: 67

  trends:
    - observation: "Success rate improving over time"
      metric: successRate
      change: +0.08
      period: "last 30 days"

    - observation: "Average cost decreasing"
      metric: avgCost
      change: -0.015
      period: "last 30 days"
yaml
patternLibrary:
  libraryId: "pl-9d8c7b6a-5e4f-3a2b-1c0d"
  lastUpdated: "2024-01-15T12:00:00Z"

  statistics:
    totalPatterns: 15
    totalAntiPatterns: 6
    totalRecommendations: 21
    executionsAnalyzed: 234
    timeSpan: "30 days"

  topPatterns:
    - patternId: "pat-001"
      name: "Fan-out-Fan-in"
      type: graph_structure
      description: "Distribute work to parallel nodes, then aggregate results"
      confidence: 0.92
      occurrences: 45
      outcomes:
        successRate: 0.89
        avgDuration: 12500
        avgCost: 0.045

    - patternId: "pat-002"
      name: "Validation First"
      type: execution_order
      description: "Run validation before expensive operations"
      confidence: 0.88
      occurrences: 67
      outcomes:
        successRate: 0.94
        avgDuration: 8200
        avgCost: 0.028

    - patternId: "pat-003"
      name: "Code Analysis Triple"
      type: skill_combination
      description: "code-complexity-analyzer + code-security-scanner + code-performance-analyzer"
      confidence: 0.85
      occurrences: 23
      outcomes:
        successRate: 0.91
        avgDuration: 15000
        avgCost: 0.062

  topAntiPatterns:
    - antiPatternId: "anti-001"
      name: "Sequential Bottleneck"
      type: bottleneck_structure
      severity: high
      occurrences: 12
      remediation: "Split large sequential node into parallelizable subtasks"

    - antiPatternId: "anti-002"
      name: "Retry Storm"
      type: excessive_retries
      severity: medium
      occurrences: 8
      remediation: "Add pre-validation to catch issues before execution"

  recommendations:
    - recommendationId: "rec-001"
      type: parallelization
      title: "Parallelize Independent Analysis"
      description: "When running multiple analysis skills, execute them in parallel"
      expectedBenefit:
        metric: duration
        improvement: 45
        confidence: 0.85
      basedOn:
        patterns: ["pat-001", "pat-003"]
        sampleSize: 68

    - recommendationId: "rec-002"
      type: ordering_optimization
      title: "Validate Early"
      description: "Move validation nodes to earliest possible position"
      expectedBenefit:
        metric: cost
        improvement: 30
        confidence: 0.88
      basedOn:
        patterns: ["pat-002"]
        antiPatterns: ["anti-001"]
        sampleSize: 67

  trends:
    - observation: "Success rate improving over time"
      metric: successRate
      change: +0.08
      period: "last 30 days"

    - observation: "Average cost decreasing"
      metric: avgCost
      change: -0.015
      period: "last 30 days"

Integration Points

集成点

  • Input: Execution traces from
    dag-execution-tracer
  • Input: Performance data from
    dag-performance-profiler
  • Input: Failure data from
    dag-failure-analyzer
  • Output: Patterns and recommendations to
    dag-graph-builder
  • Output: Optimization hints to
    dag-task-scheduler
  • 输入:来自
    dag-execution-tracer
    的执行追踪数据
  • 输入:来自
    dag-performance-profiler
    的性能数据
  • 输入:来自
    dag-failure-analyzer
    的故障数据
  • 输出:向
    dag-graph-builder
    输出模式与建议
  • 输出:向
    dag-task-scheduler
    输出优化提示

Best Practices

最佳实践

  1. Minimum Sample Size: Require 3+ observations before extracting patterns
  2. Confidence Decay: Reduce confidence for patterns not seen recently
  3. Context Matters: Patterns should include applicable conditions
  4. Actionable Output: Recommendations must be implementable
  5. Continuous Learning: Update library with each new execution

Learn from history. Find what works. Continuously improve.
  1. 最小样本量:提取模式前至少需要3次观测
  2. 置信度衰减:降低长期未出现的模式的置信度
  3. 上下文关联:模式需包含适用条件
  4. 可落地输出:建议必须可执行
  5. 持续学习:每次新执行后更新模式库

以史为鉴,择优而从,持续优化。