echo-vector 0.1.1__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 (65) hide show
  1. echo_vector-0.1.1/.claude/settings.json +16 -0
  2. echo_vector-0.1.1/.github/workflows/workflow.yml +78 -0
  3. echo_vector-0.1.1/.gitignore +67 -0
  4. echo_vector-0.1.1/.pre-commit-config.yaml +7 -0
  5. echo_vector-0.1.1/.python-version +1 -0
  6. echo_vector-0.1.1/CLAUDE.md +88 -0
  7. echo_vector-0.1.1/Makefile +48 -0
  8. echo_vector-0.1.1/PKG-INFO +288 -0
  9. echo_vector-0.1.1/README.md +211 -0
  10. echo_vector-0.1.1/demo.py +76 -0
  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/echovector/__init__.py +7 -0
  15. echo_vector-0.1.1/echovector/api/__init__.py +1 -0
  16. echo_vector-0.1.1/echovector/api/server.py +144 -0
  17. echo_vector-0.1.1/echovector/audio/__init__.py +12 -0
  18. echo_vector-0.1.1/echovector/audio/chunker.py +71 -0
  19. echo_vector-0.1.1/echovector/audio/metadata.py +58 -0
  20. echo_vector-0.1.1/echovector/audio/processor.py +53 -0
  21. echo_vector-0.1.1/echovector/audio/streaming.py +33 -0
  22. echo_vector-0.1.1/echovector/cli/__init__.py +1 -0
  23. echo_vector-0.1.1/echovector/cli/main.py +165 -0
  24. echo_vector-0.1.1/echovector/core.py +289 -0
  25. echo_vector-0.1.1/echovector/embeddings/__init__.py +15 -0
  26. echo_vector-0.1.1/echovector/embeddings/ast_model.py +41 -0
  27. echo_vector-0.1.1/echovector/embeddings/base.py +43 -0
  28. echo_vector-0.1.1/echovector/embeddings/cache.py +96 -0
  29. echo_vector-0.1.1/echovector/embeddings/clap.py +126 -0
  30. echo_vector-0.1.1/echovector/embeddings/factory.py +78 -0
  31. echo_vector-0.1.1/echovector/embeddings/hubert.py +41 -0
  32. echo_vector-0.1.1/echovector/embeddings/local.py +109 -0
  33. echo_vector-0.1.1/echovector/embeddings/wav2vec2.py +41 -0
  34. echo_vector-0.1.1/echovector/embeddings/whisper_enc.py +44 -0
  35. echo_vector-0.1.1/echovector/evaluation/__init__.py +1 -0
  36. echo_vector-0.1.1/echovector/evaluation/metrics.py +45 -0
  37. echo_vector-0.1.1/echovector/indexing/__init__.py +12 -0
  38. echo_vector-0.1.1/echovector/indexing/base.py +105 -0
  39. echo_vector-0.1.1/echovector/indexing/faiss_index.py +182 -0
  40. echo_vector-0.1.1/echovector/indexing/store.py +165 -0
  41. echo_vector-0.1.1/echovector/search/__init__.py +14 -0
  42. echo_vector-0.1.1/echovector/search/engine.py +82 -0
  43. echo_vector-0.1.1/echovector/search/filters.py +55 -0
  44. echo_vector-0.1.1/echovector/search/results.py +41 -0
  45. echo_vector-0.1.1/echovector/utils/__init__.py +6 -0
  46. echo_vector-0.1.1/echovector/utils/config.py +69 -0
  47. echo_vector-0.1.1/echovector/utils/logging.py +31 -0
  48. echo_vector-0.1.1/pyproject.toml +203 -0
  49. echo_vector-0.1.1/tests/__init__.py +0 -0
  50. echo_vector-0.1.1/tests/conftest.py +62 -0
  51. echo_vector-0.1.1/tests/e2e/test_cli.py +76 -0
  52. echo_vector-0.1.1/tests/fixtures/__init__.py +3 -0
  53. echo_vector-0.1.1/tests/fixtures/audio_generators.py +46 -0
  54. echo_vector-0.1.1/tests/integration/__init__.py +0 -0
  55. echo_vector-0.1.1/tests/integration/test_integration.py +161 -0
  56. echo_vector-0.1.1/tests/test_audio.mp3 +0 -0
  57. echo_vector-0.1.1/tests/unit/test_api.py +105 -0
  58. echo_vector-0.1.1/tests/unit/test_audio_processor.py +104 -0
  59. echo_vector-0.1.1/tests/unit/test_chunker.py +47 -0
  60. echo_vector-0.1.1/tests/unit/test_core.py +88 -0
  61. echo_vector-0.1.1/tests/unit/test_embeddings.py +143 -0
  62. echo_vector-0.1.1/tests/unit/test_faiss_index.py +105 -0
  63. echo_vector-0.1.1/tests/unit/test_results.py +79 -0
  64. echo_vector-0.1.1/tests/unit/test_search_engine.py +85 -0
  65. echo_vector-0.1.1/uv.lock +2816 -0
@@ -0,0 +1,16 @@
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
+ }
@@ -0,0 +1,78 @@
1
+ name: CI/CD
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ tags: ["v*.*.*"]
7
+ pull_request:
8
+ branches: [main, master]
9
+
10
+ jobs:
11
+ lint:
12
+ name: Lint
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: "3.12"
19
+ - name: Install ruff
20
+ run: pip install "ruff>=0.3,<1"
21
+ - name: Check formatting
22
+ run: ruff format --check echovector/ tests/
23
+ - name: Check linting
24
+ run: ruff check echovector/ tests/
25
+
26
+ typecheck:
27
+ name: Type Check
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - uses: actions/checkout@v4
31
+ - uses: actions/setup-python@v5
32
+ with:
33
+ python-version: "3.12"
34
+ - name: Install package with dev and api deps
35
+ run: pip install -e ".[dev,api]"
36
+ - name: Run mypy
37
+ run: mypy echovector/
38
+
39
+ test:
40
+ name: Test (Python ${{ matrix.python-version }})
41
+ runs-on: ubuntu-latest
42
+ strategy:
43
+ fail-fast: false
44
+ matrix:
45
+ python-version: ["3.12", "3.13"]
46
+ steps:
47
+ - uses: actions/checkout@v4
48
+ - uses: actions/setup-python@v5
49
+ with:
50
+ python-version: ${{ matrix.python-version }}
51
+ - name: Install package with dev and api deps
52
+ run: pip install -e ".[dev,api]"
53
+ - name: Format code
54
+ run: ruff format echovector/ tests/
55
+ - name: Run tests
56
+ run: pytest tests/ -m "not slow and not gpu" -q
57
+
58
+ publish:
59
+ name: Publish to PyPI
60
+ needs: [lint, typecheck, test]
61
+ if: startsWith(github.ref, 'refs/tags/v')
62
+ runs-on: ubuntu-latest
63
+ permissions:
64
+ id-token: write
65
+ contents: read
66
+ steps:
67
+ - uses: actions/checkout@v4
68
+ with:
69
+ fetch-depth: 0
70
+ - uses: actions/setup-python@v5
71
+ with:
72
+ python-version: "3.12"
73
+ - name: Install hatch
74
+ run: pip install hatch
75
+ - name: Build package
76
+ run: hatch build
77
+ - name: Publish to PyPI
78
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,67 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ *.egg-info/
7
+ *.egg
8
+ dist/
9
+ build/
10
+ .eggs/
11
+ *.whl
12
+
13
+ # Virtual environments
14
+ .venv/
15
+ venv/
16
+ env/
17
+
18
+ # IDE
19
+ .vscode/
20
+ .idea/
21
+ *.swp
22
+ *.swo
23
+ *~
24
+
25
+ # Testing
26
+ .coverage
27
+ htmlcov/
28
+ .pytest_cache/
29
+ .mutmut-cache/
30
+ .hypothesis/
31
+
32
+ # Type checking
33
+ .mypy_cache/
34
+ .dmypy.json
35
+
36
+ # Ruff
37
+ .ruff_cache/
38
+
39
+ # ML Models & Data
40
+ *.pt
41
+ *.pth
42
+ *.onnx
43
+ *.bin
44
+ models/
45
+ *.faiss
46
+ *.db
47
+
48
+ # Audio fixtures (keep generated ones)
49
+ tests/fixtures/audio/*.wav
50
+ tests/fixtures/audio/*.mp3
51
+ tests/fixtures/audio/*.flac
52
+ tests/fixtures/audio/*.m4a
53
+ !tests/fixtures/audio/.gitkeep
54
+
55
+ # Documentation build
56
+ site/
57
+
58
+ # OS
59
+ .DS_Store
60
+ Thumbs.db
61
+
62
+ # Env
63
+ .env
64
+ .env.local
65
+
66
+ # Benchmark outputs
67
+ benchmark_results/
@@ -0,0 +1,7 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.15.12
4
+ hooks:
5
+ - id: ruff-format
6
+ - id: ruff
7
+ args: [--fix]
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,88 @@
1
+ # Claude Code Behavior Rules (Speed Optimized)
2
+
3
+ ## Core principle
4
+ Prefer fast, minimal, direct edits over exploration or deep analysis.
5
+
6
+ Optimize for:
7
+ - speed of change
8
+ - minimal tool usage
9
+ - smallest sufficient context
10
+
11
+ Avoid unnecessary searching or reasoning depth unless required.
12
+
13
+ ---
14
+
15
+ ## Planning
16
+ - Skip planning for small or obvious changes.
17
+ - For larger tasks: max 3–5 bullets only.
18
+ - Do not over-explain or explore alternatives unless asked.
19
+
20
+ ---
21
+
22
+ ## File editing behavior
23
+ - Make targeted edits directly when the affected files are known or implied.
24
+ - Do NOT scan the full codebase before editing unless necessary.
25
+ - Prefer local reasoning over global search.
26
+ - Group edits into a single pass per file.
27
+
28
+ Avoid:
29
+ - broad repository exploration before action
30
+ - unnecessary dependency tracing
31
+ - repeated file re-reading
32
+
33
+ ---
34
+
35
+ ## Progress updates
36
+ Only report when:
37
+ - an edit is completed
38
+ - a bug cause is identified
39
+ - a blocker is encountered
40
+
41
+ Keep updates:
42
+ - under 50–75 words
43
+ - bullet-based only
44
+ - no narration of intermediate steps
45
+
46
+ ---
47
+
48
+ ## Debugging style
49
+ Use a fast hypothesis model:
50
+
51
+ 1. likely cause
52
+ 2. quick verification
53
+ 3. fix
54
+
55
+ Do NOT:
56
+ - exhaustively search all possible causes
57
+ - inspect unrelated modules unless required
58
+
59
+ ---
60
+
61
+ ## Tool usage rules
62
+ - Prefer fewer tool calls
63
+ - Avoid repeated file opens
64
+ - Do not re-read files unless state has changed
65
+ - Do not perform broad searches unless explicitly requested
66
+
67
+ ---
68
+
69
+ ## Code changes
70
+ - Prioritize minimal viable fix
71
+ - Avoid large refactors unless requested
72
+ - Do not optimize prematurely
73
+ - Preserve existing structure unless necessary
74
+
75
+ ---
76
+
77
+ ## When to slow down
78
+ Only increase exploration when:
79
+ - multiple files clearly involved
80
+ - root cause is unknown after initial check
81
+ - system-level change is required
82
+
83
+ ---
84
+
85
+ ## Output style
86
+ - Default to short bullet points
87
+ - Avoid repetition of context
88
+ - No step-by-step narration unless debugging complex issues
@@ -0,0 +1,48 @@
1
+ .PHONY: install lint typecheck test test-unit test-integration test-e2e test-perf coverage mutate docs serve-docs clean
2
+
3
+ install:
4
+ uv sync --all-extras
5
+
6
+ lint:
7
+ uv run ruff check echovector/ tests/
8
+ uv run ruff format --check echovector/ tests/
9
+
10
+ lint-fix:
11
+ uv run ruff check --fix echovector/ tests/
12
+ uv run ruff format echovector/ tests/
13
+
14
+ typecheck:
15
+ uv run mypy echovector/
16
+
17
+ test:
18
+ uv run pytest tests/ -v
19
+
20
+ test-unit:
21
+ uv run pytest tests/unit/ -v
22
+
23
+ test-integration:
24
+ uv run pytest tests/integration/ -v -m integration
25
+
26
+ test-e2e:
27
+ uv run pytest tests/e2e/ -v -m e2e
28
+
29
+ test-perf:
30
+ uv run pytest tests/performance/ -v -m performance
31
+
32
+ coverage:
33
+ uv run pytest tests/ --cov=echovector --cov-report=html --cov-report=term-missing
34
+
35
+ mutate:
36
+ uv run mutmut run
37
+
38
+ docs:
39
+ cd docs && uv run mkdocs build
40
+
41
+ serve-docs:
42
+ cd docs && uv run mkdocs serve
43
+
44
+ clean:
45
+ rm -rf dist/ build/ *.egg-info/ .pytest_cache/ .mypy_cache/ .ruff_cache/ htmlcov/ .coverage site/ .mutmut-cache/
46
+ find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
47
+
48
+ all: lint typecheck test
@@ -0,0 +1,288 @@
1
+ Metadata-Version: 2.4
2
+ Name: echo_vector
3
+ Version: 0.1.1
4
+ Summary: Semantic text search over audio files without full transcription
5
+ Project-URL: Homepage, https://github.com/ahron-maslin/echo_vector
6
+ Project-URL: Documentation, https://github.com/ahron-maslin/echo_vector#readme
7
+ Project-URL: Repository, https://github.com/ahron-maslin/echo_vector
8
+ Project-URL: Issues, https://github.com/ahron-maslin/echo_vector/issues
9
+ Project-URL: Changelog, https://github.com/ahron-maslin/echo_vector/blob/main/CHANGELOG.md
10
+ Author: EchoVector Contributors
11
+ License-Expression: MIT
12
+ Keywords: CLAP,FAISS,audio,embeddings,search,semantic,vector
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
22
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Classifier: Topic :: Text Processing :: Indexing
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.12
26
+ Requires-Dist: faiss-cpu<2,>=1.7
27
+ Requires-Dist: librosa<1,>=0.10
28
+ Requires-Dist: numpy<3,>=1.26
29
+ Requires-Dist: pydantic<3,>=2.5
30
+ Requires-Dist: pydub<1,>=0.25
31
+ Requires-Dist: rich<14,>=13.7
32
+ Requires-Dist: soundfile<1,>=0.12
33
+ Requires-Dist: tqdm<5,>=4.66
34
+ Requires-Dist: typer[all]<1,>=0.12
35
+ Provides-Extra: all
36
+ Requires-Dist: fastapi<1,>=0.109; extra == 'all'
37
+ Requires-Dist: httpx2<3,>=2.0; extra == 'all'
38
+ Requires-Dist: hypothesis<7,>=6.92; extra == 'all'
39
+ Requires-Dist: mkdocs-gen-files<1,>=0.5; extra == 'all'
40
+ Requires-Dist: mkdocs-literate-nav<1,>=0.6; extra == 'all'
41
+ Requires-Dist: mkdocs-material<10,>=9.5; extra == 'all'
42
+ Requires-Dist: mkdocstrings[python]<1,>=0.24; extra == 'all'
43
+ Requires-Dist: mutmut<3,>=2.4; extra == 'all'
44
+ Requires-Dist: mypy<2,>=1.8; extra == 'all'
45
+ Requires-Dist: pre-commit<4,>=3.6; extra == 'all'
46
+ Requires-Dist: pytest-asyncio<1,>=0.23; extra == 'all'
47
+ Requires-Dist: pytest-cov<6,>=5.0; extra == 'all'
48
+ Requires-Dist: pytest-xdist<4,>=3.5; extra == 'all'
49
+ Requires-Dist: pytest<9,>=8.0; extra == 'all'
50
+ 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
+ Requires-Dist: uvicorn[standard]<1,>=0.27; extra == 'all'
54
+ Provides-Extra: api
55
+ Requires-Dist: fastapi<1,>=0.109; extra == 'api'
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
+ Provides-Extra: dev
61
+ Requires-Dist: httpx2<3,>=2.0; extra == 'dev'
62
+ Requires-Dist: hypothesis<7,>=6.92; extra == 'dev'
63
+ Requires-Dist: mutmut<3,>=2.4; extra == 'dev'
64
+ Requires-Dist: mypy<2,>=1.8; extra == 'dev'
65
+ Requires-Dist: pre-commit<4,>=3.6; extra == 'dev'
66
+ Requires-Dist: pytest-asyncio<1,>=0.23; extra == 'dev'
67
+ Requires-Dist: pytest-cov<6,>=5.0; extra == 'dev'
68
+ Requires-Dist: pytest-xdist<4,>=3.5; extra == 'dev'
69
+ Requires-Dist: pytest<9,>=8.0; extra == 'dev'
70
+ Requires-Dist: ruff<1,>=0.15; extra == 'dev'
71
+ Provides-Extra: docs
72
+ Requires-Dist: mkdocs-gen-files<1,>=0.5; extra == 'docs'
73
+ Requires-Dist: mkdocs-literate-nav<1,>=0.6; extra == 'docs'
74
+ Requires-Dist: mkdocs-material<10,>=9.5; extra == 'docs'
75
+ Requires-Dist: mkdocstrings[python]<1,>=0.24; extra == 'docs'
76
+ Description-Content-Type: text/markdown
77
+
78
+ # 🔊 EchoVector
79
+
80
+ > **Semantic text search over audio files — without full transcription.**
81
+
82
+ [![CI](https://github.com/echovector/echovector/actions/workflows/test.yml/badge.svg)](https://github.com/echovector/echovector/actions/workflows/test.yml)
83
+ [![Coverage](https://img.shields.io/badge/coverage-%3E95%25-brightgreen)](.)
84
+ [![Python](https://img.shields.io/badge/python-3.12%2B-blue)](.)
85
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
86
+
87
+ ---
88
+
89
+ ## What is EchoVector?
90
+
91
+ EchoVector indexes audio files by generating **semantic embeddings directly from audio waveforms**, then lets you search them with natural language text queries — all without transcribing a single word.
92
+
93
+ ### Traditional approach (slow & expensive)
94
+
95
+ ```
96
+ Audio → Full Transcription → Text Embeddings → Text Search
97
+ ```
98
+
99
+ ### EchoVector approach (fast & efficient)
100
+
101
+ ```
102
+ Audio → Audio Chunks → Audio Embeddings ─┐
103
+ ├─► ANN Search → Results
104
+ Text Query → Text Embedding ──────────────┘
105
+ ```
106
+
107
+ ## Features
108
+
109
+ - 🎵 **Multi-format support** — MP3, WAV, FLAC, M4A
110
+ - 🧠 **Direct audio embeddings** — No transcription needed
111
+ - 🔍 **Semantic search** — Query with natural language
112
+ - ⚡ **FAISS-powered** — Approximate nearest neighbor search
113
+ - 🔌 **Pluggable backends** — CLAP, Whisper, wav2vec2, HuBERT, AST
114
+ - 🧪 **Offline smoke backend** — `local` backend for CI/Kaggle tests without model downloads
115
+ - 📊 **Rich CLI** — Progress bars, colors, benchmarking mode
116
+ - 🌐 **REST API** — Optional FastAPI server
117
+ - 📦 **Production-ready** — Typed, tested, documented
118
+
119
+ ## Quick Start
120
+
121
+ ### Installation
122
+
123
+ ```bash
124
+ pip install echovector
125
+ ```
126
+
127
+ Or with uv:
128
+
129
+ ```bash
130
+ uv add echovector
131
+ ```
132
+
133
+ ### CLI Usage
134
+
135
+ ```bash
136
+ # One-time indexing: split audio into timestamped chunks and embed each chunk
137
+ echovector index ./meetings
138
+
139
+ # Fast repeated search: embed only the text query and search the saved FAISS index
140
+ echovector search "discussion about transformers"
141
+
142
+ # Search with options
143
+ echovector search "pricing strategy" --top-k 10
144
+
145
+ # View index statistics
146
+ echovector stats
147
+ ```
148
+
149
+ For a no-download smoke test, use the deterministic local backend:
150
+
151
+ ```bash
152
+ echovector index ./meetings --backend local --store-dir ./ev-index
153
+ echovector search "high alarm tone" --backend local --store-dir ./ev-index
154
+ echovector stats --backend local --store-dir ./ev-index
155
+ ```
156
+
157
+ The search command does not reopen or scan the audio files. All expensive audio processing happens
158
+ during `index`; `search` loads the saved vector index, embeds the short text query, and returns the
159
+ nearest timestamped chunks.
160
+
161
+ ### Python API
162
+
163
+ ```python
164
+ from echovector import EchoVector
165
+
166
+ ev = EchoVector()
167
+
168
+ # Index audio files
169
+ ev.index("./meetings")
170
+
171
+ # Search with natural language
172
+ results = ev.search("conversation about CUDA kernels")
173
+
174
+ for r in results:
175
+ print(
176
+ f"{r.filepath} "
177
+ f"[{r.timestamp_range.start:.1f}s - {r.timestamp_range.end:.1f}s] "
178
+ f"score={r.score:.4f}"
179
+ )
180
+ ```
181
+
182
+ ## Testing on Kaggle
183
+
184
+ Kaggle is useful for GPU-backed CLAP tests, but first check the runtime Python version:
185
+
186
+ ```python
187
+ import sys
188
+ print(sys.version)
189
+ ```
190
+
191
+ EchoVector currently declares `Python >=3.12`. If the Kaggle image is older, install and test in a
192
+ Python 3.12-capable environment instead, or relax the project requirement only after validating the
193
+ test suite on that Python version.
194
+
195
+ ### Notebook smoke test without internet/model downloads
196
+
197
+ Upload this repository as a Kaggle dataset, attach it to a notebook, then run:
198
+
199
+ ```python
200
+ %cd /kaggle/input/<your-echo-vector-dataset>
201
+ !pip install -e . --no-deps
202
+ !pip install numpy soundfile librosa faiss-cpu typer rich pydantic
203
+ !python -m pytest tests/ -q
204
+ ```
205
+
206
+ Create a tiny audio corpus and test the real CLI/index path:
207
+
208
+ ```python
209
+ import os
210
+ import numpy as np
211
+ import soundfile as sf
212
+
213
+ audio_dir = "/kaggle/working/ev-audio"
214
+ index_dir = "/kaggle/working/ev-index"
215
+ os.makedirs(audio_dir, exist_ok=True)
216
+
217
+ sr = 16000
218
+ t = np.linspace(0, 1.0, sr, endpoint=False)
219
+ sf.write(f"{audio_dir}/high_tone.wav", 0.25 * np.sin(2 * np.pi * 880 * t), sr)
220
+ sf.write(f"{audio_dir}/low_tone.wav", 0.25 * np.sin(2 * np.pi * 110 * t), sr)
221
+ ```
222
+
223
+ ```python
224
+ !echovector index /kaggle/working/ev-audio --backend local --store-dir /kaggle/working/ev-index --reset
225
+ !echovector search "high alarm tone" --backend local --store-dir /kaggle/working/ev-index --top-k 2
226
+ !echovector stats --backend local --store-dir /kaggle/working/ev-index
227
+ ```
228
+
229
+ This validates packaging, audio loading, FAISS persistence, metadata storage, and the CLI without
230
+ depending on Hugging Face downloads.
231
+
232
+ ### CLAP semantic test
233
+
234
+ For actual semantic text-to-audio search, enable internet in the notebook settings and use a GPU
235
+ runtime if available:
236
+
237
+ ```python
238
+ !pip install transformers torch faiss-cpu librosa soundfile
239
+ !echovector index /kaggle/input/<audio-dataset> --backend clap --device cuda --store-dir /kaggle/working/clap-index --recursive --reset
240
+ !echovector search "people discussing pricing strategy" --backend clap --device cuda --store-dir /kaggle/working/clap-index --top-k 10
241
+ ```
242
+
243
+ If GPU is unavailable, replace `--device cuda` with `--device cpu`; it will be slower. Keep indexes
244
+ under `/kaggle/working` so they are writable during the notebook session.
245
+
246
+ ## Architecture
247
+
248
+ ```
249
+ echovector/
250
+ ├── audio/ # Audio loading, chunking, streaming, metadata
251
+ ├── embeddings/ # Pluggable embedding backends (CLAP, Whisper, etc.)
252
+ ├── indexing/ # Vector index backends (FAISS, with pluggable design)
253
+ ├── search/ # Search engine, filtering, result hydration
254
+ ├── cli/ # Typer-based CLI with Rich output
255
+ ├── api/ # Optional FastAPI server
256
+ ├── evaluation/ # Metrics (recall@k, throughput)
257
+ ├── benchmarks/ # Reproducible benchmark harness
258
+ └── utils/ # Config, logging, helpers
259
+ ```
260
+
261
+ ## Supported Embedding Backends
262
+
263
+ | Backend | Text+Audio Aligned | Notes |
264
+ |---------|-------------------|-------|
265
+ | **CLAP** (default) | ✅ | Best for text→audio search |
266
+ | Whisper Encoder | ❌ | Audio-only embeddings |
267
+ | wav2vec2 | ❌ | Audio-only, good for speech |
268
+ | HuBERT | ❌ | Audio-only, self-supervised |
269
+ | Audio Spectrogram Transformer | ❌ | Audio-only, classification-focused |
270
+
271
+ ## Development
272
+
273
+ ```bash
274
+ # Clone and install
275
+ git clone https://github.com/echovector/echovector.git
276
+ cd echovector
277
+ uv sync --all-extras
278
+
279
+ # Run checks
280
+ make lint
281
+ make typecheck
282
+ make test
283
+ make coverage
284
+ ```
285
+
286
+ ## License
287
+
288
+ MIT