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

# Improve Relevance

> Make search better over time with interactions, fusion strategies, and evaluations

<Frame>
  <img src="https://mintcdn.com/mixpeek/pDBzbsnRaRIThJZv/assets/mixpeek-improve-relevance.svg?fit=max&auto=format&n=pDBzbsnRaRIThJZv&q=85&s=45d5b8c4e5e572a1ffe44216cefd90d5" alt="Improve relevance: search results generate user interaction signals, which feed fusion strategies and evaluations in a feedback loop" width="900" height="300" data-path="assets/mixpeek-improve-relevance.svg" />
</Frame>

## Interaction Signals

Capture implicit user behavior — clicks, views, dwell time, purchases — to feed into retrieval optimization.

```bash theme={null}
curl -X POST "https://api.mixpeek.com/v1/retrievers/interactions" \
  -H "Authorization: Bearer $MIXPEEK_API_KEY" \
  -H "X-Namespace: $NAMESPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "execution_id": "exec_abc",
    "feature_id": "doc_xyz",
    "interaction_type": ["click"],
    "position": 3,
    "metadata": { "duration_ms": 4500 }
  }'
```

`interaction_type` is always a JSON **array** (co-occurring signals of one action, e.g. `["click", "long_view"]`), and the document is `feature_id`. Track `position` for every signal — it is recorded for analytics and evaluation (NDCG and other rank-aware metrics).

### Signal Strength

| Signal              | Weight  | When to track                             |
| ------------------- | ------- | ----------------------------------------- |
| `click`             | Medium  | User clicked a result                     |
| `long_view`         | High    | Sustained engagement (pass `duration_ms`) |
| `add_to_cart`       | High    | Intent / funnel step                      |
| `purchase`          | Highest | User completed a goal action              |
| `negative_feedback` | Penalty | User disliked / hid the result            |

See [Interaction Signals](/docs/retrieval/interactions#signal-strategy) for the full signal matrix and per-use-case patterns.

[Interaction API →](/docs/api-reference/retriever-interactions/create-interaction)

## Auto-Tune (Learned Fusion)

Auto-Tune automatically adapts fusion weights per user based on their interaction history. Instead of manually choosing weights, the system uses Thompson Sampling to learn the optimal blend of features for each user.

<CardGroup cols={3}>
  <Card title="How It Works" icon="brain" href="/docs/retrieval/auto-tune">
    Concept page — Thompson Sampling, context levels, reward signals
  </Card>

  <Card title="Reward Signals" icon="signal" href="/docs/retrieval/reward-signals">
    Configure which interactions drive learning and how much
  </Card>

  <Card title="Rollout Guide" icon="shield" href="/docs/retrieval/auto-tune-rollout">
    Traffic splitting, shadow mode, kill switch, per-user opt-out
  </Card>
</CardGroup>

**Quick setup:**

<CodeGroup>
  ```python Python SDK theme={null}
  # 1. Create a retriever with learned fusion
  retriever = client.retrievers.create(
      retriever_name="personalized-search",
      stages=[{
          "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.query}}",
                          "top_k": 100
                      },
                      {
                          "feature_uri": "mixpeek://multimodal_extractor@v1/vertex_multimodal_embedding",
                          "query": "{{INPUT.query}}",
                          "top_k": 100
                      }
                  ],
                  "fusion": "learned",
                  "learning_config": {
                      "context_features": ["INPUT.user_id"],
                      "reward_map": {"click": 1.0, "purchase": 3.0}
                  },
                  "final_top_k": 25
              }
          }
      }]
  )

  # 2. Send interactions — learning happens automatically
  client.retrievers.create_interaction(
      feature_id="doc_123",
      interaction_type=["click"],
      position=2,
      user_id="user_abc"
  )
  ```

  ```bash cURL theme={null}
  # 1. Create a retriever with learned fusion
  curl -X POST "$MP_API_URL/v1/retrievers" \
    -H "Authorization: Bearer $MP_API_KEY" \
    -H "X-Namespace: $MP_NAMESPACE" \
    -d '{
      "retriever_name": "personalized-search",
      "stages": [{
        "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.query}}",
                "top_k": 100
              },
              {
                "feature_uri": "mixpeek://multimodal_extractor@v1/vertex_multimodal_embedding",
                "query": "{{INPUT.query}}",
                "top_k": 100
              }
            ],
            "fusion": "learned",
            "learning_config": {
              "context_features": ["INPUT.user_id"],
              "reward_map": {"click": 1.0, "purchase": 3.0}
            },
            "final_top_k": 25
          }
        }
      }]
    }'

  # 2. Send interactions — learning happens automatically
  curl -X POST "$MP_API_URL/v1/retrievers/interactions" \
    -H "Authorization: Bearer $MP_API_KEY" \
    -H "X-Namespace: $MP_NAMESPACE" \
    -d '{
      "feature_id": "doc_123",
      "interaction_type": ["click"],
      "position": 2,
      "user_id": "user_abc"
    }'
  ```
</CodeGroup>

For a step-by-step walkthrough, see the [Build a Feedback Loop](/docs/tutorials/feedback-loop) tutorial.

## Fusion Strategies

When a retriever has multiple search stages, fusion strategies determine how scores combine into the final ranking.

| Strategy                                   | How it works                                 | Best for                               |
| ------------------------------------------ | -------------------------------------------- | -------------------------------------- |
| **RRF** (Reciprocal Rank Fusion)           | Combines ranks, not scores. `1/(k + rank)`   | Default — works well with no tuning    |
| **DBSF** (Distribution-Based Score Fusion) | Normalizes score distributions then averages | When scores have different scales      |
| **Weighted**                               | Manual weights per stage                     | When you know which stage matters more |
| **Max**                                    | Takes the highest score across stages        | When any match is sufficient           |
| **Learned**                                | Auto-tunes weights from interaction signals  | When you have 500+ interactions        |

Set `fusion` inside the `feature_search` stage parameters (alongside `searches` and `final_top_k`):

```json theme={null}
{
  "fusion": "rrf"
}
```

For `"fusion": "learned"`, add a `learning_config` (see the Auto-Tune example above). Learned fusion uses Thompson Sampling to shift weight toward stages whose results users engage with; with zero interactions it behaves like `rrf` and transitions as signals accumulate.

## Evaluations

Measure retriever quality against ground truth datasets with standard IR metrics.

```bash theme={null}
# Create a ground truth dataset
curl -X POST "https://api.mixpeek.com/v1/retrievers/$RETRIEVER_ID/evaluations/datasets" \
  -H "Authorization: Bearer $MIXPEEK_API_KEY" \
  -H "X-Namespace: $NAMESPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "dataset_name": "product-search-eval",
    "queries": [
      { "query": {"query_text": "wireless headphones"}, "relevant_document_ids": ["doc_1", "doc_2"] }
    ]
  }'

# Run evaluation
curl -X POST "https://api.mixpeek.com/v1/retrievers/$RETRIEVER_ID/evaluations" \
  -H "Authorization: Bearer $MIXPEEK_API_KEY" \
  -H "X-Namespace: $NAMESPACE_ID" \
  -H "Content-Type: application/json" \
  -d '{ "dataset_id": "'$DATASET_ID'", "limit": 20 }'
```

Returns Precision, Recall, F1, NDCG, MAP, and MRR at configurable cutoffs. Use evaluations to compare retriever configurations before deploying changes.

[Evaluation API →](/docs/api-reference/retriever-evaluations/run-evaluation)

## Analytics

Monitor retriever performance in production:

* **Stage latency breakdown** — identify which stages are slow
* **Cache hit rates** — verify caching is effective
* **Score distributions** — detect relevance drift
* **Query patterns** — understand what users search for

See [Analytics & Performance](/docs/operations/analytics-overview) for the analytics endpoints to build dashboards or trigger alerts on degradation.

## The Feedback Loop

```
Search → Results → User interacts → Signal captured → Fusion learns → Better results
```

1. Users search via retrievers
2. Interaction signals capture what they engage with
3. Learned fusion adjusts stage weights automatically
4. Annotations provide explicit ground truth for edge cases
5. Evaluations measure improvement quantitatively
6. The cycle repeats — retrieval improves with usage
