Feature Extraction
Transformers
Safetensors
sentence-transformers
multilingual
llava_eurobert_audio
embedding
jina-embeddings-v5
multimodal
vision
audio
vllm
video
image-feature-extraction
audio-feature-extraction
video-feature-extraction
sentence-similarity
custom_code
🇪🇺 Region: EU
Instructions to use jinaai/jina-embeddings-v5-omni-nano-text-matching with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use jinaai/jina-embeddings-v5-omni-nano-text-matching with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("feature-extraction", model="jinaai/jina-embeddings-v5-omni-nano-text-matching", trust_remote_code=True)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("jinaai/jina-embeddings-v5-omni-nano-text-matching", trust_remote_code=True, device_map="auto") - sentence-transformers
How to use jinaai/jina-embeddings-v5-omni-nano-text-matching with sentence-transformers:
from sentence_transformers import SentenceTransformer model = SentenceTransformer("jinaai/jina-embeddings-v5-omni-nano-text-matching", trust_remote_code=True) sentences = [ "The weather is lovely today.", "It's so sunny outside!", "He drove to the stadium." ] embeddings = model.encode(sentences) similarities = model.similarity(embeddings, embeddings) print(similarities.shape) # [3, 3] - Notebooks
- Google Colab
- Kaggle
sync custom_st.py from harness/src/hf_sources/nano_variant
Browse files- custom_st.py +5 -57
custom_st.py
CHANGED
|
@@ -419,34 +419,6 @@ def _build_audio_model_inputs(owner, audio_input, device, prefix: str = ""):
|
|
| 419 |
return inputs
|
| 420 |
|
| 421 |
|
| 422 |
-
def _extract_audio_from_video(video_path):
|
| 423 |
-
"""Return mono float32 audio @ 16 kHz decoded from the video's audio track, or
|
| 424 |
-
None if no audio stream is present. PyAV is already a dep for video decoding."""
|
| 425 |
-
try:
|
| 426 |
-
import av
|
| 427 |
-
import numpy as np
|
| 428 |
-
from av.audio.resampler import AudioResampler
|
| 429 |
-
except ImportError:
|
| 430 |
-
return None
|
| 431 |
-
container = av.open(video_path)
|
| 432 |
-
try:
|
| 433 |
-
audio_stream = next((s for s in container.streams if s.type == "audio"), None)
|
| 434 |
-
if audio_stream is None:
|
| 435 |
-
return None
|
| 436 |
-
resampler = AudioResampler(format="flt", layout="mono", rate=16000)
|
| 437 |
-
samples = []
|
| 438 |
-
for frame in container.decode(audio=0):
|
| 439 |
-
for rf in resampler.resample(frame):
|
| 440 |
-
samples.append(rf.to_ndarray().flatten())
|
| 441 |
-
for rf in resampler.resample(None):
|
| 442 |
-
samples.append(rf.to_ndarray().flatten())
|
| 443 |
-
if not samples:
|
| 444 |
-
return None
|
| 445 |
-
return np.concatenate(samples).astype(np.float32)
|
| 446 |
-
finally:
|
| 447 |
-
container.close()
|
| 448 |
-
|
| 449 |
-
|
| 450 |
def _eval_video_frames(video_path):
|
| 451 |
if not isinstance(video_path, str):
|
| 452 |
return video_path
|
|
@@ -692,7 +664,7 @@ class Transformer(nn.Module):
|
|
| 692 |
if first_kind == "image":
|
| 693 |
return {"_images": values, "_is_image_batch": True}
|
| 694 |
if first_kind == "video":
|
| 695 |
-
return {"
|
| 696 |
if first_kind == "audio":
|
| 697 |
return {"_audio_paths": values, "_is_audio_batch": True}
|
| 698 |
if first_kind == "pdf":
|
|
@@ -727,18 +699,6 @@ class Transformer(nn.Module):
|
|
| 727 |
hidden = self.model(**inputs).last_hidden_state
|
| 728 |
return self._last_token_pool(hidden, inputs["attention_mask"]).squeeze(0)
|
| 729 |
|
| 730 |
-
def _encode_single_video(self, video_path, device) -> torch.Tensor:
|
| 731 |
-
video = _eval_video_frames(video_path)
|
| 732 |
-
inputs = self.processor(videos=video, text=VIDEO_PROMPT, return_tensors="pt", truncation=False)
|
| 733 |
-
inputs = {k: v.to(device) for k, v in inputs.items() if torch.is_tensor(v)}
|
| 734 |
-
if "pixel_values_videos" in inputs:
|
| 735 |
-
inputs["pixel_values"] = inputs.pop("pixel_values_videos")
|
| 736 |
-
if "video_grid_thw" in inputs:
|
| 737 |
-
inputs["image_grid_thw"] = inputs.pop("video_grid_thw")
|
| 738 |
-
with torch.no_grad():
|
| 739 |
-
hidden = self.model(**inputs).last_hidden_state
|
| 740 |
-
return self._last_token_pool(hidden, inputs["attention_mask"]).squeeze(0)
|
| 741 |
-
|
| 742 |
def _encode_single_audio(self, audio_input, device, prefix: str = "") -> torch.Tensor:
|
| 743 |
inputs = _build_audio_model_inputs(self, audio_input, device, prefix=prefix)
|
| 744 |
with torch.no_grad():
|
|
@@ -875,9 +835,9 @@ class Transformer(nn.Module):
|
|
| 875 |
|
| 876 |
Each part may be a URL, a local path (sniffed by magic bytes if no
|
| 877 |
extension), a PIL.Image, a 1-D numpy audio array, a PDF (rasterised
|
| 878 |
-
to one image per page), or plain text. A video
|
| 879 |
-
|
| 880 |
-
|
| 881 |
"""
|
| 882 |
import numpy as np
|
| 883 |
from transformers import WhisperFeatureExtractor
|
|
@@ -885,17 +845,10 @@ class Transformer(nn.Module):
|
|
| 885 |
# Normalize every part first (URL -> path, content-sniff if needed).
|
| 886 |
resolved = [_resolve_input(p) for p in parts]
|
| 887 |
|
| 888 |
-
# Expand videos-with-audio: prepend extracted audio.
|
| 889 |
# Expand PDFs: rasterise into one image-part per page.
|
| 890 |
expanded = []
|
| 891 |
for kind, value in resolved:
|
| 892 |
-
if kind == "
|
| 893 |
-
if isinstance(value, str):
|
| 894 |
-
aud = _extract_audio_from_video(value)
|
| 895 |
-
if aud is not None and aud.size > 0:
|
| 896 |
-
expanded.append(("audio", aud))
|
| 897 |
-
expanded.append(("video", value))
|
| 898 |
-
elif kind == "pdf":
|
| 899 |
for page in _pdf_to_images(value):
|
| 900 |
expanded.append(("image", page))
|
| 901 |
else:
|
|
@@ -937,11 +890,6 @@ class Transformer(nn.Module):
|
|
| 937 |
features["sentence_embedding"] = torch.stack(embs)
|
| 938 |
return self._maybe_truncate(features, truncate_dim)
|
| 939 |
|
| 940 |
-
if features.get("_is_video_batch"):
|
| 941 |
-
embs = [self._encode_single_video(p, device) for p in features["_video_paths"]]
|
| 942 |
-
features["sentence_embedding"] = torch.stack(embs)
|
| 943 |
-
return self._maybe_truncate(features, truncate_dim)
|
| 944 |
-
|
| 945 |
if features.get("_is_audio_batch"):
|
| 946 |
audio_items = features.get("_audio_paths") or features.get("_audio_wrappers", [])
|
| 947 |
embs = [self._encode_single_audio(a, device) for a in audio_items]
|
|
|
|
| 419 |
return inputs
|
| 420 |
|
| 421 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 422 |
def _eval_video_frames(video_path):
|
| 423 |
if not isinstance(video_path, str):
|
| 424 |
return video_path
|
|
|
|
| 664 |
if first_kind == "image":
|
| 665 |
return {"_images": values, "_is_image_batch": True}
|
| 666 |
if first_kind == "video":
|
| 667 |
+
return {"_multipart_batch": [(v,) for v in values], "_is_multipart_batch": True}
|
| 668 |
if first_kind == "audio":
|
| 669 |
return {"_audio_paths": values, "_is_audio_batch": True}
|
| 670 |
if first_kind == "pdf":
|
|
|
|
| 699 |
hidden = self.model(**inputs).last_hidden_state
|
| 700 |
return self._last_token_pool(hidden, inputs["attention_mask"]).squeeze(0)
|
| 701 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 702 |
def _encode_single_audio(self, audio_input, device, prefix: str = "") -> torch.Tensor:
|
| 703 |
inputs = _build_audio_model_inputs(self, audio_input, device, prefix=prefix)
|
| 704 |
with torch.no_grad():
|
|
|
|
| 835 |
|
| 836 |
Each part may be a URL, a local path (sniffed by magic bytes if no
|
| 837 |
extension), a PIL.Image, a 1-D numpy audio array, a PDF (rasterised
|
| 838 |
+
to one image per page), or plain text. A video contributes its frames
|
| 839 |
+
only; pass the soundtrack as its own part to fuse both, e.g.
|
| 840 |
+
`encode(("narration.wav", "clip.mp4"))`.
|
| 841 |
"""
|
| 842 |
import numpy as np
|
| 843 |
from transformers import WhisperFeatureExtractor
|
|
|
|
| 845 |
# Normalize every part first (URL -> path, content-sniff if needed).
|
| 846 |
resolved = [_resolve_input(p) for p in parts]
|
| 847 |
|
|
|
|
| 848 |
# Expand PDFs: rasterise into one image-part per page.
|
| 849 |
expanded = []
|
| 850 |
for kind, value in resolved:
|
| 851 |
+
if kind == "pdf":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 852 |
for page in _pdf_to_images(value):
|
| 853 |
expanded.append(("image", page))
|
| 854 |
else:
|
|
|
|
| 890 |
features["sentence_embedding"] = torch.stack(embs)
|
| 891 |
return self._maybe_truncate(features, truncate_dim)
|
| 892 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 893 |
if features.get("_is_audio_batch"):
|
| 894 |
audio_items = features.get("_audio_paths") or features.get("_audio_wrappers", [])
|
| 895 |
embs = [self._encode_single_audio(a, device) for a in audio_items]
|