echo-vector 0.1.1__tar.gz → 1.0.3__tar.gz

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.
Files changed (67) hide show
  1. echo_vector-1.0.3/.claude/commands/release.md +15 -0
  2. {echo_vector-0.1.1 → echo_vector-1.0.3}/.gitignore +9 -0
  3. {echo_vector-0.1.1 → echo_vector-1.0.3}/PKG-INFO +5 -8
  4. {echo_vector-0.1.1 → echo_vector-1.0.3}/README.md +2 -2
  5. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/embeddings/clap.py +8 -20
  6. {echo_vector-0.1.1 → echo_vector-1.0.3}/pyproject.toml +3 -5
  7. echo_vector-1.0.3/tests/integration/__init__.py +0 -0
  8. {echo_vector-0.1.1 → echo_vector-1.0.3}/uv.lock +31 -36
  9. echo_vector-0.1.1/.claude/settings.json +0 -16
  10. echo_vector-0.1.1/demo.py +0 -76
  11. echo_vector-0.1.1/demo_audio/alert.wav +0 -0
  12. echo_vector-0.1.1/demo_audio/bass_talk.wav +0 -0
  13. echo_vector-0.1.1/demo_index/metadata.sqlite +0 -0
  14. /echo_vector-0.1.1/tests/__init__.py → /echo_vector-1.0.3/.claude/settings.json +0 -0
  15. {echo_vector-0.1.1 → echo_vector-1.0.3}/.github/workflows/workflow.yml +0 -0
  16. {echo_vector-0.1.1 → echo_vector-1.0.3}/.pre-commit-config.yaml +0 -0
  17. {echo_vector-0.1.1 → echo_vector-1.0.3}/.python-version +0 -0
  18. {echo_vector-0.1.1 → echo_vector-1.0.3}/CLAUDE.md +0 -0
  19. {echo_vector-0.1.1 → echo_vector-1.0.3}/Makefile +0 -0
  20. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/__init__.py +0 -0
  21. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/api/__init__.py +0 -0
  22. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/api/server.py +0 -0
  23. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/audio/__init__.py +0 -0
  24. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/audio/chunker.py +0 -0
  25. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/audio/metadata.py +0 -0
  26. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/audio/processor.py +0 -0
  27. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/audio/streaming.py +0 -0
  28. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/cli/__init__.py +0 -0
  29. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/cli/main.py +0 -0
  30. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/core.py +0 -0
  31. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/embeddings/__init__.py +0 -0
  32. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/embeddings/ast_model.py +0 -0
  33. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/embeddings/base.py +0 -0
  34. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/embeddings/cache.py +0 -0
  35. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/embeddings/factory.py +0 -0
  36. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/embeddings/hubert.py +0 -0
  37. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/embeddings/local.py +0 -0
  38. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/embeddings/wav2vec2.py +0 -0
  39. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/embeddings/whisper_enc.py +0 -0
  40. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/evaluation/__init__.py +0 -0
  41. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/evaluation/metrics.py +0 -0
  42. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/indexing/__init__.py +0 -0
  43. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/indexing/base.py +0 -0
  44. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/indexing/faiss_index.py +0 -0
  45. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/indexing/store.py +0 -0
  46. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/search/__init__.py +0 -0
  47. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/search/engine.py +0 -0
  48. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/search/filters.py +0 -0
  49. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/search/results.py +0 -0
  50. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/utils/__init__.py +0 -0
  51. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/utils/config.py +0 -0
  52. {echo_vector-0.1.1 → echo_vector-1.0.3}/echovector/utils/logging.py +0 -0
  53. {echo_vector-0.1.1/tests/integration → echo_vector-1.0.3/tests}/__init__.py +0 -0
  54. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/conftest.py +0 -0
  55. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/e2e/test_cli.py +0 -0
  56. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/fixtures/__init__.py +0 -0
  57. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/fixtures/audio_generators.py +0 -0
  58. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/integration/test_integration.py +0 -0
  59. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/test_audio.mp3 +0 -0
  60. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/unit/test_api.py +0 -0
  61. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/unit/test_audio_processor.py +0 -0
  62. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/unit/test_chunker.py +0 -0
  63. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/unit/test_core.py +0 -0
  64. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/unit/test_embeddings.py +0 -0
  65. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/unit/test_faiss_index.py +0 -0
  66. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/unit/test_results.py +0 -0
  67. {echo_vector-0.1.1 → echo_vector-1.0.3}/tests/unit/test_search_engine.py +0 -0
@@ -0,0 +1,15 @@
1
+ Run the full release pipeline: lint, typecheck, test, commit, tag, and push to trigger CI/CD publish to PyPI.
2
+
3
+ Usage: /release <version> (e.g. /release v0.1.3)
4
+
5
+ Steps:
6
+ 1. Verify a version argument was provided (format: vX.Y.Z)
7
+ 2. Run `uv run ruff format --check echovector/ tests/` and `uv run ruff check echovector/ tests/`
8
+ 3. Run `uv run mypy echovector/`
9
+ 4. Run `uv run pytest tests/ -m "not slow and not gpu" -q`
10
+ 5. If there are uncommitted changes, stage and commit them with message "release: $ARGUMENTS"
11
+ 6. Create git tag `$ARGUMENTS`
12
+ 7. Push the branch and the tag: `git push origin master` and `git push origin $ARGUMENTS`
13
+ 8. Report the tag that was pushed and remind the user to monitor CI at https://github.com/ahron-maslin/echo_vector/actions
14
+
15
+ If any step fails, stop and report the failure before proceeding.
@@ -65,3 +65,12 @@ Thumbs.db
65
65
 
66
66
  # Benchmark outputs
67
67
  benchmark_results/
68
+
69
+ # Demo artifacts
70
+ demo_audio/
71
+ demo_index/
72
+ demo.py
73
+
74
+ # EchoVector index stores
75
+ ev-index/
76
+ *-index/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: echo_vector
3
- Version: 0.1.1
3
+ Version: 1.0.3
4
4
  Summary: Semantic text search over audio files without full transcription
5
5
  Project-URL: Homepage, https://github.com/ahron-maslin/echo_vector
6
6
  Project-URL: Documentation, https://github.com/ahron-maslin/echo_vector#readme
@@ -30,7 +30,9 @@ Requires-Dist: pydantic<3,>=2.5
30
30
  Requires-Dist: pydub<1,>=0.25
31
31
  Requires-Dist: rich<14,>=13.7
32
32
  Requires-Dist: soundfile<1,>=0.12
33
+ Requires-Dist: torch<3,>=2.1
33
34
  Requires-Dist: tqdm<5,>=4.66
35
+ Requires-Dist: transformers<5,>=4.36
34
36
  Requires-Dist: typer[all]<1,>=0.12
35
37
  Provides-Extra: all
36
38
  Requires-Dist: fastapi<1,>=0.109; extra == 'all'
@@ -48,15 +50,10 @@ Requires-Dist: pytest-cov<6,>=5.0; extra == 'all'
48
50
  Requires-Dist: pytest-xdist<4,>=3.5; extra == 'all'
49
51
  Requires-Dist: pytest<9,>=8.0; extra == 'all'
50
52
  Requires-Dist: ruff<1,>=0.15; extra == 'all'
51
- Requires-Dist: torch<3,>=2.1; extra == 'all'
52
- Requires-Dist: transformers<5,>=4.36; extra == 'all'
53
53
  Requires-Dist: uvicorn[standard]<1,>=0.27; extra == 'all'
54
54
  Provides-Extra: api
55
55
  Requires-Dist: fastapi<1,>=0.109; extra == 'api'
56
56
  Requires-Dist: uvicorn[standard]<1,>=0.27; extra == 'api'
57
- Provides-Extra: clap
58
- Requires-Dist: torch<3,>=2.1; extra == 'clap'
59
- Requires-Dist: transformers<5,>=4.36; extra == 'clap'
60
57
  Provides-Extra: dev
61
58
  Requires-Dist: httpx2<3,>=2.0; extra == 'dev'
62
59
  Requires-Dist: hypothesis<7,>=6.92; extra == 'dev'
@@ -121,13 +118,13 @@ Text Query → Text Embedding ──────────────┘
121
118
  ### Installation
122
119
 
123
120
  ```bash
124
- pip install echovector
121
+ pip install echo_vector
125
122
  ```
126
123
 
127
124
  Or with uv:
128
125
 
129
126
  ```bash
130
- uv add echovector
127
+ uv add echo_vector
131
128
  ```
132
129
 
133
130
  ### CLI Usage
@@ -44,13 +44,13 @@ Text Query → Text Embedding ──────────────┘
44
44
  ### Installation
45
45
 
46
46
  ```bash
47
- pip install echovector
47
+ pip install echo_vector
48
48
  ```
49
49
 
50
50
  Or with uv:
51
51
 
52
52
  ```bash
53
- uv add echovector
53
+ uv add echo_vector
54
54
  ```
55
55
 
56
56
  ### CLI Usage
@@ -1,20 +1,16 @@
1
1
  """CLAP (Contrastive Language-Audio Pretraining) embedding backend."""
2
2
 
3
- from typing import cast
3
+ from typing import Any, cast
4
4
 
5
5
  import librosa
6
6
  import numpy as np
7
7
  import numpy.typing as npt
8
+ import torch
9
+ from transformers import ClapModel, ClapProcessor
8
10
 
9
11
  from echovector.embeddings.base import EmbeddingBackend
10
12
 
11
- try:
12
- import torch
13
- from transformers import ClapModel, ClapProcessor
14
-
15
- _CLAP_AVAILABLE = True
16
- except ImportError: # pragma: no cover
17
- _CLAP_AVAILABLE = False
13
+ _CLAP_AVAILABLE = True
18
14
 
19
15
 
20
16
  class ClapBackend(EmbeddingBackend):
@@ -33,22 +29,14 @@ class ClapBackend(EmbeddingBackend):
33
29
  Args:
34
30
  model_name: The Hugging Face model identifier.
35
31
  device: Device to run the model on (e.g., 'cpu', 'cuda').
36
-
37
- Raises:
38
- ImportError: If torch or transformers are not installed.
39
32
  """
40
- if not _CLAP_AVAILABLE:
41
- raise ImportError(
42
- "CLAP backend requires torch and transformers. "
43
- "Install them with: pip install 'echo_vector[clap]'"
44
- )
45
33
  if device is None:
46
34
  self.device = "cuda" if torch.cuda.is_available() else "cpu"
47
35
  else:
48
36
  self.device = device
49
37
 
50
- self.processor = ClapProcessor.from_pretrained(model_name)
51
- self.model = ClapModel.from_pretrained(model_name)
38
+ self.processor: Any = ClapProcessor.from_pretrained(model_name) # pyright: ignore[reportArgumentType]
39
+ self.model: Any = ClapModel.from_pretrained(model_name) # pyright: ignore[reportArgumentType]
52
40
  self.model.to(self.device)
53
41
  self.model.eval()
54
42
 
@@ -81,7 +69,7 @@ class ClapBackend(EmbeddingBackend):
81
69
 
82
70
  audios = [self._load_and_resample(path, target_sr) for path in audio_paths]
83
71
 
84
- inputs = self.processor(
72
+ inputs = cast("Any", self.processor)(
85
73
  audios=audios,
86
74
  return_tensors="pt",
87
75
  sampling_rate=target_sr,
@@ -107,7 +95,7 @@ class ClapBackend(EmbeddingBackend):
107
95
  Returns:
108
96
  A numpy array of shape (batch_size, embedding_dim).
109
97
  """
110
- inputs = self.processor(
98
+ inputs = cast("Any", self.processor)(
111
99
  text=texts,
112
100
  return_tensors="pt",
113
101
  padding=True,
@@ -37,13 +37,11 @@ dependencies = [
37
37
  "rich>=13.7,<14",
38
38
  "pydub>=0.25,<1",
39
39
  "tqdm>=4.66,<5",
40
- ]
41
-
42
- [project.optional-dependencies]
43
- clap = [
44
40
  "torch>=2.1,<3",
45
41
  "transformers>=4.36,<5",
46
42
  ]
43
+
44
+ [project.optional-dependencies]
47
45
  api = [
48
46
  "fastapi>=0.109,<1",
49
47
  "uvicorn[standard]>=0.27,<1",
@@ -66,7 +64,7 @@ docs = [
66
64
  "mkdocs-gen-files>=0.5,<1",
67
65
  "mkdocs-literate-nav>=0.6,<1",
68
66
  ]
69
- all = ["echo_vector[clap,api,dev,docs]"]
67
+ all = ["echo_vector[api,dev,docs]"]
70
68
 
71
69
  [project.scripts]
72
70
  echovector = "echovector.cli.main:app"
File without changes
@@ -477,14 +477,16 @@ dependencies = [
477
477
  { name = "pydub" },
478
478
  { name = "rich" },
479
479
  { name = "soundfile" },
480
+ { name = "torch" },
480
481
  { name = "tqdm" },
482
+ { name = "transformers" },
481
483
  { name = "typer" },
482
484
  ]
483
485
 
484
486
  [package.optional-dependencies]
485
487
  all = [
486
488
  { name = "fastapi" },
487
- { name = "httpx" },
489
+ { name = "httpx2" },
488
490
  { name = "hypothesis" },
489
491
  { name = "mkdocs-gen-files" },
490
492
  { name = "mkdocs-literate-nav" },
@@ -498,20 +500,14 @@ all = [
498
500
  { name = "pytest-cov" },
499
501
  { name = "pytest-xdist" },
500
502
  { name = "ruff" },
501
- { name = "torch" },
502
- { name = "transformers" },
503
503
  { name = "uvicorn", extra = ["standard"] },
504
504
  ]
505
505
  api = [
506
506
  { name = "fastapi" },
507
507
  { name = "uvicorn", extra = ["standard"] },
508
508
  ]
509
- clap = [
510
- { name = "torch" },
511
- { name = "transformers" },
512
- ]
513
509
  dev = [
514
- { name = "httpx" },
510
+ { name = "httpx2" },
515
511
  { name = "hypothesis" },
516
512
  { name = "mutmut" },
517
513
  { name = "mypy" },
@@ -529,18 +525,13 @@ docs = [
529
525
  { name = "mkdocstrings", extra = ["python"] },
530
526
  ]
531
527
 
532
- [package.dev-dependencies]
533
- dev = [
534
- { name = "httpx" },
535
- ]
536
-
537
528
  [package.metadata]
538
529
  requires-dist = [
539
530
  { name = "faiss-cpu", specifier = ">=1.7,<2" },
540
531
  { name = "fastapi", marker = "extra == 'all'", specifier = ">=0.109,<1" },
541
532
  { name = "fastapi", marker = "extra == 'api'", specifier = ">=0.109,<1" },
542
- { name = "httpx", marker = "extra == 'all'", specifier = ">=0.27,<1" },
543
- { name = "httpx", marker = "extra == 'dev'", specifier = ">=0.27,<1" },
533
+ { name = "httpx2", marker = "extra == 'all'", specifier = ">=2.0,<3" },
534
+ { name = "httpx2", marker = "extra == 'dev'", specifier = ">=2.0,<3" },
544
535
  { name = "hypothesis", marker = "extra == 'all'", specifier = ">=6.92,<7" },
545
536
  { name = "hypothesis", marker = "extra == 'dev'", specifier = ">=6.92,<7" },
546
537
  { name = "librosa", specifier = ">=0.10,<1" },
@@ -570,22 +561,17 @@ requires-dist = [
570
561
  { name = "pytest-xdist", marker = "extra == 'all'", specifier = ">=3.5,<4" },
571
562
  { name = "pytest-xdist", marker = "extra == 'dev'", specifier = ">=3.5,<4" },
572
563
  { name = "rich", specifier = ">=13.7,<14" },
573
- { name = "ruff", marker = "extra == 'all'", specifier = ">=0.3,<1" },
574
- { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.3,<1" },
564
+ { name = "ruff", marker = "extra == 'all'", specifier = ">=0.15,<1" },
565
+ { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.15,<1" },
575
566
  { name = "soundfile", specifier = ">=0.12,<1" },
576
- { name = "torch", marker = "extra == 'all'", specifier = ">=2.1,<3" },
577
- { name = "torch", marker = "extra == 'clap'", specifier = ">=2.1,<3" },
567
+ { name = "torch", specifier = ">=2.1,<3" },
578
568
  { name = "tqdm", specifier = ">=4.66,<5" },
579
- { name = "transformers", marker = "extra == 'all'", specifier = ">=4.36,<5" },
580
- { name = "transformers", marker = "extra == 'clap'", specifier = ">=4.36,<5" },
569
+ { name = "transformers", specifier = ">=4.36,<5" },
581
570
  { name = "typer", extras = ["all"], specifier = ">=0.12,<1" },
582
571
  { name = "uvicorn", extras = ["standard"], marker = "extra == 'all'", specifier = ">=0.27,<1" },
583
572
  { name = "uvicorn", extras = ["standard"], marker = "extra == 'api'", specifier = ">=0.27,<1" },
584
573
  ]
585
- provides-extras = ["all", "api", "clap", "dev", "docs"]
586
-
587
- [package.metadata.requires-dev]
588
- dev = [{ name = "httpx", specifier = ">=0.28.1" }]
574
+ provides-extras = ["all", "api", "dev", "docs"]
589
575
 
590
576
  [[package]]
591
577
  name = "execnet"
@@ -717,16 +703,16 @@ wheels = [
717
703
  ]
718
704
 
719
705
  [[package]]
720
- name = "httpcore"
721
- version = "1.0.9"
706
+ name = "httpcore2"
707
+ version = "2.3.0"
722
708
  source = { registry = "https://pypi.org/simple" }
723
709
  dependencies = [
724
- { name = "certifi" },
725
710
  { name = "h11" },
711
+ { name = "truststore" },
726
712
  ]
727
- sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
713
+ sdist = { url = "https://files.pythonhosted.org/packages/e6/34/18f1c596e677962f040284246f393b10a1f8ce440b3a7e69c637d0f1c7ad/httpcore2-2.3.0.tar.gz", hash = "sha256:07327e251560960eea8e969d92d4c6a325feb13cca39e25340731336c3baf924", size = 64300, upload-time = "2026-06-01T13:15:02.998Z" }
728
714
  wheels = [
729
- { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
715
+ { url = "https://files.pythonhosted.org/packages/c2/dd/3357218c69360d1cecc196c230c9a1d5c9afd5dba362056e23e60a5e64e5/httpcore2-2.3.0-py3-none-any.whl", hash = "sha256:477e9e334f74e5240dcac002e890580f36a57d40ff0fb14cc9655731d23b8415", size = 80024, upload-time = "2026-06-01T13:15:00.001Z" },
730
716
  ]
731
717
 
732
718
  [[package]]
@@ -759,18 +745,18 @@ wheels = [
759
745
  ]
760
746
 
761
747
  [[package]]
762
- name = "httpx"
763
- version = "0.28.1"
748
+ name = "httpx2"
749
+ version = "2.3.0"
764
750
  source = { registry = "https://pypi.org/simple" }
765
751
  dependencies = [
766
752
  { name = "anyio" },
767
- { name = "certifi" },
768
- { name = "httpcore" },
753
+ { name = "httpcore2" },
769
754
  { name = "idna" },
755
+ { name = "truststore" },
770
756
  ]
771
- sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
757
+ sdist = { url = "https://files.pythonhosted.org/packages/9f/9a/cca0b9145f13d8ae34b885ae28d403a1469a433abc78e0f94f4ce94e650b/httpx2-2.3.0.tar.gz", hash = "sha256:227e7c41d95a76d4077a52640564132777215fc3394e07b66a3116c33d668fa9", size = 81115, upload-time = "2026-06-01T13:15:04.324Z" }
772
758
  wheels = [
773
- { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
759
+ { url = "https://files.pythonhosted.org/packages/87/ce/ae2911859847f9ba1d6b23027e53481cbeb50b93234f355a968d300ca2cb/httpx2-2.3.0-py3-none-any.whl", hash = "sha256:6f393663bdf6dbe7fe90118e3eb5b2bd024a675cae0390ac08cec9198812d8b7", size = 74538, upload-time = "2026-06-01T13:15:01.566Z" },
774
760
  ]
775
761
 
776
762
  [[package]]
@@ -2544,6 +2530,15 @@ wheels = [
2544
2530
  { url = "https://files.pythonhosted.org/packages/c1/68/fa86e5a39608000f645535b2c124920126327ab731f8c4fafd5b07ff8d4b/triton-3.7.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce061073102714b725f3660ec6939d94a1da7984b3aa99c921417cae273672f5", size = 201546766, upload-time = "2026-05-07T18:46:42.088Z" },
2545
2531
  ]
2546
2532
 
2533
+ [[package]]
2534
+ name = "truststore"
2535
+ version = "0.10.4"
2536
+ source = { registry = "https://pypi.org/simple" }
2537
+ sdist = { url = "https://files.pythonhosted.org/packages/53/a3/1585216310e344e8102c22482f6060c7a6ea0322b63e026372e6dcefcfd6/truststore-0.10.4.tar.gz", hash = "sha256:9d91bd436463ad5e4ee4aba766628dd6cd7010cf3e2461756b3303710eebc301", size = 26169, upload-time = "2025-08-12T18:49:02.73Z" }
2538
+ wheels = [
2539
+ { url = "https://files.pythonhosted.org/packages/19/97/56608b2249fe206a67cd573bc93cd9896e1efb9e98bce9c163bcdc704b88/truststore-0.10.4-py3-none-any.whl", hash = "sha256:adaeaecf1cbb5f4de3b1959b42d41f6fab57b2b1666adb59e89cb0b53361d981", size = 18660, upload-time = "2025-08-12T18:49:01.46Z" },
2540
+ ]
2541
+
2547
2542
  [[package]]
2548
2543
  name = "typer"
2549
2544
  version = "0.25.1"
@@ -1,16 +0,0 @@
1
- {
2
- "hooks": {
3
- "PostToolUse": [
4
- {
5
- "matcher": "Edit|Write",
6
- "hooks": [
7
- {
8
- "type": "command",
9
- "command": "git add -A && git diff --cached --quiet || (COUNT=$(git diff --cached --name-only | wc -l | tr -d ' '); FILES=$(git diff --cached --name-only | head -3 | tr '\n' ' ' | sed 's/ $//'); if [ \"$COUNT\" -le 3 ]; then MSG=\"auto: edit $FILES\"; else FIRST=$(git diff --cached --name-only | head -2 | paste -sd ', '); MSG=\"auto: edit $COUNT files ($FIRST, ...)\"; fi; git commit -m \"$MSG\" 2>/dev/null || true)",
10
- "statusMessage": "Committing changes..."
11
- }
12
- ]
13
- }
14
- ]
15
- }
16
- }
echo_vector-0.1.1/demo.py DELETED
@@ -1,76 +0,0 @@
1
- import os
2
-
3
- import numpy as np
4
- import soundfile as sf
5
-
6
- from echovector import EchoVector
7
- from echovector.utils.logging import setup_logger
8
-
9
- logger = setup_logger("demo")
10
-
11
- def generate_synthetic_wav(
12
- filepath: str,
13
- duration: float,
14
- sr: int = 16000,
15
- freq: float = 440.0,
16
- ) -> None:
17
- """Generates a synthetic sine wave and saves it to a wav file."""
18
- t = np.linspace(0, duration, int(sr * duration), endpoint=False)
19
- # Simple tone
20
- data = 0.5 * np.sin(2 * np.pi * freq * t)
21
- os.makedirs(os.path.dirname(filepath), exist_ok=True)
22
- sf.write(filepath, data, sr)
23
- logger.info(f"Generated synthetic audio at {filepath}")
24
-
25
- def main() -> None:
26
- """Run an end-to-end local EchoVector demo."""
27
- print("=== EchoVector End-to-End Demo ===")
28
-
29
- # 1. Setup temporary audio directory and build index
30
- audio_dir = "./demo_audio"
31
- index_dir = "./demo_index"
32
-
33
- os.makedirs(audio_dir, exist_ok=True)
34
- os.makedirs(index_dir, exist_ok=True)
35
-
36
- # Generate a few synthetic audio clips
37
- # Clip 1: A short alert/sound (high frequency)
38
- generate_synthetic_wav(f"{audio_dir}/alert.wav", duration=5.0, freq=880.0)
39
- # Clip 2: A low tone (bass discussion)
40
- generate_synthetic_wav(f"{audio_dir}/bass_talk.wav", duration=10.0, freq=110.0)
41
-
42
- # 2. Instantiate EchoVector
43
- print("\n--- Initializing EchoVector ---")
44
- # Use the local backend so the demo runs without GPU access or model downloads.
45
- ev = EchoVector(store_dir=index_dir, backend="local")
46
-
47
- # 3. Index the synthetic audio directory
48
- print("\n--- Indexing Audio ---")
49
- ev.index(audio_dir)
50
-
51
- # 4. Search across indexed audio
52
- print("\n--- Searching the Index ---")
53
- # Since CLAP maps descriptive text queries to audio features, we query semantically
54
- query = "high frequency alarm tone"
55
- print(f"Searching for: '{query}'")
56
- results = ev.search(query, top_k=2)
57
-
58
- print("\nSearch Results:")
59
- for i, r in enumerate(results, 1):
60
- print(
61
- f"{i}. File: {r.filepath} | "
62
- f"Start: {r.timestamp_range.start:.2f}s | "
63
- f"End: {r.timestamp_range.end:.2f}s | "
64
- f"Score: {r.score:.4f}"
65
- )
66
-
67
- # 5. Index statistics
68
- print("\n--- Index Statistics ---")
69
- stats = ev.stats()
70
- for k, v in stats.items():
71
- print(f"{k}: {v}")
72
-
73
- print("\nDemo completed successfully!")
74
-
75
- if __name__ == "__main__":
76
- main()
Binary file
Binary file
File without changes
File without changes
File without changes