API сопоставления строк

Подайте два массива строк — получите сопоставленные пары. Работа асинхронная: запрос возвращает идентификатор задачи, результат забирается отдельно.

Аутентификация

Каждый запрос должен нести заголовок:

Authorization: Bearer <ваш токен>

Токен выпускается администратором сервиса и показывается один раз. Без него или с неверным — ответ 401.

Подать задачу — POST /api/v1/match
curl -X POST https://ваш-адрес/api/v1/match \
  -H "Authorization: Bearer <токен>" \
  -H "Content-Type: application/json" \
  -d '{
    "source": [
      {"id": "1", "text": "Устройство стяжки пола цементно-песчаной 50мм"}
    ],
    "target": [
      {"id": "A1", "text": "Стяжка цементно-песчаная"},
      {"id": "A2", "text": "Перегородки ГКЛ"}
    ],
    "chain": "t1+t3.rrf",
    "top_k": 5
  }'

Ответ 202:

{"job_id": "8f3c...", "status": "queued", "poll": "/api/v1/jobs/8f3c..."}
ПолеОбязательноЧто это
sourceдастроки, которые сопоставляем
targetлибо это, либо catalog_id справочник, с чем сопоставляем
catalog_id ранее загруженный справочник вместо target
chainнет цепочка подбора, по умолчанию гибрид t1+t3.rrf
top_kнетсколько кандидатов рассматривать, 1–50
propertiesнет какие свойства учитывать при подборе

У каждой строки можно передать attrs — готовые свойства (бренд, размер и прочее). Присланное вами не пересчитывается и не перетирается. Максимум строк в одном запросе: 10000.

Забрать результат — GET /api/v1/jobs/<job_id>
{
  "job_id": "8f3c...",
  "status": "completed",
  "progress": {"processed": 150, "total": 150},
  "results": [
    {
      "source_id": "1",
      "matches": [
        {"target_id": "A1", "target_text": "Стяжка цементно-песчаная",
         "score": 92.5, "rank": 1, "reason": "совпадение терминов"}
      ],
      "decision": "matched"
    }
  ],
  "stats": {"matched": 118, "ambiguous": 21, "no_match": 11, "elapsed_sec": 12.4}
}
«Не найдено» — полноценный ответ, а не ошибка. Решение no_match означает, что подходящего соответствия нет, а ambiguous — что кандидатов несколько и они близки. Сервис, который всегда что-то возвращает, заставлял бы перепроверять каждую строку вручную.
Постоянный справочник — POST /api/v1/catalogs

Если справочник у вас постоянный, загрузите его один раз и дальше ссылайтесь по catalog_id. Так векторы считаются однократно, а запросы становятся короче и дешевле.

curl -X POST https://ваш-адрес/api/v1/catalogs \
  -H "Authorization: Bearer <токен>" \
  -H "Content-Type: application/json" \
  -d '{"name": "Справочник работ", "rows": [{"id": "A1", "text": "Стяжка"}]}'
Доступные цепочки подбора
КодНазваниеСтатус
t1.bm25 Т1: BM25 (лексический поиск) доступна
t1.fuzzy Т1: нечёткое совпадение слов доступна
t1.tfidf Т1: TF-IDF и косинусная близость доступна
t1.ngram Т1: символьные 3-граммы доступна
t3.openai Т3: OpenAI Embeddings (смысловой поиск) доступна
t1+t3.rrf Т1+Т3: гибридный поиск RRF доступна
t5.llm Т5: DeepSeek выбирает кандидата доступна
t1+t3->t5 Т1+Т3 → Т5: гибридный поиск с LLM-решением доступна
t2.filter Т2: фильтр по свойствам (сужение) доступна
t2->t1+t3->t5 Т2 → Т1+Т3 → Т5: фильтр, гибрид, ЛЛМ доступна
t3.1.local Т3.1: локальные эмбеддинги (без OpenAI) доступна
t3.2.yandex Т3.2: эмбеддинги Яндекса (парные doc/query) доступна
t3.3.gigachat Т3.3: эмбеддинги GigaChat (Сбер) доступна
t6.cross Т6: cross-encoder (переранжирование) доступна
t1+t3->t6 Т1+Т3 → Т6: гибрид с переранжированием доступна
plan:Лексический поиск Лексический поиск доступна
plan:Векторный поиск Векторный поиск доступна
plan:Гибридный поиск Гибридный поиск доступна
plan:Гибрид плюс переранжирование Гибрид плюс переранжирование доступна
plan:Полный каскад с ЛЛМ Полный каскад с ЛЛМ доступна
plan:Прямой ЛЛМ без отбора кандидатов Прямой ЛЛМ без отбора кандидатов доступна
plan:Обучение на накопленном Обучение на накопленном недоступна нет T7, T6
plan:Фильтр по свойствам плюс полный каскад Фильтр по свойствам плюс полный каскад доступна

Текущий список всегда доступен по GET /api/v1/chains.

Ошибки

Всегда JSON, никогда HTML:

{"error": {"code": "unknown_chain", "message": "Неизвестная цепочка ..."}}
КодКогда
401нет токена или он отключён
400неверный запрос, недоступная цепочка, слишком много строк
404задача или справочник не найдены
413тело запроса больше допустимого