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

# Recherche

> Exécutez des branches classées ANN vectorielle, mots-clés BM25 et chronologique sur un jeu filtré avec DSL de filtres typés et top_k par branche.

`POST /v1/namespaces/{ns}/search` exécute jusqu'à trois branches classées sur un même jeu de lignes filtré. Toutes les branches sont optionnelles ; au moins une est requise. `label` et `filter` s'appliquent à chaque branche.

```json theme={null}
{
  "label": "chunk",
  "filter": ["And", [["project", "Eq", "conare"], ["created_at_ms", "Gte", 1720000000000]]],
  "include_props": ["text", "created_at_ms"],
  "branches": {
    "vector":        {"embedding": [0.1, "..."], "top_k": 40},
    "keyword":       {"query": "raw query text", "top_k": 40},
    "chronological": {"attribute": "created_at_ms", "order": "desc", "top_k": 40}
  }
}
```

Réponse — une liste classée indépendante par branche, avec le temps d'exécution serveur :

```json theme={null}
{
  "vector":        {"hits": [{"id": "chunk-123", "score": 0.83}], "index": "ivf-rabitq", "server_us": 412},
  "keyword":       {"hits": [{"id": "chunk-9", "score": 14.2}], "mode": "and", "server_us": 200},
  "chronological": {"hits": [{"id": "chunk-7", "value": 1720000000000}], "server_us": 90}
}
```

## Filtres

Deux formes sont acceptées :

* **Égalité simple** : `{"property": "project", "value": "conare"}` — servie directement depuis les listes d'affichage.
* **DSL tableau** : `[property, op, value]` avec `Eq`, `NotEq`, `Gt`, `Gte`, `Lt`, `Lte`, `In` (valeur tableau), composables via `["And", [f1, f2, ...]]` / `["Or", [...]]` jusqu'à 16 niveaux.

La comparaison est typée : les nombres se comparent numériquement, les chaînes lexicographiquement (ordre d'octets), les booléens comme `false < true`. Une incompatibilité de type ou une propriété absente ne correspond à rien — y compris pour `NotEq` — sans jamais lever d'erreur. Les opérateurs inconnus, les listes `And`/`Or` vides et les valeurs `In` non tableaux sont des `400` nommant le fautif.

## Branche vectorielle

Les scores sont **une similarité cosinus sur des vecteurs L2-normalisés, et toujours exacts** — l'index ANN (IVF + codes RaBitQ 1-bit) présélectionne les candidats, puis les rerank contre les vecteurs en pleine précision. Options :

| Champ        | Défaut           | Signification                                                                                                              |
| ------------ | ---------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `mode`       | `"auto"`         | `"auto"` choisit ANN vs exact selon un coût modélisé ; `"exact"` force brute-force ; `"ann"` exige l'index (400 si absent) |
| `nprobe`     | 7 % des clusters | Clusters sondés — augmentez pour le rappel, diminuez pour la latence                                                       |
| `oversample` | 4                | Multiplicateur de profondeur de rerank (`top_k × oversample` candidats rerankés exactement)                                |

La recherche vectorielle filtrée renvoie exactement les résultats ANN sur le sous-ensemble correspondant — le moteur élargit le sondage pour compenser la sélectivité, si bien que les filtres ne vous coûtent pas silencieusement en rappel.

**Déterminisme :** pour un état d'index fixe, des octets de requête identiques avec des paramètres identiques renvoient des listes de résultats identiques au bit — quel que soit le nombre de threads ou la concurrence. En coulisses, un échantillonneur continu rejoue \~1 % des requêtes ANN contre la vérité brute-force et publie le rappel ; l'endpoint sans identifiants `GET /recall-slo` rapporte la santé de rappel de la flotte.

## Branche mot-clé

BM25 (`k1=1.2`, `b=0.75`) sur la propriété `text`. Tokeniseur : minuscules, split sur chaque caractère non alphanumérique — pas de stemming, pas de mots vides (parité de tokeniseur mot avec Turbopuffer).

`match` contrôle la combinaison des tokens :

* `"auto"` (défaut) — exige tous les tokens ; si cela produit moins de `max(5, top_k/8)` résultats, réessayer en mode any-token. La réponse indique quel mode a été utilisé (`"mode": "and"` / `"or"`).
* `"all"` — chaque token requis.
* `"any"` — BM25 disjonctif ordinaire.

## Branche chronologique

Classe par n'importe quelle propriété entière, `asc` ou `desc` — la branche « du plus récent au plus ancien » économique d'une requête hybride.

## Projeter des propriétés

`include_props` contrôle ce qui accompagne chaque résultat : omettez-le pour id+score seulement (aucun coût supplémentaire), passez un tableau de noms pour projeter uniquement ces clés, ou `true` pour la carte complète de propriétés. La projection signifie qu'un reranker peut consommer les résultats sans un second aller-retour.

## Shim compatible Turbopuffer

`POST /v2/namespaces/{ns}/query` accepte la forme de lecture Turbopuffer — `{rank_by, filters, top_k, include_attributes}` — et renvoie `{"rows": [{"id", "$dist", ...}]}` avec `$dist` comme distance cosinus. `rank_by: ["id", "asc"]` avec `filters: ["id", "Gt", cursor]` fournit la pagination/l'export par curseur. Les formes non prises en charge sont des `400` explicites nommant le champ — jamais une requête silencieusement différente.
