Trans_for_doctors / INTEGRATION_GUIDE.md
Mintik24's picture
🎉 Полный рефакторинг проекта Medical Transcriber
e275025
# Гайд по интеграции рефакторинга
## 🚀 Быстрый старт
После рефакторинга были созданы новые модули в папке `common/`. Ниже показано, как их использовать.
## 📋 Содержание
1. [Константы вместо магических чисел](#константы)
2. [Логирование](#логирование)
3. [Валидация данных](#валидация)
4. [Типизированные структуры](#структуры)
5. [Обработка ошибок](#ошибки)
---
## Константы
### Прежде всего обновите импорты
```python
# app/gui_app.py
from common import (
UIColors,
UIDimensions,
Messages,
FontConfig,
AudioFormats,
get_logger
)
logger = get_logger(__name__)
```
### UI размеры
```python
# ДО
self.setGeometry(100, 100, 1200, 800)
# ПОСЛЕ
self.setGeometry(
100, 100,
UIDimensions.MAIN_WINDOW_WIDTH,
UIDimensions.MAIN_WINDOW_HEIGHT
)
```
### UI цвета
```python
# ДО
self.start_btn.setStyleSheet("""
QPushButton {
background-color: #4CAF50;
color: white;
}
QPushButton:hover {
background-color: #45a049;
}
""")
# ПОСЛЕ
self.start_btn.setStyleSheet(f"""
QPushButton {{
background-color: {UIColors.PRIMARY_GREEN};
color: white;
}}
QPushButton:hover {{
background-color: {UIColors.HOVER_GREEN};
}}
""")
```
### Текстовые сообщения
```python
# ДО
if not self.audio_path:
QMessageBox.warning(
self,
"Ошибка",
"Пожалуйста, выберите аудиофайл!"
)
return
# ПОСЛЕ
if not self.audio_path:
QMessageBox.warning(
self,
Messages.WARNING_TITLE,
Messages.ERROR_NO_AUDIO_FILE
)
return
```
### Диалоги выбора файлов
```python
# ДО
file_path, _ = QFileDialog.getOpenFileName(
self,
"Выберите аудиофайл",
"",
"Audio Files (*.wav *.mp3 *.m4a);;All Files (*)"
)
# ПОСЛЕ
file_path, _ = QFileDialog.getOpenFileName(
self,
"Выберите аудиофайл",
"",
AudioFormats.FILE_DIALOG_FILTER
)
```
---
## Логирование
### Инициализация (в main.py или run_gui.py)
```python
from common import configure_logging, get_logger
if __name__ == "__main__":
# Один раз в начале программы
configure_logging() # Создаст папку logs/ и файл логов
app = QApplication(sys.argv)
window = MedicalTranscriptionApp()
window.show()
sys.exit(app.exec())
```
### Использование в модулях
```python
# В каждом файле
from common import get_logger
logger = get_logger(__name__)
def my_function():
logger.info("Starting operation")
try:
# ...
logger.debug("Processing step 1")
except Exception as e:
logger.error(f"Error occurred: {e}", exc_info=True)
```
### Удалите старый код логирования
```python
# ДО (удалить)
import logging
logger = logging.getLogger(__name__)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
# ПОСЛЕ (достаточно)
from common import get_logger
logger = get_logger(__name__)
```
---
## Валидация
### Валидация аудиофайлов
```python
from common import Validator, AudioFileException
from pathlib import Path
def start_transcription(self):
try:
# Валидирует файл, проверяет существование, формат и размер
audio_file = Validator.validate_audio_file(self.audio_path)
# audio_file является объектом Path
except AudioFileException as e:
QMessageBox.critical(self, "Ошибка аудиофайла", e.message)
```
### Валидация пациента
```python
from common import Validator, ValidationException
def open_patient_dialog(self):
dialog = PatientDataDialog(self)
if dialog.exec() == QDialog.DialogCode.Accepted:
try:
data = dialog.get_data()
# Валидация каждого поля
patient_name = Validator.validate_patient_name(data["patient_name"])
patient_dob = Validator.validate_date(data["patient_dob"])
self.patient_data = data
except ValidationException as e:
QMessageBox.warning(
self,
f"Ошибка в поле {e.field}",
e.message
)
```
### Валидация текста
```python
from common import Validator, ValidationException
def correct_text(text):
try:
validated_text = Validator.validate_text(text, "transcription")
# Дальше работаем с проверенным текстом
except ValidationException as e:
logger.error(f"Validation error: {e.message}")
```
---
## Структуры данных
### Использование типизированных результатов
```python
from common import PipelineResult, TranscriptionResult, PatientMetadata
from datetime import datetime
from pathlib import Path
def process_pipeline():
# Создание структурированного результата
result = PipelineResult(
timestamp=datetime.now(),
audio_file=Path("audio.wav"),
patient_data=PatientMetadata(
name="Иванов Иван Иванович",
date_of_birth="01.01.1980",
study_area="МРТ головы"
),
transcription=TranscriptionResult(
timestamp=datetime.now(),
audio_file=Path("audio.wav"),
original_text="исходный текст",
corrected_text="исправленный текст",
corrections_count=5
),
status="success"
)
# IDE будет подсказывать все доступные поля!
print(result.status)
print(result.transcription.corrections_count)
print(result.is_successful()) # Вспомогательный метод
# Сериализация в JSON
result_dict = result.to_dict()
json.dump(result_dict, f)
```
### Создание метаданных пациента
```python
from common import PatientMetadata
patient_data = PatientMetadata(
name="Петров Петр Петрович",
date_of_birth="15.03.1975",
study_area="КТ грудной клетки",
study_number="12345",
study_date="16.01.2026",
doctor_name="Сидоров С.С."
)
# Проверка полноты данных
if patient_data.is_complete():
print("Все необходимые данные заполнены")
# Преобразование в словарь
patient_dict = patient_data.to_dict()
```
---
## Обработка ошибок
### Специфичные исключения
```python
from common import (
AudioFileException,
TranscriptionException,
APIException,
ValidationException,
ConfigurationException
)
def pipeline_process():
try:
# ...
pass
except AudioFileException as e:
# Обработка ошибок с аудио файлом
logger.error(f"Audio file error: {e.message}")
show_error_dialog(f"Ошибка аудиофайла: {e.file_path}")
except APIException as e:
# Обработка ошибок API
logger.error(f"API error: {e.message} (code: {e.status_code})")
show_error_dialog(f"Ошибка API: {e.status_code}")
except ValidationException as e:
# Обработка ошибок валидации
logger.warning(f"Validation error in {e.field}: {e.message}")
show_warning_dialog(f"Проверьте поле '{e.field}'")
except ConfigurationException as e:
# Обработка ошибок конфигурации
logger.error(f"Config error: {e}")
show_error_dialog("Неверная конфигурация")
```
### Информативные ошибки с контекстом
```python
# ДО
except Exception as e:
logger.error(f"Error: {e}")
# Непонятно, что произошло
# ПОСЛЕ
except APIException as e:
logger.error(
f"API request failed for {e.endpoint} "
f"with status {e.status_code}: {e.message}"
)
# Точно известно, что произошло, где и почему
```
---
## Шаблон для новых модулей
При создании нового модуля используйте этот шаблон:
```python
"""
Описание модуля.
Example:
>>> from my_module import MyClass
>>> obj = MyClass()
>>> result = obj.my_method()
"""
from pathlib import Path
from typing import Optional, Dict, Any
from common import get_logger, Validator, ValidationException
logger = get_logger(__name__)
class MyClass:
"""Описание класса."""
def __init__(self, param: str) -> None:
"""
Initialize.
Args:
param: Parameter description
Raises:
ValueError: If param is invalid
"""
self.param = param
logger.info(f"Initialized MyClass with param: {param}")
def my_method(self, data: str) -> Dict[str, Any]:
"""
Do something.
Args:
data: Input data
Returns:
Result dictionary
Raises:
ValidationException: If data is invalid
"""
try:
validated_data = Validator.validate_text(data)
logger.debug(f"Processing {len(validated_data)} characters")
result = {"status": "success", "data": validated_data}
logger.info("Processing completed successfully")
return result
except ValidationException as e:
logger.error(f"Validation failed: {e.message}")
raise
```
---
## Чек-лист для интеграции
### Phase 1: Основные импорты
- [ ] `common/exceptions.py` создан ✅
- [ ] `common/constants.py` создан ✅
- [ ] `common/logger.py` создан ✅
- [ ] `common/validators.py` создан ✅
- [ ] `common/models.py` создан ✅
- [ ] `common/__init__.py` создан ✅
### Phase 2: Обновление импортов в app/
- [ ] `app/gui_app.py` - добавить импорты common
- [ ] `app/main.py` - вызвать `configure_logging()`
- [ ] Заменить все магические числа на константы
- [ ] Заменить все `Exception` на специфичные типы
### Phase 3: Обновление импортов в pipeline/
- [ ] `pipeline/medical_pipeline.py` - использовать новые структуры
- [ ] `pipeline/pipeline_config.py` - использовать константы
### Phase 4: Обновление импортов в corrector/
- [ ] `corrector/llm_corrector.py` - улучшить типизацию ✅
- [ ] `corrector/openrouter_client.py` - использовать APISettings ✅
- [ ] `corrector/report_generator.py` - использовать ReportDefaults
### Phase 5: Обновление импортов в stt/
- [ ] `stt/whisper_transcriber.py` - использовать ModelDefaults
- [ ] `stt/audio_processor.py` - использовать AudioFormats
### Phase 6: Обновление импортов в knowledge_base/
- [ ] `knowledge_base/term_manager.py` - использовать новые структуры
---
## Полезные ссылки в коде
```python
# Все константы
from common import UIColors, UIDimensions, Messages, etc.
# Логирование
from common import get_logger, configure_logging
# Валидация
from common import Validator
# Структуры данных
from common import PatientMetadata, PipelineResult, etc.
# Исключения
from common import (
AudioFileException,
ValidationException,
APIException,
etc.
)
```
---
## Итого
1. **Константы** - используйте вместо магических чисел
2. **Логирование** - вызовите `configure_logging()` в main, затем `get_logger()`
3. **Валидация** - используйте `Validator.validate_*()`
4. **Структуры** - создавайте с типизацией вместо dict
5. **Ошибки** - ловите специфичные исключения
Это сделает код более читаемым, надёжным и поддерживаемым! 🎉