Vector-store authority: campagna rebased 2026-07-19¶
Archive status — 2026-10-07¶
This is a historical report. Measurements and decisions describe the original
run and revision; recommendations and commands are not current operating
instructions. Path corrections below change navigation, not measurements.
The original ignored report remains unchanged at .artifacts/analysis/2026-07-19-vector-store-authority-rebased-campaign.md
(SHA-256 452c719307ce5d30b8cf7931f8372039cf9930409e4ddbd7968769933034032b).
Some original evidence is unavailable in this checkout. The missing paths are listed below; those observations have not been independently revalidated. Do not treat this archive as a fully reproducible current benchmark.
See the report archive index for coverage and remaining gaps.
| Artifact or input reference | Current availability |
|---|---|
.artifacts/benchmarks/vector-store-authority-rebased-20260718T175643Z/ |
unavailable historical path |
Decisione¶
No-go per l'integrazione in main nello stato attuale.
Il batching elimina il blocco funzionale che aveva interrotto la prima campagna:
tutte le otto campagne ripetute e gli otto smoke di indice completo terminano
senza errori. Il candidato introduce pero regressioni sostanziali in
combinazioni supportate. La piu netta e vector_store=sqlite, backend
strutturale DuckDB: la query media su CPython passa da 4.77 s a 29.59 s (+520%)
e il costo operativo pesato da 231.60 s a 689.07 s (+198%).
SQLite/SQLite resta vicino alla baseline (+6.6% sul costo pesato medio dei tre repository), ma non basta: la modifica dichiara supporto per entrambi i vector store e le combinazioni miste fanno parte della matrice.
Scope e parita¶
| Item | Main | Candidato |
|---|---|---|
| Commit | 0a9f1f86b68572f06578833426c1420fb9a4aabf |
5e30bb39d93ba816c5b7b55fab3cc135d64064d2 |
| Codira | 1.49.0 |
1.49.0.post1.dev1 |
| Vector stores / backend strutturali | SQLite, DuckDB | SQLite, DuckDB |
| Embedding | ONNX BGE small en v1.5, CPU | identico |
| Modello e tokenizer | .codira/models/bge-small-en-v1.5/ |
identici |
| Ripetizioni | 5, warmup 1 | identiche |
Il candidato contiene bcd6f47 refactor(embeddings): make vector stores authoritative
e 5e30bb3 fix(embeddings): batch vector cache lookups. Le versioni dei plugin
backend cambiano insieme al branch: i delta misurano l'intera proposta, non il
solo helper di batching.
Macchina: Intel i7-8700K (6 core / 12 thread), Linux 6.18.38 Gentoo, 46 GiB
RAM. ONNX CPUExecutionProvider, float32, normalizzazione attiva, batch 4;
il runner ha usato batch embedding 32, 10 thread Torch e 1 interop thread.
Integrita¶
- Otto
failure-summary.json:failure_count = 0in tutti i casi. - Tutti i campioni Hyperfine hanno
exit_codes = [0]. - Otto smoke
benchmark_index.py --full: nessun campoerror. - Non ricompare
sqlite3.OperationalError: too many SQL variablesnel caso DuckDB strutturale + vector store SQLite su CPython.
Il --dry-run risolve le selezioni creando indici: e costoso, ma non e una
misura Hyperfine. Gli indici ricreabili vengono rimossi dopo questo report.
Delta candidato rispetto a main¶
Costo pesato: full_index + 3 * partial_index + 20 * query_mean; piu basso e
meglio. Percentuali positive sono regressioni.
| Vector store | Backend | Repository | Full | Partial | Query | Costo |
|---|---|---|---|---|---|---|
| SQLite | SQLite | Codira | -6.7% | -12.5% | +5.1% | -0.9% |
| SQLite | SQLite | Redis | +3.2% | +0.7% | +6.3% | +4.9% |
| SQLite | SQLite | CPython | +11.1% | -4.2% | +1.9% | +6.6% |
| SQLite | DuckDB | Codira | -33.1% | -9.8% | +14.7% | -0.9% |
| SQLite | DuckDB | Redis | -29.1% | +3.2% | +175.1% | +109.6% |
| SQLite | DuckDB | CPython | -29.6% | +3.2% | +519.9% | +197.5% |
| DuckDB | SQLite | Codira | +39.9% | -1.9% | +7.3% | +20.0% |
| DuckDB | SQLite | Redis | +62.3% | -7.8% | +28.0% | +40.3% |
| DuckDB | SQLite | CPython | +121.8% | +2.1% | -17.6% | +65.9% |
| DuckDB | DuckDB | Codira | -16.8% | +13.3% | +19.5% | +8.6% |
| DuckDB | DuckDB | Redis | -13.1% | +3.1% | +83.2% | +49.8% |
| DuckDB | DuckDB | CPython | -20.4% | -3.8% | -4.3% | -13.7% |
Interpretazione¶
- Il batching risolve la correttezza.
- SQLite/SQLite e sostanzialmente stabile: costo medio 138.19 s -> 146.29 s (+5.9%).
- SQLite vector store + DuckDB strutturale e il principale no-go: full index piu veloce, ma query su Redis e CPython molto piu lente; costo +110--198%.
- DuckDB vector store + SQLite strutturale regredisce sistematicamente: costo +20--66%, con full index CPython +122%.
- DuckDB/DuckDB non e una vittoria generale: CPython migliora (-13.7%), ma Redis peggiora (+49.8%) e Codira (+8.6%).
Non e corretto attribuire i delta al solo vector store: il branch cambia anche
autorita e ciclo di persistenza delle embedding. Il prossimo passo e profilare
le combinazioni miste separando lookup cache, flush/write e aperture di
connessione durante ctx e emb.
Causa radice della regressione¶
L'indagine successiva conferma due regressioni architetturali indipendenti.
1. Vector store SQLite: ricerca semantica lineare in Python¶
Il candidato devia EmbeddingRetrievalProducer e la ricerca della
documentazione da IndexBackend a semantic.search, che chiama sempre
VectorStore.similarity_scores. La nuova implementazione SQLite esegue:
SELECT stable_id, vector FROM vectorsper tutti i vettori del tipo;- deserializzazione di ogni blob da 384 float;
- dot product Python e ordinamento completo dei risultati.
In main, con backend strutturale DuckDB, la query equivalente veniva eseguita
da DuckDB con list_dot_product, soglia e ordinamento nel database. Il cambio
spiega la regressione selettiva SQLite-vector/DuckDB-structural: sul profilo
CPython il candidato esegue 183.5 milioni di chiamate in 128.4 s contro 9.8
milioni in 7.1 s per main; SQLiteVectorStore.similarity_scores e il suo loop
di dot product sono un hot path misurato. Il valore Hyperfine di ctx e 29.59
s contro 4.77 s (+520%).
L'autorita del vector store non richiede che la similarita sia calcolata in Python. Il contratto deve mantenere la proprieta dei vettori nel vector store, ma ogni implementazione deve fornire un percorso di scoring nativo o bulk. Per SQLite, una semplice scansione BLOB+Python non soddisfa il budget di latenza per repository grandi.
2. DuckDB vector store con backend SQLite: materializzazione per batch¶
Nel backend SQLite, ogni _flush_prepared_embedding_rows chiama in sequenza
store_cached_vectors, store_vectors e delete_pending_vectors del vector
store. Con DuckDB ciascuna operazione apre una connessione, costruisce tabelle
Arrow e scrive nel database del vector store. Il percorso viene ripetuto per
ogni batch di embedding, anche in un full reindex con cache calda.
Su CPython i due run riusano esattamente 99.123 embedding e ne ricalcolano zero.
Nonostante cio il candidato passa da 15.60 s a 362.42 s nel timing diagnostico
embedding e da 129.77 s a 431.35 s nel timing indexing. Il backend strutturale
DuckDB ha gia un percorso specializzato materialize_full_index che trasferisce
cache e vettori in un'unica transazione Arrow; il backend SQLite non lo usa.
Questo spiega perche DuckDB-vector/DuckDB-structural non mostra lo stesso
peggioramento di full index, mentre DuckDB-vector/SQLite-structural arriva a
+122% su CPython.
Condizioni per riaprire il merge¶
- Implementare scoring efficiente nel vector store SQLite (SQL/estensione vettoriale oppure batch numerico nativo), con test e benchmark CPython che dimostrino di non regredire rispetto alla baseline DuckDB strutturale.
- Estendere il contratto VectorStore con una materializzazione full-index bulk/atomica e usarla anche dal backend SQLite; non e accettabile aprire e riscrivere DuckDB per ogni batch quando tutti i vettori sono riusati.
- Ripetere la matrice 2x2. Gate proposto: nessun delta di costo pesato oltre +10% su ciascun repository e nessuna regressione query oltre +15% nei percorsi supportati.
Artefatti mantenuti e validazione¶
Sono mantenuti manifest, configurazioni ONNX, campaign-plan.json,
failure-summary.json, *-hyperfine.json, *-utility-summary.json,
*-index-phases.json, log e profili in
.artifacts/benchmarks/vector-store-authority-rebased-20260718T175643Z/.
Indici, smoke diretti e worktree temporanei sono ricreabili e vengono rimossi.
La campagna e la validazione runtime: 8/8 matrici senza fallimenti e cinque
campioni Hyperfine per comando. uv run python scripts/validate_repo.py era
gia passato sul commit candidato prima della campagna; non e rieseguito per il
solo report e la pulizia di file ignorati.