omnius 1.0.633 → 1.0.634

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -154,7 +154,12 @@ def read_wav(path: str, np):
154
154
  raise RuntimeError(
155
155
  f"Expected at most 6 seconds of caller-conditioned audio, received {waveform.size / sample_rate:.3f} seconds"
156
156
  )
157
- return waveform, sample_rate, (time.perf_counter() - started) * 1000
157
+ return (
158
+ waveform,
159
+ sample_rate,
160
+ (time.perf_counter() - started) * 1000,
161
+ "sha256:" + hashlib.sha256(raw).hexdigest(),
162
+ )
158
163
 
159
164
 
160
165
  class YAMNetTensorRT:
@@ -193,6 +198,8 @@ class YAMNetTensorRT:
193
198
  self.output_names.append(name)
194
199
  if self.input_name is None or not self.output_names:
195
200
  raise RuntimeError("YAMNet TensorRT engine did not expose input and output tensors")
201
+ self.score_output_name = self._unique_output_name(521, "AudioSet score")
202
+ self.embedding_output_name = self._unique_output_name(1024, "YAMNet embedding")
196
203
  with open(class_map_path, newline="", encoding="utf8") as handle:
197
204
  self.classes = [row["display_name"] for row in csv.DictReader(handle)]
198
205
  if len(self.classes) != 521:
@@ -205,13 +212,28 @@ class YAMNetTensorRT:
205
212
  # namespace to exactly the approved Jetson GPU before process launch.
206
213
  return self.cuda.device_metadata()
207
214
 
215
+ def _unique_output_name(self, width: int, label: str):
216
+ matches = []
217
+ for name in self.output_names:
218
+ shape = tuple(self.engine.get_tensor_shape(name))
219
+ if shape and int(shape[-1]) == width:
220
+ matches.append(name)
221
+ if len(matches) != 1:
222
+ raise RuntimeError(
223
+ f"YAMNet TensorRT engine must expose exactly one {label} output with width {width}; found {matches}"
224
+ )
225
+ return matches[0]
226
+
208
227
  def warm(self):
209
228
  # YAMNet needs >=0.975 seconds. This is a model-load probe, not a
210
229
  # captured-audio classification, and it verifies the TensorRT path is
211
230
  # actually executable before readiness is reported.
212
- self.infer(self.np.zeros(15600, dtype=self.np.float32), 1)
231
+ # Exercise and validate both exported model heads before reporting the
232
+ # persistent worker as ready. A stale score-only plan must fail here,
233
+ # rather than after an embedding caller has acquired the queue slot.
234
+ self.infer(self.np.zeros(15600, dtype=self.np.float32), 1, include_embedding=True)
213
235
 
214
- def infer(self, waveform, top_k: int):
236
+ def infer(self, waveform, top_k: int | None = None, include_embedding: bool = False):
215
237
  started = time.perf_counter()
216
238
  np = self.np
217
239
  if waveform.ndim != 1 or waveform.size < 15600:
@@ -246,16 +268,34 @@ class YAMNetTensorRT:
246
268
  for name, (host, device) in host_outputs.items():
247
269
  self.cuda.d2h(host, device, self.stream, name)
248
270
  self.cuda.synchronize(self.stream)
249
- # The converted Google model exposes output_0 with AudioSet scores.
250
- scores = next((value[0] for name, value in host_outputs.items() if value[0].shape[-1] == 521), None)
251
- if scores is None:
252
- raise RuntimeError("TensorRT YAMNet engine did not produce a 521-class score tensor")
253
- mean_scores = np.mean(scores, axis=0)
254
- indices = np.argsort(mean_scores)[-top_k:][::-1]
255
- return [
256
- {"label": self.classes[int(index)], "confidence": float(mean_scores[int(index)])}
257
- for index in indices
258
- ], (time.perf_counter() - started) * 1000
271
+ result = {}
272
+ if top_k is not None:
273
+ scores = host_outputs[self.score_output_name][0]
274
+ if scores.ndim != 2 or scores.shape[-1] != 521:
275
+ raise RuntimeError(f"YAMNet score output shape is invalid: {scores.shape}")
276
+ mean_scores = np.mean(scores, axis=0)
277
+ indices = np.argsort(mean_scores)[-top_k:][::-1]
278
+ result["classifications"] = [
279
+ {"label": self.classes[int(index)], "confidence": float(mean_scores[int(index)])}
280
+ for index in indices
281
+ ]
282
+ if include_embedding:
283
+ frame_embeddings = host_outputs[self.embedding_output_name][0]
284
+ if frame_embeddings.ndim != 2 or frame_embeddings.shape[-1] != 1024 or frame_embeddings.shape[0] < 1:
285
+ raise RuntimeError(f"YAMNet embedding output shape is invalid: {frame_embeddings.shape}")
286
+ vector = np.mean(frame_embeddings.astype(np.float32, copy=False), axis=0)
287
+ norm = float(np.linalg.norm(vector))
288
+ if not np.isfinite(norm) or norm <= 0.0:
289
+ raise RuntimeError("YAMNet embedding has an invalid L2 norm")
290
+ result["embedding"] = {
291
+ "dimension": 1024,
292
+ "frame_count": int(frame_embeddings.shape[0]),
293
+ "pooling": "mean_l2",
294
+ "dtype": "float32",
295
+ "normalization": "l2",
296
+ "values": (vector / norm).astype(np.float32).tolist(),
297
+ }
298
+ return result, (time.perf_counter() - started) * 1000
259
299
  finally:
260
300
  for allocation in allocations:
261
301
  try:
@@ -307,40 +347,48 @@ def main() -> int:
307
347
  if request.get("type") == "shutdown":
308
348
  emit({"type": "stopped"})
309
349
  return 0
310
- if request.get("type") != "classify":
311
- raise RuntimeError("unknown request type")
350
+ action = str(request.get("action") or request.get("type") or "").strip().lower()
351
+ if action not in ("classify", "embed"):
352
+ raise RuntimeError("unknown audio analysis action")
312
353
  request_id = str(request.get("id") or "")
313
354
  file_path = str(request.get("file") or "")
314
355
  if not request_id or not file_path:
315
- raise RuntimeError("classify requires id and file")
316
- waveform, sample_rate, decode_ms = read_wav(file_path, worker.np)
356
+ raise RuntimeError("audio analysis requires id and file")
357
+ waveform, sample_rate, decode_ms, input_digest = read_wav(file_path, worker.np)
317
358
  rms = float(worker.np.sqrt(worker.np.mean(worker.np.square(waveform)))) if waveform.size else 0.0
318
359
  peak = float(worker.np.max(worker.np.abs(waveform))) if waveform.size else 0.0
319
360
  # Do not force YAMNet to invent an AudioSet label for digital or
320
361
  # near-digital silence. This remains a valid, grounded result.
321
362
  low_information = rms < 0.0005 and peak < 0.002
322
363
  if low_information:
323
- classifications, inference_ms = [], 0.0
364
+ result, inference_ms = (
365
+ {"classifications": []} if action == "classify" else {"embedding": None},
366
+ 0.0,
367
+ )
324
368
  else:
325
- classifications, inference_ms = worker.infer(
369
+ result, inference_ms = worker.infer(
326
370
  waveform,
327
- max(1, min(int(request.get("top_k", 5)), 25)),
371
+ top_k=max(1, min(int(request.get("top_k", 5)), 25)) if action == "classify" else None,
372
+ include_embedding=action == "embed",
328
373
  )
329
374
  emit({
330
375
  "type": "result",
331
376
  "id": request_id,
377
+ "action": action,
332
378
  "success": True,
333
379
  "sample_rate_hz": sample_rate,
334
380
  "duration_seconds": round(float(waveform.size) / sample_rate, 6),
335
- "classifications": classifications,
381
+ "input_digest": input_digest,
336
382
  "low_information": low_information,
337
383
  "acoustic": {"rms": round(rms, 8), "peak": round(peak, 8)},
338
384
  "timings_ms": {"decode": round(decode_ms, 3), "inference": round(inference_ms, 3)},
385
+ **result,
339
386
  })
340
387
  except Exception as exc: # keep the persistent worker alive per request
341
388
  emit({
342
389
  "type": "result",
343
390
  "id": str(locals().get("request", {}).get("id", "")),
391
+ "action": str(locals().get("action", "")),
344
392
  "success": False,
345
393
  "error": str(exc),
346
394
  })
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env python3
2
+ import sys, json, base64, io
3
+ try:
4
+ import torch
5
+ import open_clip
6
+ from PIL import Image
7
+ except Exception as e:
8
+ print(json.dumps({"error":"deps_missing","message":str(e)}))
9
+ sys.exit(0)
10
+
11
+ def load_image_from_input(data):
12
+ if data.get('path'):
13
+ return Image.open(data['path']).convert('RGB')
14
+ if data.get('bytesBase64'):
15
+ b = base64.b64decode(data['bytesBase64'])
16
+ return Image.open(io.BytesIO(b)).convert('RGB')
17
+ raise RuntimeError('no input provided')
18
+
19
+ def main():
20
+ raw = sys.stdin.read()
21
+ data = json.loads(raw) if raw.strip() else {}
22
+ image = load_image_from_input(data)
23
+ model, _, preprocess = open_clip.create_model_and_transforms('ViT-B-32', pretrained='laion2b_s34b_b79k')
24
+ model.eval()
25
+ with torch.no_grad():
26
+ img_t = preprocess(image).unsqueeze(0)
27
+ emb = model.encode_image(img_t)
28
+ emb = emb / emb.norm(dim=-1, keepdim=True)
29
+ arr = emb.squeeze(0).cpu().numpy().astype('float32').tolist()
30
+ print(json.dumps({"embedding": arr}))
31
+
32
+ if __name__ == '__main__':
33
+ main()
34
+
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env python3
2
+ import sys, json
3
+ try:
4
+ import torch
5
+ import open_clip
6
+ except Exception as e:
7
+ print(json.dumps({"error":"deps_missing","message":str(e)}))
8
+ sys.exit(0)
9
+
10
+ def main():
11
+ raw = sys.stdin.read()
12
+ data = json.loads(raw) if raw.strip() else {}
13
+ text = data.get('text') or ''
14
+ model, _, preprocess = open_clip.create_model_and_transforms('ViT-B-32', pretrained='laion2b_s34b_b79k')
15
+ tokenizer = open_clip.get_tokenizer('ViT-B-32')
16
+ model.eval()
17
+ with torch.no_grad():
18
+ tokens = tokenizer([text])
19
+ emb = model.encode_text(tokens)
20
+ emb = emb / emb.norm(dim=-1, keepdim=True)
21
+ arr = emb.squeeze(0).cpu().numpy().astype('float32').tolist()
22
+ print(json.dumps({"embedding": arr}))
23
+
24
+ if __name__ == '__main__':
25
+ main()
26
+
@@ -245085,6 +245085,24 @@ var MODEL_URL = `https://huggingface.co/zeropointnine/yamnet-onnx/resolve/${MODE
245085
245085
  var CLASS_MAP_URL = `https://huggingface.co/zeropointnine/yamnet-onnx/resolve/${MODEL_REVISION}/yamnet_class_map.csv`;
245086
245086
  var SETUP_TIMEOUT_MS = 20 * 6e4;
245087
245087
 
245088
+ // packages/execution/dist/speaker-diarization-runtime.js
245089
+ init_model_store();
245090
+
245091
+ // packages/execution/dist/audio-semantic-embedding-runtime.js
245092
+ init_process_async();
245093
+ init_model_store();
245094
+ init_venv_paths();
245095
+ var SETUP_TIMEOUT_MS2 = 30 * 6e4;
245096
+
245097
+ // packages/execution/dist/speaker-embedding-runtime.js
245098
+ init_jetson_monitor();
245099
+ init_process_async();
245100
+ init_model_store();
245101
+ init_venv_paths();
245102
+ var MODEL_REVISION2 = "acf623ad8ca746e50baa432255cf8fc57c669c45";
245103
+ var MODEL_URL2 = `https://huggingface.co/Wespeaker/wespeaker-voxceleb-campplus/resolve/${MODEL_REVISION2}/voxceleb_CAM%2B%2B.onnx`;
245104
+ var SETUP_TIMEOUT_MS3 = 10 * 6e4;
245105
+
245088
245106
  // packages/execution/dist/ocr-advanced-runtime.js
245089
245107
  init_process_async();
245090
245108
  init_jetson_monitor();
@@ -290433,6 +290451,21 @@ except Exception as exc:
290433
290451
  sys.exit(1)
290434
290452
  `;
290435
290453
 
290454
+ // packages/memory/dist/audioNoveltyPrototype.js
290455
+ var AUDIO_NOVELTY_WEIGHTS = Object.freeze({
290456
+ distance: 0.6,
290457
+ uncertainty: 0.1,
290458
+ recurrence: 0.15,
290459
+ direction: 0.075,
290460
+ scene: 0.075
290461
+ });
290462
+
290463
+ // packages/memory/dist/speakerIdentityStore.js
290464
+ var DEFAULT_THRESHOLDS = Object.freeze({
290465
+ provisional: 0.78,
290466
+ ambiguityMargin: 0.04
290467
+ });
290468
+
290436
290469
  // packages/memory/dist/crl/index.js
290437
290470
  var CRL_SYMBOLS = {
290438
290471
  // Logical operators (Core)