# Good: Analyzing execution patterns
def _analyze_caching_efficiency_recursively(self, span: SpanModel, cache_stats: Dict[str, Any] = None) -> Dict[str, Any]:
    """Recursively analyze caching efficiency across the span tree."""
    if cache_stats is None:
        cache_stats = {
            'total_llm_calls': 0,
            'llm_cache_hits': 0,
            'llm_cache_misses': 0,
            'other_cache_hits': 0,
            'cached_llm_spans': [],
            'cached_other_spans': [],
            'llm_spans': []
        }

    # Track LLM calls and their caching status
    if span.type == "llm":
        cache_stats['total_llm_calls'] += 1
        cache_stats['llm_spans'].append(span.name)

        # Check for caching indicators in metadata
        metadata = span.metadata or {}
        tags = span.tags or []

        is_cached = (
            any(cache_key in metadata for cache_key in ["cache_hit", "cached", "from_cache"]) or
            any(cache_tag in tags for cache_tag in ["cache_hit", "cached"]) or
            metadata.get("cache_hit", False) or
            metadata.get("cached", False)
        )

        if is_cached:
            cache_stats['llm_cache_hits'] += 1
            cache_stats['cached_llm_spans'].append(span.name)
        else:
            cache_stats['llm_cache_misses'] += 1

    # Track non-LLM spans for caching indicators (e.g., database queries, API calls)
    else:
        metadata = span.metadata or {}
        tags = span.tags or []

        if (any(cache_key in metadata for cache_key in ["cache_hit", "cached", "from_cache"]) or
            any(cache_tag in tags for cache_tag in ["cache_hit", "cached"])):
            cache_stats['other_cache_hits'] += 1
            cache_stats['cached_other_spans'].append(span.name)

    # Recursively check nested spans
    for nested_span in span.spans:
        self._analyze_caching_efficiency_recursively(nested_span, cache_stats)

    return cache_stats

def score(self, task_span: SpanModel, **ignored_kwargs: Any) -> score_result.ScoreResult:
    # Analyze caching efficiency across an entire span tree.
    # Only for illustrative purposes.
    # Please adjust for your specific use case!
    cache_stats = self._analyze_caching_efficiency_recursively(task_span)

    llm_cache_hits = cache_stats['llm_cache_hits']
    total_llm_calls = cache_stats['total_llm_calls']
    other_cache_hits = cache_stats['other_cache_hits']

    # Calculate a cache hit ratio specifically for LLM calls
    llm_cache_hit_ratio = llm_cache_hits / max(1, total_llm_calls) if total_llm_calls > 0 else 0

    # Score based on LLM caching efficiency and total call volume
    if total_llm_calls == 0:
        # Consider other cache hits for non-LLM operations
        if other_cache_hits > 0:
            return score_result.ScoreResult(
                value=0.7,
                name=self.name,
                reason=f"No LLM calls, but {other_cache_hits} other operations cached"
            )
        else:
            return score_result.ScoreResult(
                value=0.5,
                name=self.name,
                reason="No LLM calls detected"
            )
    elif llm_cache_hit_ratio >= 0.8:
        reason = f"Excellent LLM caching: {llm_cache_hits}/{total_llm_calls} LLM calls cached ({llm_cache_hit_ratio:.1%})"
        if other_cache_hits > 0:
            reason += f" + {other_cache_hits} other cached operations"
        return score_result.ScoreResult(
            value=1.0,
            name=self.name,
            reason=reason
        )
    elif llm_cache_hit_ratio >= 0.5:
        reason = f"Good LLM caching: {llm_cache_hits}/{total_llm_calls} LLM calls cached ({llm_cache_hit_ratio:.1%})"
        if other_cache_hits > 0:
            reason += f" + {other_cache_hits} other cached operations"
        return score_result.ScoreResult(
            value=0.9,
            name=self.name,
            reason=reason
        )
    elif llm_cache_hit_ratio > 0:
        reason = f"Some LLM caching: {llm_cache_hits}/{total_llm_calls} LLM calls cached ({llm_cache_hit_ratio:.1%})"
        if other_cache_hits > 0:
            reason += f" + {other_cache_hits} other cached operations"
        return score_result.ScoreResult(
            value=0.7,
            name=self.name,
            reason=reason
        )
    elif total_llm_calls > 5:
        return score_result.ScoreResult(
            value=0.2,
            name=self.name,
            reason=f"No caching with {total_llm_calls} LLM calls - high cost/latency risk"
        )
    elif total_llm_calls > 3:
        return score_result.ScoreResult(
            value=0.4,
            name=self.name,
            reason=f"No caching with {total_llm_calls} LLM calls - consider adding cache"
        )
    else:
        return score_result.ScoreResult(
            value=0.8,
            name=self.name,
            reason=f"Efficient execution: {total_llm_calls} LLM calls (caching not critical)"
        )
```

### 3. Combine with Regular Metrics

Task span metrics provide the most value when combined with traditional output-based metrics:

```python