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

# Models

> Three tiers of compatibility model. Start with our general head, end with a model tuned to your platform's outcomes.

Every `POST /match` call runs against a compatibility model. We ship three tiers, and you progress through them as your platform accumulates outcome data.

```mermaid theme={"dark"}
graph TD
    G[General compatibility model<br/>Jean's broad outcome corpus]
    D1[Dating head]
    D2[Hiring head]
    D3[Marketplace head]
    D4[... per domain]
    T1[Your tenant model · dating]
    T2[Your tenant model · hiring]

    G --> D1
    G --> D2
    G --> D3
    G --> D4
    D1 --> T1
    D2 --> T2
```

## 1. General compatibility model

The base. A dual-encoder + cross-encoder trained on Jean's outcome corpus aggregated across every domain we operate in. The point of the general model is not to be best-in-class on any one domain. It is to give you a working starting point on day one, even for a brand-new vertical with zero in-tenant outcome data.

Used automatically when:

* You spin up a brand-new domain that we have not yet shipped a specialized head for.
* You are integrating for the first time and have not yet submitted feedback.

## 2. Domain compatibility models

For every domain we ship — `dating`, `hiring`, `founder-investor`, `marketplace`, `agent-to-agent`, `product-recommendation` — we maintain a **domain head**. Each is initialized from the general model and then trained on aggregate outcome data across all Jean tenants operating in that domain.

Two practical advantages over the general model:

* **Quality**: domain-specific signal that the general model averages out. A dating head learns that stated preferences predict the *first message* but not the *second date*; a hiring head learns that pedigree predicts the interview but not the tenure.
* **Cost**: domain heads are smaller and cheaper to serve than the general model at equivalent quality on their domain.

Active by default the moment your tenant is enabled in a domain. No code change required.

## 3. Tenant-tuned models

Your platform's own model. Initialized from the domain head, then fine-tuned on **your** outcome data via the [training flow](#the-training-flow). Captures the idiosyncrasies of your user base, your funnel, and your definition of success.

The longer you operate, the more your tenant model diverges from any off-the-shelf alternative. This is the moat. Switching providers means restarting the compounding curve.

| Tier         | Trained on                          | Available                       |
| ------------ | ----------------------------------- | ------------------------------- |
| General      | Jean's full outcome corpus          | Day one, every tenant           |
| Domain       | All tenants' outcomes in one domain | When a domain ships             |
| Tenant-tuned | Your tenant's outcomes only         | After threshold or `force=true` |

## How `/match` picks the tier

By default, `POST /match` uses **the most specific model available** for your tenant in the requested `domain`. If you have a tenant-tuned model for `dating`, it serves that. If not, it falls back to the domain head. If the domain is new and we have not built a head yet, it falls back to general.

You can pin to a specific tier per request via the stage config on `/match`:

```json theme={"dark"}
{
  "user_id": "u_alice",
  "domain": "dating",
  "stages": {
    "embedding":     { "model": "domain"  },
    "cross_encoder": { "model": "tenant"  }
  }
}
```

Accepted values: `"general"`, `"domain"`, `"tenant"`. Pin individually per stage so you can, for example, use the tenant cross-encoder while keeping the embedding retrieval on the broader domain head.

<Tip>
  Pinning is useful for A/B tests (`?model=tenant` for the treatment arm, `?model=domain` for control) and for debugging regressions after a new fine-tune deploys.
</Tip>

## The training flow

This is how a tenant-tuned model comes into existence and stays current.

<Steps>
  <Step title="Submit outcomes" icon="upload">
    Every served match has an outcome eventually. Send them to `POST /feedback` as soon as you know them. Accepted, rejected, converted, expired, plus any tenant-registered labels.
  </Step>

  <Step title="Triplets accumulate" icon="layers">
    Each labeled outcome becomes one or more training triplets (seeker, positive, negative). We hold them in a per-tenant queue. `POST /feedback` returns `triplets_pending_train` so you can see the counter rise.
  </Step>

  <Step title="Threshold crossed" icon="bell">
    When the queue passes your domain's threshold (negotiated at onboarding), an auto fine-tune kicks off. You can also force one early with `POST /train` and `"force": true`.
  </Step>

  <Step title="Tenant model deployed" icon="rocket">
    Fine-tune typically completes in 15 to 60 minutes. The new model is deployed to your tenant and immediately used as the default for future `POST /match` calls. Older runs are retained for rollback.
  </Step>

  <Step title="Loop" icon="refresh-cw">
    Continue submitting outcomes. Every subsequent fine-tune builds on the previous, so the model's "taste" sharpens the longer you operate.
  </Step>
</Steps>

```mermaid theme={"dark"}
graph LR
    M[/match served/] --> O[Outcome observed]
    O --> F[/feedback/]
    F --> Q[(Triplet queue)]
    Q -- threshold --> T[/train/]
    T --> H[New tenant head]
    H --> M
```

## What "outcome data" actually means

The training loop is only as good as the signal you feed it. Useful outcomes share two properties:

* **Tied to a specific match.** Outcomes need `seeker_id` and `candidate_id` so we can attribute the signal.
* **Indicate a real preference or business event.** A click is weak; a conversion is strong. A like is weak; a long retained relationship is strong. Use the `weight` field on `/feedback` to express how much a given outcome should pull on the gradient.

See [Submit feedback](/api-reference/feedback/submit-feedback) for the full label and weight reference.

## Cold start: what you get on day one

| Scenario                           | Default model | Quality vs. baseline                  |
| ---------------------------------- | ------------- | ------------------------------------- |
| Brand-new domain, no Jean head yet | General       | Useful baseline, beats keyword search |
| Existing domain, brand-new tenant  | Domain head   | Strong out of the box                 |
| Existing domain, mature tenant     | Tenant-tuned  | Best available, compounds over time   |

The point is that you never have to wait. You start matching the moment the API key is issued, and the quality climbs as outcomes accumulate.

## Inspecting which model served a match

Every `POST /match` response includes the model version used per stage:

```json theme={"dark"}
{
  "matches": [...],
  "pipeline_stats": {...},
  "models_used": {
    "embedding":     { "tier": "tenant", "version": "u_acme.dating.2026-05-17" },
    "cross_encoder": { "tier": "domain", "version": "dating.cx.2026-05-01" }
  }
}
```

`tier` plus `version` are stable identifiers. Log them alongside outcomes so post-hoc analysis can attribute lift to a specific deploy.

## Cross-domain reuse

A tenant model trained for `dating` is **not** automatically used for `hiring`, even within the same tenant. Each domain trains independently because the success signal differs. You can opt into cross-domain transfer at onboarding when it makes sense (for example, if you have shared identity across two adjacent verticals).
