echo-vector 0.1.1__tar.gz → 0.1.2__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 → echo_vector-0.1.2}/.gitignore +9 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/PKG-INFO +5 -8
- {echo_vector-0.1.1 → echo_vector-0.1.2}/README.md +2 -2
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/embeddings/clap.py +1 -1
- {echo_vector-0.1.1 → echo_vector-0.1.2}/pyproject.toml +3 -5
- echo_vector-0.1.2/tests/integration/__init__.py +0 -0
- echo_vector-0.1.1/.claude/settings.json +0 -16
- echo_vector-0.1.1/demo.py +0 -76
- 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/tests/__init__.py → /echo_vector-0.1.2/.claude/settings.json +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/.github/workflows/workflow.yml +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/.pre-commit-config.yaml +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/.python-version +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/CLAUDE.md +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/Makefile +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/__init__.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/api/__init__.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/api/server.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/audio/__init__.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/audio/chunker.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/audio/metadata.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/audio/processor.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/audio/streaming.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/cli/__init__.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/cli/main.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/core.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/embeddings/__init__.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/embeddings/ast_model.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/embeddings/base.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/embeddings/cache.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/embeddings/factory.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/embeddings/hubert.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/embeddings/local.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/embeddings/wav2vec2.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/embeddings/whisper_enc.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/evaluation/__init__.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/evaluation/metrics.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/indexing/__init__.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/indexing/base.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/indexing/faiss_index.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/indexing/store.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/search/__init__.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/search/engine.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/search/filters.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/search/results.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/utils/__init__.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/utils/config.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/echovector/utils/logging.py +0 -0
- {echo_vector-0.1.1/tests/integration → echo_vector-0.1.2/tests}/__init__.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/conftest.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/e2e/test_cli.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/fixtures/__init__.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/fixtures/audio_generators.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/integration/test_integration.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/test_audio.mp3 +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/unit/test_api.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/unit/test_audio_processor.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/unit/test_chunker.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/unit/test_core.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/unit/test_embeddings.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/unit/test_faiss_index.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/unit/test_results.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/tests/unit/test_search_engine.py +0 -0
- {echo_vector-0.1.1 → echo_vector-0.1.2}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: echo_vector
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
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
|
|
121
|
+
pip install echo_vector
|
|
125
122
|
```
|
|
126
123
|
|
|
127
124
|
Or with uv:
|
|
128
125
|
|
|
129
126
|
```bash
|
|
130
|
-
uv add
|
|
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
|
|
47
|
+
pip install echo_vector
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
Or with uv:
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
|
-
uv add
|
|
53
|
+
uv add echo_vector
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
### CLI Usage
|
|
@@ -40,7 +40,7 @@ class ClapBackend(EmbeddingBackend):
|
|
|
40
40
|
if not _CLAP_AVAILABLE:
|
|
41
41
|
raise ImportError(
|
|
42
42
|
"CLAP backend requires torch and transformers. "
|
|
43
|
-
"Install them with: pip install
|
|
43
|
+
"Install them with: pip install echo_vector"
|
|
44
44
|
)
|
|
45
45
|
if device is None:
|
|
46
46
|
self.device = "cuda" if torch.cuda.is_available() else "cpu"
|
|
@@ -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[
|
|
67
|
+
all = ["echo_vector[api,dev,docs]"]
|
|
70
68
|
|
|
71
69
|
[project.scripts]
|
|
72
70
|
echovector = "echovector.cli.main:app"
|
|
File without changes
|
|
@@ -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
|
|
Binary file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|