from __future__ import annotations from uuid import uuid4 from app.agents.schemas.learning import LearningSignal, PatternCandidate class LearningPatternMiner: def mine(self, signals: list[LearningSignal]) -> list[PatternCandidate]: patterns: list[PatternCandidate] = [] for signal in signals: if signal.signal_type not in {"workflow", "decomposition", "preference"}: continue description = self._build_description(signal) patterns.append( PatternCandidate( pattern_id=f"pattern-{uuid4().hex[:10]}", pattern_type=signal.signal_type, description=description, confidence=signal.confidence, evidence_refs=signal.evidence_refs[:4], ) ) return patterns @staticmethod def _build_description(signal: LearningSignal) -> str: payload = signal.payload or {} if signal.signal_type == "workflow": task_type = payload.get("task_type") or "general" execution_mode = payload.get("execution_mode") or "direct" return f"Completed {task_type} requests worked under {execution_mode} execution." if signal.signal_type == "decomposition": task_count = payload.get("task_count") or 0 return f"Requests with {task_count} concrete task refs benefit from structured decomposition." if signal.signal_type == "preference": preference = payload.get("preference") or "structured response" return f"User preference repeatedly points to {preference}." return signal.explanation or signal.signal_type