Spaces:
Sleeping
Sleeping
| # src/layout_generator/pipeline.py | |
| """ | |
| Оркестратор генерации 3D-планировок. | |
| Собирает этапы в единый объектно-ориентированный пайплайн и прогоняет контекст. | |
| Включает поддержку потоковой передачи статусов (streaming) для UI. | |
| """ | |
| import logging | |
| import time | |
| from pathlib import Path | |
| from typing import List, Generator, Tuple, Optional, Dict, Any | |
| from hydra import compose, initialize_config_dir | |
| from hydra.core.config_store import ConfigStore | |
| from omegaconf import DictConfig, OmegaConf | |
| from dsynth.scene_gen.hydra_configs import DsConfig, ShelfConfig | |
| from utils.logger import CollisionTracker | |
| from .base import BaseStep, LayoutContext | |
| from .assets import LoadAssetsStep | |
| from .planner import CalculatePlanogramStep | |
| from .topology import GenerateTopologyStep | |
| from .assembler import AssembleSceneStep | |
| from .exporter import ExportAndCompressStep | |
| logger: logging.Logger = logging.getLogger(__name__) | |
| def create_layout_pipeline() -> List[BaseStep]: | |
| """Фабрика для сборки стандартного пайплайна генерации.""" | |
| return [ | |
| LoadAssetsStep(), | |
| CalculatePlanogramStep(), | |
| GenerateTopologyStep(), | |
| AssembleSceneStep(), | |
| ExportAndCompressStep() | |
| ] | |
| def generate_layout_stream( | |
| project_dir: Path, | |
| tracker: CollisionTracker, | |
| size_n: int = 10, | |
| size_m: int = 10, | |
| layout_graph: Optional[Dict[str, Any]] = None | |
| ) -> Generator[Tuple[Optional[str], Dict[str, Any]], None, None]: | |
| """ | |
| Потоковая версия оркестратора. | |
| Возвращает кортежи: (Путь_к_модели_или_None, Словарь_статуса_для_UI). | |
| Работает исключительно на базе ИИ-графа (layout_graph). | |
| """ | |
| # Шаг 1: Инициализация (Шаг 0 зарезервирован для LLM в интерфейсе) | |
| yield None, {"step_idx": 1, "status": "running"} | |
| start_init = time.time() | |
| conf_dir: str = str(project_dir / 'configs') | |
| assets_dir: str = str(project_dir / 'assets') | |
| cs: ConfigStore = ConfigStore.instance() | |
| try: | |
| cs.store(group="shelves", name="base_shelf_config", node=ShelfConfig) | |
| cs.store(group="ds", name="main_darkstore_config_base", node=DsConfig) | |
| except Exception: | |
| pass | |
| logger.info(f"🏗 ЗАДАЧА ПЛАНОГРАММИРОВАНИЯ: Помещение {size_n}x{size_m}") | |
| with initialize_config_dir(version_base=None, config_dir=conf_dir): | |
| cfg: DictConfig = compose(config_name="main_config", overrides=[f"ds.size_n={size_n}", f"ds.size_m={size_m}"]) | |
| OmegaConf.set_struct(cfg, False) | |
| cfg.assets.assets_dir_path = assets_dir | |
| OmegaConf.resolve(cfg) | |
| context = LayoutContext( | |
| project_dir=str(project_dir), | |
| size_n=size_n, size_m=size_m, | |
| layout_graph=layout_graph, | |
| cfg=cfg, tracker=tracker | |
| ) | |
| elapsed_init = time.time() - start_init | |
| yield None, {"step_idx": 1, "status": "done", "time": elapsed_init} | |
| pipeline = create_layout_pipeline() | |
| # Шаги 2-6: Прогоняем пайплайн с замером времени | |
| for idx, step in enumerate(pipeline): | |
| step_idx = idx + 2 | |
| yield None, {"step_idx": step_idx, "status": "running"} | |
| start_t = time.time() | |
| context = step.process(context) | |
| elapsed_t = time.time() - start_t | |
| # Обработка критических ошибок на лету | |
| if not context.product_assets_lib: | |
| yield None, {"step_idx": step_idx, "status": "error", "message": "В кэше отсутствуют модели"} | |
| return | |
| if isinstance(step, GenerateTopologyStep) and not context.is_gen: | |
| yield None, {"step_idx": step_idx, "status": "error", "message": "Помещение слишком мало"} | |
| return | |
| yield None, {"step_idx": step_idx, "status": "done", "time": elapsed_t} | |
| yield context.output_filename, {"status": "finished"} | |
| def generate_inventory_driven_layout( | |
| project_dir: Path, | |
| tracker: CollisionTracker, | |
| size_n: int = 10, | |
| size_m: int = 10 | |
| ) -> str: | |
| """Обычная функция для обратной совместимости.""" | |
| final_path = "" | |
| for path, _ in generate_layout_stream( | |
| project_dir, tracker, size_n, size_m | |
| ): | |
| if path: | |
| final_path = path | |
| return final_path |