{"openapi":"3.1.0","info":{"title":"unim API","description":"Валидатор протоколов патоморфологии (Фаза 1).","version":"0.1.0"},"paths":{"/validate/spell":{"post":{"tags":["spell"],"summary":"Validate Spell","description":"Проверяет текст на опечатки и возвращает исправленный вариант.\n\nТекст разбирается на слова, проверяется через ``lookup_compound`` SymSpell\n(корректирует опечатки в нескольких словах и «разорванные» токены). Числа и\nпунктуация пропускаются (``ignore_non_words``) — медкоды и размеры не\n«исправляются».\n\n``max_edit_distance`` выше максимума SymSpell (2) отсекается здесь как 400 —\nиначе symspellpy бросит ``ValueError(\"distance too large\")`` и FastAPI отдаст\n500 без понятного сообщения.","operationId":"validate_spell_validate_spell_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpellRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpellResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/suggest":{"post":{"tags":["spell","suggest"],"summary":"Suggest","description":"Возвращает топ-N словоформ, начинающихся с префикса.\n\nАналог автодополнения в bash: пользователь начал вводить слово, API\nподсказывает продолжения из корпуса. Результат отсортирован по частоте\nв корпусе (наиболее вероятные — первыми).","operationId":"suggest_suggest_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/predict":{"post":{"tags":["predict"],"summary":"Predict","description":"Предсказывает следующее слово по контексту (как T9 / Smart Compose).\n\nАлгоритм: берём последние 1–2 слова из введённого текста как контекст,\nищем в индексе 3-грамм топ следующих слов. При промахе на 2-словном\nконтексте — backoff на 1 слово. Если и его нет — ``context_used=0``,\nклиенту стоит фолбэчить на ``/suggest`` (префикс текущего слова).","operationId":"predict_predict_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"tags":["health"],"summary":"Health","description":"Liveness-проба: статус + кол-во загруженных терминов SymSpell и контекстов n-грамм.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"PredictRequest":{"properties":{"text":{"type":"string","title":"Text","description":"Текст ДО курсора (введённая часть заключения). Клиент отправляет всё набранное к этому моменту; сервис берёт последние 1–2 слова как контекст."},"limit":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Limit","description":"Сколько вариантов следующего слова вернуть; None → 5"}},"type":"object","required":["text"],"title":"PredictRequest","description":"Тело запроса ``POST /predict``."},"PredictResponse":{"properties":{"context_used":{"type":"integer","title":"Context Used","description":"Сколько слов контекста сработало в backoff'е: 2 — 3-грамма (точное попадание), 1 — би-грамма (backoff), 0 — контекст не найден (клиенту стоит фолбэчить на /suggest)"},"predictions":{"items":{"$ref":"#/components/schemas/Prediction"},"type":"array","title":"Predictions","description":"Топ-N следующих слов, отсортированных по частоте desc"}},"type":"object","required":["context_used"],"title":"PredictResponse","description":"Ответ ``POST /predict``."},"Prediction":{"properties":{"word":{"type":"string","title":"Word","description":"Словоформа из корпуса"},"freq":{"type":"integer","title":"Freq","description":"Частота (context → word) в корпусе; выше — вероятнее"}},"type":"object","required":["word","freq"],"title":"Prediction","description":"Одно предсказанное слово."},"SpellRequest":{"properties":{"text":{"type":"string","minLength":1,"title":"Text","description":"Текст заключения (одно или несколько слов)"},"max_edit_distance":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Max Edit Distance","description":"Максимальное расстояние Левенштейна; None → настройка SymSpell (2)"},"transfer_casing":{"type":"boolean","title":"Transfer Casing","description":"Сохранять регистр из исходного текста в исправлениях","default":true}},"type":"object","required":["text"],"title":"SpellRequest","description":"Тело запроса ``POST /validate/spell``."},"SpellResponse":{"properties":{"corrected_text":{"type":"string","title":"Corrected Text","description":"Текст с применёнными исправлениями"},"tokens":{"items":{"$ref":"#/components/schemas/TokenResult"},"type":"array","title":"Tokens","description":"По-токенная разбивка с предложениями"}},"type":"object","required":["corrected_text"],"title":"SpellResponse","description":"Ответ ``POST /validate/spell``."},"SuggestRequest":{"properties":{"prefix":{"type":"string","minLength":1,"title":"Prefix","description":"Набираемый префикс (любой регистр)"},"limit":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Limit","description":"Сколько словоформ вернуть; None → настройка по умолчанию (10)"}},"type":"object","required":["prefix"],"title":"SuggestRequest","description":"Тело запроса ``POST /suggest``."},"SuggestResponse":{"properties":{"prefix":{"type":"string","title":"Prefix","description":"Нормализованный префикс (lowercase)"},"suggestions":{"items":{"$ref":"#/components/schemas/TermHit"},"type":"array","title":"Suggestions","description":"Топ-N словоформ, отсортированных по частоте desc"}},"type":"object","required":["prefix"],"title":"SuggestResponse","description":"Ответ ``POST /suggest``."},"Suggestion":{"properties":{"term":{"type":"string","title":"Term","description":"Предложенная словоформа"},"distance":{"type":"integer","title":"Distance","description":"Расстояние Левенштейна до исходного слова"},"count":{"type":"integer","title":"Count","description":"Частота в корпусе (чем выше, тем вероятнее)"}},"type":"object","required":["term","distance","count"],"title":"Suggestion","description":"Одно исправление для слова."},"TermHit":{"properties":{"term":{"type":"string","title":"Term","description":"Словоформа из словаря"},"freq":{"type":"integer","title":"Freq","description":"Частота в корпусе"}},"type":"object","required":["term","freq"],"title":"TermHit","description":"Одно совпадение автодополнения."},"TokenResult":{"properties":{"original":{"type":"string","title":"Original","description":"Исходное слово из запроса"},"suggestions":{"items":{"$ref":"#/components/schemas/Suggestion"},"type":"array","title":"Suggestions","description":"Исправления, упорядоченные по distance asc, count desc"},"is_correct":{"type":"boolean","title":"Is Correct","description":"True, если лучший вариант на distance==0"}},"type":"object","required":["original","is_correct"],"title":"TokenResult","description":"Результат проверки одного слова в составе текста."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}