Files
medtech-hackathon/contracts/models.py
T

85 lines
2.9 KiB
Python

"""Общие модели данных — контракт между агентами (Pydantic v2).
`RawRow` и `ParsedDocument` — выход любого парсера (граница агентов B → C).
`MatchResult` — выход сопоставления (агент C). `*Out`-модели — выдача API (агент D),
её же потребляет фронт (агент E). Любая правка этих типов проходит через оркестратора.
"""
from __future__ import annotations
from datetime import date
from pydantic import BaseModel, Field
# Карта тарифов: ключ — тип цены, значение — сумма в KZT.
# Возможные ключи: resident, nonresident, cis, far, insurance, partner.
PriceTiers = dict[str, float]
class RawRow(BaseModel):
"""Одна сырая строка прайса — единый выход любого парсера."""
service_name_raw: str
service_code_source: str | None = None
prices: PriceTiers = Field(default_factory=dict)
unit: str | None = None
section: str | None = None # заголовок секции — контекст специальности
class ParsedDocument(BaseModel):
"""Результат разбора одного файла прайса."""
file_name: str
file_format: str # pdf / scan_pdf / docx / xlsx / xls
partner_name: str | None = None
city: str | None = None
effective_date: date | None = None
rows: list[RawRow] = Field(default_factory=list)
raw_content: str = ""
parse_log: list[str] = Field(default_factory=list)
class MatchResult(BaseModel):
"""Результат сопоставления строки со справочником."""
service_id: str | None = None
method: str | None = None # code / exact / embedding / fuzzy / manual
confidence: float = 0.0
# Лучший кандидат для очереди верификации, даже если ниже порога автосопоставления.
suggested_service_id: str | None = None
suggested_score: float = 0.0
# --- выдача API ---
class ServiceOut(BaseModel):
service_id: str
specialty: str
name_ru: str
tarificator_code: str | None = None
class PartnerOut(BaseModel):
partner_id: str
name: str
city: str | None = None
is_active: bool = True
class PriceOut(BaseModel):
partner_id: str
partner_name: str
price_resident_kzt: float | None = None
price_nonresident_kzt: float | None = None
prices: PriceTiers = Field(default_factory=dict)
effective_date: date | None = None
class Stats(BaseModel):
"""Сводка для дашборда и отчёта о качестве."""
documents_total: int = 0
documents_done: int = 0
items_total: int = 0
auto_matched_pct: float = 0.0
unmatched_total: int = 0