Spaces:
Sleeping
Sleeping
| 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("<", "<") | |
| .replace(">", ">") | |
| .replace('"', """) | |
| .replace("'", "'") | |
| ) | |
| 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 | |
| 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) | |