flexvec 0.2.1__tar.gz → 0.4.0__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.
- flexvec-0.4.0/PKG-INFO +210 -0
- flexvec-0.4.0/README.md +189 -0
- flexvec-0.4.0/flexvec/__main__.py +7 -0
- flexvec-0.4.0/flexvec/ai/__init__.py +1 -0
- flexvec-0.4.0/flexvec/ai/skills/__init__.py +1 -0
- flexvec-0.4.0/flexvec/ai/skills/flexvec/SKILL.md +76 -0
- flexvec-0.4.0/flexvec/ai/skills/flexvec/__init__.py +1 -0
- flexvec-0.4.0/flexvec/ai/skills/flexvec/reference/mcp.md +23 -0
- flexvec-0.4.0/flexvec/ai/skills/flexvec/reference/retrieval-contract.md +35 -0
- flexvec-0.4.0/flexvec/ai/skills/flexvec/reference/sql-patterns.md +53 -0
- flexvec-0.4.0/flexvec/cli.py +200 -0
- flexvec-0.4.0/flexvec/keyword.py +265 -0
- flexvec-0.4.0/flexvec/mcp_core.py +177 -0
- flexvec-0.4.0/flexvec/mcp_server.py +210 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec/score.py +39 -118
- flexvec-0.4.0/flexvec/spec.py +393 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec/vec_ops.py +9 -5
- flexvec-0.4.0/flexvec.egg-info/PKG-INFO +210 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec.egg-info/SOURCES.txt +14 -0
- flexvec-0.4.0/flexvec.egg-info/entry_points.txt +3 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec.egg-info/requires.txt +4 -2
- {flexvec-0.2.1 → flexvec-0.4.0}/pyproject.toml +14 -5
- flexvec-0.4.0/tests/test_cli.py +206 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/tests/test_keyword.py +6 -2
- flexvec-0.4.0/tests/test_mcp_server.py +75 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/tests/test_vec_ops.py +12 -46
- flexvec-0.2.1/PKG-INFO +0 -221
- flexvec-0.2.1/README.md +0 -203
- flexvec-0.2.1/flexvec/__main__.py +0 -8
- flexvec-0.2.1/flexvec/keyword.py +0 -146
- flexvec-0.2.1/flexvec.egg-info/PKG-INFO +0 -221
- {flexvec-0.2.1 → flexvec-0.4.0}/LICENSE +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec/__init__.py +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec/embed.py +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec/execute.py +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec/onnx/__init__.py +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec/onnx/embed.py +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec/onnx/fetch.py +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec/onnx/nomic_embed.py +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec/onnx/special_tokens_map.json +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec/onnx/tokenizer.json +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec/onnx/tokenizer_config.json +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec/onnx/vocab.txt +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec.egg-info/dependency_links.txt +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/flexvec.egg-info/top_level.txt +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/setup.cfg +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/tests/test_algebraic.py +0 -0
- {flexvec-0.2.1 → flexvec-0.4.0}/tests/test_tokens_beir.py +0 -0
flexvec-0.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: flexvec
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: agent-native SQLite vector retrieval
|
|
5
|
+
Author-email: Damian Delmas <damian@getflex.dev>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/damiandelmas/flexvec
|
|
8
|
+
Project-URL: Paper, https://arxiv.org/abs/2603.22587
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: numpy
|
|
13
|
+
Provides-Extra: embed
|
|
14
|
+
Requires-Dist: onnxruntime; extra == "embed"
|
|
15
|
+
Requires-Dist: tokenizers; extra == "embed"
|
|
16
|
+
Provides-Extra: mcp
|
|
17
|
+
Requires-Dist: mcp; extra == "mcp"
|
|
18
|
+
Requires-Dist: onnxruntime; extra == "mcp"
|
|
19
|
+
Requires-Dist: tokenizers; extra == "mcp"
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# flexvec
|
|
23
|
+
|
|
24
|
+
[](https://pypi.org/project/flexvec/)
|
|
25
|
+
[](LICENSE)
|
|
26
|
+
[](https://www.python.org/)
|
|
27
|
+
|
|
28
|
+
Composable vector retrieval with SQL.
|
|
29
|
+
|
|
30
|
+
flexvec is a Python library and agent-native CLI that reshapes vector search scores before selection. Suppress a topic, weight by recency, spread across subtopics, project a direction through embedding space — all in one SQL statement. Runs in-process on SQLite with optional local MCP serving. No hosted service.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install flexvec
|
|
34
|
+
pip install "flexvec[mcp]" # agent MCP server + embeddings
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Agent-native SQLite vectorization
|
|
38
|
+
|
|
39
|
+
FlexVec can turn an existing SQLite table into an agent-ready retrieval surface.
|
|
40
|
+
Commands are JSON-first so agents can inspect, prepare, index, verify, and serve
|
|
41
|
+
one database deterministically.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
flexvec inspect app.db --json
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Create a retrieval contract:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"table": "docs",
|
|
52
|
+
"id_column": "id",
|
|
53
|
+
"text_columns": ["title", "body"],
|
|
54
|
+
"metadata_cols": ["created_at"]
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Prepare and index the database:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
flexvec prepare app.db --spec spec.json --json
|
|
62
|
+
flexvec index app.db --spec spec.json --json
|
|
63
|
+
flexvec doctor app.db --json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Query or hand the DB to an agent over MCP:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
flexvec sql app.db "SELECT v.id, v.score, c.content FROM vec_ops('similar:refund policy') v JOIN _raw_chunks c ON c.id = v.id LIMIT 10" --json
|
|
70
|
+
flexvec sql app.db "SELECT k.id, k.rank, c.content FROM keyword('refund policy') k JOIN _raw_chunks c ON c.id = k.id LIMIT 10" --no-embed --json
|
|
71
|
+
flexvec mcp app.db
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`prepare` creates FlexVec-owned `_flexvec_meta`, `_raw_chunks`, and `chunks_fts`
|
|
75
|
+
surfaces inside the target database. FlexVec does not require a Flex registry,
|
|
76
|
+
Flex cells, services, modules, or Labs packages.
|
|
77
|
+
If those tables already exist, `prepare`/`index` return warnings before reusing
|
|
78
|
+
or rebuilding them; copy the DB first or choose custom table names in the spec
|
|
79
|
+
when reuse is not intended.
|
|
80
|
+
|
|
81
|
+
## Getting started
|
|
82
|
+
|
|
83
|
+
### Your table
|
|
84
|
+
|
|
85
|
+
Any SQLite database with an embedding column works.
|
|
86
|
+
|
|
87
|
+
```sql
|
|
88
|
+
CREATE TABLE chunks (
|
|
89
|
+
id TEXT PRIMARY KEY,
|
|
90
|
+
content TEXT,
|
|
91
|
+
embedding BLOB -- float32, L2-normalized
|
|
92
|
+
);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Connect
|
|
96
|
+
|
|
97
|
+
Load embeddings into memory once. Every query after that is a matmul.
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
import sqlite3
|
|
101
|
+
from flexvec import VectorCache, register_vec_ops, execute, get_embed_fn
|
|
102
|
+
|
|
103
|
+
db = sqlite3.connect("my.db")
|
|
104
|
+
cache = VectorCache()
|
|
105
|
+
cache.load_from_db(db, "chunks", "embedding", "id")
|
|
106
|
+
register_vec_ops(db, {"chunks": cache}, get_embed_fn())
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Search
|
|
110
|
+
|
|
111
|
+
Write SQL. flexvec handles the vector math behind the scenes.
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
rows = execute(db, """
|
|
115
|
+
SELECT v.id, v.score, c.content
|
|
116
|
+
FROM vec_ops('similar:authentication patterns') v
|
|
117
|
+
JOIN chunks c ON v.id = c.id
|
|
118
|
+
ORDER BY v.score DESC LIMIT 5
|
|
119
|
+
""")
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Examples
|
|
123
|
+
|
|
124
|
+
### Suppress and diversify
|
|
125
|
+
|
|
126
|
+
Find authentication patterns without drowning in deployment and testing discussions.
|
|
127
|
+
|
|
128
|
+
```sql
|
|
129
|
+
SELECT v.id, v.score, c.content
|
|
130
|
+
FROM vec_ops(
|
|
131
|
+
'similar:authentication patterns
|
|
132
|
+
diverse suppress:deployment suppress:testing',
|
|
133
|
+
'SELECT id FROM chunks WHERE length(content) > 200') v
|
|
134
|
+
JOIN chunks c ON v.id = c.id
|
|
135
|
+
ORDER BY v.score DESC LIMIT 10
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`suppress:` pushes deployment and testing content out of the results. `diverse` spreads across subtopics instead of returning ten variations of the same match. The pre-filter scopes to chunks over 200 characters — cutting out noise before anything gets scored.
|
|
139
|
+
|
|
140
|
+
### Hybrid retrieval
|
|
141
|
+
|
|
142
|
+
Find the session where you actually fixed that OOM error — not just the logs.
|
|
143
|
+
|
|
144
|
+
```sql
|
|
145
|
+
SELECT k.id, k.rank, v.score, c.content
|
|
146
|
+
FROM keyword('OOM') k
|
|
147
|
+
JOIN vec_ops('similar:memory limit debugging worker crash fix') v ON k.id = v.id
|
|
148
|
+
JOIN chunks c ON k.id = c.id
|
|
149
|
+
ORDER BY v.score DESC LIMIT 10
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`keyword('OOM')` finds every chunk containing the term. `vec_ops()` scores by relevance to debugging and fixing. The JOIN keeps only chunks that match both — exact term plus semantic relevance.
|
|
153
|
+
|
|
154
|
+
## Tokens
|
|
155
|
+
|
|
156
|
+
Tokens reshape scores. They compose freely in a single string.
|
|
157
|
+
|
|
158
|
+
| token | what it does |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `similar:TEXT` | search for this concept |
|
|
161
|
+
| `suppress:TEXT` | push this topic out of results (stackable) |
|
|
162
|
+
| `diverse` | spread across subtopics instead of ten versions of the same answer |
|
|
163
|
+
| `decay:N` | favor recent content — N-day half-life |
|
|
164
|
+
| `centroid:id1,id2` | "more like these" — search from the average of examples |
|
|
165
|
+
| `from:A to:B` | find content along a conceptual arc |
|
|
166
|
+
| `pool:N` | how many candidates to score (default 500) |
|
|
167
|
+
|
|
168
|
+
`'similar:auth diverse suppress:oauth decay:7'` — four operations, one query.
|
|
169
|
+
|
|
170
|
+
## How it works
|
|
171
|
+
|
|
172
|
+
Every query runs three phases in one SQL statement.
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
SQL pre-filter → numpy modulation → SQL compose
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
1. **SQL pre-filter** narrows what enters scoring — by date, type, length, or any SQL expression.
|
|
179
|
+
2. **numpy modulation** scores candidates and reshapes the score array with tokens before selection.
|
|
180
|
+
3. **SQL compose** joins results back to your tables for grouping, filtering, or reranking.
|
|
181
|
+
|
|
182
|
+
The database is never modified. Results materialize as a temp table that SQL composes over.
|
|
183
|
+
|
|
184
|
+
## Performance
|
|
185
|
+
|
|
186
|
+
No index. Brute-force matmul on a numpy matrix.
|
|
187
|
+
|
|
188
|
+
| corpus | matmul | full pipeline |
|
|
189
|
+
|---|---|---|
|
|
190
|
+
| 250K | 5ms | 19ms |
|
|
191
|
+
| 500K | 7ms | 37ms |
|
|
192
|
+
| 1M | 17ms | 82ms |
|
|
193
|
+
|
|
194
|
+
128 dimensions, Nomic Embed v1.5 (Matryoshka). Pre-filtering narrows candidates before the matmul — scoped queries run in single-digit ms.
|
|
195
|
+
|
|
196
|
+
## Install
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
pip install flexvec # core (numpy only)
|
|
200
|
+
pip install flexvec[embed] # + ONNX embedder
|
|
201
|
+
pip install flexvec[mcp] # + MCP server and embedder
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## See also
|
|
205
|
+
|
|
206
|
+
- **[arXiv paper](https://arxiv.org/abs/2603.22587)** — architecture and evaluation
|
|
207
|
+
- **[flex](https://github.com/damiandelmas/flex)** — search and retrieval for AI agents (uses flexvec)
|
|
208
|
+
- **[getflex.dev](https://getflex.dev)**
|
|
209
|
+
|
|
210
|
+
MIT · Python 3.10+ · SQLite · numpy
|
flexvec-0.4.0/README.md
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# flexvec
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/flexvec/)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://www.python.org/)
|
|
6
|
+
|
|
7
|
+
Composable vector retrieval with SQL.
|
|
8
|
+
|
|
9
|
+
flexvec is a Python library and agent-native CLI that reshapes vector search scores before selection. Suppress a topic, weight by recency, spread across subtopics, project a direction through embedding space — all in one SQL statement. Runs in-process on SQLite with optional local MCP serving. No hosted service.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install flexvec
|
|
13
|
+
pip install "flexvec[mcp]" # agent MCP server + embeddings
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Agent-native SQLite vectorization
|
|
17
|
+
|
|
18
|
+
FlexVec can turn an existing SQLite table into an agent-ready retrieval surface.
|
|
19
|
+
Commands are JSON-first so agents can inspect, prepare, index, verify, and serve
|
|
20
|
+
one database deterministically.
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
flexvec inspect app.db --json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Create a retrieval contract:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"table": "docs",
|
|
31
|
+
"id_column": "id",
|
|
32
|
+
"text_columns": ["title", "body"],
|
|
33
|
+
"metadata_cols": ["created_at"]
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Prepare and index the database:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
flexvec prepare app.db --spec spec.json --json
|
|
41
|
+
flexvec index app.db --spec spec.json --json
|
|
42
|
+
flexvec doctor app.db --json
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Query or hand the DB to an agent over MCP:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
flexvec sql app.db "SELECT v.id, v.score, c.content FROM vec_ops('similar:refund policy') v JOIN _raw_chunks c ON c.id = v.id LIMIT 10" --json
|
|
49
|
+
flexvec sql app.db "SELECT k.id, k.rank, c.content FROM keyword('refund policy') k JOIN _raw_chunks c ON c.id = k.id LIMIT 10" --no-embed --json
|
|
50
|
+
flexvec mcp app.db
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`prepare` creates FlexVec-owned `_flexvec_meta`, `_raw_chunks`, and `chunks_fts`
|
|
54
|
+
surfaces inside the target database. FlexVec does not require a Flex registry,
|
|
55
|
+
Flex cells, services, modules, or Labs packages.
|
|
56
|
+
If those tables already exist, `prepare`/`index` return warnings before reusing
|
|
57
|
+
or rebuilding them; copy the DB first or choose custom table names in the spec
|
|
58
|
+
when reuse is not intended.
|
|
59
|
+
|
|
60
|
+
## Getting started
|
|
61
|
+
|
|
62
|
+
### Your table
|
|
63
|
+
|
|
64
|
+
Any SQLite database with an embedding column works.
|
|
65
|
+
|
|
66
|
+
```sql
|
|
67
|
+
CREATE TABLE chunks (
|
|
68
|
+
id TEXT PRIMARY KEY,
|
|
69
|
+
content TEXT,
|
|
70
|
+
embedding BLOB -- float32, L2-normalized
|
|
71
|
+
);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Connect
|
|
75
|
+
|
|
76
|
+
Load embeddings into memory once. Every query after that is a matmul.
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
import sqlite3
|
|
80
|
+
from flexvec import VectorCache, register_vec_ops, execute, get_embed_fn
|
|
81
|
+
|
|
82
|
+
db = sqlite3.connect("my.db")
|
|
83
|
+
cache = VectorCache()
|
|
84
|
+
cache.load_from_db(db, "chunks", "embedding", "id")
|
|
85
|
+
register_vec_ops(db, {"chunks": cache}, get_embed_fn())
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Search
|
|
89
|
+
|
|
90
|
+
Write SQL. flexvec handles the vector math behind the scenes.
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
rows = execute(db, """
|
|
94
|
+
SELECT v.id, v.score, c.content
|
|
95
|
+
FROM vec_ops('similar:authentication patterns') v
|
|
96
|
+
JOIN chunks c ON v.id = c.id
|
|
97
|
+
ORDER BY v.score DESC LIMIT 5
|
|
98
|
+
""")
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Examples
|
|
102
|
+
|
|
103
|
+
### Suppress and diversify
|
|
104
|
+
|
|
105
|
+
Find authentication patterns without drowning in deployment and testing discussions.
|
|
106
|
+
|
|
107
|
+
```sql
|
|
108
|
+
SELECT v.id, v.score, c.content
|
|
109
|
+
FROM vec_ops(
|
|
110
|
+
'similar:authentication patterns
|
|
111
|
+
diverse suppress:deployment suppress:testing',
|
|
112
|
+
'SELECT id FROM chunks WHERE length(content) > 200') v
|
|
113
|
+
JOIN chunks c ON v.id = c.id
|
|
114
|
+
ORDER BY v.score DESC LIMIT 10
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`suppress:` pushes deployment and testing content out of the results. `diverse` spreads across subtopics instead of returning ten variations of the same match. The pre-filter scopes to chunks over 200 characters — cutting out noise before anything gets scored.
|
|
118
|
+
|
|
119
|
+
### Hybrid retrieval
|
|
120
|
+
|
|
121
|
+
Find the session where you actually fixed that OOM error — not just the logs.
|
|
122
|
+
|
|
123
|
+
```sql
|
|
124
|
+
SELECT k.id, k.rank, v.score, c.content
|
|
125
|
+
FROM keyword('OOM') k
|
|
126
|
+
JOIN vec_ops('similar:memory limit debugging worker crash fix') v ON k.id = v.id
|
|
127
|
+
JOIN chunks c ON k.id = c.id
|
|
128
|
+
ORDER BY v.score DESC LIMIT 10
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`keyword('OOM')` finds every chunk containing the term. `vec_ops()` scores by relevance to debugging and fixing. The JOIN keeps only chunks that match both — exact term plus semantic relevance.
|
|
132
|
+
|
|
133
|
+
## Tokens
|
|
134
|
+
|
|
135
|
+
Tokens reshape scores. They compose freely in a single string.
|
|
136
|
+
|
|
137
|
+
| token | what it does |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `similar:TEXT` | search for this concept |
|
|
140
|
+
| `suppress:TEXT` | push this topic out of results (stackable) |
|
|
141
|
+
| `diverse` | spread across subtopics instead of ten versions of the same answer |
|
|
142
|
+
| `decay:N` | favor recent content — N-day half-life |
|
|
143
|
+
| `centroid:id1,id2` | "more like these" — search from the average of examples |
|
|
144
|
+
| `from:A to:B` | find content along a conceptual arc |
|
|
145
|
+
| `pool:N` | how many candidates to score (default 500) |
|
|
146
|
+
|
|
147
|
+
`'similar:auth diverse suppress:oauth decay:7'` — four operations, one query.
|
|
148
|
+
|
|
149
|
+
## How it works
|
|
150
|
+
|
|
151
|
+
Every query runs three phases in one SQL statement.
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
SQL pre-filter → numpy modulation → SQL compose
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
1. **SQL pre-filter** narrows what enters scoring — by date, type, length, or any SQL expression.
|
|
158
|
+
2. **numpy modulation** scores candidates and reshapes the score array with tokens before selection.
|
|
159
|
+
3. **SQL compose** joins results back to your tables for grouping, filtering, or reranking.
|
|
160
|
+
|
|
161
|
+
The database is never modified. Results materialize as a temp table that SQL composes over.
|
|
162
|
+
|
|
163
|
+
## Performance
|
|
164
|
+
|
|
165
|
+
No index. Brute-force matmul on a numpy matrix.
|
|
166
|
+
|
|
167
|
+
| corpus | matmul | full pipeline |
|
|
168
|
+
|---|---|---|
|
|
169
|
+
| 250K | 5ms | 19ms |
|
|
170
|
+
| 500K | 7ms | 37ms |
|
|
171
|
+
| 1M | 17ms | 82ms |
|
|
172
|
+
|
|
173
|
+
128 dimensions, Nomic Embed v1.5 (Matryoshka). Pre-filtering narrows candidates before the matmul — scoped queries run in single-digit ms.
|
|
174
|
+
|
|
175
|
+
## Install
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
pip install flexvec # core (numpy only)
|
|
179
|
+
pip install flexvec[embed] # + ONNX embedder
|
|
180
|
+
pip install flexvec[mcp] # + MCP server and embedder
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## See also
|
|
184
|
+
|
|
185
|
+
- **[arXiv paper](https://arxiv.org/abs/2603.22587)** — architecture and evaluation
|
|
186
|
+
- **[flex](https://github.com/damiandelmas/flex)** — search and retrieval for AI agents (uses flexvec)
|
|
187
|
+
- **[getflex.dev](https://getflex.dev)**
|
|
188
|
+
|
|
189
|
+
MIT · Python 3.10+ · SQLite · numpy
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Packaged AI-facing FlexVec assets."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Packaged FlexVec skills."""
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# FlexVec
|
|
2
|
+
|
|
3
|
+
Use this skill when an agent needs to turn an existing SQLite database into a structured vector-retrieval database, query it with SQL, or expose it over MCP.
|
|
4
|
+
|
|
5
|
+
FlexVec is agent-native. Prefer deterministic JSON commands and explicit database paths. Do not assume a Flex registry, Flex cells, Flex modules, daemon state, or Labs packages are available.
|
|
6
|
+
|
|
7
|
+
## Workflow
|
|
8
|
+
|
|
9
|
+
1. Inspect the database:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
flexvec inspect /path/to/app.db --json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
2. Create a retrieval contract JSON. Pick one source table, one stable id column, one or more text/content columns, and any metadata columns the agent should preserve.
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"table": "docs",
|
|
20
|
+
"id_column": "id",
|
|
21
|
+
"text_columns": ["title", "body"],
|
|
22
|
+
"metadata_cols": ["created_at"]
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
3. Prepare the database. This creates FlexVec-owned `_flexvec_meta`, `_raw_chunks`, and `chunks_fts` surfaces inside the target DB.
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
flexvec prepare /path/to/app.db --spec spec.json --json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
4. Index the database. This copies source rows into `_raw_chunks`, rebuilds FTS, and embeds rows when `flexvec[embed]` is installed.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
flexvec index /path/to/app.db --spec spec.json --json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
For deterministic keyword-only validation or offline environments, skip embeddings:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
flexvec index /path/to/app.db --spec spec.json --skip-embeddings --json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
5. Verify readiness:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
flexvec doctor /path/to/app.db --json
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
6. Query with SQL:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
flexvec sql /path/to/app.db "SELECT v.id, v.score, c.content FROM vec_ops('similar:refund policy') v JOIN _raw_chunks c ON c.id = v.id ORDER BY v.score DESC LIMIT 10" --json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Keyword-only query without embedding/model setup:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
flexvec sql /path/to/app.db "SELECT k.id, k.rank, c.content FROM keyword('refund policy') k JOIN _raw_chunks c ON c.id = k.id ORDER BY k.rank DESC LIMIT 10" --no-embed --json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
7. Serve over MCP:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
flexvec mcp /path/to/app.db
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Rules
|
|
69
|
+
|
|
70
|
+
- Treat the SQLite DB path as explicit state. Do not rely on hidden project globals.
|
|
71
|
+
- Use `inspect` before creating a spec.
|
|
72
|
+
- Use `prepare` before `index`.
|
|
73
|
+
- If the DB already has `_raw_chunks` or `chunks_fts`, read prepare/index warnings carefully; copy the DB first or choose custom `chunk_table`/`fts_table` names if reuse is not intended.
|
|
74
|
+
- Use `doctor` before handing the DB to another agent.
|
|
75
|
+
- Use SQL as the canonical query language; `vec_ops()` and `keyword()` are table sources.
|
|
76
|
+
- Do not import or depend on `flex.*` or Labs packages.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""FlexVec agent skill package."""
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# MCP
|
|
2
|
+
|
|
3
|
+
FlexVec MCP serves one SQLite database over stdio.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
flexvec mcp /path/to/app.db
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The MCP tool is `flexvec_search`. It accepts read-only SQL:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"query": "SELECT v.id, v.score, c.content FROM vec_ops('similar:refund policy') v JOIN _raw_chunks c ON c.id = v.id LIMIT 10"
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
For SQL/keyword-only operation without loading embeddings:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
flexvec mcp /path/to/app.db --no-embed
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
FlexVec MCP does not use a Flex registry, Flex cells, Flex modules, services, or Labs packages. The database itself carries the retrieval contract in `_flexvec_meta`.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Retrieval Contract
|
|
2
|
+
|
|
3
|
+
The retrieval contract tells FlexVec how to create a retrieval surface from one source table.
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
{
|
|
7
|
+
"table": "docs",
|
|
8
|
+
"id_column": "id",
|
|
9
|
+
"text_columns": ["title", "body"],
|
|
10
|
+
"metadata_cols": ["created_at"],
|
|
11
|
+
"chunk_table": "_raw_chunks",
|
|
12
|
+
"fts_table": "chunks_fts",
|
|
13
|
+
"embedding_col": "embedding"
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Required fields:
|
|
18
|
+
|
|
19
|
+
- `table`: source table to index.
|
|
20
|
+
- `id_column`: stable row identifier. `id_col` is also accepted.
|
|
21
|
+
- `text_columns`: text columns to join, embed, and search. `text_col` or `text_cols` are also accepted.
|
|
22
|
+
|
|
23
|
+
Optional fields:
|
|
24
|
+
|
|
25
|
+
- `metadata_cols`: columns serialized into `_raw_chunks.metadata`.
|
|
26
|
+
- `chunk_table`: FlexVec-owned retrieval table, default `_raw_chunks`.
|
|
27
|
+
- `fts_table`: FlexVec-owned FTS5 table, default `chunks_fts`.
|
|
28
|
+
- `embedding_col`: BLOB column in `chunk_table`, default `embedding`.
|
|
29
|
+
|
|
30
|
+
`prepare` stores this contract in `_flexvec_meta`. Later `index`, `doctor`, and MCP invocations can use the stored contract.
|
|
31
|
+
|
|
32
|
+
If `chunk_table` or `fts_table` already exists before FlexVec has stored a spec,
|
|
33
|
+
`prepare` reports warnings. This commonly happens when testing against a copied
|
|
34
|
+
Flex cell. Copy the database first or choose custom table names if reuse is not
|
|
35
|
+
intentional.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# SQL Patterns
|
|
2
|
+
|
|
3
|
+
FlexVec queries are SQL-first. `vec_ops()` and `keyword()` materialize temporary result tables that can be joined to `_raw_chunks` or to source tables.
|
|
4
|
+
|
|
5
|
+
Semantic retrieval:
|
|
6
|
+
|
|
7
|
+
```sql
|
|
8
|
+
SELECT v.id, v.score, c.content
|
|
9
|
+
FROM vec_ops('similar:refund policy') v
|
|
10
|
+
JOIN _raw_chunks c ON c.id = v.id
|
|
11
|
+
ORDER BY v.score DESC
|
|
12
|
+
LIMIT 10;
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Keyword retrieval:
|
|
16
|
+
|
|
17
|
+
```sql
|
|
18
|
+
SELECT k.id, k.rank, k.snippet, c.content
|
|
19
|
+
FROM keyword('refund') k
|
|
20
|
+
JOIN _raw_chunks c ON c.id = k.id
|
|
21
|
+
ORDER BY k.rank DESC
|
|
22
|
+
LIMIT 10;
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Keyword-only CLI query without embedding/model setup:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
flexvec sql app.db "SELECT k.id, k.rank, c.content FROM keyword('refund policy') k JOIN _raw_chunks c ON c.id = k.id ORDER BY k.rank DESC LIMIT 10" --no-embed --json
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Hybrid retrieval:
|
|
32
|
+
|
|
33
|
+
```sql
|
|
34
|
+
SELECT k.id, k.rank, v.score, c.content
|
|
35
|
+
FROM keyword('refund') k
|
|
36
|
+
JOIN vec_ops('similar:policy exception') v ON v.id = k.id
|
|
37
|
+
JOIN _raw_chunks c ON c.id = k.id
|
|
38
|
+
ORDER BY v.score DESC
|
|
39
|
+
LIMIT 10;
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Scoped retrieval:
|
|
43
|
+
|
|
44
|
+
```sql
|
|
45
|
+
SELECT v.id, v.score, c.content
|
|
46
|
+
FROM vec_ops(
|
|
47
|
+
'similar:customer escalation',
|
|
48
|
+
'SELECT id FROM _raw_chunks WHERE metadata LIKE ''%support%'''
|
|
49
|
+
) v
|
|
50
|
+
JOIN _raw_chunks c ON c.id = v.id
|
|
51
|
+
ORDER BY v.score DESC
|
|
52
|
+
LIMIT 10;
|
|
53
|
+
```
|