florian-hoenicke commited on
Commit
3f1b892
·
verified ·
1 Parent(s): 7ed154d

sync custom_st.py from harness/src/hf_sources/nano_variant

Browse files
Files changed (1) hide show
  1. 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 {"_video_paths": values, "_is_video_batch": True}
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 with an audio track
879
- is auto-expanded to [extracted_audio, video] so the audio tokens
880
- precede the video tokens.
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 == "video":
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]