doc2vec 1.3.0 → 2.2.0

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.
package/dist/database.js CHANGED
@@ -59,12 +59,16 @@ class DatabaseManager {
59
59
  embedding FLOAT[3072],
60
60
  product_name TEXT,
61
61
  version TEXT,
62
+ branch TEXT,
63
+ repo TEXT,
62
64
  heading_hierarchy TEXT,
63
65
  section TEXT,
64
66
  chunk_id TEXT UNIQUE,
65
67
  content TEXT,
66
68
  url TEXT,
67
- hash TEXT
69
+ hash TEXT,
70
+ chunk_index INTEGER,
71
+ total_chunks INTEGER
68
72
  );
69
73
  `);
70
74
  logger.info(`SQLite database initialized successfully`);
@@ -139,6 +143,82 @@ class DatabaseManager {
139
143
  // Nothing special to initialize as we'll use the same collection
140
144
  }
141
145
  }
146
+ static async getMetadataValue(dbConnection, key, defaultValue, logger) {
147
+ try {
148
+ if (dbConnection.type === 'sqlite') {
149
+ const stmt = dbConnection.db.prepare('SELECT value FROM vec_metadata WHERE key = ?');
150
+ const result = stmt.get(key);
151
+ if (result) {
152
+ logger.debug(`Retrieved metadata value for ${key}: ${result.value}`);
153
+ return result.value;
154
+ }
155
+ }
156
+ else if (dbConnection.type === 'qdrant') {
157
+ const metadataUUID = utils_1.Utils.generateMetadataUUID(key);
158
+ logger.debug(`Looking up metadata with UUID: ${metadataUUID}`);
159
+ try {
160
+ const response = await dbConnection.client.retrieve(dbConnection.collectionName, {
161
+ ids: [metadataUUID],
162
+ with_payload: true,
163
+ with_vector: false
164
+ });
165
+ if (response.length > 0 && response[0].payload?.metadata_value) {
166
+ const value = response[0].payload.metadata_value;
167
+ logger.debug(`Retrieved metadata value for ${key}: ${value}`);
168
+ return value;
169
+ }
170
+ }
171
+ catch (error) {
172
+ logger.warn(`Failed to retrieve metadata for ${key}:`, error);
173
+ }
174
+ }
175
+ }
176
+ catch (error) {
177
+ logger.warn(`Error retrieving metadata value for ${key}:`, error);
178
+ }
179
+ if (defaultValue !== undefined) {
180
+ logger.debug(`No metadata value found for ${key}, using default: ${defaultValue}`);
181
+ }
182
+ return defaultValue;
183
+ }
184
+ static async setMetadataValue(dbConnection, key, value, logger) {
185
+ try {
186
+ if (dbConnection.type === 'sqlite') {
187
+ const stmt = dbConnection.db.prepare(`
188
+ INSERT INTO vec_metadata (key, value) VALUES (?, ?)
189
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value
190
+ `);
191
+ stmt.run(key, value);
192
+ logger.debug(`Updated metadata value for ${key}`);
193
+ }
194
+ else if (dbConnection.type === 'qdrant') {
195
+ const metadataUUID = utils_1.Utils.generateMetadataUUID(key);
196
+ const dummyEmbeddingSize = 3072;
197
+ const dummyEmbedding = new Array(dummyEmbeddingSize).fill(0);
198
+ const metadataPoint = {
199
+ id: metadataUUID,
200
+ vector: dummyEmbedding,
201
+ payload: {
202
+ metadata_key: key,
203
+ metadata_value: value,
204
+ is_metadata: true,
205
+ content: `Metadata: ${key}`,
206
+ product_name: 'system',
207
+ version: 'metadata',
208
+ url: 'metadata://' + key
209
+ }
210
+ };
211
+ await dbConnection.client.upsert(dbConnection.collectionName, {
212
+ wait: true,
213
+ points: [metadataPoint]
214
+ });
215
+ logger.debug(`Updated metadata value for ${key}`);
216
+ }
217
+ }
218
+ catch (error) {
219
+ logger.error(`Failed to update metadata value for ${key}:`, error);
220
+ }
221
+ }
142
222
  static async getLastRunDate(dbConnection, repo, defaultDate, logger) {
143
223
  const metadataKey = `last_run_${repo.replace('/', '_')}`;
144
224
  try {
@@ -224,40 +304,98 @@ class DatabaseManager {
224
304
  }
225
305
  }
226
306
  static prepareSQLiteStatements(db) {
307
+ let cached = this.columnCache.get(db);
308
+ if (!cached) {
309
+ cached = {
310
+ hasBranch: this.hasColumn(db, 'branch'),
311
+ hasRepo: this.hasColumn(db, 'repo')
312
+ };
313
+ this.columnCache.set(db, cached);
314
+ }
315
+ const hasBranchColumn = cached.hasBranch;
316
+ const hasRepoColumn = cached.hasRepo;
317
+ const insertColumns = [
318
+ 'embedding',
319
+ 'product_name',
320
+ 'version',
321
+ ...(hasBranchColumn ? ['branch'] : []),
322
+ ...(hasRepoColumn ? ['repo'] : []),
323
+ 'heading_hierarchy',
324
+ 'section',
325
+ 'chunk_id',
326
+ 'content',
327
+ 'url',
328
+ 'hash',
329
+ 'chunk_index',
330
+ 'total_chunks'
331
+ ];
332
+ const insertPlaceholders = insertColumns.map(() => '?').join(', ');
333
+ const updateSet = [
334
+ 'embedding = ?',
335
+ 'product_name = ?',
336
+ 'version = ?',
337
+ ...(hasBranchColumn ? ['branch = ?'] : []),
338
+ ...(hasRepoColumn ? ['repo = ?'] : []),
339
+ 'heading_hierarchy = ?',
340
+ 'section = ?',
341
+ 'content = ?',
342
+ 'url = ?',
343
+ 'hash = ?',
344
+ 'chunk_index = ?',
345
+ 'total_chunks = ?'
346
+ ].join(', ');
227
347
  return {
228
348
  insertStmt: db.prepare(`
229
- INSERT INTO vec_items (embedding, product_name, version, heading_hierarchy, section, chunk_id, content, url, hash)
230
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
349
+ INSERT INTO vec_items (${insertColumns})
350
+ VALUES (${insertPlaceholders})
231
351
  `),
232
352
  checkHashStmt: db.prepare(`SELECT hash FROM vec_items WHERE chunk_id = ?`),
233
353
  updateStmt: db.prepare(`
234
- UPDATE vec_items SET embedding = ?, product_name = ?, version = ?, heading_hierarchy = ?, section = ?, content = ?, url = ?, hash = ?
354
+ UPDATE vec_items SET ${updateSet}
235
355
  WHERE chunk_id = ?
236
356
  `),
237
357
  getAllChunkIdsStmt: db.prepare(`SELECT chunk_id FROM vec_items`),
238
- deleteChunkStmt: db.prepare(`DELETE FROM vec_items WHERE chunk_id = ?`)
358
+ deleteChunkStmt: db.prepare(`DELETE FROM vec_items WHERE chunk_id = ?`),
359
+ hasBranchColumn,
360
+ hasRepoColumn
239
361
  };
240
362
  }
241
363
  static insertVectorsSQLite(db, chunk, embedding, logger, chunkHash) {
242
- const { insertStmt, updateStmt } = this.prepareSQLiteStatements(db);
364
+ const { insertStmt, updateStmt, hasBranchColumn, hasRepoColumn } = this.prepareSQLiteStatements(db);
243
365
  const hash = chunkHash || utils_1.Utils.generateHash(chunk.content);
244
366
  const transaction = db.transaction(() => {
245
- const params = [
246
- new Float32Array(embedding),
247
- chunk.metadata.product_name,
248
- chunk.metadata.version,
249
- JSON.stringify(chunk.metadata.heading_hierarchy),
250
- chunk.metadata.section,
251
- chunk.metadata.chunk_id,
252
- chunk.content,
253
- chunk.metadata.url,
254
- hash
255
- ];
367
+ // Use BigInt for true integer representation in SQLite vec0
368
+ const chunkIndex = BigInt(chunk.metadata.chunk_index | 0);
369
+ const totalChunks = BigInt(chunk.metadata.total_chunks | 0);
256
370
  try {
257
- insertStmt.run(params);
371
+ const insertValues = [
372
+ new Float32Array(embedding),
373
+ chunk.metadata.product_name,
374
+ chunk.metadata.version
375
+ ];
376
+ if (hasBranchColumn) {
377
+ insertValues.push(chunk.metadata.branch ?? null);
378
+ }
379
+ if (hasRepoColumn) {
380
+ insertValues.push(chunk.metadata.repo ?? null);
381
+ }
382
+ insertValues.push(JSON.stringify(chunk.metadata.heading_hierarchy), chunk.metadata.section, chunk.metadata.chunk_id, chunk.content, chunk.metadata.url, hash, chunkIndex, totalChunks);
383
+ insertStmt.run(...insertValues);
258
384
  }
259
385
  catch (error) {
260
- updateStmt.run([...params.slice(0, 8), chunk.metadata.chunk_id]);
386
+ const updateValues = [
387
+ new Float32Array(embedding),
388
+ chunk.metadata.product_name,
389
+ chunk.metadata.version
390
+ ];
391
+ if (hasBranchColumn) {
392
+ updateValues.push(chunk.metadata.branch ?? null);
393
+ }
394
+ if (hasRepoColumn) {
395
+ updateValues.push(chunk.metadata.repo ?? null);
396
+ }
397
+ updateValues.push(JSON.stringify(chunk.metadata.heading_hierarchy), chunk.metadata.section, chunk.content, chunk.metadata.url, hash, chunkIndex, totalChunks, chunk.metadata.chunk_id);
398
+ updateStmt.run(...updateValues);
261
399
  }
262
400
  });
263
401
  transaction();
@@ -283,11 +421,15 @@ class DatabaseManager {
283
421
  content: chunk.content,
284
422
  product_name: chunk.metadata.product_name,
285
423
  version: chunk.metadata.version,
424
+ branch: chunk.metadata.branch,
425
+ repo: chunk.metadata.repo,
286
426
  heading_hierarchy: chunk.metadata.heading_hierarchy,
287
427
  section: chunk.metadata.section,
288
428
  url: chunk.metadata.url,
289
429
  hash: hash,
290
430
  original_chunk_id: chunk.metadata.chunk_id,
431
+ chunk_index: chunk.metadata.chunk_index,
432
+ total_chunks: chunk.metadata.total_chunks,
291
433
  },
292
434
  };
293
435
  await client.upsert(collectionName, {
@@ -370,6 +512,49 @@ class DatabaseManager {
370
512
  logger.error(`Error removing obsolete chunks from Qdrant:`, error);
371
513
  }
372
514
  }
515
+ static hasColumn(db, columnName) {
516
+ try {
517
+ const columns = db.prepare('PRAGMA table_info(vec_items)').all();
518
+ return columns.some((column) => column.name === columnName);
519
+ }
520
+ catch (error) {
521
+ return false;
522
+ }
523
+ }
524
+ static removeChunksByUrlSQLite(db, url, logger) {
525
+ const deleteStmt = db.prepare(`DELETE FROM vec_items WHERE url = ?`);
526
+ const result = deleteStmt.run(url);
527
+ logger.info(`Deleted ${result.changes} chunks from SQLite for URL ${url}`);
528
+ }
529
+ static async removeChunksByUrlQdrant(db, url, logger) {
530
+ const { client, collectionName } = db;
531
+ try {
532
+ await client.delete(collectionName, {
533
+ filter: {
534
+ must: [
535
+ {
536
+ key: 'url',
537
+ match: {
538
+ text: url
539
+ }
540
+ }
541
+ ],
542
+ must_not: [
543
+ {
544
+ key: 'is_metadata',
545
+ match: {
546
+ value: true
547
+ }
548
+ }
549
+ ]
550
+ }
551
+ });
552
+ logger.info(`Deleted chunks from Qdrant for URL ${url}`);
553
+ }
554
+ catch (error) {
555
+ logger.error(`Error deleting chunks from Qdrant for URL ${url}:`, error);
556
+ }
557
+ }
373
558
  static removeObsoleteFilesSQLite(db, processedFiles, pathConfig, logger) {
374
559
  const getChunksForPathStmt = db.prepare(`
375
560
  SELECT chunk_id, url FROM vec_items
@@ -505,3 +690,4 @@ class DatabaseManager {
505
690
  }
506
691
  }
507
692
  exports.DatabaseManager = DatabaseManager;
693
+ DatabaseManager.columnCache = new WeakMap();