"""Factory helpers for leaudit's native service-layer orchestration. This module is the bridge-side assembly point for native leaudit services: - ``AuditServices`` - ``DocNormalizationService`` - ``ExtractionService`` - ``EvaluationService`` - ``RescueService`` - ``AuditService`` The platform should not construct these objects in controllers/services directly. Keep all leaudit-native wiring inside ``leaudit_bridge/``. """ from __future__ import annotations from dataclasses import dataclass from pathlib import Path from leaudit.services.audit_service import AuditService from leaudit.services.audit_services import AuditServices from leaudit.services.doc_normalization_service import DocNormalizationService from leaudit.services.evaluation_service import EvaluationService from leaudit.services.extraction_service import ExtractionService from leaudit.services.rescue_service import RescueService from fastapi_admin.config import LEAUDIT_OCR_VLM_CONCURRENCY from fastapi_modules.fastapi_leaudit.leaudit_bridge.client_factory import ( create_llm_client, create_ocr_client, create_vlm_client, ) from fastapi_modules.fastapi_leaudit.leaudit_bridge.ocr_bridge import BridgeOCRClient @dataclass(frozen=True) class NativeServiceBundle: """Fully assembled native leaudit service bundle.""" audit_service: AuditService audit_services: AuditServices normalization_service: DocNormalizationService extraction_service: ExtractionService evaluation_service: EvaluationService rescue_service: RescueService | None class AuditServiceFactory: """Build native leaudit services for one platform-side run.""" def create_bundle(self, rules_path: str | None = None) -> NativeServiceBundle: """Create a fully wired native leaudit service bundle. ``rules_path`` is only used to force the normalization adapter's classification path when the caller wants a fixed rules file. """ normalization_service, audit_services = self._create_normalization_services( rules_path=rules_path ) extraction_service = ExtractionService( session=None, llm_client=audit_services.llm_client, ) evaluation_service = EvaluationService(session=None) rescue_service = RescueService( session=None, llm_client=audit_services.llm_client, vlm_client=audit_services.vlm_client, extraction_service=extraction_service, ) audit_service = AuditService( document_service=None, normalization_service=normalization_service, extraction_service=extraction_service, evaluation_service=evaluation_service, rescue_service=rescue_service, services=AuditServices( llm_client=audit_services.llm_client, vlm_client=audit_services.vlm_client, ocr_client=audit_services.ocr_client, normalization=normalization_service, extraction=extraction_service, evaluation=evaluation_service, ), ) return NativeServiceBundle( audit_service=audit_service, audit_services=audit_service.services, normalization_service=normalization_service, extraction_service=extraction_service, evaluation_service=evaluation_service, rescue_service=rescue_service, ) def _create_normalization_services( self, rules_path: str | None = None ) -> tuple[DocNormalizationService, AuditServices]: """Create normalization service plus low-level shared clients.""" from leaudit.doc_normalization.adapter import DocNormalizationAdapter from leaudit.doc_normalization.doc_classifier import RulesFileRegistry raw_ocr = create_ocr_client() llm_client = create_llm_client() vlm_client = create_vlm_client() registry = None if rules_path is None: rules_dir = Path(__file__).resolve().parents[3] / "rules" if rules_dir.is_dir(): registry = RulesFileRegistry.from_directory(rules_dir) adapter = DocNormalizationAdapter( ocr_client=raw_ocr, registry=registry, llm_client=llm_client, vlm_client=vlm_client, force_rules_path=rules_path, ) ocr_client = BridgeOCRClient( adapter, vlm_client=vlm_client, vlm_concurrency=LEAUDIT_OCR_VLM_CONCURRENCY, ) normalization_service = DocNormalizationService(ocr_client) audit_services = AuditServices( llm_client=llm_client, vlm_client=vlm_client, ocr_client=raw_ocr, normalization=normalization_service, ) return normalization_service, audit_services __all__ = ["AuditServiceFactory", "NativeServiceBundle"]