doc2vec 2.0.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,6 +59,8 @@ 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,
@@ -141,6 +143,82 @@ class DatabaseManager {
141
143
  // Nothing special to initialize as we'll use the same collection
142
144
  }
143
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
+ }
144
222
  static async getLastRunDate(dbConnection, repo, defaultDate, logger) {
145
223
  const metadataKey = `last_run_${repo.replace('/', '_')}`;
146
224
  try {
@@ -226,32 +304,98 @@ class DatabaseManager {
226
304
  }
227
305
  }
228
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(', ');
229
347
  return {
230
348
  insertStmt: db.prepare(`
231
- INSERT INTO vec_items (embedding, product_name, version, heading_hierarchy, section, chunk_id, content, url, hash, chunk_index, total_chunks)
232
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
349
+ INSERT INTO vec_items (${insertColumns})
350
+ VALUES (${insertPlaceholders})
233
351
  `),
234
352
  checkHashStmt: db.prepare(`SELECT hash FROM vec_items WHERE chunk_id = ?`),
235
353
  updateStmt: db.prepare(`
236
- UPDATE vec_items SET embedding = ?, product_name = ?, version = ?, heading_hierarchy = ?, section = ?, content = ?, url = ?, hash = ?, chunk_index = ?, total_chunks = ?
354
+ UPDATE vec_items SET ${updateSet}
237
355
  WHERE chunk_id = ?
238
356
  `),
239
357
  getAllChunkIdsStmt: db.prepare(`SELECT chunk_id FROM vec_items`),
240
- 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
241
361
  };
242
362
  }
243
363
  static insertVectorsSQLite(db, chunk, embedding, logger, chunkHash) {
244
- const { insertStmt, updateStmt } = this.prepareSQLiteStatements(db);
364
+ const { insertStmt, updateStmt, hasBranchColumn, hasRepoColumn } = this.prepareSQLiteStatements(db);
245
365
  const hash = chunkHash || utils_1.Utils.generateHash(chunk.content);
246
366
  const transaction = db.transaction(() => {
247
367
  // Use BigInt for true integer representation in SQLite vec0
248
368
  const chunkIndex = BigInt(chunk.metadata.chunk_index | 0);
249
369
  const totalChunks = BigInt(chunk.metadata.total_chunks | 0);
250
370
  try {
251
- insertStmt.run(new Float32Array(embedding), chunk.metadata.product_name, chunk.metadata.version, JSON.stringify(chunk.metadata.heading_hierarchy), chunk.metadata.section, chunk.metadata.chunk_id, chunk.content, chunk.metadata.url, hash, chunkIndex, totalChunks);
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);
252
384
  }
253
385
  catch (error) {
254
- updateStmt.run(new Float32Array(embedding), chunk.metadata.product_name, chunk.metadata.version, JSON.stringify(chunk.metadata.heading_hierarchy), chunk.metadata.section, chunk.content, chunk.metadata.url, hash, chunkIndex, totalChunks, 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);
255
399
  }
256
400
  });
257
401
  transaction();
@@ -277,6 +421,8 @@ class DatabaseManager {
277
421
  content: chunk.content,
278
422
  product_name: chunk.metadata.product_name,
279
423
  version: chunk.metadata.version,
424
+ branch: chunk.metadata.branch,
425
+ repo: chunk.metadata.repo,
280
426
  heading_hierarchy: chunk.metadata.heading_hierarchy,
281
427
  section: chunk.metadata.section,
282
428
  url: chunk.metadata.url,
@@ -366,6 +512,49 @@ class DatabaseManager {
366
512
  logger.error(`Error removing obsolete chunks from Qdrant:`, error);
367
513
  }
368
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
+ }
369
558
  static removeObsoleteFilesSQLite(db, processedFiles, pathConfig, logger) {
370
559
  const getChunksForPathStmt = db.prepare(`
371
560
  SELECT chunk_id, url FROM vec_items
@@ -501,3 +690,4 @@ class DatabaseManager {
501
690
  }
502
691
  }
503
692
  exports.DatabaseManager = DatabaseManager;
693
+ DatabaseManager.columnCache = new WeakMap();