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

# Hybrid Scoring: How Remem Ranks Retrieved Memories

> Remem ranks memories using a 70/20/10 formula of semantic similarity, recency, and importance. Learn how each signal works so you can tune retrieval.

When you call `recall()` or `context()`, Remem doesn't return the memory with the highest cosine similarity — it returns the memory that is most **useful** right now. That distinction matters. A semantically identical memory stored six months ago is usually less useful than one stored yesterday. A fact you explicitly marked as important should surface even when the query only loosely matches. Remem's hybrid scoring formula balances all three signals to get you there.

## The Formula

```text theme={null}
final_score = 0.70 × cosine_similarity
            + 0.20 × recency_score
            + 0.10 × importance_score
```

The weights are fixed: semantic meaning carries the most influence, recency keeps results fresh, and importance gives you a lever to pin high-value facts to the top of results.

***

## The Three Signals

<AccordionGroup>
  <Accordion title="Cosine Similarity — 70%">
    **How semantically similar is the stored memory to your query?**

    This is what makes semantic search work. You don't need exact keyword matches. You ask `"where does this user live?"` and the memory `"User is based in Lagos, Nigeria"` scores high because the *meaning* aligns — not because the words overlap.

    Cosine similarity is computed against the embedding of your query using the same model that embedded the original memory. The score ranges from `0.0` (no relationship) to `1.0` (identical meaning).

    ```python theme={null}
    # This query will match "User is based in Lagos, Nigeria" at ~0.89 cosine
    memories = client.recall(
        "where does this user live?",
        user_id="user_123",
        agent_id="support_bot",
    )
    ```
  </Accordion>

  <Accordion title="Recency Score — 20%">
    **How recently was the memory stored or last accessed?**

    Recency decays exponentially over time. A memory from yesterday scores close to `1.0`; the same memory from six months ago might score `0.12`. This prevents stale facts from outranking fresh ones when semantic similarity is equal.

    You don't control recency directly — it is computed automatically from the memory's timestamp. The practical implication: if a user updates their location, the newer memory will naturally outrank the older one without you having to delete anything.
  </Accordion>

  <Accordion title="Importance Score — 10%">
    **How important did you mark this memory at store time?**

    You set this with the `importance` parameter when calling `remember()`. The value ranges from `0.0` to `1.0` and defaults to `0.5`. A higher value gives the memory a small but consistent boost across all future retrievals — useful for facts you always want surfaced regardless of recency.

    ```python theme={null}
    client.remember(
        "User is on the Enterprise plan — never suggest downgrades",
        user_id="user_123",
        agent_id="sales_bot",
        memory_type="semantic",
        importance=0.9,
    )
    ```

    <Tip>
      Use `importance=0.9` for stable facts like name, location, plan type, or communication preferences. These facts should always surface, even when they are months old.
    </Tip>
  </Accordion>
</AccordionGroup>

***

## Score Detail

Every search result includes a full breakdown of how it was ranked. You never have to guess why a memory surfaced — or didn't.

```python theme={null}
memories = client.recall(
    "where does this user live?",
    user_id="user_123",
    agent_id="support_bot",
)

for m in memories:
    print(m.memory)
    print(m.score)         # 0.8890
    print(m.score_detail)
```

The `score_detail` object looks like this:

```json theme={null}
"score_detail": {
  "cosine":     0.8900,
  "recency":    0.8800,
  "importance": 0.9000,
  "final":      0.8890
}
```

| Field        | What it means                                                                                  |
| ------------ | ---------------------------------------------------------------------------------------------- |
| `cosine`     | Raw semantic similarity between the query and this memory's embedding                          |
| `recency`    | Exponential decay score based on how recently the memory was stored                            |
| `importance` | The importance value you set when calling `remember()`                                         |
| `final`      | The weighted composite score used for ranking (`0.70×cosine + 0.20×recency + 0.10×importance`) |

<Note>
  Every result from `recall()` and `context()` includes `score_detail`. Use it when debugging unexpected retrieval behaviour — it shows you exactly which signal is driving the rank.
</Note>

***

## Tuning `min_score`

The `min_score` parameter controls the minimum final score a memory must reach to be included in results. The default is `0.70`.

```python theme={null}
# Default — balanced precision for most use cases
memories = client.recall(query, user_id="user_123", agent_id="bot")

# High precision — only return memories with strong relevance
memories = client.recall(query, user_id="user_123", agent_id="bot", min_score=0.85)

# Exploration — return anything loosely related
memories = client.recall(query, user_id="user_123", agent_id="bot", min_score=0.50)

# No filter — return all memories ranked by score
memories = client.recall(query, user_id="user_123", agent_id="bot", min_score=0.0)
```

| `min_score` | When to use                                                                                     |
| ----------- | ----------------------------------------------------------------------------------------------- |
| `0.85+`     | Precision tasks — customer support, factual Q\&A — where a wrong memory is worse than no memory |
| `0.70`      | Default — good balance for most agents                                                          |
| `0.50`      | Exploration — when you want broader context and are willing to filter in your application logic |
| `0.0`       | Debugging — inspect every ranked result to understand your memory landscape                     |

<Warning>
  Setting `min_score=0.0` in production will return every stored memory, sorted by score. This is useful for debugging but will increase latency and token usage for high-volume users.
</Warning>

***

## Practical Example: Recency in Action

The table below shows how the same semantic content can rank very differently depending on when it was stored. The query is `"where does this user live?"`.

| Memory                                                    | Cosine | Recency | Importance | Final Score |
| --------------------------------------------------------- | ------ | ------- | ---------- | ----------- |
| `"User is based in Lagos, Nigeria"` — stored 1 day ago    | 0.89   | 0.98    | 0.90       | **0.909**   |
| `"User is based in Lagos, Nigeria"` — stored 6 months ago | 0.89   | 0.12    | 0.90       | **0.737**   |
| `"User prefers dark mode"` — stored 1 day ago             | 0.41   | 0.98    | 0.70       | **0.553**   |

The newest Lagos memory wins by a wide margin, even though the content is identical to the six-month-old version. Recency ensures your agent is always working with the most current information — without you having to manually delete outdated memories.
