What Is a Cross-Encoder?
A cross-encoder takes a query and one candidate passage as a single joined input and returns one number: how well that pair matches. Nothing it produces is reusable. The two halves are read together in the same pass, and the result belongs to the pair rather than being a representation of either half that could be stored.
Joint encoding, and why it cannot be precomputed
The contrast that defines the architecture is with a bi-encoder, which sends the query and the passage through an encoder separately and compares the two resulting vectors by distance. Because each passage is encoded alone, a bi-encoder's passage vectors are computed once, stored, and searched with an index; the query never touches them until the comparison, and the comparison is arithmetic over two fixed vectors.
A cross-encoder gives that up deliberately. Query tokens and passage tokens sit in one sequence, so every part of the passage is read in the presence of every part of the query. Term-by-term correspondence, negation, qualifiers and conditions — all things that distance between two summary vectors cannot express — are available to the scoring head. The cost is exact and unavoidable: there is no passage-only representation to store, so a score exists only after a forward pass over the pair, and a shortlist of a hundred candidates requires a hundred forward passes for every query received.
That single property decides where the architecture is placed. It cannot serve as a first-stage retriever over a large store, because scoring a million passages for one query would mean a million passes. It runs second, over a shortlist that a cheap stage has already narrowed, which is why a cross-encoder is most often met under the name of the stage it serves rather than the name of the architecture it is.
| Property | How the two differ |
|---|---|
| Input | A cross-encoder reads query and passage as one sequence. A bi-encoder reads each of them alone. |
| Output | A cross-encoder returns a relevance score for the pair. A bi-encoder returns one vector per input. |
| Precomputation | Passage vectors can be built and indexed before any query arrives. Pair scores cannot. |
| Query-time cost | One pass per candidate scored, against one index lookup for the whole store. |
| Usual placement | Second stage over a shortlist, against first stage over everything. |
The two are not competitors, and a system that has chosen one has usually chosen both. The bi-encoder decides which candidates exist; the cross-encoder decides their order. Replacing the first with the second is not affordable at any store size worth indexing, and replacing the second with the first gives up precisely the evidence the joint pass was there to read.
What a pair score is and is not comparable to
A cross-encoder score is produced for one pair by one scorer, and it carries little meaning outside that setting. It cannot be compared with a distance from an embedding space. It need not be comparable between two different scorers. And unless the scorer was explicitly calibrated, the raw number does not translate into a cut-off that means the same thing on every query — a fixed threshold applied across a workload discards good candidates on some queries and admits poor ones on others. The dependable reading is the ordering of the candidates it was actually run over.
Two consequences are practical rather than theoretical. A pairwise scorer cannot rescue a passage the first stage never returned, so the ceiling on the final result was fixed before it ran. And because the score depends on both halves, editing the query wording changes every score in the list at once rather than shifting them together, which makes a pairwise stage harder to reason about than an index, where the same query returns the same neighbours every time.
There is a middle architecture worth knowing, because it gets confused with both ends. Late-interaction retrieval stores a vector per token instead of one per passage and computes the match by comparing token vectors at query time. It recovers some of the term-level sensitivity of a joint pass while keeping the passage side precomputable, and it pays for that in index size, since a passage now occupies many vectors instead of one. It is a third point on the same trade-off rather than a variant of either end of it.
How the Registry classifies a pairwise passage scoring task
Scoring each candidate passage against a query as a pair and reordering the shortlist by that score is filed as information retrieval in this registry's classification. The operation writes nothing: its entire output is an ordering over passages that were handed to it, and the classification follows what a task yields rather than what runs inside it.
The Registry's canonical brief for this entry is filed as:
Score each candidate passage against the query as a pair and reorder the shortlist by that score.
Submitted for assessment it is
classified as Information retrieval, and its wording is hashed once — to
2eb7936e5b7b11bf…, the first sixteen of sixty-four hexadecimal
characters — with the wording itself never stored. The hash is what the derivation
reads.
That class's own page is /tasks/retrieval.
Classification is one of three inputs. The other two are the configuration submitted with the task, and the permanent chart derived from that configuration — fixed by the model name, the training cutoff and the temperature alone, and never reading the task at all. The same ascendant, ruling planet and harmony therefore appear on every assessment a given configuration receives, whatever it was asked to do. The derivation is published in full at /method.
What this page does not claim about cross-encoder
Which scorer occupies the stage, how long a shortlist it is given, and what latency budget it has to fit inside are deployment decisions, and the canonical brief above fixes none of them. This registry compares no scorers, publishes no ranking quality for any of them, and has run none.
The Registry does not run this task, does not inspect any system's output for it, and validates no assessment it issues against what afterwards happens. What it does is compute — from a published method, for one submitted task and one submitted configuration — a verdict and a recommended execution window. It computes neither on this page.
Questions about cross-encoder
- What is a cross-encoder?
- A cross-encoder is a scorer that takes a query and a candidate passage as a single joined input and returns one relevance score for that pair. Because both halves are read together, the score cannot be computed in advance or stored in an index.
- What is the difference between a cross-encoder and a bi-encoder?
- A bi-encoder encodes each text separately into a vector, so passage vectors can be built ahead of time and searched with an index. A cross-encoder encodes the pair together, which lets it read the correspondence between the two texts directly, and costs one forward pass per candidate at query time.
- Why is a cross-encoder used only for reranking?
- Because its cost scales with the number of candidates scored. A first stage has to consider the whole store, which a per-pair scorer cannot afford; a second stage considers only a shortlist, where the same cost is bounded by the length of that shortlist.
- Can a cross-encoder score be used as a confidence value?
- Not without calibration. The raw output is trained to order candidates rather than to sit on a scale that means the same thing across queries, so one fixed cut-off applied to a whole workload behaves differently from query to query.
- Does a cross-encoder need its own index?
- No, and it cannot have one. There is nothing passage-only to store, because a score exists only for a query and a passage together. The index belongs to the stage in front of it.
Related entries
Order an assessment for information retrieval tasks
The Registry issues a permanent, numbered task risk assessment for one submitted task and one submitted configuration. EUR 1.90 Standard, EUR 4.90 Extended, EUR 14.90 Full Chart, which adds the permanent chart. Assessments from EUR 1.90; machine-readable at /pricing.json.