Spaces:
Runtime error
Runtime error
LPX55
Refactor app.py to modularize tab functionality by introducing greeting_tab, calculator_tab, and sepia_tab functions for improved readability and maintainability
4478d67
import gradio as gr | |
import gradio.themes | |
import numpy as np | |
from style import js_func, css_func | |
import tempfile | |
import pandas as pd | |
from greeting_tab import greeting_tab | |
from calculator_tab import calculator_tab | |
from sepia_tab import sepia_tab | |
def greet(name="Stranger", intensity=1, exclaim=False): | |
greeting = f"Hello, {name}{'!' * int(intensity)}" | |
if exclaim: | |
greeting = greeting.upper() | |
return greeting | |
def calculator(num1, operation, num2): | |
if operation == "add": | |
result = num1 + num2 | |
elif operation == "subtract": | |
result = num1 - num2 | |
elif operation == "multiply": | |
result = num1 * num2 | |
elif operation == "divide": | |
if num2 == 0: | |
raise gr.Error("Cannot divide by zero!") | |
result = num1 / num2 | |
return result | |
def sepia(input_img): | |
sepia_filter = np.array([ | |
[0.393, 0.769, 0.189], | |
[0.349, 0.686, 0.168], | |
[0.272, 0.534, 0.131] | |
]) | |
sepia_img = input_img @ sepia_filter.T | |
sepia_img = np.clip(sepia_img, 0, 255).astype(np.uint8) | |
return sepia_img | |
def download_text(text): | |
if not text: | |
text = "" | |
with tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="w", encoding="utf-8") as f: | |
f.write(text) | |
return f.name | |
def download_csv(result): | |
if result is None: | |
result = "" | |
df = pd.DataFrame({"Result": [result]}) | |
with tempfile.NamedTemporaryFile(delete=False, suffix=".csv", mode="w", encoding="utf-8") as f: | |
df.to_csv(f, index=False) | |
return f.name | |
theme = gr.Theme.from_hub("LPX55/modal_ai") | |
with gr.Blocks(theme=theme, js=js_func, css=css_func) as demo: | |
show_space_tab = gr.State(False) | |
with gr.Sidebar(width="25vw"): | |
gr.Markdown(""" | |
# 🤖 API + MCP Demo | |
_Dynamically load tabs 🤫_ | |
--- | |
**Ways to load the remote SAM2.1 Masking Tool:** | |
- **gr.load()**: Loads the remote interface at startup, just hidden until shown. | |
- **iframe**: Loads the remote UI only when you click the button (no API integration). | |
- **API Proxy**: Upload an image, and the backend will call the remote Space's API and show the result. | |
- **Open in New Tab**: Opens the remote Space in a new browser tab. | |
--- | |
**Navigation** | |
- [Greeting](#greeting) | |
- [Calculator](#calculator) | |
- [Sepia Image](#sepia-image) | |
- [Custom IFrame Loader](#custom-iframe-loader) | |
--- | |
### [GitHub Repo](https://github.com/yourrepo) | [Docs](https://yourdocs) | |
--- | |
**Tips:** | |
- Try the examples in each tab! | |
- Download your results with the button on the right. | |
""") | |
gr.Code( | |
"""from gradio_client import Client | |
client = Client("YOUR_URL") | |
print(client.predict("Alex", 5, False, api_name="/greet")) | |
""", language="python", label="**API Example:**" | |
) | |
gr.Button("Reset All", elem_id="reset-btn") | |
load_space_btn = gr.Button("Load Extra Space", elem_id="load-space-btn") | |
load_sam_btn = gr.Button("Load SAM2.1 Masking Tool (gr.load)", elem_id="load-sam-btn") | |
load_sam_iframe_btn = gr.Button("Load SAM2.1 Masking Tool (iframe)", elem_id="load-sam-iframe-btn") | |
load_sam_api_btn = gr.Button("Load SAM2.1 Masking Tool (API Proxy)", elem_id="load-sam-api-btn") | |
open_sam_tab_btn = gr.Button("Open SAM2.1 Masking Tool in New Tab", elem_id="open-sam-tab-btn") | |
with gr.Tab("Greeting"): | |
greeting_tab() | |
with gr.Tab("Calculator"): | |
calculator_tab() | |
with gr.Tab("Sepia Image"): | |
sepia_tab() | |
# Add state variables for each dynamic tab | |
extra_space_open = gr.State(True) | |
sam_tab_open = gr.State(True) | |
sam_iframe_tab_open = gr.State(True) | |
sam_api_tab_open = gr.State(True) | |
custom_iframe_tab_open = gr.State(True) | |
with gr.Tab("Extra Space", visible=False) as extra_space_tab: | |
def render_extra_space(is_open): | |
if is_open: | |
gr.Markdown("## External Gradio Space") | |
gr.HTML('<iframe src="https://huggingface.co/spaces/gradio/calculator" width="100%" height="600" style="border:none;"></iframe>') | |
close_btn = gr.Button("Close Tab") | |
def close_tab(): | |
return gr.Tab(visible=False), False | |
close_btn.click(fn=close_tab, outputs=[extra_space_tab, extra_space_open]) | |
with gr.Tab("SAM2.1 Masking Tool (gr.load)", visible=False) as sam_tab: | |
def render_sam_tab(is_open): | |
if is_open: | |
gr.Markdown("## LPX55/SAM2_1-Image-Predictor-Masking-Tool-CPU (gr.load)") | |
sam_interface = gr.load("LPX55/SAM2_1-Image-Predictor-Masking-Tool-CPU", src="spaces") | |
close_btn = gr.Button("Close Tab") | |
def close_tab(): | |
return gr.Tab(visible=False), False | |
close_btn.click(fn=close_tab, outputs=[sam_tab, sam_tab_open]) | |
with gr.Tab("SAM2.1 Masking Tool (iframe)", visible=False) as sam_iframe_tab: | |
def render_sam_iframe_tab(is_open): | |
if is_open: | |
gr.Markdown("## LPX55/SAM2_1-Image-Predictor-Masking-Tool-CPU (iframe)") | |
gr.HTML('<iframe src="https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space" width="100%" height="800" style="border:none;"></iframe>') | |
close_btn = gr.Button("Close Tab") | |
def close_tab(): | |
return gr.Tab(visible=False), False | |
close_btn.click(fn=close_tab, outputs=[sam_iframe_tab, sam_iframe_tab_open]) | |
with gr.Tab("SAM2.1 Masking Tool (API Proxy)", visible=False) as sam_api_tab: | |
def render_sam_api_tab(is_open): | |
if is_open: | |
gr.Markdown("## LPX55/SAM2_1-Image-Predictor-Masking-Tool-CPU (API Proxy)") | |
api_image = gr.Image(label="Input Image") | |
api_btn = gr.Button("Run Remote Masking") | |
api_output = gr.Textbox(label="API Response (raw)") | |
def call_sam_api(image): | |
import requests | |
import base64 | |
import json | |
if image is None: | |
return "No image uploaded." | |
with open(image, "rb") as f: | |
img_b64 = base64.b64encode(f.read()).decode() | |
payload = {"data": [img_b64]} | |
try: | |
resp = requests.post( | |
"https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space/run/predict", | |
json=payload, | |
timeout=60 | |
) | |
if resp.status_code == 200: | |
return json.dumps(resp.json(), indent=2) | |
else: | |
return f"Error: {resp.status_code} {resp.text}" | |
except Exception as e: | |
return f"Exception: {str(e)}" | |
api_btn.click(fn=call_sam_api, inputs=api_image, outputs=api_output) | |
close_btn = gr.Button("Close Tab") | |
def close_tab(): | |
return gr.Tab(visible=False), False | |
close_btn.click(fn=close_tab, outputs=[sam_api_tab, sam_api_tab_open]) | |
with gr.Tab("Custom IFrame Loader") as custom_iframe_tab: | |
def render_custom_iframe_tab(is_open): | |
if is_open: | |
gr.Markdown("## Load Any IFrame URL") | |
custom_url = gr.Textbox(label="IFrame URL", placeholder="https://example.com") | |
load_custom_iframe_btn = gr.Button("Load IFrame") | |
custom_iframe = gr.HTML(visible=True) | |
def load_custom_iframe(url): | |
if not url: | |
return "<div style='color:red'>Please enter a URL.</div>" | |
return f'<iframe src="{url}" width="100%" height="800" style="border:none;"></iframe>' | |
load_custom_iframe_btn.click(fn=load_custom_iframe, inputs=custom_url, outputs=custom_iframe) | |
close_btn = gr.Button("Close Tab") | |
def close_tab(): | |
return gr.Tab(visible=False), False | |
close_btn.click(fn=close_tab, outputs=[custom_iframe_tab, custom_iframe_tab_open]) | |
# Iframe lazy load pattern | |
heavy_iframe_src = gr.State("") | |
with gr.Tab("Heavy Space (iframe - lazy load)", visible=False) as heavy_iframe_tab: | |
iframe_html = gr.HTML("") | |
close_btn = gr.Button("Close Tab") | |
def close_heavy_iframe_tab(): | |
return gr.Tab(visible=False), "" | |
close_btn.click(fn=close_heavy_iframe_tab, outputs=[heavy_iframe_tab, iframe_html]) | |
def open_heavy_iframe_tab(): | |
src = '<iframe src="https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space" width="100%" height="800" style="border:none;"></iframe>' | |
return gr.Tab(visible=True), src | |
open_heavy_iframe_btn = gr.Button("Open Heavy Space (iframe - lazy load)") | |
open_heavy_iframe_btn.click(fn=open_heavy_iframe_tab, outputs=[heavy_iframe_tab, iframe_html]) | |
# Iframe always loaded pattern | |
with gr.Tab("Heavy Space (iframe - always loaded)", visible=True) as heavy_iframe_always_tab: | |
gr.HTML('<iframe src="https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space" width="100%" height="800" style="border:none;"></iframe>') | |
close_btn2 = gr.Button("Close Tab") | |
def close_heavy_iframe_always_tab(): | |
return gr.Tab(visible=False) | |
close_btn2.click(fn=close_heavy_iframe_always_tab, outputs=heavy_iframe_always_tab) | |
open_heavy_iframe_always_btn = gr.Button("Open Heavy Space (iframe - always loaded)") | |
def open_heavy_iframe_always_tab(): | |
return gr.Tab(visible=True) | |
open_heavy_iframe_always_btn.click(fn=open_heavy_iframe_always_tab, outputs=heavy_iframe_always_tab) | |
def show_tab(): | |
return gr.Tab(visible=True) | |
load_space_btn.click(fn=show_tab, outputs=[extra_space_tab]) | |
def show_sam_tab(): | |
return gr.Tab(visible=True) | |
load_sam_btn.click(fn=show_sam_tab, outputs=[sam_tab]) | |
def show_sam_iframe_tab(): | |
iframe_html = '<iframe src="https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space" width="100%" height="800" style="border:none;"></iframe>' | |
return gr.Tab(visible=True), iframe_html | |
load_sam_iframe_btn.click(fn=show_sam_iframe_tab, outputs=[sam_iframe_tab, sam_iframe]) | |
def show_sam_api_tab(): | |
return gr.Tab(visible=True) | |
load_sam_api_btn.click(fn=show_sam_api_tab, outputs=[sam_api_tab]) | |
def open_in_new_tab(): | |
# This function does nothing server-side, but the button will have a link | |
pass | |
open_sam_tab_btn.click(fn=open_in_new_tab, inputs=None, outputs=None, js="window.open('https://lpx55-sam2-1-image-predictor-masking-tool-cpu.hf.space', '_blank')") | |
gr.Markdown(""" | |
--- | |
## 📡 API Usage | |
- Every function in this demo is automatically available as a REST API! | |
- View the [OpenAPI schema](./openapi.json) or click "Use via API" in the footer. | |
- Try the [gradio_client](https://www.gradio.app/guides/getting-started-with-the-python-client) or [@gradio/client](https://www.gradio.app/guides/getting-started-with-the-js-client) to call these endpoints programmatically. | |
""") | |
demo.launch(mcp_server=True) | |