Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -10,22 +10,18 @@ from huggingface_hub import hf_hub_download
|
|
| 10 |
import tempfile
|
| 11 |
|
| 12 |
# --- 1. CONFIGURATION & SECRETS ---
|
| 13 |
-
# Reading secrets from Hugging Face Environment Variables
|
| 14 |
GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")
|
| 15 |
HF_TOKEN = os.environ.get("HF_TOKEN")
|
| 16 |
|
| 17 |
-
# Model Configuration
|
| 18 |
MODEL_REPO = "youkii-xr/hieroglyphic-detection"
|
| 19 |
MODEL_FILENAME = "best.pt"
|
| 20 |
JSON_DB_PATH = "gardiner_codes.json"
|
| 21 |
|
| 22 |
-
# Configure YOLO to use a writable temp directory in HF Spaces
|
| 23 |
os.environ["YOLO_CONFIG_DIR"] = "/tmp/Ultralytics"
|
| 24 |
|
| 25 |
-
# --- 2. DATA LOADING
|
| 26 |
|
| 27 |
def load_gardiner_database():
|
| 28 |
-
"""Loads the Gardiner Code database from the external JSON file."""
|
| 29 |
if os.path.exists(JSON_DB_PATH):
|
| 30 |
try:
|
| 31 |
print(f"System: Loading Gardiner codes from {JSON_DB_PATH}...")
|
|
@@ -35,13 +31,13 @@ def load_gardiner_database():
|
|
| 35 |
print(f"β οΈ Error reading JSON: {e}")
|
| 36 |
return {}
|
| 37 |
else:
|
| 38 |
-
print(f"β οΈ Warning: {JSON_DB_PATH} not found.
|
| 39 |
return {}
|
| 40 |
|
| 41 |
gardiner_data = load_gardiner_database()
|
| 42 |
gardiner_map = {k: v.get("Description", k) for k, v in gardiner_data.items()}
|
| 43 |
|
| 44 |
-
# --- 3. HTML
|
| 45 |
|
| 46 |
CATEGORIES = {
|
| 47 |
'A': "Men & Monarchs", 'B': "Women & Human Activities", 'C': "Deities",
|
|
@@ -57,7 +53,7 @@ CATEGORIES = {
|
|
| 57 |
|
| 58 |
def generate_gardiner_html():
|
| 59 |
if not gardiner_data:
|
| 60 |
-
return "<tr><td colspan='4'>No data loaded. Please upload gardiner_codes.json
|
| 61 |
|
| 62 |
html_rows = ""
|
| 63 |
grouped = {}
|
|
@@ -87,7 +83,7 @@ def generate_gardiner_html():
|
|
| 87 |
|
| 88 |
GARDINER_TABLE_CONTENT = generate_gardiner_html()
|
| 89 |
|
| 90 |
-
# --- 4. LOAD MODEL
|
| 91 |
|
| 92 |
print("System: Initializing Rosetta Decoder Core...")
|
| 93 |
try:
|
|
@@ -102,7 +98,7 @@ except Exception as e:
|
|
| 102 |
print(f"Error loading model: {e}")
|
| 103 |
model = None
|
| 104 |
|
| 105 |
-
# --- 5. CORE
|
| 106 |
|
| 107 |
def clean_ai_text(text):
|
| 108 |
text = re.sub(r'^\d+[\.\)]\s*', '', text)
|
|
@@ -196,7 +192,6 @@ def process_pipeline(image, conf_threshold):
|
|
| 196 |
unique_codes.add(code)
|
| 197 |
xyxy = box.xyxy[0].tolist()
|
| 198 |
detections.append({"code": code, "confidence": round(conf, 2), "box": xyxy})
|
| 199 |
-
|
| 200 |
crop_img = image.crop((xyxy[0], xyxy[1], xyxy[2], xyxy[3]))
|
| 201 |
crops.append((crop_img, f"{code}\n({int(conf*100)}%)"))
|
| 202 |
|
|
@@ -213,7 +208,7 @@ def process_pipeline(image, conf_threshold):
|
|
| 213 |
except Exception as e:
|
| 214 |
return None, f"System Failure: {str(e)}", "", None, str(e), None, []
|
| 215 |
|
| 216 |
-
# --- 6. UI STYLING ---
|
| 217 |
|
| 218 |
cursor_url = "url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgdmlld0JveD0iMCAwIDMyIDMyIj4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiNkNGFmMzciIHN0cm9rZS13aWR0aD0iMS41Ij4KICAgIDxwYXRoIGQ9Ik0xNiw4IEM2LDIwIDI2LDIwIDE2LDggWiIgZmlsbD0icmdiYSgyMTIsIDE3NSwgNTUsIDAuMSkiLz4KICAgIDxjaXJjbGUgY3g9IjE2IiBjeT0iMTUiIHI9IjMiIGZpbGw9IiNkNGFmMzciLz4KICAgIDxwYXRoIGQ9Ik0xNiwyMiBMMTYsMjggTDEwLDI4Ii8+CiAgPC9nPgo8L3N2Zz4=')"
|
| 219 |
|
|
@@ -283,6 +278,19 @@ code {{ font-family: 'Space Mono', monospace; background: rgba(0,0,0,0.3); paddi
|
|
| 283 |
.scrollable-box textarea {{ overflow-y: auto !important; max-height: 400px !important; background-color: rgba(0,0,0,0.3) !important; }}
|
| 284 |
button.primary-btn {{ background: var(--btn-grad) !important; border: 1px solid var(--border-color) !important; color: #000 !important; font-weight: 700 !important; font-size: 16px !important; }}
|
| 285 |
.gradio-image, .gradio-json {{ background: transparent !important; border: none !important; }}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 286 |
"""
|
| 287 |
|
| 288 |
header_html = """
|
|
@@ -318,8 +326,31 @@ guide_html = """
|
|
| 318 |
</div>
|
| 319 |
"""
|
| 320 |
|
| 321 |
-
claude_json_content = """{
|
| 322 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 323 |
trail_script = """<script>document.addEventListener('DOMContentLoaded', () => { document.addEventListener('mousemove', (e) => { if (Math.random() > 0.7) return; const dust = document.createElement('div'); dust.classList.add('gold-dust'); dust.style.left = e.clientX + 'px'; dust.style.top = e.clientY + 'px'; document.body.appendChild(dust); setTimeout(() => dust.remove(), 600); }); });</script>"""
|
| 324 |
|
| 325 |
# --- 7. MAIN APP ASSEMBLY ---
|
|
@@ -330,7 +361,7 @@ with gr.Blocks(title="Rosetta Decoder Ultimate") as demo:
|
|
| 330 |
|
| 331 |
with gr.Row(elem_classes="header-row"):
|
| 332 |
with gr.Column(scale=4): gr.HTML(header_html)
|
| 333 |
-
with gr.Column(scale=1): btn_toggle = gr.Button("π Day / Night")
|
| 334 |
|
| 335 |
with gr.Tabs():
|
| 336 |
# TAB 1: DECODER
|
|
@@ -366,12 +397,13 @@ with gr.Blocks(title="Rosetta Decoder Ultimate") as demo:
|
|
| 366 |
# TAB 2: ABOUT
|
| 367 |
with gr.TabItem("π VISION & ABOUT"): gr.HTML(mission_html)
|
| 368 |
|
| 369 |
-
# TAB 3: SETUP
|
| 370 |
with gr.TabItem("π€ SYSTEM SETUP"):
|
| 371 |
gr.HTML(guide_html)
|
| 372 |
-
|
|
|
|
| 373 |
|
| 374 |
-
# TAB 4: GARDINER CODES
|
| 375 |
with gr.TabItem("π GARDINER CODES"):
|
| 376 |
gr.HTML(f"""<div class="card"><div class="card-title">π SUPPORTED GARDINER CODES</div><div style="overflow-x: auto; max-height: 600px; overflow-y: auto;"><table class="gardiner-table"><thead><tr><th>Code</th><th>Description</th><th>Transliteration</th><th>Type</th></tr></thead><tbody>{GARDINER_TABLE_CONTENT}</tbody></table></div></div>""")
|
| 377 |
|
|
|
|
| 10 |
import tempfile
|
| 11 |
|
| 12 |
# --- 1. CONFIGURATION & SECRETS ---
|
|
|
|
| 13 |
GOOGLE_API_KEY = os.environ.get("GOOGLE_API_KEY")
|
| 14 |
HF_TOKEN = os.environ.get("HF_TOKEN")
|
| 15 |
|
|
|
|
| 16 |
MODEL_REPO = "youkii-xr/hieroglyphic-detection"
|
| 17 |
MODEL_FILENAME = "best.pt"
|
| 18 |
JSON_DB_PATH = "gardiner_codes.json"
|
| 19 |
|
|
|
|
| 20 |
os.environ["YOLO_CONFIG_DIR"] = "/tmp/Ultralytics"
|
| 21 |
|
| 22 |
+
# --- 2. DATA LOADING ---
|
| 23 |
|
| 24 |
def load_gardiner_database():
|
|
|
|
| 25 |
if os.path.exists(JSON_DB_PATH):
|
| 26 |
try:
|
| 27 |
print(f"System: Loading Gardiner codes from {JSON_DB_PATH}...")
|
|
|
|
| 31 |
print(f"β οΈ Error reading JSON: {e}")
|
| 32 |
return {}
|
| 33 |
else:
|
| 34 |
+
print(f"β οΈ Warning: {JSON_DB_PATH} not found.")
|
| 35 |
return {}
|
| 36 |
|
| 37 |
gardiner_data = load_gardiner_database()
|
| 38 |
gardiner_map = {k: v.get("Description", k) for k, v in gardiner_data.items()}
|
| 39 |
|
| 40 |
+
# --- 3. HTML GENERATORS ---
|
| 41 |
|
| 42 |
CATEGORIES = {
|
| 43 |
'A': "Men & Monarchs", 'B': "Women & Human Activities", 'C': "Deities",
|
|
|
|
| 53 |
|
| 54 |
def generate_gardiner_html():
|
| 55 |
if not gardiner_data:
|
| 56 |
+
return "<tr><td colspan='4'>No data loaded. Please upload gardiner_codes.json.</td></tr>"
|
| 57 |
|
| 58 |
html_rows = ""
|
| 59 |
grouped = {}
|
|
|
|
| 83 |
|
| 84 |
GARDINER_TABLE_CONTENT = generate_gardiner_html()
|
| 85 |
|
| 86 |
+
# --- 4. LOAD MODEL ---
|
| 87 |
|
| 88 |
print("System: Initializing Rosetta Decoder Core...")
|
| 89 |
try:
|
|
|
|
| 98 |
print(f"Error loading model: {e}")
|
| 99 |
model = None
|
| 100 |
|
| 101 |
+
# --- 5. CORE LOGIC ---
|
| 102 |
|
| 103 |
def clean_ai_text(text):
|
| 104 |
text = re.sub(r'^\d+[\.\)]\s*', '', text)
|
|
|
|
| 192 |
unique_codes.add(code)
|
| 193 |
xyxy = box.xyxy[0].tolist()
|
| 194 |
detections.append({"code": code, "confidence": round(conf, 2), "box": xyxy})
|
|
|
|
| 195 |
crop_img = image.crop((xyxy[0], xyxy[1], xyxy[2], xyxy[3]))
|
| 196 |
crops.append((crop_img, f"{code}\n({int(conf*100)}%)"))
|
| 197 |
|
|
|
|
| 208 |
except Exception as e:
|
| 209 |
return None, f"System Failure: {str(e)}", "", None, str(e), None, []
|
| 210 |
|
| 211 |
+
# --- 6. UI STYLING & ASSETS ---
|
| 212 |
|
| 213 |
cursor_url = "url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgdmlld0JveD0iMCAwIDMyIDMyIj4KICA8ZyBmaWxsPSJub25lIiBzdHJva2U9IiNkNGFmMzciIHN0cm9rZS13aWR0aD0iMS41Ij4KICAgIDxwYXRoIGQ9Ik0xNiw4IEM2LDIwIDI2LDIwIDE2LDggWiIgZmlsbD0icmdiYSgyMTIsIDE3NSwgNTUsIDAuMSkiLz4KICAgIDxjaXJjbGUgY3g9IjE2IiBjeT0iMTUiIHI9IjMiIGZpbGw9IiNkNGFmMzciLz4KICAgIDxwYXRoIGQ9Ik0xNiwyMiBMMTYsMjggTDEwLDI4Ii8+CiAgPC9nPgo8L3N2Zz4=')"
|
| 214 |
|
|
|
|
| 278 |
.scrollable-box textarea {{ overflow-y: auto !important; max-height: 400px !important; background-color: rgba(0,0,0,0.3) !important; }}
|
| 279 |
button.primary-btn {{ background: var(--btn-grad) !important; border: 1px solid var(--border-color) !important; color: #000 !important; font-weight: 700 !important; font-size: 16px !important; }}
|
| 280 |
.gradio-image, .gradio-json {{ background: transparent !important; border: none !important; }}
|
| 281 |
+
|
| 282 |
+
/* UPDATED TOGGLE BUTTON CSS */
|
| 283 |
+
button.toggle-btn {
|
| 284 |
+
background: #0a0a2e !important; /* Matches dark blue background */
|
| 285 |
+
border: 1px solid var(--border-color) !important;
|
| 286 |
+
color: var(--text-accent) !important;
|
| 287 |
+
padding: 5px 15px !important;
|
| 288 |
+
font-family: 'Space Mono', monospace;
|
| 289 |
+
box-shadow: none !important;
|
| 290 |
+
}
|
| 291 |
+
button.toggle-btn:hover {
|
| 292 |
+
background: var(--info-bg) !important;
|
| 293 |
+
}
|
| 294 |
"""
|
| 295 |
|
| 296 |
header_html = """
|
|
|
|
| 326 |
</div>
|
| 327 |
"""
|
| 328 |
|
| 329 |
+
claude_json_content = """{
|
| 330 |
+
"mcpServers": {
|
| 331 |
+
"gradio": {
|
| 332 |
+
"command": "npx",
|
| 333 |
+
"args": [
|
| 334 |
+
"mcp-remote",
|
| 335 |
+
"https://youkii-xr-hieroglyph-mcp-server.hf.space/gradio_api/mcp/",
|
| 336 |
+
"--transport",
|
| 337 |
+
"streamable-http"
|
| 338 |
+
]
|
| 339 |
+
},
|
| 340 |
+
"upload_helper": {
|
| 341 |
+
"command": "C:\\\\Python313\\\\python.exe",
|
| 342 |
+
"args": [
|
| 343 |
+
"-m",
|
| 344 |
+
"gradio",
|
| 345 |
+
"upload-mcp",
|
| 346 |
+
"https://youkii-xr-hieroglyph-mcp-server.hf.space/",
|
| 347 |
+
"C:\\\\Claude_Work"
|
| 348 |
+
]
|
| 349 |
+
}
|
| 350 |
+
}
|
| 351 |
+
}"""
|
| 352 |
+
|
| 353 |
+
# JS for Gold Dust Trail
|
| 354 |
trail_script = """<script>document.addEventListener('DOMContentLoaded', () => { document.addEventListener('mousemove', (e) => { if (Math.random() > 0.7) return; const dust = document.createElement('div'); dust.classList.add('gold-dust'); dust.style.left = e.clientX + 'px'; dust.style.top = e.clientY + 'px'; document.body.appendChild(dust); setTimeout(() => dust.remove(), 600); }); });</script>"""
|
| 355 |
|
| 356 |
# --- 7. MAIN APP ASSEMBLY ---
|
|
|
|
| 361 |
|
| 362 |
with gr.Row(elem_classes="header-row"):
|
| 363 |
with gr.Column(scale=4): gr.HTML(header_html)
|
| 364 |
+
with gr.Column(scale=1): btn_toggle = gr.Button("π Day / Night", elem_classes="toggle-btn")
|
| 365 |
|
| 366 |
with gr.Tabs():
|
| 367 |
# TAB 1: DECODER
|
|
|
|
| 397 |
# TAB 2: ABOUT
|
| 398 |
with gr.TabItem("π VISION & ABOUT"): gr.HTML(mission_html)
|
| 399 |
|
| 400 |
+
# TAB 3: SETUP (Reordered)
|
| 401 |
with gr.TabItem("π€ SYSTEM SETUP"):
|
| 402 |
gr.HTML(guide_html)
|
| 403 |
+
# Updated to show 25 lines so code box is expanded
|
| 404 |
+
gr.Code(value=claude_json_content, language="json", label="claude_desktop_config.json", interactive=False, lines=25, container=True)
|
| 405 |
|
| 406 |
+
# TAB 4: GARDINER CODES (Reordered)
|
| 407 |
with gr.TabItem("π GARDINER CODES"):
|
| 408 |
gr.HTML(f"""<div class="card"><div class="card-title">π SUPPORTED GARDINER CODES</div><div style="overflow-x: auto; max-height: 600px; overflow-y: auto;"><table class="gardiner-table"><thead><tr><th>Code</th><th>Description</th><th>Transliteration</th><th>Type</th></tr></thead><tbody>{GARDINER_TABLE_CONTENT}</tbody></table></div></div>""")
|
| 409 |
|