Spaces:
Running on RTX PRO 6000
Running on RTX PRO 6000
Stop production native USD experiment and restore GLB for every interactive asset
Browse files
Dockerfile
CHANGED
|
@@ -282,7 +282,7 @@ COPY docker/hf-space/search_fields.yaml /app/search_fields.yaml
|
|
| 282 |
# own uvicorn; remapped to 8003 here).
|
| 283 |
COPY docker/hf-space/supervisord-gpu.conf /etc/supervisor/conf.d/hf-space.conf
|
| 284 |
|
| 285 |
-
COPY docker/hf-space/nginx.conf.template /etc/nginx/hf-space.conf.template
|
| 286 |
|
| 287 |
COPY services/explorer/dist /usr/share/nginx/explorer
|
| 288 |
|
|
|
|
| 282 |
# own uvicorn; remapped to 8003 here).
|
| 283 |
COPY docker/hf-space/supervisord-gpu.conf /etc/supervisor/conf.d/hf-space.conf
|
| 284 |
|
| 285 |
+
COPY docker/hf-space/nginx-glb-production.conf.template /etc/nginx/hf-space.conf.template
|
| 286 |
|
| 287 |
COPY services/explorer/dist /usr/share/nginx/explorer
|
| 288 |
|
docker/hf-space/nginx-glb-production.conf.template
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Friendly external paths remapped to deepsearch-api's/asset-graph-service's
|
| 2 |
+
# actual routes β same mapping as
|
| 3 |
+
# usdsearch/helm/usdsearch/templates/api_gateway_config_map.yaml.
|
| 4 |
+
# deepsearch-api listens on 127.0.0.1:8000, asset-graph-service on
|
| 5 |
+
# 127.0.0.1:8010 (see docker/hf-space/supervisord.conf) β nginx is the sole
|
| 6 |
+
# process bound to the externally proxied port, so it can front every route
|
| 7 |
+
# with these rewrites plus CORS.
|
| 8 |
+
#
|
| 9 |
+
# The Explorer UI is served at `/` (root), not proxied to deepsearch-api at
|
| 10 |
+
# all β served directly from the static bundle baked into this image at
|
| 11 |
+
# build time (see the Dockerfile). Real difference from the multi-service
|
| 12 |
+
# deployment, which proxies /ui and /static/ to a *separate*
|
| 13 |
+
# deepsearch-explorer container: that bundle is just static files with
|
| 14 |
+
# same-origin relative API calls (REACT_APP_API_URL baked empty) and its
|
| 15 |
+
# own assets already use root-absolute paths (/static/js/..., /ds.png), so
|
| 16 |
+
# serving it directly at `/` β where it already expects to live β needs no
|
| 17 |
+
# extra process and no /ui prefix-stripping trick. The tradeoff: unlike the
|
| 18 |
+
# old single catch-all proxy, deepsearch-api's own root-level routes
|
| 19 |
+
# (/health, /docs, /redoc, /openapi.json) now need to be listed
|
| 20 |
+
# explicitly below, since the final `location /` falls through to the SPA
|
| 21 |
+
# instead. Also sidesteps a real problem seen live: a Space deployed with
|
| 22 |
+
# `/` returning a 301 (redirecting to `/ui`, the previous approach) broke β
|
| 23 |
+
# root cause not fully confirmed, but consistent with Hugging Face's own
|
| 24 |
+
# readiness check wanting a real 200 at `/`, not a redirect.
|
| 25 |
+
#
|
| 26 |
+
# __PORT__ is substituted with $PORT at container start (supervisord.conf),
|
| 27 |
+
# matching the Spaces convention of an operator-configurable app_port.
|
| 28 |
+
|
| 29 |
+
# >>> simready-central slim explorer (http) >>>
|
| 30 |
+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
| 31 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 32 |
+
# Included from nginx.conf's http{} (conf.d/*.conf) β an http-level directive is legal here.
|
| 33 |
+
# ONE level under /tmp on purpose: nginx mkdir()s only the last path component (no mkdir -p), and
|
| 34 |
+
# nothing in this image pre-creates a parent β /tmp/nginx-cache/slim-stats fails `nginx -t`. The
|
| 35 |
+
# `levels=` subdirectories are different: nginx creates those itself on the first write.
|
| 36 |
+
proxy_cache_path /tmp/slim-stats-cache levels=1 keys_zone=slim_stats_cache:2m max_size=256m inactive=1h use_temp_path=off;
|
| 37 |
+
# Thumbnails (/images): ~1,500 JPEGs of 27-52 KB (~75 MB) fit well inside 1g. Lives in the container's
|
| 38 |
+
# /tmp, so every deploy, restart or sleep starts it cold.
|
| 39 |
+
proxy_cache_path /tmp/slim-images-cache levels=1:2 keys_zone=slim_images_cache:10m max_size=1g inactive=7d use_temp_path=off;
|
| 40 |
+
# Library media (/library_media/ below): a file asked for under its ?v= (its content hash) never changes; the
|
| 41 |
+
# manifest (no ?v=) revalidates, so a new fetch at the next container start shows at once.
|
| 42 |
+
map $arg_v $slim_library_cache {
|
| 43 |
+
"" "no-cache";
|
| 44 |
+
default "public, max-age=31536000, immutable";
|
| 45 |
+
}
|
| 46 |
+
# <<< simready-central slim explorer (http) <<<
|
| 47 |
+
server {
|
| 48 |
+
listen __PORT__;
|
| 49 |
+
|
| 50 |
+
proxy_http_version 1.1;
|
| 51 |
+
proxy_set_header Connection "";
|
| 52 |
+
proxy_connect_timeout 5s;
|
| 53 |
+
proxy_send_timeout 60s;
|
| 54 |
+
proxy_read_timeout 60s;
|
| 55 |
+
proxy_set_header Host $host;
|
| 56 |
+
proxy_set_header X-Real-IP $remote_addr;
|
| 57 |
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
| 58 |
+
proxy_set_header X-Forwarded-Proto $scheme;
|
| 59 |
+
|
| 60 |
+
add_header Access-Control-Allow-Origin "*" always;
|
| 61 |
+
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
|
| 62 |
+
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
|
| 63 |
+
|
| 64 |
+
location /search {
|
| 65 |
+
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 66 |
+
rewrite ^/search(.*)$ /v2/deepsearch/search$1 break;
|
| 67 |
+
proxy_pass http://127.0.0.1:8000;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
location /search_hybrid {
|
| 71 |
+
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 72 |
+
rewrite ^/search_hybrid(.*)$ /v3/deepsearch/search$1 break;
|
| 73 |
+
proxy_pass http://127.0.0.1:8000;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
location /vlm_validate/search_result {
|
| 77 |
+
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 78 |
+
rewrite ^/vlm_validate/search_result(.*)$ /v3/deepsearch/vlm_validate/search_result$1 break;
|
| 79 |
+
proxy_pass http://127.0.0.1:8000;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
location /llm_parse/ {
|
| 83 |
+
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 84 |
+
rewrite ^/llm_parse/(.*)$ /v3/deepsearch/llm_parse/$1 break;
|
| 85 |
+
proxy_pass http://127.0.0.1:8000;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
# package-download (127.0.0.1:8020, pipeline/package_download/), not deepsearch-api: it answers
|
| 89 |
+
# /download/asset with the asset's whole SimReady package folder, same response contract, and
|
| 90 |
+
# forwards scope=dependencies (and anything outside a catalogued package) to deepsearch-api's
|
| 91 |
+
# own /v3/download/asset. It serves the /download/... paths itself, so no rewrite.
|
| 92 |
+
location /download {
|
| 93 |
+
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 94 |
+
proxy_pass http://127.0.0.1:8020;
|
| 95 |
+
# Fetching a whole package (or a forwarded dependency bundle) can take longer than a single thumbnail.
|
| 96 |
+
proxy_read_timeout 300s;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
location /images {
|
| 100 |
+
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 101 |
+
rewrite ^/images(.*)$ /v3/images$1 break;
|
| 102 |
+
proxy_pass http://127.0.0.1:8000;
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
location /static/ {
|
| 106 |
+
alias /usr/share/nginx/explorer/static/;
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
# asset-graph-service routes (query-time graph reads only β see
|
| 110 |
+
# docker/Dockerfile.hf-space's header for why there's no graph-builder/
|
| 111 |
+
# asset_graph_generation worker in this image). Same rewrites as the
|
| 112 |
+
# real gateway config's asset_graph_service locations, just proxying to
|
| 113 |
+
# our own internal port instead of a separate service/Space.
|
| 114 |
+
location /asset_graph/usd/scene_summary/ {
|
| 115 |
+
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 116 |
+
rewrite ^/asset_graph/usd/scene_summary/(.*)$ /asset_graph/usd/scene_summary/$1 break;
|
| 117 |
+
proxy_pass http://127.0.0.1:8010;
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
location /asset_graph/usd/scene_summary {
|
| 121 |
+
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 122 |
+
rewrite ^/asset_graph/usd/scene_summary(.*)$ /asset_graph/usd/scene_summary/$1 break;
|
| 123 |
+
proxy_pass http://127.0.0.1:8010;
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
location /asset_graph/usd/prims {
|
| 127 |
+
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 128 |
+
rewrite ^/asset_graph/usd/prims(.*)$ /asset_graph/usd/prims$1 break;
|
| 129 |
+
proxy_pass http://127.0.0.1:8010;
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
location /dependency_graph {
|
| 133 |
+
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 134 |
+
rewrite ^/dependency_graph(.*)$ /dependency_graph$1 break;
|
| 135 |
+
proxy_pass http://127.0.0.1:8010;
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
# deepsearch-api's own root-level routes β explicit now that `location /`
|
| 139 |
+
# below serves the Explorer SPA instead of proxying everything
|
| 140 |
+
# unmatched. /docs and /redoc are prefix matches, not exact: Swagger
|
| 141 |
+
# UI/ReDoc can request sub-resources under their own path.
|
| 142 |
+
location = /health { proxy_pass http://127.0.0.1:8000; }
|
| 143 |
+
location = /openapi.json { proxy_pass http://127.0.0.1:8000; }
|
| 144 |
+
# Prometheus /metrics stays private to the container (127.0.0.1:8000
|
| 145 |
+
# directly): an explicit JSON 404 rather than no location, which would
|
| 146 |
+
# fall through to the SPA's index.html with a 200.
|
| 147 |
+
location = /metrics {
|
| 148 |
+
default_type application/json;
|
| 149 |
+
return 404 '{"detail":"Not Found"}';
|
| 150 |
+
}
|
| 151 |
+
location /docs { proxy_pass http://127.0.0.1:8000; }
|
| 152 |
+
location /redoc { proxy_pass http://127.0.0.1:8000; }
|
| 153 |
+
|
| 154 |
+
# The Explorer SPA (see header comment) at root: try_files serves any of
|
| 155 |
+
# its own literal files (index.html, ds.png, favicon.ico, manifest.json,
|
| 156 |
+
# ...) directly, and falls back to index.html for anything else
|
| 157 |
+
# (client-side routing) β anything actually meant for the API above was
|
| 158 |
+
# already matched by a more specific location before nginx gets here.
|
| 159 |
+
# >>> simready-central slim explorer >>>
|
| 160 |
+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
| 161 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 162 |
+
# services/explorer/dist is SimReady Central's search-only Explorer (repo simready-central,
|
| 163 |
+
# branch slim, slim/devspace/). The locations here are additive β exact matches, longer
|
| 164 |
+
# prefixes or a regex β and none of his locations is redefined. This block carries: /config.js,
|
| 165 |
+
# a no-cache /index.html, a 10-min
|
| 166 |
+
# proxy cache on /search/stats/usd_properties, a shared proxy cache on /images,
|
| 167 |
+
# /wikidata_hierarchy.json, /library_media/ and JSON 404s for the routes this build does not have. What DOES
|
| 168 |
+
# reach beyond it: client_max_body_size 32m is server-wide (it applies to ALL his locations
|
| 169 |
+
# too); `= /images` takes the requests his `/images` prefix served before (same rewrite +
|
| 170 |
+
# proxy_pass, plus the cache); and an
|
| 171 |
+
# add_header inside one of our locations replaces his server-level headers for THOSE responses
|
| 172 |
+
# β /images and the stats cache re-declare his three CORS lines, /config.js and /index.html
|
| 173 |
+
# (same-origin UI files) do not. Applied by slim/devspace/deploy.sh.
|
| 174 |
+
client_max_body_size 32m; # query-image searches POST a base64 JPEG (nginx default 1 MB)
|
| 175 |
+
gzip_types text/css application/javascript application/json image/svg+xml; # stock gzip covers text/html only
|
| 176 |
+
|
| 177 |
+
# Runtime index registry (blocking <script src="/config.js">). The CORPUS_NAME marker is
|
| 178 |
+
# rendered by the same sed that renders the PORT marker (supervisord.conf).
|
| 179 |
+
# __DOWNLOAD_ENABLED__ is rendered the same way, from $DOWNLOAD_ENABLED
|
| 180 |
+
# (baked by docker/Dockerfile.hf-space, set true only for a
|
| 181 |
+
# storage_api-backend corpus β pipeline/bake.py's hf_space_build_args()
|
| 182 |
+
# β since that's the only backend this image runs a live hf-storage-api
|
| 183 |
+
# gRPC server for; GET /v3/download/asset works today for neither
|
| 184 |
+
# backend without it running, and this repo hasn't verified an s3-backend
|
| 185 |
+
# download path independently, so s3 corpora keep today's false).
|
| 186 |
+
# seedDefaultScope:false β boot browses the corpus. No defaultFilters (owner, 2026-10-07): the boot browse
|
| 187 |
+
# shows every license; License stays one click away in the rail.
|
| 188 |
+
# railFilters + railDefaults ["profiles","simready_metadata_asset_license","category"]: rail = Profiles + License +
|
| 189 |
+
# the Category tree, all on (owner, 2026-09-30). The rail matches a facet by its parser-catalog field NAME:
|
| 190 |
+
# search_fields.yaml names it simready_metadata_asset_license since 2026-09-23 ("license" matched nothing and
|
| 191 |
+
# hid the facet); the parser catalog
|
| 192 |
+
# docker/hf-space/search_fields.yaml stays curated to profile + license. propertyAliases: this API stores the
|
| 193 |
+
# Wikidata code as semantic:wikidata_qcode:params:semanticData (wikidata_qcode= matches nothing here), so the
|
| 194 |
+
# Explorer translates its canonical name at the wire and renames the stats key back on arrival.
|
| 195 |
+
# propertyFilterCombine "and": the API ORs every filter_by_properties_include_any token globally, so with License
|
| 196 |
+
# checked a Category pick would change nothing β a property with ONE checked value rides filter_by_properties
|
| 197 |
+
# (AND) instead; a multi-valued one (the tree's qcodes) stays the OR bucket. Measured: license 1488, one qcode 124,
|
| 198 |
+
# both in include_any 1488, license AND qcode 124.
|
| 199 |
+
location = /config.js {
|
| 200 |
+
default_type application/javascript;
|
| 201 |
+
add_header Cache-Control "no-cache, must-revalidate" always;
|
| 202 |
+
return 200 '(function(){var c="__CORPUS_NAME__";if(!c||c.indexOf("__")===0){c="usdsearch-dev";}var e={"field_name":"siglip2-embedding.embedding","dimension":1536};var f={"download":__DOWNLOAD_ENABLED__,"s3UrlRemap":false,"seedDefaultScope":false,"railFilters":["profiles","simready_metadata_asset_license","category"],"railDefaults":["profiles","simready_metadata_asset_license","category"],"propertyAliases":{"wikidata_qcode":"simready_metadata_qcode"},"propertyFilterCombine":"and","submitContentUrl":"__SUBMIT_CONTENT_URL__"};window.__SERVER_MAPPING__={"usdsearch-dev":{"name":c+" (Hugging Face)","apiUrl":"","embedding_config":e,"features":f},"hf-robotiq":{"name":"Robotiq","apiUrl":"","search_path":"/Robotiq-Official/simready-assets/","embedding_config":e,"features":Object.assign({},f,{"libraryPosters":"stills"}),"origin":{"kind":"hf","label":"Robotiq-Official/simready-assets"}},"hf-standardbots":{"name":"Standard Bots","apiUrl":"","search_path":"/standardbots/","embedding_config":e,"features":Object.assign({},f,{"libraryPosters":"stills"}),"origin":{"kind":"hf","label":"standardbots"}}};window.__DEFAULT_SERVER__="usdsearch-dev";})();';
|
| 203 |
+
}
|
| 204 |
+
# index.html must always revalidate (covers the try_files fallback too): a swap or rollback
|
| 205 |
+
# must not leave a browser holding an index.html that names deleted chunks.
|
| 206 |
+
location = /index.html {
|
| 207 |
+
root /usr/share/nginx/explorer;
|
| 208 |
+
add_header Cache-Control "no-cache" always;
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
# Property inventory (rail facets + parser grounding): multi-MB aggregation β cached 10 min.
|
| 212 |
+
location = /search/stats/usd_properties {
|
| 213 |
+
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 214 |
+
rewrite ^/search(.*)$ /v2/deepsearch/search$1 break;
|
| 215 |
+
proxy_pass http://127.0.0.1:8000;
|
| 216 |
+
proxy_ignore_headers Cache-Control Expires;
|
| 217 |
+
proxy_cache slim_stats_cache;
|
| 218 |
+
proxy_cache_key "$request_uri";
|
| 219 |
+
proxy_cache_valid 200 10m;
|
| 220 |
+
proxy_cache_lock on;
|
| 221 |
+
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
|
| 222 |
+
proxy_read_timeout 120s;
|
| 223 |
+
add_header X-Cache-Status $upstream_cache_status always;
|
| 224 |
+
# add_header above drops his server-level headers β re-declared as in his template
|
| 225 |
+
add_header Access-Control-Allow-Origin "*" always;
|
| 226 |
+
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
|
| 227 |
+
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
|
| 228 |
+
}
|
| 229 |
+
# Thumbnails: his `location /images` rewrite + proxy_pass (this exact match wins over his prefix)
|
| 230 |
+
# plus a SHARED cache β every cold /images costs the API ~150 CPU-ms on its one event loop.
|
| 231 |
+
# Keyed by the full URI (image_key, or asset_url + img_offset); the API's `Cache-Control: private`
|
| 232 |
+
# is ignored on purpose. Valid ONLY while the image runs with STORAGE_REQUIRE_AUTH=False (deploy.sh
|
| 233 |
+
# refuses a hub Dockerfile without it): with per-user storage auth, add
|
| 234 |
+
# `proxy_no_cache $arg_asset_url; proxy_cache_bypass $arg_asset_url;` so the access-checked
|
| 235 |
+
# asset_url path is never shared (image_key is content-addressed and unchecked). add_header here
|
| 236 |
+
# drops his server-level headers, so his three CORS lines are re-declared; proxy_hide_header
|
| 237 |
+
# keeps a chained nginx (check.sh --replica) to its own X-Cache-Status.
|
| 238 |
+
location = /images {
|
| 239 |
+
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 240 |
+
rewrite ^/images(.*)$ /v3/images$1 break;
|
| 241 |
+
proxy_pass http://127.0.0.1:8000;
|
| 242 |
+
proxy_cache slim_images_cache;
|
| 243 |
+
proxy_cache_key "$request_uri";
|
| 244 |
+
proxy_ignore_headers Cache-Control Expires;
|
| 245 |
+
proxy_hide_header X-Cache-Status;
|
| 246 |
+
proxy_cache_valid 200 7d;
|
| 247 |
+
proxy_cache_lock on;
|
| 248 |
+
proxy_cache_lock_timeout 15s;
|
| 249 |
+
proxy_cache_use_stale error timeout updating;
|
| 250 |
+
add_header X-Cache-Status $upstream_cache_status always;
|
| 251 |
+
add_header Access-Control-Allow-Origin "*" always;
|
| 252 |
+
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
|
| 253 |
+
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
|
| 254 |
+
}
|
| 255 |
+
# Our 404s are JSON like the API's own (a bare `return 404;` would be nginx's text/html error
|
| 256 |
+
# page): reachable only from the locations below, so nothing of his changes.
|
| 257 |
+
location @slim_not_found {
|
| 258 |
+
default_type application/json;
|
| 259 |
+
return 404 '{"detail":"Not Found"}';
|
| 260 |
+
}
|
| 261 |
+
# The Category tree: the `hierarchy` stage's output, restored with the index run (pipeline/hierarchy/store.py);
|
| 262 |
+
# absent β a real 404 and the Explorer falls back to its __full_path tree.
|
| 263 |
+
location = /wikidata_hierarchy.json {
|
| 264 |
+
root /app/hf-space-pipeline/.build/restore/hierarchy;
|
| 265 |
+
try_files /category_hierarchy.json @slim_not_found;
|
| 266 |
+
}
|
| 267 |
+
# One request per result page (QA 6881558: Hugging Face limits each user to ~2,000 requests a minute,
|
| 268 |
+
# and a page of per-image checks took 50): deepsearch-api's /vlm_validate/search_result_batch streams one
|
| 269 |
+
# NDJSON verdict per hit. The Explorer calls this path; the request and the lines are the same.
|
| 270 |
+
# Unbuffered so verdicts land as they come; heartbeats keep the stream open.
|
| 271 |
+
location = /vlm_validate/batch_stream {
|
| 272 |
+
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 273 |
+
rewrite ^ /v3/deepsearch/vlm_validate/search_result_batch break;
|
| 274 |
+
proxy_pass http://127.0.0.1:8000;
|
| 275 |
+
proxy_buffering off;
|
| 276 |
+
proxy_read_timeout 120s;
|
| 277 |
+
gzip off;
|
| 278 |
+
add_header X-Accel-Buffering no always;
|
| 279 |
+
add_header Access-Control-Allow-Origin "*" always;
|
| 280 |
+
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
|
| 281 |
+
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
|
| 282 |
+
}
|
| 283 |
+
# Any other /vlm_validate/ path: a JSON 404, never the SPA's index.html.
|
| 284 |
+
location /vlm_validate/ {
|
| 285 |
+
default_type application/json;
|
| 286 |
+
return 404 '{"detail":"Not Found"}';
|
| 287 |
+
}
|
| 288 |
+
# Six qualified partner robots are installed from one SHA-pinned S3 ZIP by
|
| 289 |
+
# pipeline/partner_viewer.py. Its own viewer uses these root-relative paths;
|
| 290 |
+
# the USD path is narrower than the native-USD release service's route.
|
| 291 |
+
location = /trial { absolute_redirect off; return 308 /trial/; }
|
| 292 |
+
location = /trial/ {
|
| 293 |
+
root /app/hf-space-pipeline/.build/partner_viewer;
|
| 294 |
+
try_files /trial/index.html @slim_not_found;
|
| 295 |
+
}
|
| 296 |
+
location ^~ /trial/ { root /app/hf-space-pipeline/.build/partner_viewer; index index.html; try_files $uri @slim_not_found; }
|
| 297 |
+
location ^~ /media/ { root /app/hf-space-pipeline/.build/partner_viewer; try_files $uri @slim_not_found; }
|
| 298 |
+
location ^~ /rust/ { root /app/hf-space-pipeline/.build/partner_viewer; try_files $uri @slim_not_found; }
|
| 299 |
+
location ^~ /three/ { root /app/hf-space-pipeline/.build/partner_viewer; try_files $uri @slim_not_found; }
|
| 300 |
+
location ^~ /usd-round2/ { root /app/hf-space-pipeline/.build/partner_viewer; try_files $uri @slim_not_found; }
|
| 301 |
+
location ^~ /usd/usd-central/rust-assets/hf- {
|
| 302 |
+
root /app/hf-space-pipeline/.build/partner_viewer;
|
| 303 |
+
try_files $uri @slim_not_found;
|
| 304 |
+
}
|
| 305 |
+
# Library media β the Explorer's joints viewer (model.glb + articulation.json), moving-parts and drop-test
|
| 306 |
+
# clips, per asset of this corpus: static files pipeline/library_media.py fetches at container start from
|
| 307 |
+
# the artifact bucket (supervisord program library-media). Not there (not fetched yet, or none for
|
| 308 |
+
# this corpus) β a JSON 404 and the Explorer shows no media; never the SPA's index.html. Range requests
|
| 309 |
+
# (Safari's <video>) are nginx's own. add_header drops his server-level headers: his CORS lines re-declared.
|
| 310 |
+
# Native USD is a separately pinned release. Its verified 2 GiB cache keeps
|
| 311 |
+
# the full catalog out of the Space's boot-time restore and disk budget.
|
| 312 |
+
# User-requested production rollback: every interactive asset uses GLB.
|
| 313 |
+
location = /library_media/usdsearch-dev/usd-catalog.json {
|
| 314 |
+
alias /app/hf-space-pipeline/pipeline/native_usd_releases/production-glb-catalog.json;
|
| 315 |
+
default_type application/json;
|
| 316 |
+
add_header Cache-Control "no-store";
|
| 317 |
+
gzip_types application/json;
|
| 318 |
+
}
|
| 319 |
+
location /usd/usd-central/ {
|
| 320 |
+
default_type application/json;
|
| 321 |
+
add_header Cache-Control "no-store";
|
| 322 |
+
return 404 '{"detail":"Native USD experiment is paused; use GLB"}';
|
| 323 |
+
}
|
| 324 |
+
location /usd-rust/ {
|
| 325 |
+
root /usr/share/nginx/explorer;
|
| 326 |
+
try_files $uri =404;
|
| 327 |
+
gzip_static on;
|
| 328 |
+
add_header X-Content-Type-Options nosniff;
|
| 329 |
+
}
|
| 330 |
+
# The three picker entries share one physical corpus and one media archive.
|
| 331 |
+
# Keep partner URLs on the same files so a scoped picker can load their RTX
|
| 332 |
+
# media and native USD catalog without duplicating the archive on disk.
|
| 333 |
+
location = /library_media/hf-robotiq/usd-catalog.json {
|
| 334 |
+
root /app/hf-space-pipeline/.build;
|
| 335 |
+
default_type application/json;
|
| 336 |
+
add_header Cache-Control "no-cache" always;
|
| 337 |
+
}
|
| 338 |
+
location = /library_media/hf-standardbots/usd-catalog.json {
|
| 339 |
+
root /app/hf-space-pipeline/.build;
|
| 340 |
+
default_type application/json;
|
| 341 |
+
add_header Cache-Control "no-cache" always;
|
| 342 |
+
}
|
| 343 |
+
location ^~ /library_media/hf-robotiq/ {
|
| 344 |
+
rewrite ^/library_media/hf-robotiq/(.*)$ /library_media/usdsearch-dev/$1 last;
|
| 345 |
+
}
|
| 346 |
+
location ^~ /library_media/hf-standardbots/ {
|
| 347 |
+
rewrite ^/library_media/hf-standardbots/(.*)$ /library_media/usdsearch-dev/$1 last;
|
| 348 |
+
}
|
| 349 |
+
location /library_media/ {
|
| 350 |
+
root /app/hf-space-pipeline/.build; # .build/library_media/: outside .build/restore/, which the index restore empties
|
| 351 |
+
try_files $uri @slim_not_found;
|
| 352 |
+
types { application/json json; model/gltf-binary glb; video/mp4 mp4; image/jpeg jpg; image/webp webp; }
|
| 353 |
+
default_type application/octet-stream;
|
| 354 |
+
gzip_types application/json model/gltf-binary; # meshopt GLBs still shrink under gzip
|
| 355 |
+
add_header Cache-Control $slim_library_cache always;
|
| 356 |
+
add_header X-Content-Type-Options nosniff always;
|
| 357 |
+
add_header Access-Control-Allow-Origin "*" always;
|
| 358 |
+
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
|
| 359 |
+
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
|
| 360 |
+
}
|
| 361 |
+
# Central's per-user surface is absent in this build: hard 404s, never the SPA's index.html.
|
| 362 |
+
location ~ ^/(auth|packs|prefs|chats|created_assets|concept_images|meshy_quota|info|process|folder_hierarchy\.json|category_hierarchy\.json|api/create-chat|api/cad2simready)(/|$) {
|
| 363 |
+
default_type application/json;
|
| 364 |
+
return 404 '{"detail":"Not Found"}';
|
| 365 |
+
}
|
| 366 |
+
# <<< simready-central slim explorer <<<
|
| 367 |
+
location / {
|
| 368 |
+
root /usr/share/nginx/explorer;
|
| 369 |
+
try_files $uri $uri/ /index.html;
|
| 370 |
+
}
|
| 371 |
+
}
|
docker/hf-space/supervisord-gpu.conf
CHANGED
|
@@ -136,6 +136,8 @@ stderr_logfile=/dev/stderr
|
|
| 136 |
stderr_logfile_maxbytes=0
|
| 137 |
|
| 138 |
[program:native-usd]
|
|
|
|
|
|
|
| 139 |
command=/usr/bin/env -u PYTHONPATH /bin/sh -c "cd /app/hf-space-pipeline && exec /app/.venv/bin/python -m pipeline.native_usd"
|
| 140 |
directory=/app/hf-space-pipeline
|
| 141 |
user=1000
|
|
|
|
| 136 |
stderr_logfile_maxbytes=0
|
| 137 |
|
| 138 |
[program:native-usd]
|
| 139 |
+
; User stopped the production USD experiment. Preserve artifacts for later.
|
| 140 |
+
autostart=false
|
| 141 |
command=/usr/bin/env -u PYTHONPATH /bin/sh -c "cd /app/hf-space-pipeline && exec /app/.venv/bin/python -m pipeline.native_usd"
|
| 142 |
directory=/app/hf-space-pipeline
|
| 143 |
user=1000
|
pipeline/native_usd_releases/production-glb-catalog.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|