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

# Пошук

> Виконуйте вектор ANN, BM25 і хронологічну гілки над одним відфільтрованим набором рядків із типізованою DSL фільтрів і власним top_k для кожної гілки.

`POST /v1/namespaces/{ns}/search` виконує до трьох ранжованих гілок над одним відфільтрованим набором рядків. Усі гілки опціональні; потрібна хоча б одна. `label` і `filter` застосовуються до кожної гілки.

```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}
  }
}
```

Відповідь — один незалежний ранжований список на гілку з часом виконання на сервері:

```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}
}
```

## Фільтри

Приймаються дві форми:

* **Одна рівність**: `{"property": "project", "value": "conare"}` — обслуговується прямо з posting lists.
* **Масив-DSL**: `[property, op, value]` з `Eq`, `NotEq`, `Gt`, `Gte`, `Lt`, `Lte`, `In` (значення-масив), композуються через `["And", [f1, f2, ...]]` / `["Or", [...]]` до 16 рівнів вкладеності.

Порівняння типізоване: числа порівнюються числово, рядки — лексикографічно (за порядком байтів), boolean — як `false < true`. Невідповідність типу чи відсутність властивості нічому не відповідає — включно з `NotEq` — і не є помилкою. Невідомі оператори, порожні списки `And`/`Or` та не-масиви для `In` — це `400` із зазначенням винуватця.

## Векторна гілка

Оцінки — це **косинусна подібність на L2-унормованих векторах, і завжди точні**: індекс ANN (IVF + RaBitQ 1-бітні коди) відбирає кандидатів, потім реренкує їх проти повнорозмірних векторів. Опції:

| Поле         | За замовчуванням | Значення                                                                                                                                 |
| ------------ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `mode`       | `"auto"`         | `"auto"` обирає ANN vs exact за модельованою вартістю; `"exact"` примусово brute force; `"ann"` вимагає індекс (400 за його відсутності) |
| `nprobe`     | 7% кластерів     | Скільки кластерів проходить пробінг — підвищуйте для recall, знижуйте для затримки                                                       |
| `oversample` | 4                | Множник глибини реренкінгу (`top_k × oversample` кандидатів реренкуються точно)                                                          |

Векторний пошук з фільтрами повертає рівно результати ANN-на-відповідній-підмножині — рушій розширює пробінг, щоб компенсувати селективність, тож фільтри не крадуть у вас recall тихо.

**Детермінізм:** за фіксованого стану індексу ідентичні байти запиту з ідентичними параметрами повертають байт-в-байт однакові списки збігів — за будь-якої кількості потоків чи конкурентності. За лаштунками безперервний семплер відтворює \~1% запитів ANN проти brute-force ground truth і публікує recall; ендпоінт `GET /recall-slo` (без облікових даних) звітує про здоровʼя recall у флоті.

## Гілка ключових слів

BM25 (`k1=1.2`, `b=0.75`) поверх властивості `text`. Токенайзер: нижній регістр, розбиття за кожним не-літеро-цифровим символом — без стемінгу, без stopwords (паритет word-токенайзера з Turbopuffer).

`match` контролює комбінацію токенів:

* `"auto"` (за замовчуванням) — вимагати всі токени; якщо це дає менше ніж `max(5, top_k/8)` збігів, повторити як будь-який токен. Відповідь повідомляє, який режим виконався (`"mode": "and"` / `"or"`).
* `"all"` — кожен токен обовʼязковий.
* `"any"` — звичайний диз'юнктивний BM25.

## Хронологічна гілка

Ранжує за будь-якою цілочисельною властивістю, `asc` чи `desc` — дешева нога «спершу найновіше» гібридного запиту.

## Проекція властивостей

`include_props` контролює, що їде разом із кожним збігом: пропустіть — і отримаєте лише id+score (без зайвих витрат), передайте масив імен — щоб спроектувати лише ці ключі, або `true` — щоб отримати повну мапу властивостей. Проекція означає, що реренкер може споживати збіги без другого round-trip запиту.

## Turbopuffer-сумісний shim

`POST /v2/namespaces/{ns}/query` приймає форму читання Turbopuffer — `{rank_by, filters, top_k, include_attributes}` — і повертає `{"rows": [{"id", "$dist", ...}]}` з `$dist` як косинусною відстанню. `rank_by: ["id", "asc"]` разом із `filters: ["id", "Gt", cursor]` дає курсорну пагінацію/експорт. Непідтримувані форми — це явні `400` із назвою поля, а не тихо інший запит.
