# `Milvex.Ranker`

Builder functions for hybrid search rerankers.

Provides three reranking strategies:
- `weighted/1` - Weighted average scoring
- `rrf/1` - Reciprocal Rank Fusion
- `decay/2` - Decay function scoring based on field proximity

## Examples

    {:ok, ranker} = Ranker.weighted([0.7, 0.3])
    {:ok, ranker} = Ranker.rrf(k: 60)
    {:ok, ranker} = Ranker.decay(:gauss, field: "timestamp", origin: 1_710_000_000, scale: 86_400)

# `decay`

```elixir
@spec decay(
  :gauss | :exp | :linear,
  keyword()
) :: {:ok, Milvex.Ranker.DecayRanker.t()} | {:error, Milvex.Errors.Invalid.t()}
```

Creates a decay function ranker for hybrid search.

Applies a decay curve to a numeric field, scoring documents higher
when the field value is closer to the origin.

## Parameters

  - `function` - Decay curve: `:gauss`, `:exp`, or `:linear`
  - `opts` - Keyword list of options

## Options

  - `:field` - (required) Name of the numeric field
  - `:origin` - (required) Center point (integer)
  - `:scale` - (required) Distance from origin where score = decay (positive integer)
  - `:offset` - Zone around origin with full score (default: 0)
  - `:decay` - Score at scale distance (default: 0.5, must be between 0 and 1 exclusive)

## Examples

    {:ok, ranker} = Ranker.decay(:gauss, field: "timestamp", origin: 1_710_000_000, scale: 86_400)
    {:ok, ranker} = Ranker.decay(:exp, field: "publish_time", origin: 1_710_000_000, scale: 3600, offset: 300, decay: 0.3)

# `rrf`

```elixir
@spec rrf(keyword()) ::
  {:ok, Milvex.Ranker.RRFRanker.t()} | {:error, Milvex.Errors.Invalid.t()}
```

Creates an RRF (Reciprocal Rank Fusion) ranker.

## Options

  - `:k` - Smoothness parameter (default: 60, must be positive)

## Examples

    {:ok, ranker} = Ranker.rrf()
    {:ok, ranker} = Ranker.rrf(k: 100)

# `weighted`

```elixir
@spec weighted([number()]) ::
  {:ok, Milvex.Ranker.WeightedRanker.t()} | {:error, Milvex.Errors.Invalid.t()}
```

Creates a weighted ranker with the given weights.

Each weight corresponds to a sub-search in the hybrid search.
The number of weights must match the number of searches.

## Examples

    {:ok, ranker} = Ranker.weighted([0.8, 0.2])

---

*Consult [api-reference.md](api-reference.md) for complete listing*
