commit 6a7872b3452d8fd4c4a7edb4e2ce583e50c9e9ec Author: “Naeel” Date: Fri Aug 28 08:53:16 2026 +0300 Initialize recipe recognition repository diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3270609 --- /dev/null +++ b/.gitignore @@ -0,0 +1,52 @@ +# Python bytecode and caches +__pycache__/ +*.py[cod] +*$py.class +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ +.coverage +htmlcov/ + +# Virtual environments +.venv/ +venv/ +env/ +ENV/ + +# Packaging and build output +build/ +dist/ +*.egg-info/ +.eggs/ +pip-wheel-metadata/ + +# Local configuration and secrets +.env +.env.* +!.env.example +*.pem +*.key + +# Local databases and runtime files +*.db +*.sqlite +*.sqlite3 +instance/ +uploads/ +*.log + +# IDE and OS files +.vscode/ +.idea/ +.DS_Store +Thumbs.db + +# Common binary artifacts +*.bin +*.exe +*.so +*.dll +*.zip +*.tar +*.gz \ No newline at end of file diff --git a/PLAN/chat_messages.md b/PLAN/chat_messages.md new file mode 100644 index 0000000..3d49aca --- /dev/null +++ b/PLAN/chat_messages.md @@ -0,0 +1,204 @@ +Пользователь: +/home/naeel/MED/recipe/PLAN/recipe1.png - пример рецепта +/home/naeel/MED/recipe/PLAN/gemini.md - то что жемини советует + +надо - план создания приложения для андроида, которое +1. будет вычленять прямоукльник с датой рецепта и прямоугольник с названиями/дозировками лекарств и отправлять выделенное на сервер для дальнейшей обработки +2. после обработки сервер перешлёт обратно в приложение распознынне данные, которое приложение выведет на экран на место рукописного текста +пример - как гугл переводчик в режиме распознавания + +ФИО ДР пациента не должны быть копированы, их прямоугольник не доолжен выделяться. или - выделяться но явно показываться что не используется, заблюрены или как то иначе + +план - коротко, без воды, понятно, НИКАКОГО КОДА, кодить будут агенты, от тебя - архитектурные идеи, что гового из библиотек можно использовать, что - писать самим + +задание понятно ? + +Ассистент: +Задание понятно. Изучил рецепт и план Gemini. Готовлю архитектурный план. + +Ассистент: +--- + +## План: Android-приложение распознавания рецепта + +**Суть:** снимок бланка → выделение зон → OCR на сервере → наложение текста поверх рукописного (AR-режим). Зона ФИО/ДР — визуально заблюрена, на сервер не отправляется. + +--- + +### Архитектура (4 слоя) + +``` +Camera → [Document Scanner] → aligned bitmap + ↓ + [Zone Detector] ←— ML Kit Text Recognition + ↓ + PATIENT | DATE | MEDICATIONS | OTHER + ↓blur ↓ ↓ + не отправляется POST /api/v1/recognize + ↓ + [Server OCR] + ↓ + JSON {date, medications[]} + ↓ + [AR Overlay Renderer] +``` + +--- + +### Клиент — Android / Kotlin / Compose + +**Готовые библиотеки:** +- `ML Kit Document Scanner` — захват + перспективная коррекция бланка +- `ML Kit Text Recognition v2` — определение bounding boxes зон +- `Ktor Client` — HTTP + kotlinx.serialization +- `Jetpack Compose + Material 3` — UI +- `Coil Compose` — отображение bitmap + +**Писать самим:** +- **Zone Classifier** — эвристика: y-позиция блока + ключевые слова ("Rp.", "Ф.И.О.", "Дата рождения") +- **Privacy Masking** — Compose Canvas: blur overlay на PATIENT-зоне +- **AR Overlay Renderer** — Compose Canvas с наложением текста поверх изображения + +--- + +### Сервер — Python / FastAPI + +**Готовые:** +- `FastAPI + pydantic` — API +- `Google Cloud Vision API` или `Azure Computer Vision` — OCR рукописи +- `Tesseract 5 + LSTM` — self-hosted альтернатива + +**Писать самим:** +- Обёртка OCR API +- Парсер структуры лекарств + +--- + +### Фазы + +1. Capture + Alignment +2. Zone Detection + Privacy +3. Server OCR +4. AR Overlay + +--- + +Пользователь: +надо учитывать что это - названия лекарств то есть ограниченный набор слов + +Ассистент: +Важное замечание. Это даёт два преимущества: + +1. На сервере — нормализация через справочник. +2. В промпте LLM — контекст ограниченного словаря. +3. В Zone Classifier — дополнительные сигналы вроде `Rp.`, `Tab.`, `мг`, `мл`. + +Результат должен нормализоваться по справочнику лекарственных средств, например через `rapidfuzz` и локальную SQLite-копию ГРЛС. Низкая уверенность помечается как `uncertain: true` и показывается пользователю для проверки. + +Пользователь: +- `gpt-oss-120b` + +Ассистент: +`gpt-oss-120b` — модель на GitHub Models / Azure AI Foundry с OpenAI-совместимым API. В серверной части вместо отдельного OCR API и дополнительного парсера можно использовать один вызов Vision LLM, если конкретный endpoint принимает изображения. + +Пользователь: +120 billions наврное это ознавает + +Ассистент: +Да, скорее всего «120B» означает 120 миллиардов параметров. Уточните: это конкретная модель, которая уже у вас развёрнута, или планируете деплоить? И это Vision-модель, принимающая изображения? + +Пользователь: +- `gpt-oss-120b` + +Ассистент: +Хорошо. Вот финальный обновлённый план: + +## План: Android-приложение распознавания рецепта + +**Суть:** снимок бланка → выделение зон → Vision LLM на сервере → AR-наложение распознанного текста. Зона ФИО/ДР — заблюрена, на сервер не отправляется. + +### Архитектура + +``` +Camera → [ML Kit Document Scanner] → aligned bitmap + ↓ + [ML Kit Text Recognition v2] + ↓ + [Zone Classifier] + / | \\ + PATIENT DATE MEDICATIONS + (blur, ↓ ↓ + не шлём) POST /api/v1/recognize + ↓ + [FastAPI + gpt-oss-120b] + один Vision LLM запрос → + JSON {date, medications[]} + ↓ + [AR Overlay Renderer] +``` + +### Клиент — Android / Kotlin / Compose + +**Готовые:** +- ML Kit Document Scanner +- ML Kit Text Recognition v2 +- Ktor Client + kotlinx.serialization +- Jetpack Compose + Material 3 + Coil Compose + +**Писать самим:** +- Zone Classifier для нескольких форм бланков +- Form Detector +- Privacy Masking +- AR Overlay Renderer + +### Сервер — Python / FastAPI + +**Готовые:** +- FastAPI + pydantic +- openai Python SDK для gpt-oss-120b + +**Писать самим:** +- LLM-промпт с возвратом строго JSON +- Валидация ответа pydantic +- Retry при невалидном JSON +- Нормализация названий лекарств по справочнику ГРЛС + +### Протокол + +Request `POST /api/v1/recognize`: + +``` +zones: [ + { type: "DATE", image: "" }, + { type: "MEDICATIONS", image: "" } +] +``` + +Response: + +``` +{ + date: "12.03.2025", + medications: [ + { + name: "Амоксициллин", + raw: "Амоксицил", + uncertain: false, + dose: "500 мг", + instructions: "3 р/день" + } + ] +} +``` + +### Фазы + +1. Capture +2. Zone Detection + Privacy +3. Server LLM OCR +4. AR Overlay + +### Ограниченный набор названий лекарств + +Названия лекарств нужно проверять по справочнику, а не принимать ответ LLM без проверки. Рекомендуется хранить локальную SQLite-копию ГРЛС: МНН, торговые названия, формы выпуска и дозировки. Для сопоставления использовать `rapidfuzz`; при низком совпадении возвращать `uncertain: true`. Нельзя автоматически подменять сомнительное название без показа пользователю и возможности исправления. + diff --git a/PLAN/gemini.md b/PLAN/gemini.md new file mode 100644 index 0000000..68ad93a --- /dev/null +++ b/PLAN/gemini.md @@ -0,0 +1,80 @@ +```kotlin +// filename: AndroidCropPipelinePlan.md +// Architectural plan for building an Android handwriting text block cropper MVP using ML Kit. + +``` + +### Архитектура приложения + +Приложение нацелено на максимальную скорость и простоту: оно получает кадр с камеры, определяет границы бланка рецепта, выравнивает его, находит области с рукописным текстом и отправляет нарезку на бланке в виде массива `Base64` на бэкенд. + +--- + +### Библиотеки и стек (Android / Kotlin) + +* **UI Framework:** Jetpack Compose + Material 3. +* **Camera:** `androidx.camera:camera-camera2` (CameraX). +* **Document Scanner (Выравнивание бланка):** `com.google.android.gms:play-services-mlkit-document-scanner` (Google ML Kit Document Scanner API). +* **Text Detection (Поиск BoundingBoxes):** `com.google.android.gms:play-services-mlkit-text-recognition` (ML Kit Text Recognition). +* **Network / HTTP:** `io.ktor:ktor-client-android` + `io.ktor:ktor-client-content-negotiation` (Ktor Client). +* **Image Processing:** `io.coil-kt:coil-compose` (отображение) + стандартный `android.graphics.Bitmap`. + +--- + +### Пошаговый план разработки для Агента + +#### 1. Инициализация и разрешения + +* Настроить `build.gradle.kts` с указанными выше библиотеками. +* Запросить стандартные разрешения `CAMERA` и доступ к хранилищу. + +#### 2. Захват и выравнивание бланка (Document Scanner) + +* Использовать `GmsDocumentScannerOptions`: +* Режим: `SCANNER_MODE_FULL`. +* Формат: `RESULT_FORMAT_JPEG`. +* Лимит страниц: `1`. + + +* Запустить интентом `GmsDocumentScanning.getClient(options).getStartScanIntent(...)`. +* Получить обратно отсканированный, обрезанный и выровненный `Uri` рецепта. + +#### 3. Поиск рукописных прямоугольников (Bounding Boxes) + +* Преобразовать `Uri` выровненного бланка в `InputImage.fromFilePath`. +* Запустить `TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS)`. +* Из полученного `Text` пройтись по `Text.TextBlock` или `Text.Line`. +* Извлечь прямоугольники: `val rect: Rect? = block.boundingBox`. + +#### 4. Нарезка Bitmap (Cropping) + +* Загрузить исходный `Bitmap` бланка. +* Для каждого полученного `Rect` выполнить: +```kotlin +val cropBitmap = Bitmap.createBitmap( + originalBitmap, + rect.left, + rect.top, + rect.width(), + rect.height() +) + +``` + + +* Конвертировать каждый `cropBitmap` в строку Base64 (JPEG, quality 90). + +#### 5. Отправка на бэкенд + +* Сформировать DTO: +```kotlin +@Serializable +data class RecipePayload( + val clientVersion: String = "1.0", + val snippets: List // Array of Base64 strings +) + +``` + + +* Отправить `POST`-запрос через Ktor на эндпоинт `/api/v1/recognize`. \ No newline at end of file diff --git a/PLAN/recipe1.png b/PLAN/recipe1.png new file mode 100644 index 0000000..c1a6bef Binary files /dev/null and b/PLAN/recipe1.png differ