> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mixpeek.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Score Threshold

> Drop results below an absolute score and return no results when nothing qualifies

The Score Threshold stage applies an **absolute** quality gate: it drops every document whose score on a chosen field fails a minimum bar. When nothing clears the bar it returns an **empty** result set and sets `all_below_threshold` — the signal your UI uses to show a "no good results" state instead of presenting weak matches.

<Note>
  **Stage Category**: REDUCE (N documents → ≤ N documents)

  **Transformation**: keeps only documents meeting `min_score`; the set may become empty.
</Note>

## Why not just normalize and filter?

`score_normalize` with `min_max` always rescales the **top** result to `1.0` — so a threshold on the normalized score can *never* reject an all-bad result set (the best match is always 1.0). Score Threshold gates on the **raw or calibrated** score, so "everything is below the bar" is expressible. Threshold on a calibrated score — the [`rerank`](/retrieval/stages/rerank) cross-encoder score is ideal (`score_field: "scores.rerank"`), since it is far more absolute and comparable than a raw cosine similarity.

## When to Use

| Use Case                      | Description                                                         |
| ----------------------------- | ------------------------------------------------------------------- |
| **Suppress weak matches**     | Don't show results that aren't good enough to be useful             |
| **"No good results" UX**      | Branch to a no-results / suggestion state via `all_below_threshold` |
| **Quality gate after rerank** | Hard-gate on the calibrated cross-encoder score                     |
| **Confidence cutoffs**        | Only surface high-confidence matches to end users                   |

## When NOT to Use

| Scenario                         | Recommended Alternative                                  |
| -------------------------------- | -------------------------------------------------------- |
| Rescale scores for comparison    | [`score_normalize`](/retrieval/stages/score-normalize)   |
| Keep top-N regardless of quality | [`limit`](/retrieval/stages/limit)                       |
| Filter by metadata fields        | [`attribute_filter`](/retrieval/stages/attribute-filter) |
| Reorder by score                 | [`sort_relevance`](/retrieval/stages/sort-relevance)     |

## Parameters

| Parameter       | Type   | Default      | Description                                                                            |
| --------------- | ------ | ------------ | -------------------------------------------------------------------------------------- |
| `min_score`     | float  | *(required)* | Absolute minimum score a document must meet to be kept                                 |
| `score_field`   | string | `score`      | Score field to gate on. Dot-paths supported (e.g. `scores.rerank`, `metadata.quality`) |
| `comparison`    | string | `gte`        | Keep docs whose score is `gte` (≥) or `gt` (strictly >) `min_score`                    |
| `missing_score` | string | `drop`       | What to do with documents lacking `score_field`: `drop` or `keep`                      |

## Response Metadata

| Field                          | Description                                                |
| ------------------------------ | ---------------------------------------------------------- |
| `all_below_threshold`          | `true` when **no** document met the bar (empty result set) |
| `input_count` / `output_count` | Documents in / kept                                        |
| `dropped`                      | Documents removed                                          |
| `missing_score_docs`           | Documents that lacked `score_field`                        |

## Configuration Examples

<CodeGroup>
  ```json Gate on the rerank score theme={null}
  {
    "stage_name": "score_threshold",
    "stage_type": "reduce",
    "config": {
      "stage_id": "score_threshold",
      "parameters": {
        "min_score": 0.5,
        "score_field": "scores.rerank"
      }
    }
  }
  ```

  ```json Strict cutoff on raw score theme={null}
  {
    "stage_name": "score_threshold",
    "stage_type": "reduce",
    "config": {
      "stage_id": "score_threshold",
      "parameters": {
        "min_score": 0.7,
        "comparison": "gt"
      }
    }
  }
  ```

  ```json Keep docs missing the score field theme={null}
  {
    "stage_name": "score_threshold",
    "stage_type": "reduce",
    "config": {
      "stage_id": "score_threshold",
      "parameters": {
        "min_score": 0.5,
        "score_field": "scores.rerank",
        "missing_score": "keep"
      }
    }
  }
  ```
</CodeGroup>

## "No Good Results → Suggestions" Pattern

Gate on the rerank score; when nothing qualifies, the empty result + `all_below_threshold` tells your application to fall back to [`query_expand`](/retrieval/stages/query-expand) for adjacent suggestions instead of showing weak matches.

```json theme={null}
[
  {
    "stage_name": "feature_search",
    "stage_type": "filter",
    "config": {
      "stage_id": "feature_search",
      "parameters": {
        "searches": [
          {"feature_uri": "mixpeek://text_extractor@v1/multilingual_e5_large_instruct_v1", "query": {"input_mode": "text", "value": "{{INPUT.query}}"}}
        ],
        "final_top_k": 50
      }
    }
  },
  {
    "stage_name": "rerank",
    "stage_type": "sort",
    "config": {
      "stage_id": "rerank",
      "parameters": {
        "inference_name": "BAAI__bge_reranker_v2_m3",
        "query": "{{INPUT.query}}",
        "document_field": "content"
      }
    }
  },
  {
    "stage_name": "score_threshold",
    "stage_type": "reduce",
    "config": {
      "stage_id": "score_threshold",
      "parameters": {
        "min_score": 0.5,
        "score_field": "scores.rerank"
      }
    }
  }
]
```

<Tip>
  Calibrate `min_score` empirically: run representative queries (including ones that *should* return nothing) and pick the value that separates good from bad on the rerank score. The right cutoff is query-domain specific.
</Tip>

## Performance

| Metric         | Value              |
| -------------- | ------------------ |
| **Latency**    | \< 1ms             |
| **Memory**     | O(N)               |
| **Cost**       | Free               |
| **Complexity** | O(N) (single pass) |

## Related

* [Score Normalize](/retrieval/stages/score-normalize) - Rescale scores to a common range
* [Rerank](/retrieval/stages/rerank) - Calibrated cross-encoder scores to gate on
* [Query Expand](/retrieval/stages/query-expand) - Adjacent suggestions when nothing qualifies
* [Limit](/retrieval/stages/limit) - Truncate to top-N regardless of score
