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.
- echo_vector-0.1.1/.claude/settings.json +16 -0
- echo_vector-0.1.1/.github/workflows/workflow.yml +78 -0
- echo_vector-0.1.1/.gitignore +67 -0
- echo_vector-0.1.1/.pre-commit-config.yaml +7 -0
- echo_vector-0.1.1/.python-version +1 -0
- echo_vector-0.1.1/CLAUDE.md +88 -0
- echo_vector-0.1.1/Makefile +48 -0
- echo_vector-0.1.1/PKG-INFO +288 -0
- echo_vector-0.1.1/README.md +211 -0
- echo_vector-0.1.1/demo.py +76 -0
- echo_vector-0.1.1/demo_audio/alert.wav +0 -0
- echo_vector-0.1.1/demo_audio/bass_talk.wav +0 -0
- echo_vector-0.1.1/demo_index/metadata.sqlite +0 -0
- echo_vector-0.1.1/echovector/__init__.py +7 -0
- echo_vector-0.1.1/echovector/api/__init__.py +1 -0
- echo_vector-0.1.1/echovector/api/server.py +144 -0
- echo_vector-0.1.1/echovector/audio/__init__.py +12 -0
- echo_vector-0.1.1/echovector/audio/chunker.py +71 -0
- echo_vector-0.1.1/echovector/audio/metadata.py +58 -0
- echo_vector-0.1.1/echovector/audio/processor.py +53 -0
- echo_vector-0.1.1/echovector/audio/streaming.py +33 -0
- echo_vector-0.1.1/echovector/cli/__init__.py +1 -0
- echo_vector-0.1.1/echovector/cli/main.py +165 -0
- echo_vector-0.1.1/echovector/core.py +289 -0
- echo_vector-0.1.1/echovector/embeddings/__init__.py +15 -0
- echo_vector-0.1.1/echovector/embeddings/ast_model.py +41 -0
- echo_vector-0.1.1/echovector/embeddings/base.py +43 -0
- echo_vector-0.1.1/echovector/embeddings/cache.py +96 -0
- echo_vector-0.1.1/echovector/embeddings/clap.py +126 -0
- echo_vector-0.1.1/echovector/embeddings/factory.py +78 -0
- echo_vector-0.1.1/echovector/embeddings/hubert.py +41 -0
- echo_vector-0.1.1/echovector/embeddings/local.py +109 -0
- echo_vector-0.1.1/echovector/embeddings/wav2vec2.py +41 -0
- echo_vector-0.1.1/echovector/embeddings/whisper_enc.py +44 -0
- echo_vector-0.1.1/echovector/evaluation/__init__.py +1 -0
- echo_vector-0.1.1/echovector/evaluation/metrics.py +45 -0
- echo_vector-0.1.1/echovector/indexing/__init__.py +12 -0
- echo_vector-0.1.1/echovector/indexing/base.py +105 -0
- echo_vector-0.1.1/echovector/indexing/faiss_index.py +182 -0
- echo_vector-0.1.1/echovector/indexing/store.py +165 -0
- echo_vector-0.1.1/echovector/search/__init__.py +14 -0
- echo_vector-0.1.1/echovector/search/engine.py +82 -0
- echo_vector-0.1.1/echovector/search/filters.py +55 -0
- echo_vector-0.1.1/echovector/search/results.py +41 -0
- echo_vector-0.1.1/echovector/utils/__init__.py +6 -0
- echo_vector-0.1.1/echovector/utils/config.py +69 -0
- echo_vector-0.1.1/echovector/utils/logging.py +31 -0
- echo_vector-0.1.1/pyproject.toml +203 -0
- echo_vector-0.1.1/tests/__init__.py +0 -0
- echo_vector-0.1.1/tests/conftest.py +62 -0
- echo_vector-0.1.1/tests/e2e/test_cli.py +76 -0
- echo_vector-0.1.1/tests/fixtures/__init__.py +3 -0
- echo_vector-0.1.1/tests/fixtures/audio_generators.py +46 -0
- echo_vector-0.1.1/tests/integration/__init__.py +0 -0
- echo_vector-0.1.1/tests/integration/test_integration.py +161 -0
- echo_vector-0.1.1/tests/test_audio.mp3 +0 -0
- echo_vector-0.1.1/tests/unit/test_api.py +105 -0
- echo_vector-0.1.1/tests/unit/test_audio_processor.py +104 -0
- echo_vector-0.1.1/tests/unit/test_chunker.py +47 -0
- echo_vector-0.1.1/tests/unit/test_core.py +88 -0
- echo_vector-0.1.1/tests/unit/test_embeddings.py +143 -0
- echo_vector-0.1.1/tests/unit/test_faiss_index.py +105 -0
- echo_vector-0.1.1/tests/unit/test_results.py +79 -0
- echo_vector-0.1.1/tests/unit/test_search_engine.py +85 -0
- 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 @@
|
|
|
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
|
+
[](https://github.com/echovector/echovector/actions/workflows/test.yml)
|
|
83
|
+
[](.)
|
|
84
|
+
[](.)
|
|
85
|
+
[](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
|