Spaces:
Running on RTX PRO 6000
Running on RTX PRO 6000
Deploy simready-assets run 20261020-a3cb7f2 (GPU variant)
Browse files- Dockerfile +14 -11
- README.md +2 -2
- docker/hf-space/nginx.conf.template +46 -19
- docker/hf-space/supervisord-gpu.conf +40 -12
- docker/hf-space/supervisord.conf +11 -5
- services/explorer/dist/static/css/main.ed151f6a.css +0 -0
- services/explorer/dist/static/js/main.01872f5b.js +0 -0
- services/explorer/dist/static/js/main.01872f5b.js.LICENSE.txt +0 -39
- services/explorer/dist/static/js/main.0ed32d3d.js +0 -0
- services/explorer/dist/static/js/main.0ed32d3d.js.LICENSE.txt +0 -39
Dockerfile
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
# deploy:
|
| 2 |
# GPU variant of the single-container MVP image for Hugging Face Spaces
|
| 3 |
# (Docker SDK): everything docker/Dockerfile.hf-space has (OpenSearch + Neo4j
|
| 4 |
# + Redis + deepsearch-api + asset-graph-service + nginx under supervisord),
|
|
@@ -349,12 +349,12 @@ ENV HF_STORAGE_API_TOKEN= \
|
|
| 349 |
ASSERT_ADMIN_USER=false \
|
| 350 |
USDSEARCH_VISION_VALIDATION_ENABLED=false \
|
| 351 |
USDSEARCH_LLM_PARSING_ENABLED=false \
|
| 352 |
-
# Validation limits are per deepsearch-api
|
| 353 |
-
# each of the
|
| 354 |
-
# at most 16 at once
|
| 355 |
-
# the endpoint, with 16 ~1.5 s (2026-10-15 benchmark on the endpoint's own vLLM args).
|
| 356 |
USDSEARCH_VISION_VALIDATION_MAX_CONCURRENT=16 \
|
| 357 |
-
USDSEARCH_VISION_VALIDATION_CACHE_SIZE=
|
| 358 |
USDSEARCH_LLM_PARSING_FIELDS_FILEPATH=/app/search_fields.yaml \
|
| 359 |
USDSEARCH_LLM_PARSING_PROMPT_FILEPATH=/app/llm_parse_prompt.txt \
|
| 360 |
# Business telemetry — same as docker/Dockerfile.hf-space, see its comment.
|
|
@@ -384,11 +384,14 @@ ENV HF_STORAGE_API_TOKEN= \
|
|
| 384 |
SIGLIP2_TRITON_SERVER_URL=localhost:8001 \
|
| 385 |
TRITON_SERVER_URL=localhost:8001 \
|
| 386 |
SIGLIP2_TRITON_SERVER_SSL=false \
|
| 387 |
-
# deepsearch-api
|
| 388 |
-
#
|
| 389 |
-
# (
|
| 390 |
-
#
|
| 391 |
-
|
|
|
|
|
|
|
|
|
|
| 392 |
PORT=7860
|
| 393 |
|
| 394 |
ARG RUN_ID
|
|
|
|
| 1 |
+
# deploy: 20261020-a3cb7f2 (simready-assets)
|
| 2 |
# GPU variant of the single-container MVP image for Hugging Face Spaces
|
| 3 |
# (Docker SDK): everything docker/Dockerfile.hf-space has (OpenSearch + Neo4j
|
| 4 |
# + Redis + deepsearch-api + asset-graph-service + nginx under supervisord),
|
|
|
|
| 349 |
ASSERT_ADMIN_USER=false \
|
| 350 |
USDSEARCH_VISION_VALIDATION_ENABLED=false \
|
| 351 |
USDSEARCH_LLM_PARSING_ENABLED=false \
|
| 352 |
+
# Validation limits are per deepsearch-api process: 16 checks in flight and an 83k-verdict cache in
|
| 353 |
+
# each of the 6 processes (DEEPSEARCH_API_PROCESSES below), 96 and ~500k in all (Redis keeps every verdict
|
| 354 |
+
# anyway). One search's page runs at most 16 at once (usdsearch's BATCH_CONCURRENCY); with 8, a 50-check
|
| 355 |
+
# page took ~3 s on the endpoint, with 16 ~1.5 s (2026-10-15 benchmark on the endpoint's own vLLM args).
|
| 356 |
USDSEARCH_VISION_VALIDATION_MAX_CONCURRENT=16 \
|
| 357 |
+
USDSEARCH_VISION_VALIDATION_CACHE_SIZE=83333 \
|
| 358 |
USDSEARCH_LLM_PARSING_FIELDS_FILEPATH=/app/search_fields.yaml \
|
| 359 |
USDSEARCH_LLM_PARSING_PROMPT_FILEPATH=/app/llm_parse_prompt.txt \
|
| 360 |
# Business telemetry — same as docker/Dockerfile.hf-space, see its comment.
|
|
|
|
| 384 |
SIGLIP2_TRITON_SERVER_URL=localhost:8001 \
|
| 385 |
TRITON_SERVER_URL=localhost:8001 \
|
| 386 |
SIGLIP2_TRITON_SERVER_SSL=false \
|
| 387 |
+
# deepsearch-api processes, ONE uvicorn worker each, behind nginx's least_conn
|
| 388 |
+
# upstream (supervisord-gpu.conf, nginx.conf.template). 6 for a10g-large
|
| 389 |
+
# (12 vCPU / 46 GB): 6, 8 and 12 carried the same load in the lab (docs/
|
| 390 |
+
# search-performance.md), 6 costs the least memory. Must equal supervisord-gpu.conf's
|
| 391 |
+
# numprocs: nginx renders its upstream from this, so never set it as a Space
|
| 392 |
+
# Variable. DEEPSEARCH_API_WORKERS is no longer read (a leftover Space Variable
|
| 393 |
+
# of that name does nothing).
|
| 394 |
+
DEEPSEARCH_API_PROCESSES=6 \
|
| 395 |
PORT=7860
|
| 396 |
|
| 397 |
ARG RUN_ID
|
README.md
CHANGED
|
@@ -5,7 +5,7 @@ colorFrom: green
|
|
| 5 |
colorTo: blue
|
| 6 |
sdk: docker
|
| 7 |
app_port: 7860
|
| 8 |
-
hardware:
|
| 9 |
---
|
| 10 |
|
| 11 |
# SimReady Central USD Search
|
|
@@ -13,7 +13,7 @@ hardware: t4-medium
|
|
| 13 |
SimReady Central USD Search — single-container demo (OpenSearch + Neo4j +
|
| 14 |
Redis + deepsearch-api + asset-graph-service, SigLIP2 embeddings via a local
|
| 15 |
siglip2-triton process — see docker/Dockerfile.hf-space-gpu). Runs on a GPU
|
| 16 |
-
hardware tier (
|
| 17 |
docker/Dockerfile.hf-space variant, which routes SigLIP2 to NVCF instead.
|
| 18 |
The index itself is pulled from the artifact S3 bucket at container
|
| 19 |
startup, not baked in. Deployed by
|
|
|
|
| 5 |
colorTo: blue
|
| 6 |
sdk: docker
|
| 7 |
app_port: 7860
|
| 8 |
+
hardware: a10g-large
|
| 9 |
---
|
| 10 |
|
| 11 |
# SimReady Central USD Search
|
|
|
|
| 13 |
SimReady Central USD Search — single-container demo (OpenSearch + Neo4j +
|
| 14 |
Redis + deepsearch-api + asset-graph-service, SigLIP2 embeddings via a local
|
| 15 |
siglip2-triton process — see docker/Dockerfile.hf-space-gpu). Runs on a GPU
|
| 16 |
+
hardware tier (a10g-large), unlike the free-tier
|
| 17 |
docker/Dockerfile.hf-space variant, which routes SigLIP2 to NVCF instead.
|
| 18 |
The index itself is pulled from the artifact S3 bucket at container
|
| 19 |
startup, not baked in. Deployed by
|
docker/hf-space/nginx.conf.template
CHANGED
|
@@ -1,10 +1,11 @@
|
|
| 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
|
| 5 |
-
#
|
| 6 |
-
#
|
| 7 |
-
#
|
|
|
|
| 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
|
|
@@ -103,6 +104,14 @@ map $http_accept_encoding $slim_accepts_br {
|
|
| 103 |
"~*(^|,)\s*br\s*(;|,|$)" 1;
|
| 104 |
}
|
| 105 |
# <<< simready-central slim explorer (http) <<<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
server {
|
| 107 |
listen __PORT__;
|
| 108 |
|
|
@@ -123,25 +132,25 @@ server {
|
|
| 123 |
location /search {
|
| 124 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 125 |
rewrite ^/search(.*)$ /v2/deepsearch/search$1 break;
|
| 126 |
-
proxy_pass http://
|
| 127 |
}
|
| 128 |
|
| 129 |
location /search_hybrid {
|
| 130 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 131 |
rewrite ^/search_hybrid(.*)$ /v3/deepsearch/search$1 break;
|
| 132 |
-
proxy_pass http://
|
| 133 |
}
|
| 134 |
|
| 135 |
location /vlm_validate/search_result {
|
| 136 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 137 |
rewrite ^/vlm_validate/search_result(.*)$ /v3/deepsearch/vlm_validate/search_result$1 break;
|
| 138 |
-
proxy_pass http://
|
| 139 |
}
|
| 140 |
|
| 141 |
location /llm_parse/ {
|
| 142 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 143 |
rewrite ^/llm_parse/(.*)$ /v3/deepsearch/llm_parse/$1 break;
|
| 144 |
-
proxy_pass http://
|
| 145 |
}
|
| 146 |
|
| 147 |
# package-download (127.0.0.1:8020, pipeline/package_download/), not deepsearch-api: it answers
|
|
@@ -187,7 +196,7 @@ server {
|
|
| 187 |
location /images {
|
| 188 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 189 |
rewrite ^/images(.*)$ /v3/images$1 break;
|
| 190 |
-
proxy_pass http://
|
| 191 |
}
|
| 192 |
|
| 193 |
location /static/ {
|
|
@@ -227,8 +236,8 @@ server {
|
|
| 227 |
# below serves the Explorer SPA instead of proxying everything
|
| 228 |
# unmatched. /docs and /redoc are prefix matches, not exact: Swagger
|
| 229 |
# UI/ReDoc can request sub-resources under their own path.
|
| 230 |
-
location = /health { proxy_pass http://
|
| 231 |
-
location = /openapi.json { proxy_pass http://
|
| 232 |
# /metrics is NOT deepsearch-api's (127.0.0.1:8000/metrics stays private to
|
| 233 |
# the container): it is pipeline/cache_metrics.py's page, an allow-list of
|
| 234 |
# cache hit/miss counters (supervisord program cache-metrics). Not up yet:
|
|
@@ -241,8 +250,8 @@ server {
|
|
| 241 |
default_type application/json;
|
| 242 |
return 503 '{"detail":"cache metrics are not running"}';
|
| 243 |
}
|
| 244 |
-
location /docs { proxy_pass http://
|
| 245 |
-
location /redoc { proxy_pass http://
|
| 246 |
|
| 247 |
# The Explorer SPA (see header comment) at root: try_files serves any of
|
| 248 |
# its own literal files (index.html, ds.png, favicon.ico, manifest.json,
|
|
@@ -389,7 +398,7 @@ server {
|
|
| 389 |
location = /search/stats/usd_properties {
|
| 390 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 391 |
rewrite ^/search(.*)$ /v2/deepsearch/search$1 break;
|
| 392 |
-
proxy_pass http://
|
| 393 |
proxy_ignore_headers Cache-Control Expires;
|
| 394 |
proxy_cache slim_stats_cache;
|
| 395 |
proxy_cache_key "$request_uri";
|
|
@@ -415,7 +424,7 @@ server {
|
|
| 415 |
location = /images {
|
| 416 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 417 |
rewrite ^/images(.*)$ /v3/images$1 break;
|
| 418 |
-
proxy_pass http://
|
| 419 |
proxy_cache slim_images_cache;
|
| 420 |
proxy_cache_key "$request_uri";
|
| 421 |
proxy_ignore_headers Cache-Control Expires;
|
|
@@ -446,7 +455,7 @@ server {
|
|
| 446 |
location = /llm_parse/query {
|
| 447 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 448 |
rewrite ^/llm_parse/(.*)$ /v3/deepsearch/llm_parse/$1 break;
|
| 449 |
-
proxy_pass http://
|
| 450 |
proxy_cache slim_parse_cache;
|
| 451 |
proxy_cache_key "$slim_today|$request_uri|$request_body";
|
| 452 |
proxy_cache_bypass $slim_not_post $request_body_file;
|
|
@@ -473,7 +482,7 @@ server {
|
|
| 473 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 474 |
if ($slim_count_probe) { rewrite ^ /_slim_count_probe last; }
|
| 475 |
rewrite ^/search_hybrid(.*)$ /v3/deepsearch/search$1 break;
|
| 476 |
-
proxy_pass http://
|
| 477 |
}
|
| 478 |
# The Explorer's background count probes (limit-1 and file-name searches for its totals; SimReady Central's
|
| 479 |
# gateway caches them the same way): their own zone, 30 min, stale while one request refreshes an entry. Never a
|
|
@@ -481,7 +490,7 @@ server {
|
|
| 481 |
location = /_slim_count_probe {
|
| 482 |
internal;
|
| 483 |
rewrite ^ /v3/deepsearch/search break;
|
| 484 |
-
proxy_pass http://
|
| 485 |
proxy_cache slim_count_cache;
|
| 486 |
proxy_cache_key "$request_uri|$request_body";
|
| 487 |
proxy_cache_bypass $slim_not_post $request_body_file $slim_probe_skip;
|
|
@@ -533,7 +542,7 @@ server {
|
|
| 533 |
location = /vlm_validate/batch_stream {
|
| 534 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 535 |
rewrite ^ /v3/deepsearch/vlm_validate/search_result_batch break;
|
| 536 |
-
proxy_pass http://
|
| 537 |
proxy_buffering off;
|
| 538 |
proxy_read_timeout 120s;
|
| 539 |
gzip off;
|
|
@@ -616,3 +625,21 @@ server {
|
|
| 616 |
try_files $uri $uri/ /index.html;
|
| 617 |
}
|
| 618 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 runs as single-worker processes on 127.0.0.1:8101, 8102, ...
|
| 5 |
+
# (the `deepsearch` upstream below; how many: DEEPSEARCH_API_PROCESSES, see
|
| 6 |
+
# docker/hf-space/supervisord-gpu.conf), asset-graph-service on
|
| 7 |
+
# 127.0.0.1:8010 — nginx is the sole process bound to the externally proxied
|
| 8 |
+
# port, so it can front every route with these rewrites plus CORS.
|
| 9 |
#
|
| 10 |
# The Explorer UI is served at `/` (root), not proxied to deepsearch-api at
|
| 11 |
# all — served directly from the static bundle baked into this image at
|
|
|
|
| 104 |
"~*(^|,)\s*br\s*(;|,|$)" 1;
|
| 105 |
}
|
| 106 |
# <<< simready-central slim explorer (http) <<<
|
| 107 |
+
# deepsearch-api's processes, one uvicorn worker each. least_conn, not `uvicorn --workers N`: with N workers on one
|
| 108 |
+
# socket the kernel hands nearly every connection to 2-3 of them, and the rest of the CPU sits idle (lab load test
|
| 109 |
+
# 2026-10-15, docs/search-performance.md). __DEEPSEARCH_API_SERVERS__ is rendered at container start from
|
| 110 |
+
# DEEPSEARCH_API_PROCESSES (the nginx program in supervisord*.conf).
|
| 111 |
+
upstream deepsearch {
|
| 112 |
+
least_conn;
|
| 113 |
+
__DEEPSEARCH_API_SERVERS__
|
| 114 |
+
}
|
| 115 |
server {
|
| 116 |
listen __PORT__;
|
| 117 |
|
|
|
|
| 132 |
location /search {
|
| 133 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 134 |
rewrite ^/search(.*)$ /v2/deepsearch/search$1 break;
|
| 135 |
+
proxy_pass http://deepsearch;
|
| 136 |
}
|
| 137 |
|
| 138 |
location /search_hybrid {
|
| 139 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 140 |
rewrite ^/search_hybrid(.*)$ /v3/deepsearch/search$1 break;
|
| 141 |
+
proxy_pass http://deepsearch;
|
| 142 |
}
|
| 143 |
|
| 144 |
location /vlm_validate/search_result {
|
| 145 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 146 |
rewrite ^/vlm_validate/search_result(.*)$ /v3/deepsearch/vlm_validate/search_result$1 break;
|
| 147 |
+
proxy_pass http://deepsearch;
|
| 148 |
}
|
| 149 |
|
| 150 |
location /llm_parse/ {
|
| 151 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 152 |
rewrite ^/llm_parse/(.*)$ /v3/deepsearch/llm_parse/$1 break;
|
| 153 |
+
proxy_pass http://deepsearch;
|
| 154 |
}
|
| 155 |
|
| 156 |
# package-download (127.0.0.1:8020, pipeline/package_download/), not deepsearch-api: it answers
|
|
|
|
| 196 |
location /images {
|
| 197 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 198 |
rewrite ^/images(.*)$ /v3/images$1 break;
|
| 199 |
+
proxy_pass http://deepsearch;
|
| 200 |
}
|
| 201 |
|
| 202 |
location /static/ {
|
|
|
|
| 236 |
# below serves the Explorer SPA instead of proxying everything
|
| 237 |
# unmatched. /docs and /redoc are prefix matches, not exact: Swagger
|
| 238 |
# UI/ReDoc can request sub-resources under their own path.
|
| 239 |
+
location = /health { proxy_pass http://deepsearch; }
|
| 240 |
+
location = /openapi.json { proxy_pass http://deepsearch; }
|
| 241 |
# /metrics is NOT deepsearch-api's (127.0.0.1:8000/metrics stays private to
|
| 242 |
# the container): it is pipeline/cache_metrics.py's page, an allow-list of
|
| 243 |
# cache hit/miss counters (supervisord program cache-metrics). Not up yet:
|
|
|
|
| 250 |
default_type application/json;
|
| 251 |
return 503 '{"detail":"cache metrics are not running"}';
|
| 252 |
}
|
| 253 |
+
location /docs { proxy_pass http://deepsearch; }
|
| 254 |
+
location /redoc { proxy_pass http://deepsearch; }
|
| 255 |
|
| 256 |
# The Explorer SPA (see header comment) at root: try_files serves any of
|
| 257 |
# its own literal files (index.html, ds.png, favicon.ico, manifest.json,
|
|
|
|
| 398 |
location = /search/stats/usd_properties {
|
| 399 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 400 |
rewrite ^/search(.*)$ /v2/deepsearch/search$1 break;
|
| 401 |
+
proxy_pass http://deepsearch;
|
| 402 |
proxy_ignore_headers Cache-Control Expires;
|
| 403 |
proxy_cache slim_stats_cache;
|
| 404 |
proxy_cache_key "$request_uri";
|
|
|
|
| 424 |
location = /images {
|
| 425 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 426 |
rewrite ^/images(.*)$ /v3/images$1 break;
|
| 427 |
+
proxy_pass http://deepsearch;
|
| 428 |
proxy_cache slim_images_cache;
|
| 429 |
proxy_cache_key "$request_uri";
|
| 430 |
proxy_ignore_headers Cache-Control Expires;
|
|
|
|
| 455 |
location = /llm_parse/query {
|
| 456 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 457 |
rewrite ^/llm_parse/(.*)$ /v3/deepsearch/llm_parse/$1 break;
|
| 458 |
+
proxy_pass http://deepsearch;
|
| 459 |
proxy_cache slim_parse_cache;
|
| 460 |
proxy_cache_key "$slim_today|$request_uri|$request_body";
|
| 461 |
proxy_cache_bypass $slim_not_post $request_body_file;
|
|
|
|
| 482 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 483 |
if ($slim_count_probe) { rewrite ^ /_slim_count_probe last; }
|
| 484 |
rewrite ^/search_hybrid(.*)$ /v3/deepsearch/search$1 break;
|
| 485 |
+
proxy_pass http://deepsearch;
|
| 486 |
}
|
| 487 |
# The Explorer's background count probes (limit-1 and file-name searches for its totals; SimReady Central's
|
| 488 |
# gateway caches them the same way): their own zone, 30 min, stale while one request refreshes an entry. Never a
|
|
|
|
| 490 |
location = /_slim_count_probe {
|
| 491 |
internal;
|
| 492 |
rewrite ^ /v3/deepsearch/search break;
|
| 493 |
+
proxy_pass http://deepsearch;
|
| 494 |
proxy_cache slim_count_cache;
|
| 495 |
proxy_cache_key "$request_uri|$request_body";
|
| 496 |
proxy_cache_bypass $slim_not_post $request_body_file $slim_probe_skip;
|
|
|
|
| 542 |
location = /vlm_validate/batch_stream {
|
| 543 |
if ($request_method = OPTIONS) { add_header Content-Length 0 always; add_header Content-Type "text/plain" always; return 204; }
|
| 544 |
rewrite ^ /v3/deepsearch/vlm_validate/search_result_batch break;
|
| 545 |
+
proxy_pass http://deepsearch;
|
| 546 |
proxy_buffering off;
|
| 547 |
proxy_read_timeout 120s;
|
| 548 |
gzip off;
|
|
|
|
| 625 |
try_files $uri $uri/ /index.html;
|
| 626 |
}
|
| 627 |
}
|
| 628 |
+
# The API's old address, for the in-container callers that use it directly (package-download's fallback to the
|
| 629 |
+
# API's own /v3/download, its size and spell-vocab passes): spread over the same processes. Loopback only.
|
| 630 |
+
server {
|
| 631 |
+
listen 127.0.0.1:8000;
|
| 632 |
+
access_log off;
|
| 633 |
+
client_max_body_size 0;
|
| 634 |
+
proxy_http_version 1.1;
|
| 635 |
+
proxy_set_header Connection "";
|
| 636 |
+
proxy_set_header Host $host;
|
| 637 |
+
proxy_buffering off;
|
| 638 |
+
proxy_request_buffering off;
|
| 639 |
+
proxy_connect_timeout 5s;
|
| 640 |
+
proxy_send_timeout 600s;
|
| 641 |
+
proxy_read_timeout 600s;
|
| 642 |
+
location / {
|
| 643 |
+
proxy_pass http://deepsearch;
|
| 644 |
+
}
|
| 645 |
+
}
|
docker/hf-space/supervisord-gpu.conf
CHANGED
|
@@ -159,19 +159,45 @@ stdout_logfile_maxbytes=0
|
|
| 159 |
stderr_logfile=/dev/stderr
|
| 160 |
stderr_logfile_maxbytes=0
|
| 161 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
[program:deepsearch-api]
|
| 163 |
-
;
|
| 164 |
-
;
|
| 165 |
-
;
|
| 166 |
-
;
|
| 167 |
-
;
|
| 168 |
-
;
|
| 169 |
-
;
|
| 170 |
-
; [program:
|
| 171 |
; USDSEARCH_LLM_PARSING_CACHE_SIZE 0 (a Space variable overrides it): no
|
| 172 |
-
; per-
|
| 173 |
; "made last week" with yesterday's parse; nginx caches parses per day instead.
|
| 174 |
-
|
|
|
|
|
|
|
|
|
|
| 175 |
directory=/app
|
| 176 |
user=1000
|
| 177 |
autorestart=true
|
|
@@ -200,10 +226,12 @@ stderr_logfile=/dev/stderr
|
|
| 200 |
stderr_logfile_maxbytes=0
|
| 201 |
|
| 202 |
[program:nginx]
|
| 203 |
-
; See docker/hf-space/supervisord.conf's own copy (identical command)
|
|
|
|
|
|
|
| 204 |
; a space before a ";" or "#" in a command: supervisord reads it as an inline
|
| 205 |
; comment and cuts the command there (2026-10-15: nginx FATAL on prod).
|
| 206 |
-
command=/bin/sh -c "until curl -sf http://localhost:
|
| 207 |
user=root
|
| 208 |
autorestart=true
|
| 209 |
startsecs=3
|
|
|
|
| 159 |
stderr_logfile=/dev/stderr
|
| 160 |
stderr_logfile_maxbytes=0
|
| 161 |
|
| 162 |
+
[program:deepsearch-seed]
|
| 163 |
+
; Runs once per container start, before any deepsearch-api process: waits on
|
| 164 |
+
; siglip2-triton's own readiness (via its remapped HTTP port, 8003 — see
|
| 165 |
+
; [program:siglip2-triton] above), runs pipeline/hf_space_seed.py, then
|
| 166 |
+
; empties PROMETHEUS_MULTIPROC_DIR, where the processes share their metrics
|
| 167 |
+
; (a counter is the sum over all of them; [program:cache-metrics] reads its
|
| 168 |
+
; cache counters there), and leaves /tmp/deepsearch-seed.done for them. Not
|
| 169 |
+
; in deepsearch-api's own command: each of its processes would wipe the
|
| 170 |
+
; directory the others write to.
|
| 171 |
+
command=/usr/bin/env -u PYTHONPATH /bin/sh -c "rm -f /tmp/deepsearch-seed.done && until curl -sf http://localhost:8003/v2/health/ready >/dev/null 2>&1; do sleep 2; done; cd /app/hf-space-pipeline && /app/.venv/bin/python -m pipeline.hf_space_seed && rm -rf /tmp/deepsearch-api-prometheus && mkdir -p /tmp/deepsearch-api-prometheus && touch /tmp/deepsearch-seed.done"
|
| 172 |
+
directory=/app
|
| 173 |
+
user=1000
|
| 174 |
+
autorestart=unexpected
|
| 175 |
+
exitcodes=0
|
| 176 |
+
startsecs=0
|
| 177 |
+
; Started before the API processes (lower priority), which also wait 3 s before looking for
|
| 178 |
+
; the marker: a /tmp kept across a container restart can't let them skip this run's seed.
|
| 179 |
+
priority=10
|
| 180 |
+
stdout_logfile=/dev/stdout
|
| 181 |
+
stdout_logfile_maxbytes=0
|
| 182 |
+
stderr_logfile=/dev/stderr
|
| 183 |
+
stderr_logfile_maxbytes=0
|
| 184 |
+
|
| 185 |
[program:deepsearch-api]
|
| 186 |
+
; 6 processes with ONE uvicorn worker each, on 127.0.0.1:8101-8106, behind
|
| 187 |
+
; nginx's least_conn upstream (nginx.conf.template). Not `uvicorn --workers 6`:
|
| 188 |
+
; there the kernel hands nearly every connection to 2-3 workers and most of
|
| 189 |
+
; the CPU idles (docs/search-performance.md). numprocs is read from
|
| 190 |
+
; DEEPSEARCH_API_PROCESSES (Dockerfile.hf-space-gpu), the same value nginx renders its
|
| 191 |
+
; upstream from, so the two can't differ (a Space Variable changes both). Supervisord
|
| 192 |
+
; restarts one process that dies without touching the others. Each waits for
|
| 193 |
+
; [program:deepsearch-seed].
|
| 194 |
; USDSEARCH_LLM_PARSING_CACHE_SIZE 0 (a Space variable overrides it): no
|
| 195 |
+
; per-process parse LRU. Its key has no date, so after midnight it answered
|
| 196 |
; "made last week" with yesterday's parse; nginx caches parses per day instead.
|
| 197 |
+
process_name=%(program_name)s_%(process_num)02d
|
| 198 |
+
numprocs=%(ENV_DEEPSEARCH_API_PROCESSES)s
|
| 199 |
+
numprocs_start=1
|
| 200 |
+
command=/usr/bin/env -u PYTHONPATH /bin/sh -c "sleep 3; until [ -f /tmp/deepsearch-seed.done ]; do sleep 2; done; cd /app && exec env PROMETHEUS_MULTIPROC_DIR=/tmp/deepsearch-api-prometheus USDSEARCH_LLM_PARSING_CACHE_SIZE=\"${USDSEARCH_LLM_PARSING_CACHE_SIZE:-0}\" /app/.venv/bin/python -m uvicorn deepsearch_api.main:app --host 127.0.0.1 --port 81%(process_num)02d --workers 1"
|
| 201 |
directory=/app
|
| 202 |
user=1000
|
| 203 |
autorestart=true
|
|
|
|
| 226 |
stderr_logfile_maxbytes=0
|
| 227 |
|
| 228 |
[program:nginx]
|
| 229 |
+
; See docker/hf-space/supervisord.conf's own copy (identical command): it waits
|
| 230 |
+
; for all DEEPSEARCH_API_PROCESSES API processes (after ~90 s, for at least one: nginx's
|
| 231 |
+
; upstream skips a process that doesn't answer) and renders the upstream from the same list. Never put
|
| 232 |
; a space before a ";" or "#" in a command: supervisord reads it as an inline
|
| 233 |
; comment and cuts the command there (2026-10-15: nginx FATAL on prod).
|
| 234 |
+
command=/bin/sh -c "n=${DEEPSEARCH_API_PROCESSES:-1}; ports=; ups=; i=1; while [ $i -le $n ]; do ports=\"$ports $((8100+i))\"; ups=\"$ups server 127.0.0.1:$((8100+i));\"; i=$((i+1)); done; t=0; until curl -sf http://localhost:8010/docs >/dev/null 2>&1 && { (for p in $ports; do curl -sf http://localhost:$p/health >/dev/null 2>&1 || exit 1; done) || { [ $t -ge 90 ] && (for p in $ports; do curl -sf http://localhost:$p/health >/dev/null 2>&1 && exit 0; done; exit 1); }; }; do sleep 2; t=$((t+2)); done; dl=false; case '%(ENV_DOWNLOAD_ENABLED)s' in [Tt]rue|1) if [ -f /app/hf-space-pipeline/.build/restore/hf-storage-api-catalog.yaml ]; then dl=true; else echo 'nginx: no hf-storage-api catalog, rendering download:false' >&2; fi;; esac; vf=glb; case $VIEWER_FORMAT in glb|usd|auto) vf=$VIEWER_FORMAT;; *) [ -z \"$VIEWER_FORMAT\" ] || echo 'nginx: VIEWER_FORMAT is not glb, usd or auto: rendering viewerFormat glb' >&2;; esac; sed -e 's/__PORT__/%(ENV_PORT)s/' -e 's|__CORPUS_NAME__|%(ENV_CORPUS_NAME)s|g' -e 's/__DOWNLOAD_ENABLED__/'$dl'/' -e 's|__SUBMIT_CONTENT_URL__|%(ENV_SUBMIT_CONTENT_URL)s|g' -e 's/__VIEWER_FORMAT__/'$vf'/' -e \"s/__DEEPSEARCH_API_SERVERS__/$ups/\" /etc/nginx/hf-space.conf.template > /etc/nginx/conf.d/hf-space.conf && exec nginx -g 'daemon off;'"
|
| 235 |
user=root
|
| 236 |
autorestart=true
|
| 237 |
startsecs=3
|
docker/hf-space/supervisord.conf
CHANGED
|
@@ -171,9 +171,11 @@ stderr_logfile=/dev/stderr
|
|
| 171 |
stderr_logfile_maxbytes=0
|
| 172 |
|
| 173 |
[program:deepsearch-api]
|
| 174 |
-
; Bound to localhost only
|
| 175 |
-
;
|
| 176 |
-
;
|
|
|
|
|
|
|
| 177 |
;
|
| 178 |
; Runs pipeline/hf_space_seed.py first and only execs uvicorn once it
|
| 179 |
; succeeds: that script waits for opensearch (started in parallel by
|
|
@@ -190,7 +192,7 @@ stderr_logfile_maxbytes=0
|
|
| 190 |
; USDSEARCH_LLM_PARSING_CACHE_SIZE 0 (a Space variable overrides it): no
|
| 191 |
; per-worker parse LRU. Its key has no date, so after midnight it answered
|
| 192 |
; "made last week" with yesterday's parse; nginx caches parses per day instead.
|
| 193 |
-
command=/bin/sh -c "cd /app/hf-space-pipeline && /app/.venv/bin/python -m pipeline.hf_space_seed && cd /app && rm -rf /tmp/deepsearch-api-prometheus && mkdir -p /tmp/deepsearch-api-prometheus && exec env PROMETHEUS_MULTIPROC_DIR=/tmp/deepsearch-api-prometheus USDSEARCH_LLM_PARSING_CACHE_SIZE=\"${USDSEARCH_LLM_PARSING_CACHE_SIZE:-0}\" /app/.venv/bin/python -m uvicorn deepsearch_api.main:app --host 127.0.0.1 --port
|
| 194 |
directory=/app
|
| 195 |
user=1000
|
| 196 |
autorestart=true
|
|
@@ -240,11 +242,15 @@ stderr_logfile_maxbytes=0
|
|
| 240 |
; %(ENV_PORT)s is substituted by supervisord itself, so no extra templating
|
| 241 |
; tool (envsubst etc.) is needed in the image.
|
| 242 |
;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 243 |
; Never put a space before a ";" or "#" in a command: supervisord's parser
|
| 244 |
; reads " ;" and " #" as the start of an inline comment and cuts the command
|
| 245 |
; there (2026-10-15: a " ;;" case arm left nginx FATAL, "No closing
|
| 246 |
; quotation"). tests/test_hf_space_runtime.py parses with supervisor itself.
|
| 247 |
-
command=/bin/sh -c "until curl -sf http://localhost:
|
| 248 |
user=root
|
| 249 |
autorestart=true
|
| 250 |
startsecs=3
|
|
|
|
| 171 |
stderr_logfile_maxbytes=0
|
| 172 |
|
| 173 |
[program:deepsearch-api]
|
| 174 |
+
; Bound to localhost only, on 127.0.0.1:8101: the one server of nginx's
|
| 175 |
+
; `deepsearch` upstream in this image (DEEPSEARCH_API_PROCESSES=1; the GPU
|
| 176 |
+
; image runs several, see supervisord-gpu.conf). nginx (below) is the sole
|
| 177 |
+
; process bound to the externally proxied port, so it can front every route
|
| 178 |
+
; with the friendly-URL rewrites and CORS headers in nginx.conf.template.
|
| 179 |
;
|
| 180 |
; Runs pipeline/hf_space_seed.py first and only execs uvicorn once it
|
| 181 |
; succeeds: that script waits for opensearch (started in parallel by
|
|
|
|
| 192 |
; USDSEARCH_LLM_PARSING_CACHE_SIZE 0 (a Space variable overrides it): no
|
| 193 |
; per-worker parse LRU. Its key has no date, so after midnight it answered
|
| 194 |
; "made last week" with yesterday's parse; nginx caches parses per day instead.
|
| 195 |
+
command=/bin/sh -c "cd /app/hf-space-pipeline && /app/.venv/bin/python -m pipeline.hf_space_seed && cd /app && rm -rf /tmp/deepsearch-api-prometheus && mkdir -p /tmp/deepsearch-api-prometheus && exec env PROMETHEUS_MULTIPROC_DIR=/tmp/deepsearch-api-prometheus USDSEARCH_LLM_PARSING_CACHE_SIZE=\"${USDSEARCH_LLM_PARSING_CACHE_SIZE:-0}\" /app/.venv/bin/python -m uvicorn deepsearch_api.main:app --host 127.0.0.1 --port 8101 --workers 1"
|
| 196 |
directory=/app
|
| 197 |
user=1000
|
| 198 |
autorestart=true
|
|
|
|
| 242 |
; %(ENV_PORT)s is substituted by supervisord itself, so no extra templating
|
| 243 |
; tool (envsubst etc.) is needed in the image.
|
| 244 |
;
|
| 245 |
+
; Waits for asset-graph-service and every deepsearch-api process
|
| 246 |
+
; (127.0.0.1:8101 .. 8100+DEEPSEARCH_API_PROCESSES), and renders the
|
| 247 |
+
; template's `deepsearch` upstream from that same list.
|
| 248 |
+
;
|
| 249 |
; Never put a space before a ";" or "#" in a command: supervisord's parser
|
| 250 |
; reads " ;" and " #" as the start of an inline comment and cuts the command
|
| 251 |
; there (2026-10-15: a " ;;" case arm left nginx FATAL, "No closing
|
| 252 |
; quotation"). tests/test_hf_space_runtime.py parses with supervisor itself.
|
| 253 |
+
command=/bin/sh -c "n=${DEEPSEARCH_API_PROCESSES:-1}; ports=; ups=; i=1; while [ $i -le $n ]; do ports=\"$ports $((8100+i))\"; ups=\"$ups server 127.0.0.1:$((8100+i));\"; i=$((i+1)); done; t=0; until curl -sf http://localhost:8010/docs >/dev/null 2>&1 && { (for p in $ports; do curl -sf http://localhost:$p/health >/dev/null 2>&1 || exit 1; done) || { [ $t -ge 90 ] && (for p in $ports; do curl -sf http://localhost:$p/health >/dev/null 2>&1 && exit 0; done; exit 1); }; }; do sleep 2; t=$((t+2)); done; dl=false; case '%(ENV_DOWNLOAD_ENABLED)s' in [Tt]rue|1) if [ -f /app/hf-space-pipeline/.build/restore/hf-storage-api-catalog.yaml ]; then dl=true; else echo 'nginx: no hf-storage-api catalog, rendering download:false' >&2; fi;; esac; vf=glb; case $VIEWER_FORMAT in glb|usd|auto) vf=$VIEWER_FORMAT;; *) [ -z \"$VIEWER_FORMAT\" ] || echo 'nginx: VIEWER_FORMAT is not glb, usd or auto: rendering viewerFormat glb' >&2;; esac; sed -e 's/__PORT__/%(ENV_PORT)s/' -e 's|__CORPUS_NAME__|%(ENV_CORPUS_NAME)s|g' -e 's/__DOWNLOAD_ENABLED__/'$dl'/' -e 's|__SUBMIT_CONTENT_URL__|%(ENV_SUBMIT_CONTENT_URL)s|g' -e 's/__VIEWER_FORMAT__/'$vf'/' -e \"s/__DEEPSEARCH_API_SERVERS__/$ups/\" /etc/nginx/hf-space.conf.template > /etc/nginx/conf.d/hf-space.conf && exec nginx -g 'daemon off;'"
|
| 254 |
user=root
|
| 255 |
autorestart=true
|
| 256 |
startsecs=3
|
services/explorer/dist/static/css/main.ed151f6a.css
DELETED
|
The diff for this file is too large to render.
See raw diff
|
|
|
services/explorer/dist/static/js/main.01872f5b.js
DELETED
|
The diff for this file is too large to render.
See raw diff
|
|
|
services/explorer/dist/static/js/main.01872f5b.js.LICENSE.txt
DELETED
|
@@ -1,39 +0,0 @@
|
|
| 1 |
-
/**
|
| 2 |
-
* @license React
|
| 3 |
-
* react-dom.production.min.js
|
| 4 |
-
*
|
| 5 |
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
| 6 |
-
*
|
| 7 |
-
* This source code is licensed under the MIT license found in the
|
| 8 |
-
* LICENSE file in the root directory of this source tree.
|
| 9 |
-
*/
|
| 10 |
-
|
| 11 |
-
/**
|
| 12 |
-
* @license React
|
| 13 |
-
* react-jsx-runtime.production.min.js
|
| 14 |
-
*
|
| 15 |
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
| 16 |
-
*
|
| 17 |
-
* This source code is licensed under the MIT license found in the
|
| 18 |
-
* LICENSE file in the root directory of this source tree.
|
| 19 |
-
*/
|
| 20 |
-
|
| 21 |
-
/**
|
| 22 |
-
* @license React
|
| 23 |
-
* react.production.min.js
|
| 24 |
-
*
|
| 25 |
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
| 26 |
-
*
|
| 27 |
-
* This source code is licensed under the MIT license found in the
|
| 28 |
-
* LICENSE file in the root directory of this source tree.
|
| 29 |
-
*/
|
| 30 |
-
|
| 31 |
-
/**
|
| 32 |
-
* @license React
|
| 33 |
-
* scheduler.production.min.js
|
| 34 |
-
*
|
| 35 |
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
| 36 |
-
*
|
| 37 |
-
* This source code is licensed under the MIT license found in the
|
| 38 |
-
* LICENSE file in the root directory of this source tree.
|
| 39 |
-
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
services/explorer/dist/static/js/main.0ed32d3d.js
DELETED
|
The diff for this file is too large to render.
See raw diff
|
|
|
services/explorer/dist/static/js/main.0ed32d3d.js.LICENSE.txt
DELETED
|
@@ -1,39 +0,0 @@
|
|
| 1 |
-
/**
|
| 2 |
-
* @license React
|
| 3 |
-
* react-dom.production.min.js
|
| 4 |
-
*
|
| 5 |
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
| 6 |
-
*
|
| 7 |
-
* This source code is licensed under the MIT license found in the
|
| 8 |
-
* LICENSE file in the root directory of this source tree.
|
| 9 |
-
*/
|
| 10 |
-
|
| 11 |
-
/**
|
| 12 |
-
* @license React
|
| 13 |
-
* react-jsx-runtime.production.min.js
|
| 14 |
-
*
|
| 15 |
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
| 16 |
-
*
|
| 17 |
-
* This source code is licensed under the MIT license found in the
|
| 18 |
-
* LICENSE file in the root directory of this source tree.
|
| 19 |
-
*/
|
| 20 |
-
|
| 21 |
-
/**
|
| 22 |
-
* @license React
|
| 23 |
-
* react.production.min.js
|
| 24 |
-
*
|
| 25 |
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
| 26 |
-
*
|
| 27 |
-
* This source code is licensed under the MIT license found in the
|
| 28 |
-
* LICENSE file in the root directory of this source tree.
|
| 29 |
-
*/
|
| 30 |
-
|
| 31 |
-
/**
|
| 32 |
-
* @license React
|
| 33 |
-
* scheduler.production.min.js
|
| 34 |
-
*
|
| 35 |
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
| 36 |
-
*
|
| 37 |
-
* This source code is licensed under the MIT license found in the
|
| 38 |
-
* LICENSE file in the root directory of this source tree.
|
| 39 |
-
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|