RunPodRun / app.py
Theflame47's picture
Update app.py
68316d3 verified
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, JSONResponse
import os, pathlib, json
from Deployment_UI import router as deployment_ui_router
from Deployment_UI_BE import router as deployment_be_router
from modelblob import router as modelblob_router # NEW (blob page + /modelblob.json)
app = FastAPI()
app.include_router(deployment_ui_router)
app.include_router(deployment_be_router)
app.include_router(modelblob_router) # NEW
LOCAL_BLOB_PATH = os.getenv("MODEL_BLOB_PATH", "/tmp/model_blob.json")
def _load_blob_text() -> str:
try:
if os.path.exists(LOCAL_BLOB_PATH):
return pathlib.Path(LOCAL_BLOB_PATH).read_text(encoding="utf-8")
except Exception:
pass
return "{\n \"note\": \"paste or programmatically write the model blob to /tmp/model_blob.json\"\n}"
def html_escape(s: str) -> str:
return (
s.replace("&", "&")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace('"', "&quot;")
.replace("'", "&#39;")
)
@app.get("/", response_class=HTMLResponse)
def landing_page() -> HTMLResponse:
blob_text = _load_blob_text()
html = f"""
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>RunPod Model Tester — Blob</title>
<style>
body {{ font-family: system-ui, sans-serif; margin: 24px; }}
pre {{ border:1px solid #ddd; border-radius:8px; padding:12px; background:#fafafa; max-height:50vh; overflow:auto; }}
.btn {{ display:inline-block; width:100%; max-width:680px; padding:12px 16px; margin:10px 0;
border:none; border-radius:8px; color:#fff; background:#0078d7; cursor:pointer; }}
.btn.secondary {{ background:#444; }}
.row {{ max-width: 980px; }}
#msg {{ margin-top:10px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size:12px; }}
/* overlay */
#blobOverlay {{ display:none; position:fixed; inset:0; background:rgba(0,0,0,.6); z-index:9999; }}
#blobCard {{ position:absolute; inset:4%; background:#0d1117; border-radius:12px; overflow:hidden;
box-shadow:0 10px 40px rgba(0,0,0,.5); }}
#blobHeader {{ padding:8px 12px; background:#111; color:#c9d1d9; display:flex; justify-content:space-between; align-items:center; }}
#closeBlob {{ width:auto; padding:6px 10px; }}
</style>
</head>
<body>
<div class="row">
<h1>RunPod Model Tester — Blob</h1>
<div id="count">{len(blob_text)}</div>
<div>
<div style="font-size:12px; color:#555; margin-bottom:6px;">Model blob (read-only)</div>
<pre id="blob" aria-label="model blob">{html_escape(blob_text)}</pre>
</div>
<!-- CHANGED: pass blob URL to the UI; no separate ingest button -->
<a href="/Deployment_UI?blob_url=/modelblob.json"
class="btn secondary" style="text-decoration:none; text-align:center;">
Open Deployment UI
</a>
<button id="openBlob" class="btn secondary">View Model Blob</button>
<div id="msg"></div>
</div>
<!-- Overlay -->
<div id="blobOverlay" aria-hidden="true">
<div id="blobCard">
<div id="blobHeader">
<div>Model Blob</div>
<button id="closeBlob" class="btn secondary">Close</button>
</div>
<iframe src="/modelblob" title="Model Blob" style="width:100%; height:calc(100% - 44px); border:0;"></iframe>
</div>
</div>
<script>
function setMsg(s) {{
document.getElementById("msg").textContent = s;
}}
// Overlay controls
const overlay = document.getElementById("blobOverlay");
document.getElementById("openBlob").addEventListener("click", () => {{
overlay.style.display = "block";
overlay.setAttribute("aria-hidden", "false");
}});
document.getElementById("closeBlob").addEventListener("click", () => {{
overlay.style.display = "none";
overlay.setAttribute("aria-hidden", "true");
}});
overlay.addEventListener("click", (e) => {{
if (e.target === overlay) {{
overlay.style.display = "none";
overlay.setAttribute("aria-hidden", "true");
}}
}});
</script>
</body>
</html>
"""
return HTMLResponse(html)
# kept for compatibility but no longer used by the UI flow
@app.post("/set_blob")
async def set_blob(req: Request):
try:
ctype = req.headers.get("content-type","")
if "application/json" in ctype:
data = await req.json()
txt = data.get("blob") if isinstance(data, dict) else None
else:
form = await req.form()
txt = form.get("blob")
if not isinstance(txt, str) or not txt.strip():
return JSONResponse({"error": "Missing 'blob' string"}, 400)
pathlib.Path(LOCAL_BLOB_PATH).write_text(txt, encoding="utf-8")
return JSONResponse({"ok": True, "path": LOCAL_BLOB_PATH})
except Exception as e:
return JSONResponse({"error": str(e)}, 500)