Skip to content
Back to skills

082 Claude 0ec5282b

ASecurity

Reranker provider implementations for relevance-based document ranking.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
businesspythongoapidocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 082-claude_0ec5282b --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 082 Claude 0ec5282b?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 082 Claude 0ec5282b
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-082-claude-0ec5282b/badge)](https://www.skillsdirectory.com/skills/tools-only-082-claude-0ec5282b)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Reranker Providers

Reranker provider implementations for relevance-based document ranking.

## Files

- **`base.py`**: Abstract base class `RerankerModel` defining the interface
- **`jina.py`**: Jina AI reranker models
- **`voyage.py`**: Voyage AI reranker models
- **`transformers.py`**: Local HuggingFace transformers reranker models

## Patterns

### Base Class Contract

All providers inherit from `RerankerModel` (base.py:15) and must:

1. **Implement abstract methods**:
   - `rerank()`: Synchronous reranking
   - `arerank()`: Async reranking
   - `_get_models()`: Return list of available models
   - `_get_default_model()`: Return default model name
   - `to_langchain()`: Convert to LangChain-compatible reranker
   - `provider` property: Return provider name string

2. **Override `__post_init__()`**:
   - Call `super().__post_init__()` first (initializes model_name if None)
   - Set `api_key` from parameter or environment variable (if API-based)
   - Set `base_url` (if API-based)
   - Call `self._create_http_clients()` last (for API providers)

3. **Return standardized response**:
   - Use `RerankResponse` from `esperanto.common_types.reranker`
   - Contains list of `RerankResult` objects with `index`, `document`, `relevance_score`

### Input Validation

Base class provides `_validate_inputs()` (base.py:171):

- Checks query is non-empty string
- Validates documents is non-empty list of strings
- Normalizes `top_k` to min(top_k, len(documents))
- Returns validated tuple: `(query, documents, top_k)`

Call this in your `rerank()` and `arerank()` implementations:

```python
def rerank(self, query: str, documents: List[str], top_k: Optional[int] = None, **kwargs):
    query, documents, top_k = self._validate_inputs(query, documents, top_k)
    # ... proceed with reranking
```

### Score Normalization

Base class provides `_normalize_scores()` (base.py:209):

- Applies min-max normalization to 0-1 range
- Handles edge case where all scores are identical
- Use when provider returns scores outside 0-1 range

Most providers return relevance scores in 0-1 range natively, but some (like transformers cross-encoders) may return unbounded scores.

### HTTP Client Pattern

Same as other providers:

```python
def __post_init__(self):
    super().__post_init__()
    self.api_key = self.api_key or os.getenv("PROVIDER_API_KEY")
    self.base_url = self.base_url or "https://api.provider.com/v1"
    self._create_http_clients()
```

### Response Construction

Build `RerankResponse` from API results:

```python
from esperanto.common_types.reranker import RerankResponse, RerankResult

results = [
    RerankResult(
        index=idx,
        document=documents[idx],
        relevance_score=score
    )
    for idx, score in sorted_results[:top_k]
]

return RerankResponse(
    model=self.get_model_name(),
    results=results,
    usage={"tokens": tokens_used}  # if available
)
```

## Integration

- Imported by `factory.py` via `AIFactory._provider_modules["reranker"]`
- Uses types from `esperanto.common_types.reranker` (`RerankResponse`, `RerankResult`)
- Inherits mixins from `esperanto.utils.timeout` and `esperanto.utils.ssl`

## Gotchas

- **top_k handling**: If `top_k` is None, return ALL documents ranked (not just top N)
- **Index preservation**: `RerankResult.index` should be the original index in input documents list
- **Score ordering**: Results should be sorted by relevance_score descending (highest first)
- **Empty documents**: Call `_validate_inputs()` to catch empty lists early
- **Local vs API**: Transformers provider doesn't need API key, others do
- **Model name optional**: Unlike other provider types, reranker model_name is optional (has defaults)
- **Async for sync models**: Local transformers models don't have true async - use executor or run_in_executor
- **LangChain integration**: Some providers don't have native LangChain reranker classes - may need custom wrapper
- **Usage tracking**: Not all providers return token usage - set to None if unavailable
- **Deprecation warnings**: Use `_get_models()` internally (not `.models` property)

## When Adding a New Provider

1. Create new file `provider_name.py`
2. Import `RerankerModel` from `esperanto.providers.reranker.base`
3. Import `RerankResponse`, `RerankResult` from `esperanto.common_types.reranker`
4. Define class inheriting from `RerankerModel`
5. Implement all abstract methods
6. Add `__post_init__()` following the pattern
7. Use `_validate_inputs()` for input validation
8. Use `_normalize_scores()` if needed
9. Add provider to `factory.py` in `_provider_modules["reranker"]` dict
10. Write tests in `tests/providers/reranker/test_provider_name.py`
11. Add documentation in `docs/` if public provider

## Special Cases

### Transformers Provider

- Uses HuggingFace cross-encoder models locally
- No API key needed
- Downloads models to cache on first use
- Scores may be unbounded - use `_normalize_scores()`
- Model names are HuggingFace model IDs (e.g., "cross-encoder/ms-marco-MiniLM-L-12-v2")
- Can run on GPU if available

### Jina and Voyage

- Both are API-based services
- Return scores in 0-1 range (no normalization needed)
- Support batch processing (multiple queries at once in some cases)
- Have usage/billing limits

## Common Implementation Patterns

### Sorting and Slicing

Always sort by score descending before slicing:

```python
# Get scores from API
scores = api_response["scores"]

# Create index-score pairs
indexed_scores = [(idx, score) for idx, score in enumerate(scores)]

# Sort by score descending
sorted_results = sorted(indexed_scores, key=lambda x: x[1], reverse=True)

# Take top_k
top_results = sorted_results[:top_k]

# Build response
results = [
    RerankResult(index=idx, document=documents[idx], relevance_score=score)
    for idx, score in top_results
]
```

### Error Handling

Catch provider-specific errors and convert to standard exceptions:

```python
try:
    response = self.client.post(url, json=payload)
    response.raise_for_status()
except httpx.HTTPStatusError as e:
    raise RuntimeError(f"Reranking failed: {e.response.text}")
except Exception as e:
    raise RuntimeError(f"Reranking error: {str(e)}")
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.