youkii-xr commited on
Commit
16edc55
·
verified ·
1 Parent(s): a2782c2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +70 -66
app.py CHANGED
@@ -9,6 +9,7 @@ import re
9
  from huggingface_hub import hf_hub_download
10
  import tempfile
11
  import numpy as np
 
12
  from typing import List, Tuple, Dict, Any
13
 
14
  # --- 1. CONFIGURATION & SECRETS ---
@@ -20,6 +21,8 @@ MODEL_FILENAME = "best.pt"
20
  JSON_DB_PATH = "gardiner_codes.json"
21
 
22
  os.environ["YOLO_CONFIG_DIR"] = "/tmp/Ultralytics"
 
 
23
 
24
  # --- 2. DATA LOADING ---
25
 
@@ -164,7 +167,7 @@ except Exception as e:
164
  model = None
165
 
166
  # --- 5. MAIN UI PIPELINE (Orchestrator) ---
167
- # Used for the Web Interface (Returns complex Objects)
168
 
169
  def process_pipeline(image, conf_threshold):
170
  if image is None: return None, "", "", None, "", None, []
@@ -187,51 +190,66 @@ def process_pipeline(image, conf_threshold):
187
  return None, f"System Failure: {str(e)}", "", None, str(e), None, []
188
 
189
  # --- 6. MCP API FUNCTIONS (Optimized for Claude) ---
190
- # Changes: Short Names, File Path Returns (No Base64)
 
 
191
 
192
- def api_detect(image: Image.Image, conf: float = 0.25) -> Tuple[str, Dict[str, Any]]:
193
  """
194
- detect: Scans image for hieroglyphs.
195
- Returns: 1. File path to the annotated image. 2. JSON summary of findings.
 
 
196
  """
197
  ann_img, dets, _ = core_detect(image, conf)
198
 
199
- # SAVE to temp file and return PATH string
200
- with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as t:
 
201
  ann_img.save(t.name)
202
  path = t.name
203
 
204
  return path, {"count": len(dets), "detections": dets}
205
 
206
- def api_translate(keywords_text: str) -> Tuple[str, str]:
207
  """
208
- translate: Takes comma-separated codes (e.g. 'G43, X1'). Returns Mystical & Academic text.
 
209
  """
210
  if isinstance(keywords_text, str):
211
  keywords = [k.strip() for k in keywords_text.split(',')]
212
  else:
213
  keywords = ["Unknown"]
214
  mystical, academic = core_translate(keywords)
 
215
  clean_mystical = re.sub('<[^<]+?>', '', mystical)
216
  return clean_mystical, academic
217
 
218
- def api_analytics(json_data: Dict[str, Any]) -> str:
219
  """
220
- analytics: Takes JSON detection data.
221
- Returns: File path to the generated statistical chart image.
 
222
  """
223
  dets = json_data.get("detections", [])
224
- fig = core_analytics(dets, 1000, 1000)
 
225
 
226
- # SAVE to temp file and return PATH string
227
- with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as t:
 
 
 
228
  fig.savefig(t.name, format='png', facecolor='#0f0f23')
229
  path = t.name
230
  plt.close(fig)
231
  return path
232
 
233
- def api_list_codes() -> Dict[str, Any]:
234
- """list_codes: Returns the full supported Gardiner code database."""
 
 
 
235
  return gardiner_data
236
 
237
  # --- 7. HTML GENERATORS ---
@@ -398,7 +416,30 @@ guide_html = """
398
  </div>
399
  """
400
 
401
- claude_json_content = """{ "mcpServers": { "gradio": { "command": "npx", "args": [ "mcp-remote", "https://youkii-xr-hieroglyph-mcp-server.hf.space/gradio_api/mcp/", "--transport", "streamable-http" ] }, "upload_helper": { "command": "C:\\\\Python313\\\\python.exe", "args": [ "-m", "gradio", "upload-mcp", "https://youkii-xr-hieroglyph-mcp-server.hf.space/", "C:\\\\Claude_Work" ] } } }"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
 
403
  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>"""
404
 
@@ -408,52 +449,7 @@ with gr.Blocks(title="Rosetta Decoder Ultimate") as demo:
408
  gr.HTML(f"<style>{custom_css}</style>")
409
  gr.HTML(trail_script)
410
 
411
- # --- Hidden API Buttons for MCP (Granular Access) ---
412
- # These buttons define the TOOLS for Claude.
413
- # Note: We output 'gr.Textbox' for images now, so it returns the FILE PATH string.
414
-
415
- with gr.Column(visible=False):
416
- # 1. Detect (Returns Path & JSON)
417
- btn_mcp_detect = gr.Button("Detect")
418
- api_detect_out_path = gr.Textbox()
419
- api_detect_out_json = gr.JSON()
420
- btn_mcp_detect.click(
421
- fn=api_detect,
422
- inputs=[gr.Image(label="Input Image"), gr.Number(value=0.25, label="Conf")],
423
- outputs=[api_detect_out_path, api_detect_out_json],
424
- api_name="detect" # Short name
425
- )
426
-
427
- # 2. Translate
428
- btn_mcp_trans = gr.Button("Translate")
429
- api_trans_out_mystical = gr.Textbox()
430
- api_trans_out_academic = gr.Textbox()
431
- btn_mcp_trans.click(
432
- fn=api_translate,
433
- inputs=[gr.Textbox(label="Keywords")],
434
- outputs=[api_trans_out_mystical, api_trans_out_academic],
435
- api_name="translate" # Short name
436
- )
437
-
438
- # 3. Analytics (Returns Path)
439
- btn_mcp_analytics = gr.Button("Analytics")
440
- api_analytics_out_path = gr.Textbox()
441
- btn_mcp_analytics.click(
442
- fn=api_analytics,
443
- inputs=[gr.JSON(label="Data")],
444
- outputs=[api_analytics_out_path],
445
- api_name="analytics" # Short name
446
- )
447
-
448
- # 4. Get List
449
- btn_mcp_list = gr.Button("List")
450
- api_list_out = gr.JSON()
451
- btn_mcp_list.click(
452
- fn=api_list_codes,
453
- inputs=[],
454
- outputs=[api_list_out],
455
- api_name="list_codes"
456
- )
457
 
458
  # --- Visible UI ---
459
  with gr.Row(elem_classes="header-row"):
@@ -497,7 +493,7 @@ with gr.Blocks(title="Rosetta Decoder Ultimate") as demo:
497
  # TAB 3: SETUP
498
  with gr.TabItem("🤖 SYSTEM SETUP"):
499
  gr.HTML(guide_html)
500
- # Expanded Code Box
501
  gr.Code(value=claude_json_content, language="json", label="claude_desktop_config.json", interactive=False, lines=30)
502
 
503
  # TAB 4: GARDINER CODES
@@ -513,4 +509,12 @@ with gr.Blocks(title="Rosetta Decoder Ultimate") as demo:
513
  btn_cam.click(fn=process_pipeline, inputs=[img_cam, slider_conf_cam], outputs=outputs)
514
 
515
  if __name__ == "__main__":
516
- demo.launch(mcp_server=True, ssr_mode=False, allowed_paths=["/tmp", "."])
 
 
 
 
 
 
 
 
 
9
  from huggingface_hub import hf_hub_download
10
  import tempfile
11
  import numpy as np
12
+ # IMPORTANT: Importing necessary types for MCP definitions
13
  from typing import List, Tuple, Dict, Any
14
 
15
  # --- 1. CONFIGURATION & SECRETS ---
 
21
  JSON_DB_PATH = "gardiner_codes.json"
22
 
23
  os.environ["YOLO_CONFIG_DIR"] = "/tmp/Ultralytics"
24
+ # Ensure temp directory exists for plot saving
25
+ os.makedirs("/tmp/gradio_results", exist_ok=True)
26
 
27
  # --- 2. DATA LOADING ---
28
 
 
167
  model = None
168
 
169
  # --- 5. MAIN UI PIPELINE (Orchestrator) ---
170
+ # Used *only* by the Web Interface (Returns complex Objects like gr.Plot)
171
 
172
  def process_pipeline(image, conf_threshold):
173
  if image is None: return None, "", "", None, "", None, []
 
190
  return None, f"System Failure: {str(e)}", "", None, str(e), None, []
191
 
192
  # --- 6. MCP API FUNCTIONS (Optimized for Claude) ---
193
+ # These functions are explicitly defined as MCP tools at the bottom of the script.
194
+ # They use TYPE HINTS so Claude knows what arguments to provide.
195
+ # They return FILE PATHS (strings) for images, not base64 objects.
196
 
197
+ def detect_hieroglyphs(image: Image.Image, conf: float = 0.25) -> Tuple[str, Dict[str, Any]]:
198
  """
199
+ Scans an image for Egyptian hieroglyphs.
200
+ Returns a tuple containing:
201
+ 1. The file path to the annotated image result.
202
+ 2. A JSON summary of detected codes and their bounding boxes.
203
  """
204
  ann_img, dets, _ = core_detect(image, conf)
205
 
206
+ # Save to a temp file and return the PATH string
207
+ # Using a fixed temp dir ensures the path is accessible
208
+ with tempfile.NamedTemporaryFile(dir="/tmp/gradio_results", suffix=".jpg", delete=False) as t:
209
  ann_img.save(t.name)
210
  path = t.name
211
 
212
  return path, {"count": len(dets), "detections": dets}
213
 
214
+ def translate_codes(keywords_text: str) -> Tuple[str, str]:
215
  """
216
+ Takes a comma-separated string of Gardiner codes (e.g., 'G43, X1, N5').
217
+ Returns two translations: a mystical interpretation and an academic translation.
218
  """
219
  if isinstance(keywords_text, str):
220
  keywords = [k.strip() for k in keywords_text.split(',')]
221
  else:
222
  keywords = ["Unknown"]
223
  mystical, academic = core_translate(keywords)
224
+ # Strip HTML tags for clean text return to Claude
225
  clean_mystical = re.sub('<[^<]+?>', '', mystical)
226
  return clean_mystical, academic
227
 
228
+ def get_analytics_chart(json_data: Dict[str, Any]) -> str:
229
  """
230
+ Generates statistical charts based on detection data.
231
+ Input: The JSON output from the 'detect_hieroglyphs' tool.
232
+ Returns: The file path to the generated chart image.
233
  """
234
  dets = json_data.get("detections", [])
235
+ # Use fixed dimensions for consistency
236
+ fig = core_analytics(dets, 640, 640)
237
 
238
+ if fig is None:
239
+ return "No data to plot."
240
+
241
+ # Save to a temp file and return the PATH string
242
+ with tempfile.NamedTemporaryFile(dir="/tmp/gradio_results", suffix=".png", delete=False) as t:
243
  fig.savefig(t.name, format='png', facecolor='#0f0f23')
244
  path = t.name
245
  plt.close(fig)
246
  return path
247
 
248
+ def list_all_codes() -> Dict[str, Any]:
249
+ """
250
+ Returns the complete database of supported Gardiner codes and their descriptions.
251
+ Useful for looking up specific symbol meanings.
252
+ """
253
  return gardiner_data
254
 
255
  # --- 7. HTML GENERATORS ---
 
416
  </div>
417
  """
418
 
419
+ # FIX 1: Reformatted JSON string with multiline triple-quotes so it displays expanded.
420
+ claude_json_content = """{
421
+ "mcpServers": {
422
+ "gradio": {
423
+ "command": "npx",
424
+ "args": [
425
+ "mcp-remote",
426
+ "https://youkii-xr-hieroglyph-mcp-server.hf.space/gradio_api/mcp/",
427
+ "--transport",
428
+ "streamable-http"
429
+ ]
430
+ },
431
+ "upload_helper": {
432
+ "command": "C:\\\\Python313\\\\python.exe",
433
+ "args": [
434
+ "-m",
435
+ "gradio",
436
+ "upload-mcp",
437
+ "https://youkii-xr-hieroglyph-mcp-server.hf.space/",
438
+ "C:\\\\Claude_Work"
439
+ ]
440
+ }
441
+ }
442
+ }"""
443
 
444
  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>"""
445
 
 
449
  gr.HTML(f"<style>{custom_css}</style>")
450
  gr.HTML(trail_script)
451
 
452
+ # (Removed hidden buttons - tools are now defined explicitly in launch())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
453
 
454
  # --- Visible UI ---
455
  with gr.Row(elem_classes="header-row"):
 
493
  # TAB 3: SETUP
494
  with gr.TabItem("🤖 SYSTEM SETUP"):
495
  gr.HTML(guide_html)
496
+ # JSON box will now be expanded due to multiline string above
497
  gr.Code(value=claude_json_content, language="json", label="claude_desktop_config.json", interactive=False, lines=30)
498
 
499
  # TAB 4: GARDINER CODES
 
509
  btn_cam.click(fn=process_pipeline, inputs=[img_cam, slider_conf_cam], outputs=outputs)
510
 
511
  if __name__ == "__main__":
512
+ # FIX 2 & 3: Explicitly define short tool names and ensure images are handled correctly.
513
+ # By passing the functions directly to mcp_tools, Gradio uses the function name as the tool name.
514
+ # The /tmp/gradio_results path ensures Claude can read the generated image files.
515
+ demo.launch(
516
+ mcp_server=True,
517
+ mcp_tools=[detect_hieroglyphs, translate_codes, get_analytics_chart, list_all_codes],
518
+ ssr_mode=False,
519
+ allowed_paths=["/tmp", "/tmp/gradio_results", "."]
520
+ )