> ## 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.

# MaxSim Rerank

> Rescore candidates with late-interaction token vectors, such as ColBERT's

The MaxSim Rerank stage takes the documents an earlier stage found and scores each one by MaxSim: every query token vector is matched to its most similar token vector in the document, and those best matches are summed. Token vectors come from a multi-vector feature, for example the ColBERT extractor's `mixpeek://colbert_extractor@v1/colbertv2_v1`.

Only the candidates are scored. The vector store reads the token vectors of the documents you pass in and returns one score per document, so the cost grows with the number of candidates.

<Note>
  **Stage Category**: SORT (Rescores and reorders)

  **Transformation**: N documents → N documents (rescored, reordered)
</Note>

## When to Use

| Use Case | Description |
| - | - |
| **Dense search, then late interaction** | A fast dense search finds 100 candidates; MaxSim orders them with ColBERT's token-level precision |
| **Keyword or fused candidates** | Any candidate list works, as long as its documents (or their source objects) have token vectors |
| **Large collections** | Rescoring the top candidates reads far fewer token vectors than exhaustive MaxSim over every document |

## Parameters

| Parameter | Type | Default | Description |
| - | - | - | - |
| `feature_uri` | string | required | The multi-vector feature to score with |
| `query` | string | `{{INPUT.query}}` | Query text, encoded by the feature's own model |
| `top_n` | integer | all, up to 1000 | Rescore only the first `top_n` documents; the rest keep their order after them |
| `match_on` | string | `document_id` | `document_id`: the candidates themselves hold the token vectors. `root_object_id`: the token vectors live in another collection built over the same bucket objects |
| `missing` | string | `bottom` | A candidate with no token vectors: `bottom` keeps it after the scored ones, `drop` removes it |
| `query_vectors` | list of vectors | none | The query's token vectors, if you encoded the query yourself |

## Two collections over one bucket

A collection runs one extractor. To search densely and rerank with ColBERT, create two collections over the same bucket: one with the text extractor, one with the ColBERT extractor. Search the text collection, then rerank with `match_on: root_object_id`. Each candidate is scored with the best MaxSim among the ColBERT documents made from its source object.

```json theme={null}
{
  "stages": [
    {
      "stage_name": "dense",
      "stage_id": "feature_search",
      "parameters": {
        "searches": [
          {
            "feature_uri": "mixpeek://text_extractor@v1/multilingual_e5_large_instruct_v1",
            "query": {"input_mode": "text", "value": "{{INPUT.query}}"},
            "top_k": 100
          }
        ],
        "final_top_k": 100
      }
    },
    {
      "stage_name": "late-interaction",
      "stage_id": "maxsim_rerank",
      "parameters": {
        "feature_uri": "mixpeek://colbert_extractor@v1/colbertv2_v1",
        "query": "{{INPUT.query}}",
        "top_n": 100,
        "match_on": "root_object_id"
      }
    }
  ]
}
```

## What the stage reports

The stage's metadata in the execution response carries `candidates`, `scored`, `missing_tokens` and `query_tokens`. With `match_on: root_object_id` it also reports `source_objects` and `token_documents_scored`, the number of token documents the vector store scored.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.