Spyspook/layout-viewer
0
1# src/ui/layout.py
2
3"""
4Модуль верстки пользовательского интерфейса Gradio.
5ИСПРАВЛЕНО: Удалена тема Soft для возврата стандартных шрифтов.
6ДОБАВЛЕНО: Компоненты для просмотра 2D SVG-плана и скачивания JSON-артефактов.
7"""
8import gradio as gr
9from omegaconf import DictConfig
10
11from .callbacks import (
12 generate_wrapper,
13 get_cache_status_text,
14 get_inventory_json
15)
16
17def create_ui(cfg: DictConfig) -> gr.Blocks:
18 """
19 Создает структуру веб-интерфейса.
20 """
21 with gr.Blocks(title="ИИ-Мерчандайзер 3D") as app:
22 gr.Markdown("# 🏪 Интеллектуальный генератор 3D-планировок")
23
24 # 1. Текстовое табло с общей статистикой
25 server_status = gr.Textbox(
26 value=get_cache_status_text,
27 label="Статус сервера и общая статистика",
28 interactive=False,
29 lines=2
30 )
31
32 # 2. Инспектор ассортимента (под аккордеоном)
33 with gr.Accordion("📦 Детальный просмотр доступных SKU", open=False):
34 inventory_inspect = gr.JSON(
35 value=get_inventory_json,
36 label="Иерархия товаров в ОЗУ"
37 )
38
39 # 3. Панель управления
40 with gr.Row():
41 prompt_input = gr.Textbox(
42 label="✨ Текстовый запрос к ИИ-мерчандайзеру",
43 placeholder="Например: Поставь молоко в холодильник, а пиво на стеллаж напротив.",
44 lines=2,
45 scale=4
46 )
47 generate_btn = gr.Button("🚀 Сгенерировать", variant="primary", scale=1)
48
49 # 4. Область вывода результатов генерации
50 with gr.Row():
51 with gr.Column(scale=1):
52 status_output = gr.Textbox(
53 label="Чек-лист выполнения",
54 value="🟢 Ожидание запуска...",
55 interactive=False,
56 lines=15
57 )
58
59 with gr.Column(scale=3):
60 # Вкладки для переключения между 3D и 2D
61 with gr.Tabs():
62 with gr.TabItem("🎮 3D Сцена"):
63 output_3d = gr.Model3D(
64 label="Результат 3D-рендера",
65 clear_color=[0.9, 0.9, 0.9, 1.0],
66 height=600
67 )
68 with gr.TabItem("🗺️ 2D План (SVG)"):
69 output_svg = gr.Image(
70 label="Векторный план расстановки",
71 type="filepath",
72 interactive=False
73 )
74
75 # 5. Панель артефактов (для скачивания)
76 with gr.Row():
77 draft_json_out = gr.File(label="📥 Скачать черновик LLM (Draft JSON)")
78 final_json_out = gr.File(label="📥 Скачать финальный расчет (Final JSON)")
79 history_json_out = gr.File(label="📥 Скачать историю LLM (JSONL)")
80 draft_svg_file_out = gr.File(label="📥 Draft SVG")
81 svg_file_out = gr.File(label="📥 Скачать 2D План (SVG)")
82
83 # Привязка событий: теперь функция должна возвращать 5 значений (3D, Чеклист, SVG-превью, Draft, Final, SVG-файл)
84 # Так как SVG-файл и SVG-превью - это один и тот же файл, мы просто передадим его путь дважды в outputs
85 generate_btn.click(
86 fn=generate_wrapper,
87 inputs=[prompt_input],
88 outputs=[
89 output_3d,
90 status_output,
91 output_svg,
92 draft_json_out,
93 final_json_out,
94 svg_file_out,
95 history_json_out,
96 draft_svg_file_out
97 ],
98 show_progress="hidden"
99 )
100
101 return app