Skip to content

Commit 6aec315

Browse files
committed
Adde automatic reindex when model/provider changes
1 parent 8ab9114 commit 6aec315

2 files changed

Lines changed: 68 additions & 2 deletions

File tree

API.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ Configures the embedding model to use.
114114
- Remote embedding requires a free API key from [vectors.space](https://vectors.space) (set via `memory_set_apikey`)
115115
- Settings are persisted in `dbmem_settings` table
116116
- For local models, the embedding engine is initialized immediately
117+
- **Automatic reindex**: If a model was previously configured and the new provider/model differs, all existing content is automatically re-embedded with the new model. File-based entries are re-read from disk; text-based entries are re-embedded from stored content. Errors on individual entries are silently skipped (best-effort)
117118

118119
**Example:**
119120
```sql

src/sqlite-memory.c

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,8 @@ static void dbmem_version (sqlite3_context *context, int argc, sqlite3_value **a
859859
sqlite3_result_text(context, SQLITE_DBMEMORY_VERSION, -1, NULL);
860860
}
861861

862+
static int dbmem_reindex(dbmem_context *ctx);
863+
862864
static void dbmem_set_model (sqlite3_context *context, int argc, sqlite3_value **argv) {
863865
// 2 TEXT arguments: provider and model
864866

@@ -877,7 +879,14 @@ static void dbmem_set_model (sqlite3_context *context, int argc, sqlite3_value *
877879

878880
// retrieve context
879881
dbmem_context *ctx = (dbmem_context *)sqlite3_user_data(context);
880-
882+
883+
// detect model change (only if a model was previously configured)
884+
bool model_changed = false;
885+
if (ctx->provider && ctx->model) {
886+
model_changed = (strcasecmp(ctx->provider, provider) != 0 ||
887+
strcasecmp(ctx->model, model) != 0);
888+
}
889+
881890
bool is_local_provider = (strcasecmp(provider, DBMEM_LOCAL_PROVIDER) == 0);
882891
#ifdef DBMEM_OMIT_LOCAL_ENGINE
883892
if (is_local_provider) {
@@ -942,7 +951,12 @@ static void dbmem_set_model (sqlite3_context *context, int argc, sqlite3_value *
942951
dbmem_settings_sync(ctx, DBMEM_SETTINGS_KEY_PROVIDER, argv[0]);
943952
dbmem_settings_sync(ctx, DBMEM_SETTINGS_KEY_MODEL, argv[1]);
944953
}
945-
954+
955+
// reindex all content if the model changed
956+
if (model_changed && rc == SQLITE_OK) {
957+
rc = dbmem_reindex(ctx);
958+
}
959+
946960
(rc == SQLITE_OK) ? sqlite3_result_int(context, 1) : sqlite3_result_error(context, sqlite3_errmsg(db), -1);
947961
}
948962

@@ -1293,6 +1307,57 @@ static int dbmem_process_file (dbmem_context *ctx, const char *path) {
12931307
return rc;
12941308
}
12951309

1310+
static int dbmem_reindex (dbmem_context *ctx) {
1311+
sqlite3 *db = ctx->db;
1312+
int rc = SQLITE_OK;
1313+
1314+
// copy all content to a temp table
1315+
rc = sqlite3_exec(db, "CREATE TEMP TABLE dbmem_reindex AS SELECT path, value, context FROM dbmem_content;", NULL, NULL, NULL);
1316+
if (rc != SQLITE_OK) return rc;
1317+
1318+
// clear all indexed data
1319+
if (fts5_is_available) {
1320+
sqlite3_exec(db, "DELETE FROM dbmem_vault_fts;", NULL, NULL, NULL);
1321+
}
1322+
sqlite3_exec(db, "DELETE FROM dbmem_vault;", NULL, NULL, NULL);
1323+
sqlite3_exec(db, "DELETE FROM dbmem_content;", NULL, NULL, NULL);
1324+
1325+
// reset dimension so the new model's dimension is auto-detected
1326+
ctx->dimension = 0;
1327+
ctx->dimension_saved = false;
1328+
ctx->vector_extension_available = false;
1329+
1330+
// iterate temp table one row at a time
1331+
sqlite3_stmt *vm = NULL;
1332+
rc = sqlite3_prepare_v2(db, "SELECT path, value, context FROM dbmem_reindex;", -1, &vm, NULL);
1333+
if (rc != SQLITE_OK) goto cleanup;
1334+
1335+
while (sqlite3_step(vm) == SQLITE_ROW) {
1336+
const char *path = (const char *)sqlite3_column_text(vm, 0);
1337+
const char *value = (const char *)sqlite3_column_text(vm, 1);
1338+
int value_len = sqlite3_column_bytes(vm, 1);
1339+
const char *context = (const char *)sqlite3_column_text(vm, 2);
1340+
1341+
dbmem_context_reset_temp_values(ctx);
1342+
ctx->context = context;
1343+
1344+
if (path && dbmem_file_exists(path)) {
1345+
dbmem_process_file(ctx, path);
1346+
} else if (value && value_len > 0) {
1347+
ctx->path = path;
1348+
dbmem_process_buffer(ctx, value, value_len);
1349+
}
1350+
// else: skip entries that can't be rebuilt
1351+
}
1352+
1353+
rc = SQLITE_OK;
1354+
1355+
cleanup:
1356+
if (vm) sqlite3_finalize(vm);
1357+
sqlite3_exec(db, "DROP TABLE IF EXISTS dbmem_reindex;", NULL, NULL, NULL);
1358+
return rc;
1359+
}
1360+
12961361
static int dbmem_scan_callback (const char *path, void *data) {
12971362
dbmem_context *ctx = (dbmem_context *)data;
12981363

0 commit comments

Comments
 (0)