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

# Cross Compare

> Multi-tier cross-collection content matching with configurable classification

![Cross Compare stage showing multi-tier matching cascade between source and reference collections](https://mintcdn.com/mixpeek/TwtTrae3Fi3EFJ72/assets/retrievers/cross-compare.svg?fit=max\&auto=format\&n=TwtTrae3Fi3EFJ72\&q=85\&s=469f62624aa2d633d1f989b6fcec9910)

The Cross Compare stage compares source documents against a reference collection using a cascading match strategy: exact → fuzzy → semantic → visual. Each match is classified using configurable rules, enabling drift detection, deduplication, and compliance checking workflows.

> [!NOTE]
>
> **Stage Category**: APPLY (Cross-collection comparison)
>
> **Transformation**: N documents → M finding documents (`findings` mode) or N documents → N enriched documents (`enrich` mode)

## When to Use

| Use Case | Description |
| - | - |
| **Content drift detection** | Compare video UI against documentation to find outdated content |
| **Product catalog matching** | Match supplier products against internal catalog |
| **Content deduplication** | Check new content against existing corpus |
| **Compliance checking** | Verify content against requirements or standards |
| **Cross-reference validation** | Validate labels, features, or terms across sources |

## When NOT to Use

| Scenario | Recommended Alternative |
| - | - |
| Simple field joins | `document_enrich` |
| External API enrichment | `api_call` |
| Single-collection filtering | `attribute_filter` or `feature_search` |
| Semantic similarity search | `feature_search` |

## Parameters

> [!NOTE]
>
> These tables are generated from `CrossCompareParameters`, the model the stage
> validates against. `GET /v1/retrievers/stages` serves the same schema, so
> Studio's stage form and any agent reading the API see exactly these fields.

### Core Parameters

| Parameter | Type | Default | Description |
| - | - | - | - |
| `reference_collection_id` | string | *Required* | Collection containing the reference documents to compare against |
| `source_field` | string | `content` | Field on source documents holding the comparison elements. A string is used as-is; a list is treated as pre-extracted elements. |
| `reference_field` | string | `content` | Field on reference documents holding the comparison content |
| `extraction_mode` | string | `raw` | How to split the field into elements: `raw`, `lines`, `labels`, or `list` |

### Matching Configuration

`match_tiers` is a list of tier objects, not a list of strings. Each entry
carries its own threshold, so different tiers can accept at different scores.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `match_tiers` | MatchTierConfig\[] | `[{"type": "exact"}, {"type": "fuzzy", "threshold": 0.75}]` | Ordered cascade. Matching stops at the first tier that succeeds. |

Fields on each `MatchTierConfig`:

| Field | Type | Default | Description |
| - | - | - | - |
| `type` | string | *Required* | `exact` (case-insensitive equality), `fuzzy` (SequenceMatcher ratio), or `vector` (embedding search) |
| `threshold` | float | `0.75` | Minimum score for this tier to accept a match |
| `feature_uri` | string | `null` | Feature URI to search, for `vector` tiers |
| `vectors` | object\[] | `null` | Several weighted vectors combined into one score, for `vector` tiers |
| `classifications` | ClassificationRule\[] | `null` | Rules for this tier only. Falls back to the global `classifications`. |
| `min_words` | integer | `1` | Skip elements shorter than this, for `vector` tiers |
| `cross_page_fallback` | boolean | `true` | If an aligned-page search finds nothing, retry across all reference pages |

### Classification

| Parameter | Type | Default | Description |
| - | - | - | - |
| `classifications` | ClassificationRule\[] | See below | Score-to-label rules, evaluated in order, first match wins |
| `no_match_label` | string | `no_match` | Label applied when no tier matches |

A `ClassificationRule` is `{"min_score": float, "label": string}`, both required.

Default rules:

```json theme={null}
[
  {"min_score": 0.95, "label": "exact_match"},
  {"min_score": 0.85, "label": "close_match"},
  {"min_score": 0.65, "label": "partial_match"},
  {"min_score": 0.0, "label": "no_match"}
]
```

### Output Configuration

| Parameter | Type | Default | Description |
| - | - | - | - |
| `output_mode` | string | `findings` | `findings` (N-to-M, one document per comparison) or `enrich` (1-to-1, results attached to the source document) |
| `output_field` | string | `comparison_results` | Field the results land on, in `enrich` mode |

### Reference & Source Configuration

| Parameter | Type | Default | Description |
| - | - | - | - |
| `reference_limit` | integer | `200` | Maximum reference documents to fetch |
| `reference_doc_type` | string | `null` | Only use reference docs of this `doc_type`. `null` fetches all. |
| `source_location_field` | string | `start_time` | Field holding the source location reference (timestamp, page) |
| `source_doc_type_field` | string | `doc_type` | Field that names the source document's type |
| `source_doc_type_filter` | string | `null` | Only process source docs whose type matches. `null` processes all. |
| `filter_generic_labels` | boolean | `true` | In `labels` mode, drop generic UI labels (`Save`, `Cancel`, `Next`) that cannot meaningfully differ |
| `signal_fields` | object | `{}` | Map of signal name to source payload field, e.g. `{"transcript": "content"}` |

### Alignment

Used when source documents should be compared against a specific reference page
rather than the whole collection.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `alignment_mode` | string | `none` | `none` for a flat comparison, `grouped` to align source groups to reference pages |
| `alignment_group_field` | string | `vlm_page_context` | Field to group source documents by |
| `alignment_feature_uri` | string | `null` | Feature URI used for the alignment vector search |
| `alignment_limit` | integer | `5` | Reference pages considered for each alignment group |
| `alignment_query_fields` | string\[] | `["vlm_page_context", "content"]` | Source fields combined into the alignment query text |

## Extraction Modes

> [tab] raw
>
> Use the field value as a single element. Best for comparing whole content blocks.
>
> ```json theme={null}
> {"extraction_mode": "raw"}
> ```

> [tab] lines
>
> Split by newlines. Each line becomes a comparison element. Useful for step-by-step instructions or structured text.
>
> ```json theme={null}
> {"extraction_mode": "lines"}
> ```

> [tab] labels
>
> Extract UI/feature labels via pattern matching. Identifies instruction patterns ("Click **Settings**"), em-dash separators ("Label — description"), and action labels ("Configure X").
>
> Generic labels like "Save", "Cancel", "Next" are filtered by default.
>
> ```json theme={null}
> {"extraction_mode": "labels", "filter_generic_labels": true}
> ```

> [tab] list
>
> Field is already a list of elements. Used directly without extraction.
>
> ```json theme={null}
> {"extraction_mode": "list"}
> ```

## Matching Cascade

Tiers run in the order you list them and matching stops at the first success:

```
For each source element:
  ├─ exact:  case-insensitive string equality        → score 1.0
  ├─ fuzzy:  SequenceMatcher ratio  ≥ tier threshold
  └─ vector: embedding similarity   ≥ tier threshold
```

There are three tier types. Text and image matching are both `vector` tiers,
distinguished by the `feature_uri` you point the tier at, so a visual comparison
is a `vector` tier on an image feature rather than a separate tier type.

If no tier matches, the element gets `match_tier: "none"` and the
`no_match_label` classification.

## Configuration Examples

```json Content Drift Detection theme={null}
{
  "stage_name": "cross_compare",
  "stage_type": "apply",
  "config": {
    "stage_id": "cross_compare",
    "parameters": {
      "reference_collection_id": "col_documentation",
      "source_field": "content",
      "reference_field": "content",
      "extraction_mode": "labels",
      "match_tiers": [
        {"type": "exact"},
        {"type": "fuzzy", "threshold": 0.75},
        {"type": "vector", "threshold": 0.85, "feature_uri": "mixpeek://text_extractor@v1/multilingual_e5_large_instruct_v1"},
        {"type": "vector", "threshold": 0.55, "feature_uri": "mixpeek://image_extractor@v1/google_siglip_base_v1"}
      ],
      "source_doc_type_filter": "scene",
      "source_location_field": "start_time",
      "classifications": [
        {"min_score": 0.95, "label": "current"},
        {"min_score": 0.75, "label": "needs_review"},
        {"min_score": 0.0, "label": "outdated"}
      ]
    }
  }
}
```

```json Product Catalog Matching theme={null}
{
  "stage_name": "cross_compare",
  "stage_type": "apply",
  "config": {
    "stage_id": "cross_compare",
    "parameters": {
      "reference_collection_id": "col_internal_catalog",
      "source_field": "product_name",
      "reference_field": "product_name",
      "extraction_mode": "raw",
      "match_tiers": [
        {"type": "exact"},
        {"type": "fuzzy", "threshold": 0.80}
      ],
      "output_mode": "enrich",
      "output_field": "catalog_match",
      "classifications": [
        {"min_score": 0.95, "label": "exact_match"},
        {"min_score": 0.80, "label": "likely_match"},
        {"min_score": 0.0, "label": "no_match"}
      ]
    }
  }
}
```

```json Content Deduplication theme={null}
{
  "stage_name": "cross_compare",
  "stage_type": "apply",
  "config": {
    "stage_id": "cross_compare",
    "parameters": {
      "reference_collection_id": "col_existing_corpus",
      "source_field": "content",
      "reference_field": "content",
      "extraction_mode": "lines",
      "match_tiers": [
        {"type": "exact"},
        {"type": "fuzzy", "threshold": 0.75},
        {"type": "vector", "threshold": 0.90, "feature_uri": "mixpeek://text_extractor@v1/multilingual_e5_large_instruct_v1"}
      ],
      "output_mode": "enrich",
      "output_field": "duplication_analysis",
      "classifications": [
        {"min_score": 0.95, "label": "duplicate"},
        {"min_score": 0.80, "label": "near_duplicate"},
        {"min_score": 0.0, "label": "unique"}
      ]
    }
  }
}
```

```json Compliance Checking theme={null}
{
  "stage_name": "cross_compare",
  "stage_type": "apply",
  "config": {
    "stage_id": "cross_compare",
    "parameters": {
      "reference_collection_id": "col_requirements",
      "source_field": "content",
      "reference_field": "requirement_text",
      "extraction_mode": "lines",
      "match_tiers": [
        {"type": "exact"},
        {"type": "fuzzy", "threshold": 0.70},
        {"type": "vector", "threshold": 0.80, "feature_uri": "mixpeek://text_extractor@v1/multilingual_e5_large_instruct_v1"}
      ],
      "output_mode": "findings",
      "classifications": [
        {"min_score": 0.90, "label": "compliant"},
        {"min_score": 0.70, "label": "partial"},
        {"min_score": 0.0, "label": "non_compliant"}
      ]
    }
  }
}
```

## Output Schema

### Findings Mode

Each comparison produces a finding document:

```json theme={null}
{
  "element_type": "text",
  "source_content": "Configure API Keys",
  "source_location": "00:01:23",
  "reference_match": "API Key Configuration",
  "reference_url": "https://docs.example.com/api-keys",
  "match_tier": "fuzzy",
  "match_score": 0.87,
  "classification": "close_match",
  "confidence": 0.92,
  "signals": {
    "context_match": true,
    "workflow_match": false,
    "transcript_match": true
  }
}
```

### Enrich Mode

Comparison results attached as a field on source documents:

```json theme={null}
{
  "document_id": "doc_source_123",
  "content": "...",
  "comparison_results": [
    {
      "element_type": "text",
      "source_content": "Configure API Keys",
      "match_tier": "fuzzy",
      "match_score": 0.87,
      "classification": "close_match",
      "confidence": 0.92
    }
  ]
}
```

### Finding Fields

| Field | Type | Description |
| - | - | - |
| `element_type` | string | Type of element: `text`, `code`, `visual`, or custom |
| `source_content` | string | Content from the source document |
| `source_location` | string | Location reference (timestamp, page number) |
| `reference_match` | string | Best matching content from reference |
| `reference_url` | string | URL or ID of matched reference document |
| `match_tier` | string | Tier used: `exact`, `fuzzy`, `semantic`, `visual`, `none` |
| `match_score` | float | Match score (0.0 - 1.0) |
| `classification` | string | Label from classification rules |
| `confidence` | float | Multi-signal confidence (0.0 - 1.0) |
| `signals` | object | Corroborating signals used in confidence |

## Performance

| Scenario | Expected Latency | Notes |
| - | - | - |
| Exact + fuzzy only (50 docs) | 50-200ms | In-memory string matching |
| With semantic tier (50 docs) | 200-500ms | MVS vector queries |
| With visual comparison (50 docs) | 500-1500ms | Multiple vector queries |
| Large reference set (200 docs) | 300-800ms | More candidates to compare |

> [!TIP]
>
> Reference documents are fetched once and reused across all source documents. The matching cascade short-circuits at the first successful tier, so ordering `match_tiers` from fastest to slowest (exact → fuzzy → vector) is optimal.

**Limits:**

* Max source documents per execution: 50
* Max reference documents fetched: 200 (configurable via `reference_limit`)

## Common Pipeline Patterns

### Drift Detection Pipeline

```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}}" },
          "top_k": 50
        }],
        "final_top_k": 50
      }
    }
  },
  {
    "stage_name": "cross_compare",
    "stage_type": "apply",
    "config": {
      "stage_id": "cross_compare",
      "parameters": {
        "reference_collection_id": "col_documentation",
        "source_field": "content",
        "reference_field": "content",
        "extraction_mode": "labels",
        "match_tiers": [
          {"type": "exact"},
          {"type": "fuzzy", "threshold": 0.75},
          {"type": "vector", "threshold": 0.85, "feature_uri": "mixpeek://text_extractor@v1/multilingual_e5_large_instruct_v1"},
          {"type": "vector", "threshold": 0.55, "feature_uri": "mixpeek://image_extractor@v1/google_siglip_base_v1"}
        ],
        "classifications": [
          {"min_score": 0.95, "label": "current"},
          {"min_score": 0.75, "label": "needs_review"},
          {"min_score": 0.0, "label": "outdated"}
        ]
      }
    }
  }
]
```

### Catalog Match + Transform

```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}}" },
          "top_k": 30
        }],
        "final_top_k": 30
      }
    }
  },
  {
    "stage_name": "cross_compare",
    "stage_type": "apply",
    "config": {
      "stage_id": "cross_compare",
      "parameters": {
        "reference_collection_id": "col_reference_catalog",
        "source_field": "product_name",
        "reference_field": "product_name",
        "match_tiers": [
        {"type": "exact"},
        {"type": "fuzzy", "threshold": 0.75}
      ],
        "output_mode": "enrich",
        "output_field": "match_result"
      }
    }
  },
  {
    "stage_name": "json_transform",
    "stage_type": "apply",
    "config": {
      "stage_id": "json_transform",
      "parameters": {
        "template": "{\"product\": \"{{ DOC.product_name }}\", \"match_status\": \"{{ DOC.match_result[0].classification }}\", \"score\": {{ DOC.match_result[0].match_score }}}"
      }
    }
  }
]
```

## Error Handling

| Error | Behavior |
| - | - |
| Reference collection not found | Stage fails with error |
| No reference documents found | All elements classified as `no_match` |
| Vector index not available | Semantic/visual tiers skipped silently |
| Source field missing on document | Document skipped |
| Exceeds max\_working\_documents | Extra documents passed through unchanged |

## vs Other Enrichment Stages

| Feature | cross\_compare | document\_enrich | api\_call |
| - | - | - | - |
| **Purpose** | Multi-tier comparison with classification | Simple field join/lookup | External API enrichment |
| **Data source** | Internal MVS namespaces | Internal MVS namespaces | External HTTP APIs |
| **Matching** | Cascading: exact → fuzzy → semantic → visual | Top-1 vector or key match | N/A |
| **Output** | Classified findings with scores | Joined fields | API response |
| **Latency** | 50-1500ms | 5-20ms | 100-500ms |
| **Best for** | Drift detection, dedup, compliance | Cross-collection joins | Third-party data |

## Related

* [Document Enrich](https://docs.mixpeek.com/docs/retrieval/stages/document-enrich.md) - Simple cross-collection joins
* [Feature Search](https://docs.mixpeek.com/docs/retrieval/stages/feature-search.md) - Vector search (often used before cross\_compare)
* [JSON Transform](https://docs.mixpeek.com/docs/retrieval/stages/json-transform.md) - Transform comparison output
* [Taxonomy Enrich](https://docs.mixpeek.com/docs/retrieval/stages/taxonomy-enrich.md) - Classification enrichment


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