docs(tasks): add B11 (Anthropic -> local Ollama) and B12 (ISRID priors)
Both are Section B (needs-context): B11 touches the AnalysisResult contract and the question of where an LLM is needed at all; B12 touches scoring coefficients and the DB schema, which project rules keep off limits to automated edits. B11 records the key finding that the LLM does not compute priorities -- the math already lives in geo_service/scoring_service/psychotype_service and analyze_with_fallback already returns a full AnalysisResult with no API. The only unique in-hot-path LLM role is parsing free-text reports, so a strict intake form and a local provider are independent levers. B12 notes ISRID supplies empirical priors for the currently hand-tuned zone weights, with the legal status of the database flagged as a blocking question to resolve before any data enters the repo. Summary table updated to B1-B12. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+35
-1
@@ -627,6 +627,40 @@ sed -i 's/sar_mchs/vector_mchs/g; s#/root/sar-mchs#/root/vector#g' DEPLOY.md
|
||||
## B10 — Секреты и деплой (`.env`)
|
||||
**Тип:** security/deploy, исключено из делегирования. `.env` содержит плейсхолдеры `ANTHROPIC_API_KEY=your_...` и слабый `JWT_SECRET=your_jwt_secret_here_change_in_production`. Установка реального ключа Claude (для выхода из fallback) и генерация стойкого `JWT_SECRET` — ручная операция с секретами.
|
||||
|
||||
## B11 — Переход с Anthropic API на локальный Ollama
|
||||
**Тип:** архитектура / приватность, needs-context. Исключено из делегирования: затрагивает контракт `AnalysisResult` и границу «где вообще нужна LLM».
|
||||
|
||||
**Мотив:** данные о пропавших без вести (особенно о детях) не должны покидать контур. Сейчас `backend/services/claude_service.py` ходит во внешний Anthropic API. Целевой провайдер — локальная Ollama (lxc200 на pve-node2, 192.168.0.17, уже поднята под OpenHands).
|
||||
|
||||
**Ключевой факт для решения:** LLM НЕ считает приоритеты. Вся математика уже в `geo_service.build_search_zones` + `scoring_service.WeightedScorer` (7 взвешенных факторов + множители по возрасту/сезону/профилю) + `psychotype_service`. Метод `analyze_with_fallback` уже отдаёт полноценный `AnalysisResult` вообще без API. Единственная уникальная роль модели в hot-path — разбор неструктурированного текста донесения в поля `profiles`/`circumstances`; остальное (`behavioral_prediction`, `immediate_actions`, `summary`) — переупаковка уже отранжированного топ-5.
|
||||
|
||||
**Отсюда два независимых рычага (не взаимоисключающие):**
|
||||
1. Строгая категоризованная форма ввода (чипы/дропдауны/числа) — убирает саму НЕОБХОДИМОСТЬ в LLM, скоринг становится чистой математикой. Свободнотекстовое поле `circumstances` оставить для чтения человеком.
|
||||
2. Локальная модель — сохраняет LLM, но переносит провайдера внутрь контура. Недетерминизм и риск галлюцинаций при этом НЕ исчезают.
|
||||
|
||||
**Рекомендуемая слоёная схема:** скоринг ВСЕГДА детерминированный (то есть инвертировать текущую логику — сегодняшний fallback становится основным путём, а не аварийным); форма — способ ввода по умолчанию; Ollama — опциональный ЧЕРНОВОЙ парсер, который предзаполняет форму для подтверждения оператором, никогда не имеет решающего слова и никогда не считает приоритеты.
|
||||
|
||||
**Объём работ:** абстрагировать провайдера за интерфейсом (сейчас класс жёстко завязан на пакет `anthropic`), вынести выбор в конфиг (`LLM_PROVIDER`, `OLLAMA_BASE_URL`, имя модели), учесть отсутствие у Ollama нативного tool-use и более слабое следование формату JSON (из-за этого B2 — устойчивое извлечение JSON — становится критичным), покрыть тестами оба провайдера. Отдельно решить судьбу `ANTHROPIC_API_KEY` в `.env` (см. B10).
|
||||
|
||||
**Зависимости:** пересекается с B2 (парсинг JSON) и B10 (секреты). Делать после решения по B4 (мёртвая мобильная форма) — иначе неясно, какая форма ввода целевая.
|
||||
|
||||
## B12 — Внесение данных из ISRID (международная база инцидентов ПСР)
|
||||
**Тип:** данные / доменная модель, needs-context. Исключено из делегирования: напрямую затрагивает коэффициенты скоринга и схему БД.
|
||||
|
||||
**Что это:** ISRID (International Search & Rescue Incident Database, Robert Koester, «Lost Person Behavior») — международная база инцидентов поисково-спасательных операций со статистикой поведения потерявшихся по категориям субъекта: кольцевые модели и модели рассеивания (дистанции по процентилям от точки потери), типовые места обнаружения, зависимость от рельефа и категории субъекта.
|
||||
|
||||
**Зачем именно нам:** сейчас веса зонального скоринга (`forest 0.25`, `water 0.20`, …) и радиусы зон заданы вручную, экспертно. ISRID даёт внешние ЭМПИРИЧЕСКИЕ априорные значения для тех же величин по международной выборке — это позволяет заменить часть догадок статистикой и резко снижает объём собственных данных, нужный для калибровки.
|
||||
|
||||
**Как стыкуется с планом по 14-летнему архиву спецдонесений:** ISRID — источник априорных значений, собственный архив — источник локальной калибровки (местная специфика: рельеф, климат, структура вызовов). Правильный порядок — сначала ISRID как базовая линия, затем поправки по своим данным. Именно эта комбинация делает переход к чисто статистической модели реалистичным.
|
||||
|
||||
**Что нужно решить до начала:**
|
||||
- **Правовой статус — блокирующий вопрос.** ISRID не является свободно распространяемой базой: доступ к данным и производным моделям регулируется автором/правообладателем. Условия использования (в частности, допустимость зашивать производные коэффициенты в наш продукт) нужно выяснить ДО внесения каких-либо данных в репозиторий. Вопрос не технический.
|
||||
- **Единицы и категории.** Категории субъекта в ISRID (hiker, dementia, child по возрастным группам, autism, …) не совпадают один-к-одному с нашими профилями; дистанции даны в своих единицах и привязаны к типу местности. Нужны явные словари соответствия и решение, что делать с профилями без аналога.
|
||||
- **Редкие профили.** По РАС и эпилепсии выборки малы даже в ISRID — там сохранить экспертные коэффициенты и помечать их как «не выведенные из данных».
|
||||
- **Куда кладём.** Отдельный версионированный справочник априорных значений с указанием источника на каждую величину, а не правка констант в коде: нужно всегда понимать, какое число откуда взялось (ISRID / свой архив / эксперт).
|
||||
|
||||
**Жёсткое правило:** ни ISRID, ни архив не дают права автоматически перезаписывать формулу весов — изменение коэффициентов проходит через ревью человека (см. B1 и «Жёсткие исключения» в начале файла).
|
||||
|
||||
---
|
||||
|
||||
# Сводка
|
||||
@@ -635,6 +669,6 @@ sed -i 's/sar_mchs/vector_mchs/g; s#/root/sar-mchs#/root/vector#g' DEPLOY.md
|
||||
|---|---|---|
|
||||
| Atomic (backend) | A1–A9 | локальной LLM |
|
||||
| Atomic (frontend) | A10–A16 | локальной LLM |
|
||||
| Needs-context | B1–B10 | сильной модели / человеку |
|
||||
| Needs-context | B1–B12 | сильной модели / человеку |
|
||||
|
||||
**Рекомендуемый порядок для локальной модели:** A8 и A7 первыми (чистка мёртвого кода и зелёный CI дают чистую базу для проверки остальных), затем backend A1–A6, затем docs A9, затем frontend A10–A16. После каждой backend-задачи прогонять `PYTHONPATH=/root/vector python -m pytest backend/tests -q`.
|
||||
|
||||
Reference in New Issue
Block a user