Files
leaudit-platform-backend/fastapi_modules/fastapi_leaudit/leaudit_bridge/auditServiceFactory.py
T
wren 246c0e5ded feat: complete M1-M3 infrastructure — OSS client, native execution chain, rule lifecycle API, system docs
- M1: unified OSS client (upload/download/presign) + path utils + config
- M2: rule service with validate/create/publish/rollback + binding CRUD endpoints
- M3: native AuditCtx runner, file/rule resolvers, storage adapter with full persistence
- docs: SYSTEM_OVERVIEW.md as comprehensive architecture reference
- fix: double finalize — terminal state now written once by finalize_run
2026-04-28 11:49:55 +08:00

133 lines
4.7 KiB
Python

"""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_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)
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"]