dirsql-plugin-embeddings 0.1.12__tar.gz → 0.1.14__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 (34) hide show
  1. dirsql_plugin_embeddings-0.1.14/PKG-INFO +102 -0
  2. dirsql_plugin_embeddings-0.1.14/README.md +89 -0
  3. dirsql_plugin_embeddings-0.1.14/changelog.d/2026-08-12-no-per-call-progress-bar.md +3 -0
  4. dirsql_plugin_embeddings-0.1.14/e2e-attestations/claude-814-suppress-per-call-progress.json +7 -0
  5. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/embedding/worker.py +4 -2
  6. dirsql_plugin_embeddings-0.1.12/PKG-INFO +0 -61
  7. dirsql_plugin_embeddings-0.1.12/README.md +0 -48
  8. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/.gitignore +0 -0
  9. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/changelog.d/2026-08-10-delete-old-surface.md +0 -0
  10. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/changelog.d/2026-08-10-embed-worker.md +0 -0
  11. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/changelog.d/2026-08-11-one-liner-cli.md +0 -0
  12. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/e2e-attestations/claude-804-embed-worker.json +0 -0
  13. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/e2e-attestations/claude-805-one-liner.json +0 -0
  14. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/migrations.d/2026-08-10-delete-old-surface.md +0 -0
  15. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/pyproject.toml +0 -0
  16. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/__init__.py +0 -0
  17. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/cli/__init__.py +0 -0
  18. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/cli/main.py +0 -0
  19. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/cli/search.py +0 -0
  20. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/cli/worker.py +0 -0
  21. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/dirsql.toml +0 -0
  22. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/embedding/__init__.py +0 -0
  23. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/embedding/cache.py +0 -0
  24. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/embedding/model.py +0 -0
  25. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/embedding/progress.py +0 -0
  26. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/embedding/values.py +0 -0
  27. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/search/__init__.py +0 -0
  28. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/search/output.py +0 -0
  29. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/search/run.py +0 -0
  30. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/src/dirsql_plugin_embeddings/search/sql.py +0 -0
  31. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/testing-conventions.toml +0 -0
  32. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/tests/conftest.py +0 -0
  33. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/tests/e2e/__init__.py +0 -0
  34. {dirsql_plugin_embeddings-0.1.12 → dirsql_plugin_embeddings-0.1.14}/tests/integration/__init__.py +0 -0
@@ -0,0 +1,102 @@
1
+ Metadata-Version: 2.5
2
+ Name: dirsql-plugin-embeddings
3
+ Version: 0.1.14
4
+ Summary: First-party dirsql plugin: semantic search over files.
5
+ Requires-Python: >=3.10
6
+ Requires-Dist: cachetta>=0.7
7
+ Requires-Dist: click>=8
8
+ Requires-Dist: dirsql
9
+ Requires-Dist: model2vec>=0.6
10
+ Requires-Dist: sqlite-vec>=0.1
11
+ Requires-Dist: tqdm>=4
12
+ Description-Content-Type: text/markdown
13
+
14
+ # dirsql-plugin-embeddings
15
+
16
+ A first-party [`dirsql`](https://github.com/thekevinscott/dirsql) plugin for
17
+ semantic search over files.
18
+
19
+ Installing the plugin loads the
20
+ [`sqlite-vec`](https://github.com/asg017/sqlite-vec) extension (for
21
+ `vec_distance_cosine()` and friends) and declares an `embed()` SQL scalar
22
+ function that turns TEXT or BLOB values into embedding vectors:
23
+
24
+ ```sh
25
+ uvx --with dirsql-plugin-embeddings dirsql "
26
+ SELECT path
27
+ FROM (SELECT path, embed(content ->> 'abstract') AS emb
28
+ FROM './arxiv-firehose/data/**/metadata.json')
29
+ ORDER BY vec_distance_cosine(emb, embed('local private models'))
30
+ LIMIT 10"
31
+ ```
32
+
33
+ For the common case — one glob, one question, top-k paths — the package is
34
+ also its own command, generating and running exactly that SQL:
35
+
36
+ ```sh
37
+ uvx dirsql-plugin-embeddings '**/*.md' "local private models" -k 10
38
+ ```
39
+
40
+ - **Corpus glob: required first positional.** The plugin never picks a
41
+ default corpus; you always say which files are in scope. A bare glob is
42
+ fine here — the command normalizes it to the `./`-relative form the SQL
43
+ layer requires (`**/*.md` → `./**/*.md`).
44
+ - **Query text: second positional.** Query text, model id, and glob are
45
+ SQL-escaped into the generated query.
46
+ - **`-k` / `--limit`** (both spellings, default 10): the number of results.
47
+ It is exactly the SQL `LIMIT` of the generated query — no other cutoff
48
+ exists.
49
+ - **`--model <id>`**: templates the model id as `embed()`'s second argument
50
+ in the generated SQL (see [Model](#model)).
51
+
52
+ Results print one `path<TAB>distance` line per match, closest first.
53
+
54
+ > **Top-k is `LIMIT k`.** sqlite-vec's `MATCH ... AND k = N` idiom belongs to
55
+ > its `vec0` virtual table, which `dirsql` does not use. For plain
56
+ > expressions, sqlite-vec's own documented pattern is the one above:
57
+ > `ORDER BY vec_distance_cosine(...) LIMIT k`.
58
+
59
+ ## Zero cost when unused
60
+
61
+ `embed()` is inert until a query calls it: no worker process is spawned and
62
+ no model is loaded for queries that never use it. On the first call, dirsql
63
+ spawns the plugin's worker process (`dirsql-plugin-embeddings worker`), which
64
+ serves every call of the invocation over stdin/stdout. Only the values the
65
+ query actually selects are embedded — the worker receives values, not paths,
66
+ and never opens files itself.
67
+
68
+ ## Model
69
+
70
+ Embeddings come from [model2vec](https://github.com/MinishLab/model2vec)
71
+ (static embeddings — numpy + tokenizers, no torch), defaulting to
72
+ [`minishlab/potion-retrieval-32M`](https://huggingface.co/minishlab/potion-retrieval-32M).
73
+ The model downloads to the standard Hugging Face cache on the first ever run
74
+ (on the order of a hundred megabytes — seconds to a few minutes depending on
75
+ your connection), with progress on stderr when stderr is a TTY; every later
76
+ run loads it from disk.
77
+
78
+ An optional second argument overrides the model per call — the id must be
79
+ model2vec-loadable (sentence-transformers/torch models are out of scope):
80
+
81
+ ```sql
82
+ SELECT embed('some text', 'minishlab/potion-base-8M')
83
+ ```
84
+
85
+ The one-liner's `--model` flag templates the same second argument.
86
+
87
+ ## Vector cache
88
+
89
+ Computed vectors are cached at `~/.cache/dirsql/embeddings/` (or
90
+ `$XDG_CACHE_HOME/dirsql/embeddings/` when `XDG_CACHE_HOME` is set), keyed by
91
+ the SHA-256 of the value bytes plus the model identifier — changing either
92
+ recomputes; switching models never serves stale vectors. There is no
93
+ eviction: **the directory is safe to wipe at any time**; the only cost is
94
+ re-embedding. The cache never lives inside a queried tree — the worker
95
+ receives values, not paths, and writes nothing anywhere else.
96
+
97
+ ## Docs
98
+
99
+ - [Search documents by meaning](https://thekevinscott.github.io/dirsql/howto/search-by-meaning)
100
+ — the guide to both invocation styles.
101
+ - [`[[dirsql.function]]`](https://thekevinscott.github.io/dirsql/reference/config#dirsql-function)
102
+ — the core mechanism `embed()` is built on.
@@ -0,0 +1,89 @@
1
+ # dirsql-plugin-embeddings
2
+
3
+ A first-party [`dirsql`](https://github.com/thekevinscott/dirsql) plugin for
4
+ semantic search over files.
5
+
6
+ Installing the plugin loads the
7
+ [`sqlite-vec`](https://github.com/asg017/sqlite-vec) extension (for
8
+ `vec_distance_cosine()` and friends) and declares an `embed()` SQL scalar
9
+ function that turns TEXT or BLOB values into embedding vectors:
10
+
11
+ ```sh
12
+ uvx --with dirsql-plugin-embeddings dirsql "
13
+ SELECT path
14
+ FROM (SELECT path, embed(content ->> 'abstract') AS emb
15
+ FROM './arxiv-firehose/data/**/metadata.json')
16
+ ORDER BY vec_distance_cosine(emb, embed('local private models'))
17
+ LIMIT 10"
18
+ ```
19
+
20
+ For the common case — one glob, one question, top-k paths — the package is
21
+ also its own command, generating and running exactly that SQL:
22
+
23
+ ```sh
24
+ uvx dirsql-plugin-embeddings '**/*.md' "local private models" -k 10
25
+ ```
26
+
27
+ - **Corpus glob: required first positional.** The plugin never picks a
28
+ default corpus; you always say which files are in scope. A bare glob is
29
+ fine here — the command normalizes it to the `./`-relative form the SQL
30
+ layer requires (`**/*.md` → `./**/*.md`).
31
+ - **Query text: second positional.** Query text, model id, and glob are
32
+ SQL-escaped into the generated query.
33
+ - **`-k` / `--limit`** (both spellings, default 10): the number of results.
34
+ It is exactly the SQL `LIMIT` of the generated query — no other cutoff
35
+ exists.
36
+ - **`--model <id>`**: templates the model id as `embed()`'s second argument
37
+ in the generated SQL (see [Model](#model)).
38
+
39
+ Results print one `path<TAB>distance` line per match, closest first.
40
+
41
+ > **Top-k is `LIMIT k`.** sqlite-vec's `MATCH ... AND k = N` idiom belongs to
42
+ > its `vec0` virtual table, which `dirsql` does not use. For plain
43
+ > expressions, sqlite-vec's own documented pattern is the one above:
44
+ > `ORDER BY vec_distance_cosine(...) LIMIT k`.
45
+
46
+ ## Zero cost when unused
47
+
48
+ `embed()` is inert until a query calls it: no worker process is spawned and
49
+ no model is loaded for queries that never use it. On the first call, dirsql
50
+ spawns the plugin's worker process (`dirsql-plugin-embeddings worker`), which
51
+ serves every call of the invocation over stdin/stdout. Only the values the
52
+ query actually selects are embedded — the worker receives values, not paths,
53
+ and never opens files itself.
54
+
55
+ ## Model
56
+
57
+ Embeddings come from [model2vec](https://github.com/MinishLab/model2vec)
58
+ (static embeddings — numpy + tokenizers, no torch), defaulting to
59
+ [`minishlab/potion-retrieval-32M`](https://huggingface.co/minishlab/potion-retrieval-32M).
60
+ The model downloads to the standard Hugging Face cache on the first ever run
61
+ (on the order of a hundred megabytes — seconds to a few minutes depending on
62
+ your connection), with progress on stderr when stderr is a TTY; every later
63
+ run loads it from disk.
64
+
65
+ An optional second argument overrides the model per call — the id must be
66
+ model2vec-loadable (sentence-transformers/torch models are out of scope):
67
+
68
+ ```sql
69
+ SELECT embed('some text', 'minishlab/potion-base-8M')
70
+ ```
71
+
72
+ The one-liner's `--model` flag templates the same second argument.
73
+
74
+ ## Vector cache
75
+
76
+ Computed vectors are cached at `~/.cache/dirsql/embeddings/` (or
77
+ `$XDG_CACHE_HOME/dirsql/embeddings/` when `XDG_CACHE_HOME` is set), keyed by
78
+ the SHA-256 of the value bytes plus the model identifier — changing either
79
+ recomputes; switching models never serves stale vectors. There is no
80
+ eviction: **the directory is safe to wipe at any time**; the only cost is
81
+ re-embedding. The cache never lives inside a queried tree — the worker
82
+ receives values, not paths, and writes nothing anywhere else.
83
+
84
+ ## Docs
85
+
86
+ - [Search documents by meaning](https://thekevinscott.github.io/dirsql/howto/search-by-meaning)
87
+ — the guide to both invocation styles.
88
+ - [`[[dirsql.function]]`](https://thekevinscott.github.io/dirsql/reference/config#dirsql-function)
89
+ — the core mechanism `embed()` is built on.
@@ -0,0 +1,3 @@
1
+ **Fixed**
2
+
3
+ - **`embed()` no longer renders a progress bar for every call.** The worker embeds exactly one value per protocol round trip, so the per-call tqdm bar could only ever say `1/1` — on a TTY a 20-file corpus query printed ~21 of them to stderr. The bar is gone; the Hugging Face model-*download* bar, which measures something worth watching, is unchanged and still TTY-gated. (#814)
@@ -0,0 +1,7 @@
1
+ {
2
+ "command": "uv run --with-editable ../../packages/python python -m pytest tests/e2e/ -x -q",
3
+ "ran_at": 1786552300,
4
+ "exit_code": 0,
5
+ "commit": "b1fc5a6a475a8f93eab7a3a652b5c982269768a8",
6
+ "branch": "claude/814-suppress-per-call-progress"
7
+ }
@@ -3,7 +3,6 @@ from hashlib import sha256
3
3
 
4
4
  from . import model
5
5
  from .cache import make_cache
6
- from .progress import stderr_is_tty
7
6
  from .values import ProtocolError, decode_value
8
7
 
9
8
  MALFORMED_SHAPE = (
@@ -27,7 +26,10 @@ class Worker:
27
26
 
28
27
  def _compute(self, digest, identifier):
29
28
  text, loaded = self._pending
30
- (vector,) = loaded.encode([text], show_progress_bar=stderr_is_tty())
29
+ # No progress bar: the protocol embeds one value per round trip, so a
30
+ # per-call bar can only ever say 1/1. The model *download* bar, which
31
+ # measures something, is TTY-gated in `progress.configure`.
32
+ (vector,) = loaded.encode([text], show_progress_bar=False)
31
33
  return [float(component) for component in vector]
32
34
 
33
35
  def embed(self, text, model_id):
@@ -1,61 +0,0 @@
1
- Metadata-Version: 2.5
2
- Name: dirsql-plugin-embeddings
3
- Version: 0.1.12
4
- Summary: First-party dirsql plugin: semantic search over files.
5
- Requires-Python: >=3.10
6
- Requires-Dist: cachetta>=0.7
7
- Requires-Dist: click>=8
8
- Requires-Dist: dirsql
9
- Requires-Dist: model2vec>=0.6
10
- Requires-Dist: sqlite-vec>=0.1
11
- Requires-Dist: tqdm>=4
12
- Description-Content-Type: text/markdown
13
-
14
- # dirsql-plugin-embeddings
15
-
16
- A first-party [`dirsql`](https://github.com/thekevinscott/dirsql) plugin for
17
- semantic search over files.
18
-
19
- Installing the plugin loads the
20
- [`sqlite-vec`](https://github.com/asg017/sqlite-vec) extension (for
21
- `vec_distance_cosine()` and friends) and declares an `embed()` SQL scalar
22
- function that turns TEXT or BLOB values into embedding vectors:
23
-
24
- ```sh
25
- uvx --with dirsql-plugin-embeddings dirsql "
26
- SELECT path
27
- FROM (SELECT path, embed(content ->> 'abstract') AS emb
28
- FROM 'arxiv-firehose/data/**/metadata.json')
29
- ORDER BY vec_distance_cosine(emb, embed('local private models'))
30
- LIMIT 10"
31
- ```
32
-
33
- `embed()` is inert until a query calls it: no worker process is spawned and no
34
- model is loaded for queries that never use it. On the first call, dirsql
35
- spawns the plugin's worker process (`dirsql-plugin-embeddings worker`), which
36
- serves every call of the invocation over stdin/stdout.
37
-
38
- ## Model
39
-
40
- Embeddings come from [model2vec](https://github.com/MinishLab/model2vec)
41
- (static embeddings — numpy + tokenizers, no torch), defaulting to
42
- [`minishlab/potion-retrieval-32M`](https://huggingface.co/minishlab/potion-retrieval-32M).
43
- The model downloads to the standard Hugging Face cache on the first ever run,
44
- with progress on stderr when stderr is a TTY.
45
-
46
- An optional second argument overrides the model per call — the id must be
47
- model2vec-loadable (sentence-transformers/torch models are out of scope):
48
-
49
- ```sql
50
- SELECT embed('some text', 'minishlab/potion-base-8M')
51
- ```
52
-
53
- ## Vector cache
54
-
55
- Computed vectors are cached at `~/.cache/dirsql/embeddings/` (or
56
- `$XDG_CACHE_HOME/dirsql/embeddings/` when `XDG_CACHE_HOME` is set), keyed by
57
- the SHA-256 of the value bytes plus the model identifier — changing either
58
- recomputes; switching models never serves stale vectors. There is no
59
- eviction: **the directory is safe to wipe at any time**; the only cost is
60
- re-embedding. The cache never lives inside a queried tree — the worker
61
- receives values, not paths, and writes nothing anywhere else.
@@ -1,48 +0,0 @@
1
- # dirsql-plugin-embeddings
2
-
3
- A first-party [`dirsql`](https://github.com/thekevinscott/dirsql) plugin for
4
- semantic search over files.
5
-
6
- Installing the plugin loads the
7
- [`sqlite-vec`](https://github.com/asg017/sqlite-vec) extension (for
8
- `vec_distance_cosine()` and friends) and declares an `embed()` SQL scalar
9
- function that turns TEXT or BLOB values into embedding vectors:
10
-
11
- ```sh
12
- uvx --with dirsql-plugin-embeddings dirsql "
13
- SELECT path
14
- FROM (SELECT path, embed(content ->> 'abstract') AS emb
15
- FROM 'arxiv-firehose/data/**/metadata.json')
16
- ORDER BY vec_distance_cosine(emb, embed('local private models'))
17
- LIMIT 10"
18
- ```
19
-
20
- `embed()` is inert until a query calls it: no worker process is spawned and no
21
- model is loaded for queries that never use it. On the first call, dirsql
22
- spawns the plugin's worker process (`dirsql-plugin-embeddings worker`), which
23
- serves every call of the invocation over stdin/stdout.
24
-
25
- ## Model
26
-
27
- Embeddings come from [model2vec](https://github.com/MinishLab/model2vec)
28
- (static embeddings — numpy + tokenizers, no torch), defaulting to
29
- [`minishlab/potion-retrieval-32M`](https://huggingface.co/minishlab/potion-retrieval-32M).
30
- The model downloads to the standard Hugging Face cache on the first ever run,
31
- with progress on stderr when stderr is a TTY.
32
-
33
- An optional second argument overrides the model per call — the id must be
34
- model2vec-loadable (sentence-transformers/torch models are out of scope):
35
-
36
- ```sql
37
- SELECT embed('some text', 'minishlab/potion-base-8M')
38
- ```
39
-
40
- ## Vector cache
41
-
42
- Computed vectors are cached at `~/.cache/dirsql/embeddings/` (or
43
- `$XDG_CACHE_HOME/dirsql/embeddings/` when `XDG_CACHE_HOME` is set), keyed by
44
- the SHA-256 of the value bytes plus the model identifier — changing either
45
- recomputes; switching models never serves stale vectors. There is no
46
- eviction: **the directory is safe to wipe at any time**; the only cost is
47
- re-embedding. The cache never lives inside a queried tree — the worker
48
- receives values, not paths, and writes nothing anywhere else.