Page MenuHomePhabricator

Serve jina-embeddings-v5-text-nano on Lift Wing
Closed, ResolvedPublic

Assigned To
Authored By
OKarakaya-WMF
Tue, Jul 21, 11:15 AM
Referenced Files
F96107056: image.png
Mon, Jul 27, 11:23 AM
F96107043: image.png
Mon, Jul 27, 11:23 AM
F96101504: image.png
Mon, Jul 27, 9:21 AM
F95034828: image.png
Tue, Jul 21, 12:44 PM

Description

Summary

Deploy the Jina Embeddings v5 text nano (retrieval) model as an InferenceService on Lift Wing, served via vLLM in the llm namespace, alongside the existing Qwen3 embeddings service. The model produces 768-dimensional embeddings exposed through a KServe / OpenAI-compatible predict API.

The service is served through the shared embeddings model server (extended for vLLM pooling on the jina-embeddings branch of inference-services) and deployed via the kserve-inference chart, mirroring the existing embeddings / embeddings-staging isvcs.

Technical notes

  • We have recently created an initial implementation on the jina-embeddings branch of inference-services: the embeddings model server (src/models/embeddings/model_server/model.py) has a vLLM pooling code path (VLLM_RUNNER=pooling, POOLING_TYPE=LAST, TRUST_REMOTE_CODE=True, encode(pooling_task="embed")), plus a jina-embeddings docker-compose service and README docs. The implementation confirmed to be working locally for both qwen3 and jina embeddings.
  • Dependency requirement: Jina v5 requires transformers>=5.0.0. The embeddings service requirements.txt already pins transformers==5.0.0 (and kserve==0.16.0); the base image provides vLLM 0.14. Any base-image or dependency bump must preserve transformers>=5.0.0.
  • License risk (potential blocker): the retrieval variant is CC BY-NC 4.0 (non-commercial); the base model is Apache-2.0. WMF commercial-use terms must be confirmed with Legal before a production deploy. to be confirmed
  • Base image risk: the production Blubber image is AMD vLLM 0.14; Jina v5 docs reference newer vLLM. If model load fails on architecture/API mismatch, escalate to a newer amd-vllm base image. The AMD image cannot run on a Mac without an AMD GPU.
  • Deployment follows the existing embeddings pattern in helmfile.d/ml-services/llm/values-ml-serve-eqiad.yaml (image, STORAGE_URI from wmf-ml-models S3, env vars, 1× AMD GPU, 6 CPU / 16Gi, node affinity + mi300x-experiments tolerations).
  • Monitoring is already enabled namespace-wide (monitoring.enabled: true → prometheus scrape on :8080/metrics); the new isvc inherits it, so no new monitoring config is expected.
  • Load testing builds on the existing test/locust/models/embeddings/embeddings_test.py (currently targets /v1/models/qwen3-embedding:predict).
  • Removing qwen3 embeddings is out of scope. We can remove it once Search Team stops using it. It will enable us to be more flexible with the deployments.
  • Check with the team if we need something special for alerting.
  • Requirements Check with the team if we already have a docker image that satisfies the requirements below;

image.png (349×289 px, 19 KB)

Our current images are behind of all dependencies above.

Acceptance criteria

  • jina-embeddings branch of inference-services finalized, service builds and serves locally/on a GPU host, and merged; new embeddings image published by PipelineBot.
  • Model weights uploaded to the wmf-ml-models S3 bucket with a recorded STORAGE_URI/version path.
  • jina-embeddings and jina-embeddings-staging isvc entries added to values-ml-serve-eqiad.yaml, deployed to staging, and reaching Ready.
  • New isvc appears in Prometheus/Grafana Lift Wing dashboards. (as enabled by default)
  • Locust load test added under test/locust/models/embeddings/ targeting the jina endpoint, with a captured latency/RPS baseline.
  • Run locust tests and compare with the qwen3 embeddings results.
  • Production deployment
  • Update documentation: https://wikitech.wikimedia.org/wiki/Machine_Learning/LiftWing/Large_Language_Models

Details

Related Changes in Gerrit:
SubjectAuthorRepoBranchLines +/-
Ozgeoperations/deployment-chartsmaster+6 -4
Ozgemachinelearning/liftwing/inference-servicesmain+2 -81
Ozgeoperations/deployment-chartsmaster+2 -0
Ozgeoperations/deployment-chartsmaster+2 -0
Ozgeoperations/deployment-chartsmaster+1 -1
Ozgemachinelearning/liftwing/inference-servicesmain+7 -0
Ozgeoperations/deployment-chartsmaster+1 -1
Ozgeoperations/deployment-chartsmaster+3 -1
Ozgeoperations/deployment-chartsmaster+1 -1
Ozgemachinelearning/liftwing/inference-servicesmain+73 -2
Ozgemachinelearning/liftwing/inference-servicesmain+35 -98
Ozgeoperations/deployment-chartsmaster+50 -5
Ozgemachinelearning/liftwing/inference-servicesmain+7 -2
Ozgeoperations/deployment-chartsmaster+1 -1
Ozgeoperations/deployment-chartsmaster+4 -22
Ozgemachinelearning/liftwing/inference-servicesmain+1 -1
Hasharintegration/configmaster+1 -0
Ozgeintegration/configmaster+10 -0
Ozgemachinelearning/liftwing/inference-servicesmain+458 -0
Ozgeoperations/deployment-chartsmaster+3 -1
Ozgemachinelearning/liftwing/inference-servicesmain+71 -6
Ozgeoperations/deployment-chartsmaster+2 -2
Ozgeoperations/deployment-chartsmaster+2 -2
Ozgeoperations/deployment-chartsmaster+4 -2
Ozgemachinelearning/liftwing/inference-servicesmain+7 -1
Ozgeoperations/deployment-chartsmaster+1 -3
Ozgeoperations/deployment-chartsmaster+2 -0
Show related patches Customize query in gerrit

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes

Change #1314791 had a related patch set uploaded (by Ozge; author: Ozge):

[operations/deployment-charts@master] ml-services: switch jina-embeddings-staging to Triton flash attention

https://gerrit.wikimedia.org/r/1314791

Change #1314791 merged by Ozge:

[operations/deployment-charts@master] ml-services: switch jina-embeddings-staging to Triton flash attention

https://gerrit.wikimedia.org/r/1314791

this time the server started successfully but the inference is sometimes slow (less than a second to 30 seconds.)
looking into a possible solution.

ozge@deploy1003:/srv/deployment-charts/helmfile.d/ml-services/llm$ kubectl logs -f jina-embeddings-staging-predictor-00006-deployment-56886959hn9v
+ source common_settings.sh
+++ /srv/venv/bin/python -c 'from python.resource_utils import get_cpu_count; print(get_cpu_count())'
++ CPU_COUNT=6
++ echo 'CPU count detected from get_cpu_count: 6'
++ export OMP_NUM_THREADS=6
++ OMP_NUM_THREADS=6
CPU count detected from get_cpu_count: 6
OMP_NUM_THREADS set to: 6
++ echo 'OMP_NUM_THREADS set to: 6'
+ MODEL_SERVER_PATH=model_server/model.py
+ exec /srv/venv/bin/python model_server/model.py
/srv/venv/lib/python3.12/site-packages/torchvision/io/image.py:14: UserWarning: Failed to load image Python extension: 'Could not load this library: /srv/venv/lib/python3.12/site-packages/torchvision/image.so'If you don't plan on using image functionality from `torchvision.io`, you can ignore this warning. Otherwise, there might be something wrong with your environment. Did you have `libjpeg` or `libpng` installed before building `torchvision` from source?
  warn(
INFO:root:Loading vLLM model...
INFO:root:Using vLLM runner=pooling
INFO:root:Using pooler_config seq_pooling_type=LAST
INFO 07-23 12:13:31 [utils.py:278] non-default args: {'served_model_name': 'jina-embedding', 'runner': 'pooling', 'trust_remote_code': True, 'dtype': 'float16', 'max_model_len': 8192, 'enable_prefix_caching': False, 'gpu_memory_utilization': 0.9, 'max_num_batched_tokens': 8192, 'enforce_eager': True, 'pooler_config': PoolerConfig(task=None, pooling_type=None, seq_pooling_type='LAST', tok_pooling_type=None, use_activation=None, dimensions=None, enable_chunked_processing=False, max_embed_len=None, logit_mean=None, logit_sigma=None, logit_bias=None, logit_scale=None, step_tag_id=None, returned_token_ids=None), 'model': '/mnt/models/'}
WARNING 07-23 12:13:31 [envs.py:2057] Unknown vLLM environment variable detected: VLLM_RUNNER
WARNING 07-23 12:13:31 [envs.py:2057] Unknown vLLM environment variable detected: VLLM_USE_TRITON_FLASH_ATTN
[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
INFO 07-23 12:13:44 [model.py:994] Resolved `--convert auto` to `--convert embed`. Pass the value explicitly to silence this message.
INFO 07-23 12:13:44 [model.py:617] Resolved architecture: TransformersEmbeddingModel
WARNING 07-23 12:13:44 [model.py:2090] Casting torch.bfloat16 to torch.float16.
INFO 07-23 12:13:44 [model.py:1752] Using max model len 8192
INFO 07-23 12:13:44 [vllm.py:977] Asynchronous scheduling is disabled.
WARNING 07-23 12:13:44 [vllm.py:1033] Enforce eager set, disabling torch.compile and CUDAGraphs. This is equivalent to setting -cc.mode=none -cc.cudagraph_mode=none
WARNING 07-23 12:13:44 [vllm.py:1058] Inductor compilation was disabled by user settings, optimizations settings that are only active during inductor compilation will be ignored.
INFO 07-23 12:13:44 [kernel.py:270] Final IR op priority after setting platform defaults: IrOpPriorityConfig(rms_norm=['vllm_c', 'native'], fused_add_rms_norm=['vllm_c', 'native'])
INFO 07-23 12:13:44 [vllm.py:1234] Cudagraph is disabled under eager mode
INFO 07-23 12:13:44 [compilation.py:312] Enabled custom fusions: norm_quant, act_quant
[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
WARNING 07-23 12:13:46 [system_utils.py:157] We must use the `spawn` multiprocessing start method. Overriding VLLM_WORKER_MULTIPROC_METHOD to 'spawn'. See https://docs.vllm.ai/en/latest/usage/troubleshooting.html#python-multiprocessing for more information. Reasons: CUDA is initialized
/srv/venv/lib/python3.12/site-packages/torchvision/io/image.py:14: UserWarning: Failed to load image Python extension: 'Could not load this library: /srv/venv/lib/python3.12/site-packages/torchvision/image.so'If you don't plan on using image functionality from `torchvision.io`, you can ignore this warning. Otherwise, there might be something wrong with your environment. Did you have `libjpeg` or `libpng` installed before building `torchvision` from source?
  warn(
(EngineCore pid=124) INFO 07-23 12:13:58 [core.py:112] Initializing a V1 LLM engine (v0.22.1) with config: model='/mnt/models/', speculative_config=None, tokenizer='/mnt/models/', skip_tokenizer_init=False, tokenizer_mode=auto, revision=None, tokenizer_revision=None, trust_remote_code=True, dtype=torch.float16, max_seq_len=8192, download_dir=None, load_format=auto, tensor_parallel_size=1, pipeline_parallel_size=1, data_parallel_size=1, decode_context_parallel_size=1, dcp_comm_backend=ag_rs, disable_custom_all_reduce=False, quantization=None, quantization_config=None, enforce_eager=True, enable_return_routed_experts=False, kv_cache_dtype=auto, device_config=cuda, structured_outputs_config=StructuredOutputsConfig(backend='auto', disable_any_whitespace=False, disable_additional_properties=False, reasoning_parser='', reasoning_parser_plugin='', enable_in_reasoning=False), observability_config=ObservabilityConfig(show_hidden_metrics_for_version=None, otlp_traces_endpoint=None, collect_detailed_traces=None, kv_cache_metrics=False, kv_cache_metrics_sample=0.01, cudagraph_metrics=False, enable_layerwise_nvtx_tracing=False, enable_mfu_metrics=False, enable_mm_processor_stats=False, enable_logging_iteration_details=False), seed=0, served_model_name=jina-embedding, enable_prefix_caching=False, enable_chunked_prefill=False, pooler_config=PoolerConfig(task=None, pooling_type=None, seq_pooling_type='LAST', tok_pooling_type='ALL', use_activation=None, dimensions=None, enable_chunked_processing=False, max_embed_len=None, logit_mean=None, logit_sigma=None, logit_bias=None, logit_scale=None, step_tag_id=None, returned_token_ids=None), compilation_config={'mode': <CompilationMode.NONE: 0>, 'debug_dump_path': None, 'cache_dir': '', 'compile_cache_save_format': 'binary', 'backend': 'inductor', 'custom_ops': ['+sparse_attn_indexer', 'all'], 'ir_enable_torch_wrap': False, 'splitting_ops': [], 'compile_mm_encoder': False, 'cudagraph_mm_encoder': False, 'encoder_cudagraph_token_budgets': [], 'encoder_cudagraph_max_vision_items_per_batch': 0, 'encoder_cudagraph_max_frames_per_batch': None, 'compile_sizes': [], 'compile_ranges_endpoints': [8192], 'inductor_compile_config': {'enable_auto_functionalized_v2': False, 'size_asserts': False, 'alignment_asserts': False, 'scalar_asserts': False, 'combo_kernels': True, 'benchmark_combo_kernel': True}, 'inductor_passes': {}, 'cudagraph_mode': <CUDAGraphMode.NONE: 0>, 'cudagraph_num_of_warmups': 0, 'cudagraph_capture_sizes': [], 'cudagraph_copy_inputs': False, 'cudagraph_specialize_lora': True, 'use_inductor_graph_partition': False, 'pass_config': {'fuse_norm_quant': True, 'fuse_act_quant': True, 'fuse_attn_quant': False, 'enable_sp': False, 'fuse_gemm_comms': False, 'fuse_allreduce_rms': False, 'fuse_rope_kvcache_cat_mla': False, 'fuse_act_padding': False, 'fuse_mla_dual_rms_norm': False, 'fuse_rope_kvcache': False}, 'max_cudagraph_capture_size': 0, 'dynamic_shapes_config': {'type': <DynamicShapesType.BACKED: 'backed'>, 'evaluate_guards': False, 'assume_32_bit_indexing': False}, 'local_cache_dir': None, 'fast_moe_cold_start': True, 'static_all_moe_layers': []}, kernel_config=KernelConfig(ir_op_priority=IrOpPriorityConfig(rms_norm=['vllm_c', 'native'], fused_add_rms_norm=['vllm_c', 'native']), enable_flashinfer_autotune=True, moe_backend='auto', linear_backend='auto')
(EngineCore pid=124) INFO 07-23 12:13:59 [parallel_state.py:1422] world_size=1 rank=0 local_rank=0 distributed_init_method=tcp://10.67.22.31:45469 backend=nccl
[W723 12:13:59.621155399 socket.cpp:207] [c10d] The hostname of the client socket cannot be retrieved. err=-3
(EngineCore pid=124) INFO 07-23 12:13:59 [parallel_state.py:1735] rank 0 in world size 1 is assigned as DP rank 0, PP rank 0, PCP rank 0, TP rank 0, EP rank N/A, EPLB rank N/A
(EngineCore pid=124) INFO 07-23 12:14:00 [gpu_model_runner.py:5037] Starting to load model /mnt/models/...
(EngineCore pid=124) WARNING 07-23 12:14:00 [utils.py:192] TransformersEmbeddingModel has no vLLM implementation, falling back to Transformers implementation. Some features may not be supported and performance may not be optimal.
(EngineCore pid=124) INFO 07-23 12:14:00 [base.py:117] Using Transformers modeling backend.
(EngineCore pid=124) /srv/venv/lib/python3.12/site-packages/transformers/modeling_attn_mask_utils.py:71: FutureWarning: The attention mask API under `transformers.modeling_attn_mask_utils` (`AttentionMaskConverter`) is deprecated and will be removed in Transformers v5.10. Please use the new API in `transformers.masking_utils`.
(EngineCore pid=124)   warnings.warn(DEPRECATION_MESSAGE, FutureWarning)
(EngineCore pid=124) INFO 07-23 12:14:00 [rocm.py:552] Found incompatible backend(s) [TURBOQUANT] with AttentionType.ENCODER_ONLY. Overriding with ROCM_ATTN out of potential backends: ['ROCM_ATTN', 'ROCM_AITER_UNIFIED_ATTN', 'TRITON_ATTN'].
(EngineCore pid=124) WARNING 07-23 12:14:00 [compilation.py:1303] Op 'sparse_attn_indexer' not present in model, enabling with '+sparse_attn_indexer' has no effect
(EngineCore pid=124) INFO 07-23 12:14:00 [weight_utils.py:922] Filesystem type for checkpoints: EXT4. Checkpoint size: 0.39 GiB. Available RAM: 1422.00 GiB.
(EngineCore pid=124) INFO 07-23 12:14:00 [weight_utils.py:945] Auto-prefetch is disabled because the filesystem (EXT4) is not a recognized network FS (NFS/Lustre). If you want to force prefetching, start vLLM with --safetensors-load-strategy=prefetch.
Loading safetensors checkpoint shards:   0% Completed | 0/1 [00:00<?, ?it/s]
Loading safetensors checkpoint shards: 100% Completed | 1/1 [00:00<00:00, 16.39it/s]
(EngineCore pid=124)
(EngineCore pid=124) INFO 07-23 12:14:01 [default_loader.py:397] Loading weights took 0.07 seconds
(EngineCore pid=124) INFO 07-23 12:14:01 [gpu_model_runner.py:5132] Model loading took 0.4 GiB memory and 0.443395 seconds
(EngineCore pid=124) INFO 07-23 12:14:51 [jit_monitor.py:54] Kernel JIT monitor activated — Triton JIT compilations during inference will be logged as warnings.
(EngineCore pid=124) INFO 07-23 12:14:51 [core.py:309] init engine (profile, create kv cache, warmup model) took 49.66 s
(EngineCore pid=124) [transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
(EngineCore pid=124) [transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
(EngineCore pid=124) [transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
(EngineCore pid=124) [transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
(EngineCore pid=124) INFO 07-23 12:14:52 [vllm.py:977] Asynchronous scheduling is disabled.
(EngineCore pid=124) WARNING 07-23 12:14:52 [vllm.py:1033] Enforce eager set, disabling torch.compile and CUDAGraphs. This is equivalent to setting -cc.mode=none -cc.cudagraph_mode=none
(EngineCore pid=124) WARNING 07-23 12:14:52 [vllm.py:1058] Inductor compilation was disabled by user settings, optimizations settings that are only active during inductor compilation will be ignored.
(EngineCore pid=124) INFO 07-23 12:14:52 [kernel.py:270] Final IR op priority after setting platform defaults: IrOpPriorityConfig(rms_norm=['vllm_c', 'native'], fused_add_rms_norm=['vllm_c', 'native'])
(EngineCore pid=124) INFO 07-23 12:14:52 [vllm.py:1234] Cudagraph is disabled under eager mode
(EngineCore pid=124) INFO 07-23 12:14:52 [compilation.py:312] Enabled custom fusions: norm_quant, act_quant
INFO 07-23 12:14:52 [offline.py:41] Supported pooling task: embed
INFO:root:vLLM model loaded successfully!
2026-07-23 12:14:52.759 1 kserve INFO [model_server.py:register_model():406] Registering model: jina-embedding
2026-07-23 12:14:52.760 1 kserve INFO [model_server.py:setup_event_loop():286] Setting max asyncio worker threads as 32
2026-07-23 12:14:52.828 1 kserve INFO [server.py:_register_endpoints():111] OpenAI endpoints not registered
2026-07-23 12:14:52.828 1 kserve INFO [server.py:_register_endpoints():119] Time series endpoints not registered
2026-07-23 12:14:52.828 1 kserve INFO [server.py:start():170] Starting uvicorn with 1 workers
2026-07-23 12:14:52.874 1 uvicorn.error INFO:     Started server process [1]
2026-07-23 12:14:52.874 1 uvicorn.error INFO:     Waiting for application startup.
2026-07-23 12:14:52.876 1 kserve INFO [server.py:start():70] Starting gRPC server with 4 workers
2026-07-23 12:14:52.876 1 kserve INFO [server.py:start():71] Starting gRPC server on [::]:8081
2026-07-23 12:14:52.876 1 uvicorn.error INFO:     Application startup complete.
2026-07-23 12:14:52.876 1 uvicorn.error INFO:     Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
2026-07-23 12:15:06.803 uvicorn.access INFO:     127.0.0.6:33369 1 - "GET /metrics HTTP/1.1" 200 OK
2026-07-23 12:15:06.804 1 kserve.trace kserve.io.metrics: 0.006485939025878906 ['http_status:200', 'http_method:GET', 'time:wall']
2026-07-23 12:15:06.804 1 kserve.trace kserve.io.metrics: 0.006460000000000576 ['http_status:200', 'http_method:GET', 'time:cpu']
2026-07-23 12:15:16.083 uvicorn.access INFO:     127.0.0.6:52617 1 - "GET /metrics HTTP/1.1" 200 OK

jina nano model is based on EuroBert and it falls back to transformers (Resolved architecture: TransformersEmbeddingModel).
jina small is official supported in vllm.

The advantage of jina small is that it's larger than nano and expected to have a better performance.
The disadvantage is that it's not based on EuroBERT but qwen3.

jina small is supported via vllm but jina nano is not supported:

https://github.com/vllm-project/vllm/pull/39575

Therefore, it falls back to transformers.

TransformersEmbeddingModel has no vLLM implementation, falling back to Transformers implementation. Some features may not be supported and performance may not be optimal.

Change #1314822 had a related patch set uploaded (by Ozge; author: Ozge):

[operations/deployment-charts@master] ml-services: switch jina-embeddings-staging to AITER unified attention

https://gerrit.wikimedia.org/r/1314822

Change #1314822 merged by Ozge:

[operations/deployment-charts@master] ml-services: switch jina-embeddings-staging to AITER unified attention

https://gerrit.wikimedia.org/r/1314822

Jino Nano is a EuroBERT based model and it falls back to transformers at server start-up and does not use vllm features.

Logs during the server start-up:

TransformersEmbeddingModel has no vLLM implementation, falling back to Transformers implementation. Some features may not be supported and performance may not be optimal.

As we run it on vllm images, the performance is very slow.
If we want to continue with Jina Nano, we need to change to a transformer based image. However, we should still expect higher latency compared to current production model.

Jina Small is a Qwen3 based model and it supports vllm features ( vllm recipe, git commit ). However, it's based on Qwen3.
I'll confirm Jina Small works well in our infrastructure and then we need to communicate with the teams.
Meanwhile it would be awesome to have a second look to confirm the findings @kevinbazira .

Change #1314849 had a related patch set uploaded (by Ozge; author: Ozge):

[machinelearning/liftwing/inference-services@main] embeddings: Add CPU-only local build and simplify pooling path

https://gerrit.wikimedia.org/r/1314849

Change #1314849 merged by jenkins-bot:

[machinelearning/liftwing/inference-services@main] embeddings: Add CPU-only local build and simplify pooling path

https://gerrit.wikimedia.org/r/1314849

Change #1314864 had a related patch set uploaded (by Ozge; author: Ozge):

[operations/deployment-charts@master] ml-services: give jina-embeddings-staging a longer startup window

https://gerrit.wikimedia.org/r/1314864

Change #1314864 abandoned by Ozge:

[operations/deployment-charts@master] ml-services: give jina-embeddings-staging a longer startup window

Reason:

invalid

https://gerrit.wikimedia.org/r/1314864

Change #1314864 restored by Ozge:

[operations/deployment-charts@master] ml-services: give jina-embeddings-staging a longer startup window

https://gerrit.wikimedia.org/r/1314864

Change #1314864 merged by Ozge:

[operations/deployment-charts@master] ml-services: give jina-embeddings-staging a longer startup window

https://gerrit.wikimedia.org/r/1314864

I've tested with enforce eager = false.
Now the latency is consistent with ~50 miliseconds.
This is better than before although still slower than my local cpu with ~5 miliseconds.

- name: ENFORCE_EAGER
          value: "False"

When I download the nano model, I get modeling_eurobert.py which is the transformers implementation of eurobert. I think this is the reason why we fallback to transformers and not able to use vllm features.

I've downloaded small model as well, and it has qwen3 config file. Therefore, I believe it will be able to use the vllm features. @kevinbazira

Possible next steps:

Continue with Jina Nano

  • Convert jina-nano into a transformer based image.
  • Deploy to staging.
  • Run load tests and compare with the current production model.
  • Last time we have achieved 3X performance boost via switching from transformers to vllm. The difference was larger as we increased the load. With this model, we will need to convert back to transformers. On the other hand, this model is smaller than production.

Switch to Jina Small:

  • Communicate with the teams the possibility of using Jina Small.
  • Jina Small is a larger model than Jina Nano. Therefore, I expect a better accuracy.
  • Jina Small is still a Qwen3 based model which we want to replace.

I'll continue debugging Jina Nano on Monday.

Thank you for the detailed investigation @OKarakaya-WMF! I reproduced jina-nano serving on ml-lab1002 (tested both HF Transformers and vLLM with retrieval model variant). Your conclusions are confirmed:

  • No native vLLM implementation. Nano resolves to TransformersEmbeddingModel and falls back to vLLM's generic Transformers backend. This is expected: nano is EuroBERT-based, and vLLM PR #39575 covers the Qwen3-based jina-small, not nano. None of the vLLM gains from T418976 apply here.
  • Jina Small is natively supported (vLLM recipe exists for MI300X), but it's a different model than what Research team evaluated: 677M params, 1024-dim embeddings, Qwen3-0.6B base. Switching would need a fresh quality eval from Research and has downstream implications for Search (dimension change, index rebuild).

I've shared scripts and results below:

  1. Scripts: F95570413: jina_nano_retrieval_transformers.py and P95142 jina_nano_retrieval_vllm.py
  2. Results:
    1somebody@ml-lab1002:~$
    2somebody@ml-lab1002:~$ ls
    3jina_nano_retrieval_transformers.py jina_nano_retrieval_vllm.py venv
    4somebody@ml-lab1002:~$
    5somebody@ml-lab1002:~$
    6somebody@ml-lab1002:~$
    7somebody@ml-lab1002:~$
    8somebody@ml-lab1002:~$ python3 jina_nano_retrieval_transformers.py
    9Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.
    10config.json: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1.13k/1.13k [00:00<00:00, 3.14MB/s]
    11configuration_jina_embeddings_v5.py: 100%|███████████████████████████████████████████████████████████████████████████████████████████| 137/137 [00:00<00:00, 775kB/s]
    12configuration_eurobert.py: 100%|████████████████████████████████████████████████████████████████████████████████████████████████| 12.1k/12.1k [00:00<00:00, 29.8MB/s]
    13[transformers] A new version of the following files was downloaded from https://huggingface.co/jinaai/jina-embeddings-v5-text-nano:
    14- configuration_eurobert.py
    15. Make sure to double-check they do not contain any added malicious code. To avoid downloading new versions of the code file, you can pin a revision.
    16[transformers] A new version of the following files was downloaded from https://huggingface.co/jinaai/jina-embeddings-v5-text-nano:
    17- configuration_jina_embeddings_v5.py
    18- configuration_eurobert.py
    19. Make sure to double-check they do not contain any added malicious code. To avoid downloading new versions of the code file, you can pin a revision.
    20/srv/venv/lib/python3.12/site-packages/torchvision/io/image.py:14: UserWarning: Failed to load image Python extension: 'Could not load this library: /srv/venv/lib/python3.12/site-packages/torchvision/image.so'If you don't plan on using image functionality from `torchvision.io`, you can ignore this warning. Otherwise, there might be something wrong with your environment. Did you have `libjpeg` or `libpng` installed before building `torchvision` from source?
    21 warn(
    22modeling_jina_embeddings_v5.py: 100%|███████████████████████████████████████████████████████████████████████████████████████████| 4.12k/4.12k [00:00<00:00, 11.6MB/s]
    23modeling_eurobert.py: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████| 48.9k/48.9k [00:00<00:00, 74.3MB/s]
    24[transformers] A new version of the following files was downloaded from https://huggingface.co/jinaai/jina-embeddings-v5-text-nano:
    25- modeling_eurobert.py
    26. Make sure to double-check they do not contain any added malicious code. To avoid downloading new versions of the code file, you can pin a revision.
    27[transformers] A new version of the following files was downloaded from https://huggingface.co/jinaai/jina-embeddings-v5-text-nano:
    28- modeling_jina_embeddings_v5.py
    29- modeling_eurobert.py
    30. Make sure to double-check they do not contain any added malicious code. To avoid downloading new versions of the code file, you can pin a revision.
    31model.safetensors: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████| 424M/424M [00:01<00:00, 358MB/s]
    32/srv/venv/lib/python3.12/site-packages/transformers/modeling_attn_mask_utils.py:71: FutureWarning: The attention mask API under `transformers.modeling_attn_mask_utils` (`AttentionMaskConverter`) is deprecated and will be removed in Transformers v5.10. Please use the new API in `transformers.masking_utils`.
    33 warnings.warn(DEPRECATION_MESSAGE, FutureWarning)
    34Loading weights: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████| 110/110 [00:00<00:00, 10944.69it/s]
    35Fetching 8 files: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 8/8 [00:00<00:00, 11.98it/s]
    36Download complete: 100%|████████████████████████████████████████████████████████████████████████████████████████████████████████| 54.4M/54.4M [00:00<00:00, 79.0MB/s]
    37tokenizer_config.json: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████| 50.6k/50.6k [00:00<00:00, 134MB/s]
    38tokenizer.json: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████| 17.2M/17.2M [00:00<00:00, 35.1MB/s]
    39special_tokens_map.json: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████| 582/582 [00:00<00:00, 2.31MB/s]
    40[transformers] `use_return_dict` is deprecated! Use `return_dict` instead!
    41/srv/venv/lib/python3.12/site-packages/transformers/modeling_attn_mask_utils.py:202: FutureWarning: The attention mask API under `transformers.modeling_attn_mask_utils` (`AttentionMaskConverter`) is deprecated and will be removed in Transformers v5.10. Please use the new API in `transformers.masking_utils`.
    42 warnings.warn(DEPRECATION_MESSAGE, FutureWarning)
    43Query embeddings: (2, 768)
    44Document embeddings: (3, 768)
    45
    46Query: 'What is the capital of Burkina Faso?'
    47 1. [+0.8452] Ouagadougou is the capital and largest city of Burkina Faso, with a po...
    48 2. [+0.0684] The Great Wall of China is a series of fortifications built across the...
    49 3. [+0.0327] Climate change has led to rising sea levels and more frequent extreme ...
    50
    51Query: 'impacts of climate change on coastal cities'
    52 1. [+0.7831] Climate change has led to rising sea levels and more frequent extreme ...
    53 2. [+0.0742] Ouagadougou is the capital and largest city of Burkina Faso, with a po...
    54 3. [+0.0622] The Great Wall of China is a series of fortifications built across the...
    55
    56Saved embeddings to transformers_retrieval_embeddings.pt (compare with vLLM output for parity).
    57somebody@ml-lab1002:~$
    58somebody@ml-lab1002:~$
    59somebody@ml-lab1002:~$
    60somebody@ml-lab1002:~$ ls
    61jina_nano_retrieval_transformers.py jina_nano_retrieval_vllm.py transformers_retrieval_embeddings.pt venv
    62somebody@ml-lab1002:~$
    63somebody@ml-lab1002:~$
    64somebody@ml-lab1002:~$
    65somebody@ml-lab1002:~$ python3 jina_nano_retrieval_vllm.py
    66/srv/venv/lib/python3.12/site-packages/torchvision/io/image.py:14: UserWarning: Failed to load image Python extension: 'Could not load this library: /srv/venv/lib/python3.12/site-packages/torchvision/image.so'If you don't plan on using image functionality from `torchvision.io`, you can ignore this warning. Otherwise, there might be something wrong with your environment. Did you have `libjpeg` or `libpng` installed before building `torchvision` from source?
    67 warn(
    68Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.
    69Loaded prompt prefixes from repo config:
    70 query = 'Query: '
    71 document = 'Document: '
    72
    73INFO 07-24 09:13:28 [utils.py:278] non-default args: {'trust_remote_code': True, 'dtype': 'bfloat16', 'disable_log_stats': True, 'enforce_eager': True, 'model': 'jinaai/jina-embeddings-v5-text-nano-retrieval'}
    74[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    75[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    76[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    77INFO 07-24 09:13:36 [config.py:876] Found sentence-transformers modules configuration.
    78INFO 07-24 09:13:36 [config.py:903] Found pooling configuration.
    79INFO 07-24 09:13:36 [model.py:942] Resolved `--runner auto` to `--runner pooling`. Pass the value explicitly to silence this message.
    80INFO 07-24 09:13:36 [model.py:994] Resolved `--convert auto` to `--convert embed`. Pass the value explicitly to silence this message.
    81INFO 07-24 09:13:36 [model.py:617] Resolved architecture: TransformersEmbeddingModel
    82INFO 07-24 09:13:36 [model.py:1752] Using max model len 8192
    83INFO 07-24 09:13:36 [vllm.py:977] Asynchronous scheduling is disabled.
    84WARNING 07-24 09:13:36 [vllm.py:1033] Enforce eager set, disabling torch.compile and CUDAGraphs. This is equivalent to setting -cc.mode=none -cc.cudagraph_mode=none
    85WARNING 07-24 09:13:36 [vllm.py:1058] Inductor compilation was disabled by user settings, optimizations settings that are only active during inductor compilation will be ignored.
    86INFO 07-24 09:13:37 [kernel.py:270] Final IR op priority after setting platform defaults: IrOpPriorityConfig(rms_norm=['vllm_c', 'native'], fused_add_rms_norm=['vllm_c', 'native'])
    87INFO 07-24 09:13:37 [vllm.py:1234] Cudagraph is disabled under eager mode
    88INFO 07-24 09:13:37 [compilation.py:312] Enabled custom fusions: norm_quant, act_quant
    89[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    90[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    91[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    92[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    93[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    94[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    95[transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    96WARNING 07-24 09:13:40 [system_utils.py:157] We must use the `spawn` multiprocessing start method. Overriding VLLM_WORKER_MULTIPROC_METHOD to 'spawn'. See https://docs.vllm.ai/en/latest/usage/troubleshooting.html#python-multiprocessing for more information. Reasons: CUDA is initialized
    97/srv/venv/lib/python3.12/site-packages/torchvision/io/image.py:14: UserWarning: Failed to load image Python extension: 'Could not load this library: /srv/venv/lib/python3.12/site-packages/torchvision/image.so'If you don't plan on using image functionality from `torchvision.io`, you can ignore this warning. Otherwise, there might be something wrong with your environment. Did you have `libjpeg` or `libpng` installed before building `torchvision` from source?
    98 warn(
    99(EngineCore pid=1761) INFO 07-24 09:13:47 [core.py:112] Initializing a V1 LLM engine (v0.22.1) with config: model='jinaai/jina-embeddings-v5-text-nano-retrieval', speculative_config=None, tokenizer='jinaai/jina-embeddings-v5-text-nano-retrieval', skip_tokenizer_init=False, tokenizer_mode=auto, revision=None, tokenizer_revision=None, trust_remote_code=True, dtype=torch.bfloat16, max_seq_len=8192, download_dir=None, load_format=auto, tensor_parallel_size=1, pipeline_parallel_size=1, data_parallel_size=1, decode_context_parallel_size=1, dcp_comm_backend=ag_rs, disable_custom_all_reduce=True, quantization=None, quantization_config=None, enforce_eager=True, enable_return_routed_experts=False, kv_cache_dtype=auto, device_config=cuda, structured_outputs_config=StructuredOutputsConfig(backend='auto', disable_any_whitespace=False, disable_additional_properties=False, reasoning_parser='', reasoning_parser_plugin='', enable_in_reasoning=False), observability_config=ObservabilityConfig(show_hidden_metrics_for_version=None, otlp_traces_endpoint=None, collect_detailed_traces=None, kv_cache_metrics=False, kv_cache_metrics_sample=0.01, cudagraph_metrics=False, enable_layerwise_nvtx_tracing=False, enable_mfu_metrics=False, enable_mm_processor_stats=False, enable_logging_iteration_details=False), seed=0, served_model_name=jinaai/jina-embeddings-v5-text-nano-retrieval, enable_prefix_caching=False, enable_chunked_prefill=False, pooler_config=PoolerConfig(task=None, pooling_type=None, seq_pooling_type='LAST', tok_pooling_type='ALL', use_activation=True, dimensions=None, enable_chunked_processing=False, max_embed_len=None, logit_mean=None, logit_sigma=None, logit_bias=None, logit_scale=None, step_tag_id=None, returned_token_ids=None), compilation_config={'mode': <CompilationMode.NONE: 0>, 'debug_dump_path': None, 'cache_dir': '', 'compile_cache_save_format': 'binary', 'backend': 'inductor', 'custom_ops': ['+sparse_attn_indexer', 'all'], 'ir_enable_torch_wrap': False, 'splitting_ops': [], 'compile_mm_encoder': False, 'cudagraph_mm_encoder': False, 'encoder_cudagraph_token_budgets': [], 'encoder_cudagraph_max_vision_items_per_batch': 0, 'encoder_cudagraph_max_frames_per_batch': None, 'compile_sizes': [], 'compile_ranges_endpoints': [8192], 'inductor_compile_config': {'enable_auto_functionalized_v2': False, 'size_asserts': False, 'alignment_asserts': False, 'scalar_asserts': False, 'combo_kernels': True, 'benchmark_combo_kernel': True}, 'inductor_passes': {}, 'cudagraph_mode': <CUDAGraphMode.NONE: 0>, 'cudagraph_num_of_warmups': 0, 'cudagraph_capture_sizes': [], 'cudagraph_copy_inputs': False, 'cudagraph_specialize_lora': True, 'use_inductor_graph_partition': False, 'pass_config': {'fuse_norm_quant': True, 'fuse_act_quant': True, 'fuse_attn_quant': False, 'enable_sp': False, 'fuse_gemm_comms': False, 'fuse_rope_kvcache_cat_mla': False, 'fuse_act_padding': False}, 'max_cudagraph_capture_size': 0, 'dynamic_shapes_config': {'type': <DynamicShapesType.BACKED: 'backed'>, 'evaluate_guards': False, 'assume_32_bit_indexing': False}, 'local_cache_dir': None, 'fast_moe_cold_start': True, 'static_all_moe_layers': []}, kernel_config=KernelConfig(ir_op_priority=IrOpPriorityConfig(rms_norm=['vllm_c', 'native'], fused_add_rms_norm=['vllm_c', 'native']), enable_flashinfer_autotune=True, moe_backend='auto', linear_backend='auto')
    100(EngineCore pid=1761) INFO 07-24 09:13:48 [parallel_state.py:1422] world_size=1 rank=0 local_rank=0 distributed_init_method=tcp://10.64.161.5:33911 backend=nccl
    101(EngineCore pid=1761) INFO 07-24 09:13:48 [parallel_state.py:1735] rank 0 in world size 1 is assigned as DP rank 0, PP rank 0, PCP rank 0, TP rank 0, EP rank N/A, EPLB rank N/A
    102(EngineCore pid=1761) INFO 07-24 09:13:49 [gpu_model_runner.py:5037] Starting to load model jinaai/jina-embeddings-v5-text-nano-retrieval...
    103(EngineCore pid=1761) Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.
    104(EngineCore pid=1761) WARNING 07-24 09:13:49 [utils.py:192] TransformersEmbeddingModel has no vLLM implementation, falling back to Transformers implementation. Some features may not be supported and performance may not be optimal.
    105(EngineCore pid=1761) INFO 07-24 09:13:49 [base.py:117] Using Transformers modeling backend.
    106(EngineCore pid=1761) /srv/venv/lib/python3.12/site-packages/transformers/modeling_attn_mask_utils.py:71: FutureWarning: The attention mask API under `transformers.modeling_attn_mask_utils` (`AttentionMaskConverter`) is deprecated and will be removed in Transformers v5.10. Please use the new API in `transformers.masking_utils`.
    107(EngineCore pid=1761) warnings.warn(DEPRECATION_MESSAGE, FutureWarning)
    108(EngineCore pid=1761) INFO 07-24 09:13:49 [rocm.py:552] Found incompatible backend(s) [TURBOQUANT] with AttentionType.ENCODER_ONLY. Overriding with ROCM_ATTN out of potential backends: ['ROCM_ATTN', 'TRITON_ATTN'].
    109(EngineCore pid=1761) WARNING 07-24 09:13:49 [compilation.py:1303] Op 'sparse_attn_indexer' not present in model, enabling with '+sparse_attn_indexer' has no effect
    110(EngineCore pid=1761) INFO 07-24 09:13:49 [weight_utils.py:647] No model.safetensors.index.json found in remote.
    111(EngineCore pid=1761) INFO 07-24 09:13:49 [weight_utils.py:922] Filesystem type for checkpoints: XFS. Checkpoint size: 0.39 GiB. Available RAM: 368.44 GiB.
    112(EngineCore pid=1761) INFO 07-24 09:13:49 [weight_utils.py:945] Auto-prefetch is disabled because the filesystem (XFS) is not a recognized network FS (NFS/Lustre). If you want to force prefetching, start vLLM with --safetensors-load-strategy=prefetch.
    113Loading safetensors checkpoint shards: 0% Completed | 0/1 [00:00<?, ?it/s]
    114Loading safetensors checkpoint shards: 100% Completed | 1/1 [00:00<00:00, 2.87it/s]
    115Loading safetensors checkpoint shards: 100% Completed | 1/1 [00:00<00:00, 2.87it/s]
    116(EngineCore pid=1761)
    117(EngineCore pid=1761) INFO 07-24 09:13:50 [default_loader.py:397] Loading weights took 0.37 seconds
    118(EngineCore pid=1761) INFO 07-24 09:13:50 [gpu_model_runner.py:5132] Model loading took 0.4 GiB memory and 0.998819 seconds
    119(EngineCore pid=1761) INFO 07-24 09:13:51 [jit_monitor.py:54] Kernel JIT monitor activated — Triton JIT compilations during inference will be logged as warnings.
    120(EngineCore pid=1761) INFO 07-24 09:13:51 [core.py:309] init engine (profile, create kv cache, warmup model) took 0.75 s
    121(EngineCore pid=1761) [transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    122(EngineCore pid=1761) [transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    123(EngineCore pid=1761) [transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    124(EngineCore pid=1761) [transformers] Unrecognized keys in `rope_parameters` for 'rope_type'='default': {'factor'}
    125(EngineCore pid=1761) INFO 07-24 09:13:53 [vllm.py:977] Asynchronous scheduling is disabled.
    126(EngineCore pid=1761) WARNING 07-24 09:13:53 [vllm.py:1033] Enforce eager set, disabling torch.compile and CUDAGraphs. This is equivalent to setting -cc.mode=none -cc.cudagraph_mode=none
    127(EngineCore pid=1761) WARNING 07-24 09:13:53 [vllm.py:1058] Inductor compilation was disabled by user settings, optimizations settings that are only active during inductor compilation will be ignored.
    128(EngineCore pid=1761) INFO 07-24 09:13:53 [kernel.py:270] Final IR op priority after setting platform defaults: IrOpPriorityConfig(rms_norm=['vllm_c', 'native'], fused_add_rms_norm=['vllm_c', 'native'])
    129(EngineCore pid=1761) INFO 07-24 09:13:53 [vllm.py:1234] Cudagraph is disabled under eager mode
    130(EngineCore pid=1761) INFO 07-24 09:13:53 [compilation.py:312] Enabled custom fusions: norm_quant, act_quant
    131INFO 07-24 09:13:53 [offline.py:41] Supported pooling task: embed
    132INFO 07-24 09:13:53 [io_processor.py:61] Loaded prompt prefixes for input_type: ['query', 'document']
    133Processed prompts: 0%| | 0/2 [00:00<?, ?it/s, est. speed input: 0.00 toks/s, output: 0.00 toks/s](EngineCore pid=1761) WARNING 07-24 09:13:54 [jit_monitor.py:103] Triton kernel JIT compilation during inference: _fwd_kernel. This causes a latency spike; consider extending warmup to cover this shape/config.
    134Processed prompts: 100%|███████████████████████████████████████████████████████████| 2/2 [00:00<00:00, 2.85it/s, est. speed input: 0.00 toks/s, output: 0.00 toks/s]
    135Processed prompts: 100%|██████████████████████████████████████████████████████████| 3/3 [00:00<00:00, 103.60it/s, est. speed input: 0.00 toks/s, output: 0.00 toks/s]
    136
    137Query embeddings: (2, 768)
    138Document embeddings: (3, 768)
    139
    140Query: 'What is the capital of Burkina Faso?'
    141 1. [+0.8449] Ouagadougou is the capital and largest city of Burkina Faso, with a po...
    142 2. [+0.0690] The Great Wall of China is a series of fortifications built across the...
    143 3. [+0.0332] Climate change has led to rising sea levels and more frequent extreme ...
    144
    145Query: 'impacts of climate change on coastal cities'
    146 1. [+0.7827] Climate change has led to rising sea levels and more frequent extreme ...
    147 2. [+0.0752] Ouagadougou is the capital and largest city of Burkina Faso, with a po...
    148 3. [+0.0640] The Great Wall of China is a series of fortifications built across the...
    149
    150Parity vs transformers backend (cosine per input, expect ~1.0):
    151 queries: ['0.99991', '0.99995']
    152 documents: ['0.99994', '0.99995', '0.99994']
    153(EngineCore pid=1761) INFO 07-24 09:13:54 [core.py:1266] Shutdown initiated (timeout=0)
    154(EngineCore pid=1761) INFO 07-24 09:13:54 [core.py:1289] Shutdown complete
    155somebody@ml-lab1002:~$
    156somebody@ml-lab1002:~$

Loading the jinaai/jina-embeddings-v5-text-nano-retrieval model from HuggingFace emits:

INFO 07-24 07:47:53 [config.py:876] Found sentence-transformers modules configuration.
INFO 07-24 07:47:53 [config.py:903] Found pooling configuration.
INFO 07-24 07:48:12 [io_processor.py:61] Loaded prompt prefixes for input_type: ['query', 'document']

The staging pod logs show none of these. I checked the bucket:

$ s3cmd -c /etc/s3cmd/cfg.d/ml-team.cfg ls -H s3://wmf-ml-models/jina-embeddings/v1/20260723064742/
2026-07-23 06:47  1361   s3://wmf-ml-models/jina-embeddings/v1/20260723064742/config.json
2026-07-23 06:47    11K  s3://wmf-ml-models/jina-embeddings/v1/20260723064742/configuration_eurobert.py
2026-07-23 06:47   403M  s3://wmf-ml-models/jina-embeddings/v1/20260723064742/model.safetensors
2026-07-23 06:47    47K  s3://wmf-ml-models/jina-embeddings/v1/20260723064742/modeling_eurobert.py
2026-07-23 06:47    16M  s3://wmf-ml-models/jina-embeddings/v1/20260723064742/tokenizer.json
2026-07-23 06:47   487   s3://wmf-ml-models/jina-embeddings/v1/20260723064742/tokenizer_config.json

Missing: modules.json, config_sentence_transformers.json (holds the Query: / Document: prefixes), 1_Pooling/config.json. With these present, vLLM auto-resolves runner=pooling and seq_pooling_type=LAST from the model config, same as it does for the qwen3-embeddings isvc in T418976, removing the need for manual env overrides. The prompt-prefix mechanism in the next comment also depends on these files.

We have to upload a complete snapshot of the jinaai/jina-embeddings-v5-text-nano-retrieval model to the swift bucket.

The retrieval variant was trained with asymmetric prefixes (from config_sentence_transformers.json):

query    = 'Query: '
document = 'Document: '

Our model-server's preprocess() passes raw strings through, so the staging endpoint is embedding text without these prefixes. This means:

  • Any quality numbers from the staging endpoint understate the model.
  • If the Research team evaluated via transformers (which auto-prefixes via prompt_name=), their numbers and our served outputs are different embeddings for the same input.

The fix: vLLM's io_processor already loads these prefixes from config_sentence_transformers.json and applies them via an input_type parameter, visible in my ml-lab run: Loaded prompt prefixes for input_type: ['query', 'document']. Once the model snapshot upload is completed (T432717#12152920), we can plumb input_type through the KServe payload. This is similar to the qwen3-embeddings prompt contract from T412338, with two differences: (a) jina requires Document: prefix on the indexing side too, and (b) I'm proposing server-side application (client sends input_type, server applies the trained prefix) rather than client-composed prompt strings.

For this model we can move forward and serve it via HF Transformers (sentence-transformers interface). We can also add flash-attention for inference speed if the boost is needed.

vLLM adds no value. Without a native implementation, vLLM wraps the same HF modeling code we'd run directly. The parity check proves it: cosine 0.99991-0.99995 between backends. We're carrying vLLM's complexity for identical output.

What vLLM costs us: the eager/graph-capture dilemma: per-shape Triton JIT spikes of 1-30s with enforce_eager=True, or ~70 min startups with it off (behind a progress-deadline: 7200s where every pod reschedule is a >1h outage); an MI300X tied up by a 239M model at ~5 RPS; and a version gap: the model card pins vllm==0.15.1, we run 0.22.1, unsupported on a fallback path on the ROCm stack that has been this program's recurring pain point (see AITER revert history in T418976).

What Transformers gives us: it's the model's native backend. prompt_name="query"/"document" applies prefixes automatically, so the prefix problem reported in T432717#12152929 disappears. ~5 ms model time on CPU against <300 ms / ~5 RPS NFRs from T412338 leaves plenty of headroom with no JIT/graph-capture failure modes, and frees the MI300X. (If a GPU deployment is ever needed, flash_attention_2 as in the original qwen3-embeddings transformers image.)

On standardization: this is a scoped exception to the T418976 vLLM consolidation, not drift: encoder-class embedding models without native vLLM support serve on the transformers image. The input_type API contract keeps the backend invisible to the Search team (switching later costs them nothing), and the parity gate validates whichever backend sits behind the endpoint.

Hey @kevinbazira thank you for the confirmation!

I was thinking to use base: docker-registry.wikimedia.org/amd-pytorch25:2.5.1rocm6.1-1 for the transformer implementation
However, we will need torch>=2.8.0.

vllm had pytorch 2.8 but I see the max is 2.5 in the amd folder.
https://gerrit.wikimedia.org/r/plugins/gitiles/operations/docker-images/production-images/+/refs/heads/master/images/amd/

Do you know if we have rocm pythorch 2.8 somewhere or should we build a new image?

image.png (486×340 px, 26 KB)

Hey @kevinbazira thank you for the confirmation!

I was thinking to use base: docker-registry.wikimedia.org/amd-pytorch25:2.5.1rocm6.1-1 for the transformer implementation
However, we will need torch>=2.8.0.

vllm had pytorch 2.8 but I see the max is 2.5 in the amd folder.
https://gerrit.wikimedia.org/r/plugins/gitiles/operations/docker-images/production-images/+/refs/heads/master/images/amd/

Do you know if we have rocm pythorch 2.8 somewhere or should we build a new image?

image.png (486×340 px, 26 KB)

Yep, I see the WMF amd-pytorch images cap at PyTorch 2.5 ( amd-pytorch25 ), which is way below the torch>=2.8.0.

However, the amd-vllm022 image ships PyTorch 2.10 with ROCm support ( amd-vllm022 ). We can use it as the base image for the transformers serving path: it gives us a ROCm-compatible PyTorch that satisfies the >=2.8.0 requirement. We just don't have to invoke vLLM at runtime and use HF transformers instead. It's what I used in my ml-lab run: P95140 Both HuggingFace transformers and vLLM successfully loaded jina-embeddings model on ML-Lab using MI210 GPU

I've tried enabling flash attention2 in both mllabs and in kserve.

It's recommended in both of the Eurobert and jina model cards:

image.png (735×184 px, 24 KB)

image.png (663×181 px, 28 KB)

However, it turns out that it's not implemented:

On mllabs:

docker run --rm \
  --network host \
  --device=/dev/kfd --device=/dev/dri \
  --group-add video --group-add 105 \
  --security-opt seccomp=unconfined \
  -e HIP_VISIBLE_DEVICES=0 \
  -e http_proxy=http://webproxy:8080 \
  -e https_proxy=http://webproxy:8080 \
  -v "$HOME/jina-5-transformers:/srv/app" \
  -e HF_HOME=/srv/app/hf-cache \
  -w /srv/app \
  docker-registry.wikimedia.org/ml/amd-vllm022:gfx90agfx942rocm7.2.0pytorch2.10.0flash-attn2.8.3aiter0.1.13vllm0.22.1-3 \
  /srv/venv/bin/python jina_nano_retrieval_transformers.py
model = AutoModel.from_pretrained(
    MODEL_ID,
    trust_remote_code=True,
    dtype=dtype,
    _attn_implementation="flash_attention_2",  # optional, GPU + flash-attn only
).to(device)
model.eval()
  File "/srv/venv/lib/python3.12/site-packages/transformers/modeling_utils.py", line 2041, in get_correct_attn_implementation
    self._flash_attn_can_dispatch(flash_attn_version=fa_version, is_init_check=is_init_check)
  File "/srv/venv/lib/python3.12/site-packages/transformers/modeling_utils.py", line 1760, in _flash_attn_can_dispatch
    raise ValueError(
ValueError: EuroBertModel does not support Flash Attention 2 yet. Please request to add support where the model is hosted, on its model hub page: https://huggingface.co/jinaai/jina-embeddings-v5-text-nano/discussions/new or in the Transformers GitHub repo: https://github.com/huggingface/transformers/issues/new

I get the same error with kserve as expected.
My best guess is that they mean Nvidia and not AMD.
I'm getting convinced that Eurobert is not production ready and mostly for research purposes as it does not support both vllm and flash attention2.

@kevinbazira , I believe you should get the same error with your set up in mllabs if you enable flash attention2.

I've tried enabling flash attention2 in both mllabs and in kserve.

...
I get the same error with kserve as expected.
My best guess is that they mean Nvidia and not AMD.
I'm getting convinced that Eurobert is not production ready and mostly for research purposes as it does not support both vllm and flash attention2.

@kevinbazira , I believe you should get the same error with your set up in mllabs if you enable flash attention2.

I've reproduced this issue on ml-lab in P95176 EuroBertModel does not support Flash Attention 2 yet. Since the docs mention that flash_attention_2 is optional, we can do without it for now.

Flash attention2 worked after enabling it manually:

"""
jina-embeddings-v5-text-nano — retrieval task via HuggingFace Transformers.

Uses the BASE multi-task repo (jinaai/jina-embeddings-v5-text-nano). Its custom
encode() applies the retrieval LoRA adapter AND the query/document prompt
prefixes for you — you just pass task + prompt_name.

Run: python3 jina_nano_retrieval_transformers.py
"""

import torch
import torch.nn.functional as F
from transformers import AutoConfig, AutoModel
from transformers.dynamic_module_utils import get_class_from_dynamic_module

MODEL_ID = "jinaai/jina-embeddings-v5-text-nano"

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# bf16 recommended on GPU (matches the model card); fp32 is safer/faster on CPU.
dtype = torch.bfloat16 if device.type == "cuda" else torch.float32
# flash_attn 2.8.3 is provided by amd-vllm022 on GPU; SDPA on CPU.
attn_implementation = "flash_attention_2" if device.type == "cuda" else "sdpa"

# Jina's custom from_pretrained only forwards config+dtype to EuroBert, so set
# attn on the config. transformers>=5 checks `_supports_flash_attn` while
# EuroBert remote code still declares the older `_supports_flash_attn_2`.
config = AutoConfig.from_pretrained(MODEL_ID, trust_remote_code=True)
config._attn_implementation = attn_implementation
if attn_implementation == "flash_attention_2":
    print("Flash Attention 2 is active")
    EuroBertPreTrainedModel = get_class_from_dynamic_module(
        "modeling_eurobert.EuroBertPreTrainedModel",
        MODEL_ID,
    )
    EuroBertPreTrainedModel._supports_flash_attn = True

model = AutoModel.from_pretrained(
    MODEL_ID,
    config=config,
    trust_remote_code=True,
    dtype=dtype,
).to(device)
model.eval()

# Confirm FA2 is active on the loaded EuroBert backbone (not just the request).
base = model.get_base_model() if hasattr(model, "get_base_model") else model
active_attn = getattr(base.config, "_attn_implementation", None)
print(f"[attn] requested={attn_implementation}")
print(f"[attn] active on {type(base).__name__}.config={active_attn}")
print(f"[attn] device={device}, dtype={dtype}, cuda={torch.cuda.is_available()}")
if attn_implementation == "flash_attention_2":
    import flash_attn

    print(f"[attn] flash_attn package version={flash_attn.__version__}")
    if active_attn != "flash_attention_2":
        raise RuntimeError(
            f"Expected flash_attention_2 on loaded model, got {active_attn!r}"
        )
    print("[attn] confirmed: using Flash Attention 2")

# --- Asymmetric retrieval: queries and documents get DIFFERENT prompt_names ---
queries = [
    "What is the capital of Burkina Faso?",
    "impacts of climate change on coastal cities",
]
documents = [
    "Ouagadougou is the capital and largest city of Burkina Faso, "
    "with a population of about 2.5 million.",
    "Climate change has led to rising sea levels and more frequent extreme "
    "weather events, threatening infrastructure in low-lying coastal cities.",
    "The Great Wall of China is a series of fortifications built across "
    "the historical northern borders of ancient Chinese states.",
]

with torch.inference_mode():
    query_embeddings = model.encode(
        texts=queries,
        task="retrieval",
        prompt_name="query",  # "Query: " prefix applied internally
    )
    document_embeddings = model.encode(
        texts=documents,
        task="retrieval",
        prompt_name="document",  # "Document: " prefix applied internally
    )

# L2-normalize (idempotent if encode() already normalized) so that
# dot product == cosine similarity. Cast to fp32 for stable comparison output.
q = F.normalize(torch.as_tensor(query_embeddings, dtype=torch.float32), p=2, dim=1)
d = F.normalize(torch.as_tensor(document_embeddings, dtype=torch.float32), p=2, dim=1)

print(f"Query embeddings:    {tuple(q.shape)}")   # (2, 768)
print(f"Document embeddings: {tuple(d.shape)}\n")  # (3, 768)

scores = q @ d.T  # cosine similarity matrix: queries x documents
for i, query in enumerate(queries):
    print(f"Query: {query!r}")
    ranked = sorted(enumerate(scores[i].tolist()), key=lambda x: -x[1])
    for rank, (j, score) in enumerate(ranked, start=1):
        print(f"  {rank}. [{score:+.4f}] {documents[j][:70]}...")
    print()

# Save embeddings (on CPU, so any consumer can load them regardless of device)
# for cross-backend parity checking against the vLLM script.
torch.save({"queries": q.cpu(), "documents": d.cpu()},
           "transformers_retrieval_embeddings.pt")
print("Saved embeddings to transformers_retrieval_embeddings.pt "
      "(compare with vLLM output for parity).")
ill be removed in Transformers v5.10. Please use the new API in `transformers.masking_utils`.
  warnings.warn(DEPRECATION_MESSAGE, FutureWarning)
Loading weights:   0%|          | 0/110 [00:00<?, ?it/s]Flash Attention 2 is active
Loading weights: 100%|██████████| 110/110 [00:00<00:00, 9924.78it/s]
Fetching 8 files: 100%|██████████| 8/8 [00:00<00:00, 7139.24it/s]
[transformers] `use_return_dict` is deprecated! Use `return_dict` instead!
[attn] requested=flash_attention_2
[attn] active on JinaEmbeddingsV5Model.config=flash_attention_2
[attn] device=cuda, dtype=torch.bfloat16, cuda=True
[attn] flash_attn package version=2.8.3
[attn] confirmed: using Flash Attention 2
Query embeddings:    (2, 768)
Document embeddings: (3, 768)

Query: 'What is the capital of Burkina Faso?'
  1. [+0.8454] Ouagadougou is the capital and largest city of Burkina Faso, with a po...
  2. [+0.0690] The Great Wall of China is a series of fortifications built across the...
  3. [+0.0328] Climate change has led to rising sea levels and more frequent extreme ...

Query: 'impacts of climate change on coastal cities'
  1. [+0.7814] Climate change has led to rising sea levels and more frequent extreme ...
  2. [+0.0740] Ouagadougou is the capital and largest city of Burkina Faso, with a po...
  3. [+0.0614] The Great Wall of China is a series of fortifications built across the...

Saved embeddings to transformers_retrieval_embeddings.pt (compare with vLLM output for parity).
ozge@ml-lab1002:~/jina-5-transformers$

Change #1318100 had a related patch set uploaded (by Ozge; author: Ozge):

[machinelearning/liftwing/inference-services@main] embeddings: Add SentenceTransformer backend for Jina embeddings

https://gerrit.wikimedia.org/r/1318100

I've created a patch to serve jina nano embeddings with transformers (SentenceTransformer).
Can you take a look when you have time? @kevinbazira

I've created a patch to serve jina nano embeddings with transformers (SentenceTransformer).
Can you take a look when you have time? @kevinbazira

Thank you for working on this. I had a look and left a comment on the patch.

thank you @kevinbazira . I've addressed your comment.

LGTM! +1

Change #1318100 merged by jenkins-bot:

[machinelearning/liftwing/inference-services@main] embeddings: Add SentenceTransformer backend for Jina embeddings

https://gerrit.wikimedia.org/r/1318100

Change #1318243 had a related patch set uploaded (by Ozge; author: Ozge):

[integration/config@master] inference-services: Add CI pipeline job for embeddings-transformers server

https://gerrit.wikimedia.org/r/1318243

Change #1318243 merged by jenkins-bot:

[integration/config@master] inference-services: Add CI pipeline job for embeddings-transformers server

https://gerrit.wikimedia.org/r/1318243

Change #1318570 had a related patch set uploaded (by Hashar; author: Hashar):

[integration/config@master] inference-services: trigger embeddings-transformers in Zuul

https://gerrit.wikimedia.org/r/1318570

Change #1318570 merged by jenkins-bot:

[integration/config@master] inference-services: trigger embeddings-transformers in Zuul

https://gerrit.wikimedia.org/r/1318570

Change #1318664 had a related patch set uploaded (by Ozge; author: Ozge):

[machinelearning/liftwing/inference-services@main] embeddings: Add SentenceTransformer backend for Jina embeddings - match pipeline names

https://gerrit.wikimedia.org/r/1318664

Change #1318664 merged by jenkins-bot:

[machinelearning/liftwing/inference-services@main] embeddings: Add SentenceTransformer backend for Jina embeddings - match pipeline names

https://gerrit.wikimedia.org/r/1318664

Change #1318669 had a related patch set uploaded (by Ozge; author: Ozge):

[operations/deployment-charts@master] ml-services: Update jina-embeddings-staging to transformers image

https://gerrit.wikimedia.org/r/1318669

@kevinbazira

I've created a patch to deploy sentence transformers version to staging.
Can you take a look when you have time?

https://gerrit.wikimedia.org/r/c/operations/deployment-charts/+/1318669

@kevinbazira

I've created a patch to deploy sentence transformers version to staging.
Can you take a look when you have time?

https://gerrit.wikimedia.org/r/c/operations/deployment-charts/+/1318669

Thank you for working on this. I had a look at the patch and it LGTM!

Change #1318669 merged by Ozge:

[operations/deployment-charts@master] ml-services: Update jina-embeddings-staging to transformers image

https://gerrit.wikimedia.org/r/1318669

Change #1318695 had a related patch set uploaded (by Ozge; author: Ozge):

[operations/deployment-charts@master] ml-services: Update jina-embeddings model version in eqiad

https://gerrit.wikimedia.org/r/1318695

@kevinbazira ,

I've created a patch to add missing config files.
I exclude onnx and gguf files as I think they are not need for rocm amd.

hf download jinaai/jina-embeddings-v5-text-nano-retrieval \
  --local-dir /path/to/local/dir \
  --exclude "onnx/*" "*.gguf"
(venv) ozge@stat1010:~/models$ s3cmd -c /etc/s3cmd/cfg.d/ml-team.cfg ls -H s3://wmf-ml-models/jina-embeddings/v1/20260728115813/
                    DIR  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/.cache/
                    DIR  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/1_Pooling/
2026-07-28 11:58     2K  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/.gitattributes
2026-07-28 11:58     9K  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/README.md
2026-07-28 11:58  1361   s3://wmf-ml-models/jina-embeddings/v1/20260728115813/config.json
2026-07-28 11:58   274   s3://wmf-ml-models/jina-embeddings/v1/20260728115813/config_sentence_transformers.json
2026-07-28 11:58    11K  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/configuration_eurobert.py
2026-07-28 11:58   403M  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/model.safetensors
2026-07-28 11:58    47K  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/modeling_eurobert.py
2026-07-28 11:58   349   s3://wmf-ml-models/jina-embeddings/v1/20260728115813/modules.json
2026-07-28 11:58    16M  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/tokenizer.json
2026-07-28 11:58   487   s3://wmf-ml-models/jina-embeddings/v1/20260728115813/tokenizer_config.json

Can you take a look when you have time?

https://gerrit.wikimedia.org/r/c/operations/deployment-charts/+/1318695

@kevinbazira ,

I've created a patch to add missing config files.
I exclude onnx and gguf files as I think they are not need for rocm amd.

hf download jinaai/jina-embeddings-v5-text-nano-retrieval \
  --local-dir /path/to/local/dir \
  --exclude "onnx/*" "*.gguf"
(venv) ozge@stat1010:~/models$ s3cmd -c /etc/s3cmd/cfg.d/ml-team.cfg ls -H s3://wmf-ml-models/jina-embeddings/v1/20260728115813/
                    DIR  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/.cache/
                    DIR  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/1_Pooling/
2026-07-28 11:58     2K  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/.gitattributes
2026-07-28 11:58     9K  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/README.md
2026-07-28 11:58  1361   s3://wmf-ml-models/jina-embeddings/v1/20260728115813/config.json
2026-07-28 11:58   274   s3://wmf-ml-models/jina-embeddings/v1/20260728115813/config_sentence_transformers.json
2026-07-28 11:58    11K  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/configuration_eurobert.py
2026-07-28 11:58   403M  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/model.safetensors
2026-07-28 11:58    47K  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/modeling_eurobert.py
2026-07-28 11:58   349   s3://wmf-ml-models/jina-embeddings/v1/20260728115813/modules.json
2026-07-28 11:58    16M  s3://wmf-ml-models/jina-embeddings/v1/20260728115813/tokenizer.json
2026-07-28 11:58   487   s3://wmf-ml-models/jina-embeddings/v1/20260728115813/tokenizer_config.json

Can you take a look when you have time?

https://gerrit.wikimedia.org/r/c/operations/deployment-charts/+/1318695

Thank you for adding the missing config files. LGTM!

Change #1318695 merged by jenkins-bot:

[operations/deployment-charts@master] ml-services: Update jina-embeddings model version in eqiad

https://gerrit.wikimedia.org/r/1318695

prod locust latest test results to compare:
https://phabricator.wikimedia.org/T418976#11703437

98.90 req/s
77 ms in 98%

Change #1319042 had a related patch set uploaded (by Ozge; author: Ozge):

[machinelearning/liftwing/inference-services@main] embeddings: Parameterize Locust test for multiple embedding models

https://gerrit.wikimedia.org/r/1319042

Load test results are much better than I expected and slightly lower than current prod.

  • Jina: 95 percentile latency is 75 ms with 95.24 req/s
  • prod: 95 percentile latency is 70 ms with 98.90 req/s
export HOST=jina-embeddings-staging
export MODEL_NAME=jina-embedding
export USE_PROMPT=false

(venv) ozge@stat1010:~/repos/wiki/gerrit/inference-services/test/locust$ MODEL=embeddings locust --host https://inference.svc.eqiad.wmnet:30443 --users 10 --run-time 4m
Min length: 10, Max length: 350
       question_length
count      4610.000000
mean         78.490456
std          37.470874
min          20.000000
25%          58.000000
50%          73.000000
75%          90.000000
max         348.000000
Prompt length:  108
[2026-07-29 09:24:17,392] stat1010/INFO/locust.main: Run time limit set to 240 seconds
[2026-07-29 09:24:17,392] stat1010/INFO/locust.main: Starting Locust 2.31.5
[2026-07-29 09:24:17,393] stat1010/INFO/locust.runners: Ramping to 10 users at a rate of 10.00 per second
[2026-07-29 09:24:17,393] stat1010/INFO/locust.runners: All users spawned: {"Embeddings": 10} (10 total users)
[2026-07-29 09:28:16,893] stat1010/INFO/locust.main: --run-time limit reached, shutting down
Load test results are within the threshold
[2026-07-29 09:28:17,008] stat1010/INFO/locust.main: Shutting down (exit code 0)
Type     Name                                                                          # reqs      # fails |    Avg     Min     Max    Med |   req/s  failures/s
--------|----------------------------------------------------------------------------|-------|-------------|-------|-------|-------|-------|--------|-----------
POST     /v1/models/jina-embedding:predict                                              22817     0(0.00%) |     53      12     347     52 |   95.24        0.00
--------|----------------------------------------------------------------------------|-------|-------------|-------|-------|-------|-------|--------|-----------
         Aggregated                                                                     22817     0(0.00%) |     53      12     347     52 |   95.24        0.00

Response time percentiles (approximated)
Type     Name                                                                                  50%    66%    75%    80%    90%    95%    98%    99%  99.9% 99.99%   100% # reqs
--------|--------------------------------------------------------------------------------|--------|------|------|------|------|------|------|------|------|------|------|------
POST     /v1/models/jina-embedding:predict                                                      52     58     61     64     70     75     82     92    310    340    350  22817
--------|--------------------------------------------------------------------------------|--------|------|------|------|------|------|------|------|------|------|------|------
         Aggregated                                                                             52     58     61     64     70     75     82     92    310    340    350  22817

Change #1319042 merged by jenkins-bot:

[machinelearning/liftwing/inference-services@main] embeddings: Parameterize Locust test for multiple embedding models

https://gerrit.wikimedia.org/r/1319042

Change #1319056 had a related patch set uploaded (by Ozge; author: Ozge):

[machinelearning/liftwing/inference-services@main] embeddings: Switch Jina embeddings to SentenceTransformers backend - Clean up.

https://gerrit.wikimedia.org/r/1319056

Change #1319056 merged by jenkins-bot:

[machinelearning/liftwing/inference-services@main] embeddings: Switch Jina embeddings to SentenceTransformers backend - Clean up.

https://gerrit.wikimedia.org/r/1319056

Change #1319061 had a related patch set uploaded (by Ozge; author: Ozge):

[operations/deployment-charts@master] ml-services: Add jina-embeddings production isvc to llm namespace

https://gerrit.wikimedia.org/r/1319061

Change #1319061 merged by jenkins-bot:

[operations/deployment-charts@master] ml-services: Add jina-embeddings production isvc to llm namespace

https://gerrit.wikimedia.org/r/1319061

I've removed ml-serve1012 and interesting that the response time has increased from ~50 ms to ~5 seconds. I'll set ml-serve1012 to see if this is the issue.

response_time: 5.714561s
ozge@stat1010:~$ curl "https://inference.svc.eqiad.wmnet:30443/v1/models/jina-embeddings:predict"   -X POST   -d '{"input": ["hello world"]}'   -H "Host: jina-embeddings.llm.wikimedia.org"   -H "Content-Type: application/json"   --http1.1   -w "\nresponse_time: %{time_total}s\n"
ozge@deploy1003:~$ kubectl get pod -l serving.kserve.io/inferenceservice=jina-embeddings   -o wide
NAME                                                          READY   STATUS    RESTARTS   AGE   IP            NODE                       NOMINATED NODE   READINESS GATES
jina-embeddings-predictor-00001-deployment-5c44b6bf55-89cq6   3/3     Running   0          14m   10.67.19.95   ml-serve1014.eqiad.wmnet   <none>           <none>

confirmed that the high performance results (close to current prod) are from ml-serve1012 (192GB).
The latency increases to ~5 seconds (not acceptable for prod) when we place the app to another node (24GB).

Change #1319437 had a related patch set uploaded (by Ozge; author: Ozge):

[machinelearning/liftwing/inference-services@main] embeddings: Log GPU memory usage during load and inference

https://gerrit.wikimedia.org/r/1319437

Change #1319437 merged by Ozge:

[machinelearning/liftwing/inference-services@main] embeddings: Log GPU memory usage during load and inference

https://gerrit.wikimedia.org/r/1319437

Change #1319443 had a related patch set uploaded (by Ozge; author: Ozge):

[operations/deployment-charts@master] ml-services: Upgrade jina-embeddings-staging image to log GPU memory

https://gerrit.wikimedia.org/r/1319443

Change #1319443 merged by Ozge:

[operations/deployment-charts@master] ml-services: Upgrade jina-embeddings-staging image to log GPU memory

https://gerrit.wikimedia.org/r/1319443

this does not seem to be a memory issue as peak values are low and free memory is high.
from jina-embeddings-staging:

INFO:root:Performing inference (sentences=2 total_chars=31 max_chars=20)...
INFO:root:GPU mem [before_encode] device='AMD Radeon Graphics': allocated=0.477 GiB (2.0%) reserved=0.494 GiB (2.1%) slack=0.017 GiB peak_allocated=0.477 GiB (2.0%) peak_reserved=0.494 GiB device_used=1.496 GiB (6.2%) device_free=22.504 GiB device_total=24.000 GiB inactive_split=0.017 GiB ooms=0 alloc_retries=0
Batches: 100%|██████████| 1/1 [00:11<00:00, 11.53s/it]
INFO:root:GPU mem [after_encode] device='AMD Radeon Graphics': allocated=0.477 GiB (2.0%) reserved=0.494 GiB (2.1%) slack=0.017 GiB peak_allocated=0.478 GiB (2.0%) peak_reserved=0.494 GiB device_used=1.506 GiB (6.3%) device_free=22.494 GiB device_total=24.000 GiB inactive_split=0.017 GiB ooms=0 alloc_retries=0
2026-07-30 11:08:07.558 1 kserve.trace requestId: e6f98a34-b541-48d8-954f-fc28fe0d0fcb, preprocess_ms: 0.012159348, explain_ms: 0, predict_ms: 11531.426668167, postprocess_ms: 0.026941299
2026-07-30 11:08:07.559 uvicorn.access INFO:     127.0.0.6:0 1 - "POST /v1/models/jina-embeddings-staging%3Apredict HTTP/1.1" 200 OK
2

Change #1319448 had a related patch set uploaded (by Ozge; author: Ozge):

[operations/deployment-charts@master] ml-services: Tune jina-embeddings vLLM dtype and attention backend

https://gerrit.wikimedia.org/r/1319448

Change #1319448 merged by Ozge:

[operations/deployment-charts@master] ml-services: Tune jina-embeddings vLLM dtype and attention backend

https://gerrit.wikimedia.org/r/1319448

Change #1319452 had a related patch set uploaded (by Ozge; author: Ozge):

[operations/deployment-charts@master] ml-services: Tune jina-embeddings vLLM dtype and attention backend

https://gerrit.wikimedia.org/r/1319452

Change #1319452 merged by Ozge:

[operations/deployment-charts@master] ml-services: Tune jina-embeddings vLLM dtype and attention backend

https://gerrit.wikimedia.org/r/1319452

Change #1319456 had a related patch set uploaded (by Ozge; author: Ozge):

[machinelearning/liftwing/inference-services@main] embeddings: Log model parameter and buffer device placement

https://gerrit.wikimedia.org/r/1319456

Change #1319456 merged by Ozge:

[machinelearning/liftwing/inference-services@main] embeddings: Log model parameter and buffer device placement

https://gerrit.wikimedia.org/r/1319456

Change #1319491 had a related patch set uploaded (by Ozge; author: Ozge):

[operations/deployment-charts@master] ml-services: jina-embeddings-staging getting back to the previous image

https://gerrit.wikimedia.org/r/1319491

Change #1319491 merged by Ozge:

[operations/deployment-charts@master] ml-services: jina-embeddings-staging getting back to the previous image

https://gerrit.wikimedia.org/r/1319491

Change #1319808 had a related patch set uploaded (by Ozge; author: Ozge):

[operations/deployment-charts@master] ml-services: Set TORCH_BLAS_PREFER_HIPBLASLT=0 for jina-embeddings-v5-text-nano

https://gerrit.wikimedia.org/r/1319808

Change #1319808 merged by Ozge:

[operations/deployment-charts@master] ml-services: Set TORCH_BLAS_PREFER_HIPBLASLT=0 for jina-embeddings-v5-text-nano

https://gerrit.wikimedia.org/r/1319808

attention eager after TORCH_BLAS_PREFER_HIPBLASLT=0 fix.

(venv) ozge@stat1010:~/repos/wiki/gerrit/inference-services/test/locust$ MODEL=embeddings locust --host https://inference.svc.eqiad.wmnet:30443 --users 10 --run-time 4m
Min length: 10, Max length: 350
       question_length
count      4610.000000
mean         78.490456
std          37.470874
min          20.000000
25%          58.000000
50%          73.000000
75%          90.000000
max         348.000000
Prompt length:  108
[2026-07-31 10:33:08,628] stat1010/INFO/locust.main: Run time limit set to 240 seconds
[2026-07-31 10:33:08,628] stat1010/INFO/locust.main: Starting Locust 2.31.5
[2026-07-31 10:33:08,628] stat1010/INFO/locust.runners: Ramping to 10 users at a rate of 10.00 per second
[2026-07-31 10:33:08,629] stat1010/INFO/locust.runners: All users spawned: {"Embeddings": 10} (10 total users)
[2026-07-31 10:37:08,040] stat1010/INFO/locust.main: --run-time limit reached, shutting down
Load test results are within the threshold
[2026-07-31 10:37:08,144] stat1010/INFO/locust.main: Shutting down (exit code 1)
Type     Name                                                                          # reqs      # fails |    Avg     Min     Max    Med |   req/s  failures/s
--------|----------------------------------------------------------------------------|-------|-------------|-------|-------|-------|-------|--------|-----------
POST     /v1/models/jina-embeddings:predict                                             27011     1(0.00%) |     37      10     614     36 |  112.79        0.00
--------|----------------------------------------------------------------------------|-------|-------------|-------|-------|-------|-------|--------|-----------
         Aggregated                                                                     27011     1(0.00%) |     37      10     614     36 |  112.79        0.00

Response time percentiles (approximated)
Type     Name                                                                                  50%    66%    75%    80%    90%    95%    98%    99%  99.9% 99.99%   100% # reqs
--------|--------------------------------------------------------------------------------|--------|------|------|------|------|------|------|------|------|------|------|------
POST     /v1/models/jina-embeddings:predict                                                     36     41     44     47     52     57     63     70    300    560    610  27011
--------|--------------------------------------------------------------------------------|--------|------|------|------|------|------|------|------|------|------|------|------
         Aggregated                                                                             36     41     44     47     52     57     63     70    300    560    610  27011

Error report
# occurrences      Error
------------------|---------------------------------------------------------------------------------------------------------------------------------------------
1                  POST /v1/models/jina-embeddings:predict: BadStatusCode('https://inference.svc.eqiad.wmnet:30443/v1/models/jina-embeddings:predict', code=502)
------------------|---------------------------------------------------------------------------------------------------------------------------------------------

Change #1319810 had a related patch set uploaded (by Ozge; author: Ozge):

[operations/deployment-charts@master] ml-services: Set ATTN_IMPLEMENTATION=sdpa for jina-embeddings

https://gerrit.wikimedia.org/r/1319810

Change #1319810 merged by Ozge:

[operations/deployment-charts@master] ml-services: Set ATTN_IMPLEMENTATION=sdpa for jina-embeddings

https://gerrit.wikimedia.org/r/1319810

attention sdpa after TORCH_BLAS_PREFER_HIPBLASLT=0 fix.

sdpa is slightly better than eager.

  • prod: 95 percentile latency is 70 ms with 98.90 req/s
  • jina: 95 percentile latency is 50 ms with 119.90 req/s
(venv) ozge@stat1010:~/repos/wiki/gerrit/inference-services/test/locust$ MODEL=embeddings locust --host https://inference.svc.eqiad.wmnet:30443 --users 10 --run-time 4m
Min length: 10, Max length: 350
       question_length
count      4610.000000
mean         78.490456
std          37.470874
min          20.000000
25%          58.000000
50%          73.000000
75%          90.000000
max         348.000000
Prompt length:  108
[2026-07-31 10:43:33,056] stat1010/INFO/locust.main: Run time limit set to 240 seconds
[2026-07-31 10:43:33,056] stat1010/INFO/locust.main: Starting Locust 2.31.5
[2026-07-31 10:43:33,057] stat1010/INFO/locust.runners: Ramping to 10 users at a rate of 10.00 per second
[2026-07-31 10:43:33,057] stat1010/INFO/locust.runners: All users spawned: {"Embeddings": 10} (10 total users)
[2026-07-31 10:47:32,489] stat1010/INFO/locust.main: --run-time limit reached, shutting down
Load test results are within the threshold
[2026-07-31 10:47:32,637] stat1010/INFO/locust.main: Shutting down (exit code 0)
Type     Name                                                                          # reqs      # fails |    Avg     Min     Max    Med |   req/s  failures/s
--------|----------------------------------------------------------------------------|-------|-------------|-------|-------|-------|-------|--------|-----------
POST     /v1/models/jina-embeddings:predict                                             28721     0(0.00%) |     32       9     357     29 |  119.90        0.00
--------|----------------------------------------------------------------------------|-------|-------------|-------|-------|-------|-------|--------|-----------
         Aggregated                                                                     28721     0(0.00%) |     32       9     357     29 |  119.90        0.00

Response time percentiles (approximated)
Type     Name                                                                                  50%    66%    75%    80%    90%    95%    98%    99%  99.9% 99.99%   100% # reqs
--------|--------------------------------------------------------------------------------|--------|------|------|------|------|------|------|------|------|------|------|------
POST     /v1/models/jina-embeddings:predict                                                     29     34     37     39     45     50     57    250    290    310    360  28721
--------|--------------------------------------------------------------------------------|--------|------|------|------|------|------|------|------|------|------|------|------
         Aggregated                                                                             29     34     37     39     45     50     57    250    290    310    360  28721

Change #1319834 had a related patch set uploaded (by Ozge; author: Ozge):

[machinelearning/liftwing/inference-services@main] embeddings: Remove temporary GPU memory debug logging

https://gerrit.wikimedia.org/r/1319834

Change #1319834 merged by jenkins-bot:

[machinelearning/liftwing/inference-services@main] embeddings: Remove temporary GPU memory debug logging

https://gerrit.wikimedia.org/r/1319834

Change #1319971 had a related patch set uploaded (by Ozge; author: Ozge):

[operations/deployment-charts@master] ml-services: update jina-embeddings image and tune staging inference config

https://gerrit.wikimedia.org/r/1319971

Change #1319971 merged by jenkins-bot:

[operations/deployment-charts@master] ml-services: update jina-embeddings image and tune staging inference config

https://gerrit.wikimedia.org/r/1319971

I'm closing this task as we have deployed Jina Nano embeddings to liftwing successfully.

After some performance improvements, we managed to serve Jina Nano on Liftwing with the following stats:

jina: 95 percentile latency is 50 ms with 119.90 req/s
prod: 95 percentile latency is 70 ms with 98.90 req/s

Good news is that it's faster than current prod.

A sample request would be:

ozge@stat1010:~$ curl "https://inference.svc.eqiad.wmnet:30443/v1/models/jina-embeddings:predict"   -X POST   -d '{"input": ["hello world"]}'   -H "Host: jina-embeddings.llm.wikimedia.org"   -H "Content-Type: application/json"   --http1.1   -w "\nresponse_time: %{time_total}s\n"