File size: 3,709 Bytes
cde2c39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import gradio as gr
import sys
import os
import importlib.util
from pathlib import Path
from huggingface_hub import hf_hub_download

print("===== Application Startup =====")

MODEL_REPO = "fcu52005505/X281-weights"
MODEL_FILE = "core_logic.so"
CACHE_DIR = Path("./model_cache")
CACHE_DIR.mkdir(exist_ok=True)

core_logic = None

# 檢查 HF Token
HF_TOKEN = os.getenv("HF_TOKEN")
if HF_TOKEN is None:
    raise RuntimeError(
        "❌ 缺少 HF_TOKEN!請在 Space 的 Settings → Variables and secrets 設定。"
    )

print(f"HF_TOKEN loaded: {HF_TOKEN is not None}")

# 下載 .so(使用快取)
so_path = CACHE_DIR / MODEL_FILE

if not so_path.exists():
    print(f"📥 正在從 {MODEL_REPO} 下載 {MODEL_FILE} ...")
    downloaded_path = hf_hub_download(
        repo_id=MODEL_REPO,
        filename=MODEL_FILE,
        repo_type="model",
        token=HF_TOKEN,
        local_dir=str(CACHE_DIR),
        local_dir_use_symlinks=False
    )
    print(f"✅ .so 下載完成: {downloaded_path}")
else:
    print(f"✅ 使用快取 .so: {so_path}")

# 動態載入 core_logic.so
try:
    spec = importlib.util.spec_from_file_location(
        "core_logic",
        str(so_path)
    )
    if spec and spec.loader:
        core_logic = importlib.util.module_from_spec(spec)
        sys.modules["core_logic"] = core_logic
        spec.loader.exec_module(core_logic)
        print("✅ core_logic.so 載入成功")
    else:
        raise RuntimeError("❌ 無法建立模組規格 (Spec creation failed)")
except Exception as e:
    print(f"❌ core_logic.so 載入發生錯誤: {e}")
    import traceback
    traceback.print_exc()
    core_logic = None

# ==========================================
def bridge_function(file_obj, zoom_level, preserve_details, progress=gr.Progress()):
    if core_logic is None:
        yield "❌ 嚴重錯誤:核心模組載入失敗 (No module named 'core_logic'),請檢查 Logs。", None
        return

    if file_obj is None:
        yield "❌ 請先上傳檔案", None
        return

    def update_progress(p, msg):
        progress(p, desc=msg)

    yield "🚀 檔案接收成功,處理中...", None

    try:
        result_msg, output_path = core_logic.run_conversion(
            file_obj.name,
            zoom_level,
            preserve_details,
            progress_callback=update_progress
        )

        if "Success" in result_msg:
            yield f"✅ 轉換成功! ({result_msg})", output_path
        else:
            yield f"❌ {result_msg}", None

    except Exception as e:
        yield f"❌ 執行錯誤: {e}", None


# ==========================================

with gr.Blocks(title="GeoJSON 轉 PMTiles") as demo:
    gr.Markdown("## 🗺️ GeoJSON to PMTiles")

    with gr.Row():
        with gr.Column():
            input_file = gr.File(label="上傳 GeoJSON (自動開始)")
            with gr.Group():
                zoom_slider = gr.Slider(0, 20, value=14, step=1, label="Max Zoom")
                preserve_checkbox = gr.Checkbox(label="強制保留細節", value=True)
            btn = gr.Button("開始轉換")

        with gr.Column():
            status_box = gr.Textbox(label="狀態", value="等待中...", interactive=False)
            output_file = gr.File(label="下載")

    input_file.upload(
        bridge_function,
        [input_file, zoom_slider, preserve_checkbox],
        [status_box, output_file]
    )
    btn.click(
        bridge_function,
        [input_file, zoom_slider, preserve_checkbox],
        [status_box, output_file]
    )


# ==========================================
if __name__ == "__main__":
    demo.queue(default_concurrency_limit=10).launch(show_api=False)