embedded-raptor 1.0.0 → 2.0.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.
Files changed (43) hide show
  1. package/README.md +20 -20
  2. package/dist/cli.cjs +26 -4
  3. package/dist/cli.mjs +25 -3
  4. package/dist/commands/delete.d.ts +41 -0
  5. package/dist/commands/delete.d.ts.map +1 -0
  6. package/dist/commands/index.d.ts +1 -0
  7. package/dist/commands/index.d.ts.map +1 -1
  8. package/dist/{engine-D06Gh_gw.mjs → engine-BvJ0ls3b.mjs} +74 -12
  9. package/dist/engine-Cuz0P5Od.mjs +1164 -0
  10. package/dist/engine-DLM7PWhV.cjs +1203 -0
  11. package/dist/{engine-Bl1yeWoe.cjs → engine-Iq0_dbnk.cjs} +75 -13
  12. package/dist/engine.d.ts +55 -17
  13. package/dist/engine.d.ts.map +1 -1
  14. package/dist/index.cjs +1 -1
  15. package/dist/index.mjs +1 -1
  16. package/dist/storage-engine/constants.d.ts +53 -0
  17. package/dist/storage-engine/constants.d.ts.map +1 -0
  18. package/dist/storage-engine/data-format.d.ts +35 -0
  19. package/dist/storage-engine/data-format.d.ts.map +1 -0
  20. package/dist/storage-engine/file-lock.d.ts +35 -0
  21. package/dist/storage-engine/file-lock.d.ts.map +1 -0
  22. package/dist/storage-engine/index.d.ts +14 -0
  23. package/dist/storage-engine/index.d.ts.map +1 -0
  24. package/dist/storage-engine/key-index.d.ts +54 -0
  25. package/dist/storage-engine/key-index.d.ts.map +1 -0
  26. package/dist/storage-engine/migration.d.ts +26 -0
  27. package/dist/storage-engine/migration.d.ts.map +1 -0
  28. package/dist/storage-engine/mutex.d.ts +23 -0
  29. package/dist/storage-engine/mutex.d.ts.map +1 -0
  30. package/dist/storage-engine/storage-engine.d.ts +85 -0
  31. package/dist/storage-engine/storage-engine.d.ts.map +1 -0
  32. package/dist/storage-engine/types.d.ts +85 -0
  33. package/dist/storage-engine/types.d.ts.map +1 -0
  34. package/dist/storage-engine/wal-format.d.ts +22 -0
  35. package/dist/storage-engine/wal-format.d.ts.map +1 -0
  36. package/dist/storage-engine/wal.d.ts +32 -0
  37. package/dist/storage-engine/wal.d.ts.map +1 -0
  38. package/dist/types.d.ts +2 -0
  39. package/dist/types.d.ts.map +1 -1
  40. package/package.json +9 -5
  41. package/dist/engine-DISO9uFr.mjs +0 -31601
  42. package/dist/engine-KhnrAv7v.cjs +0 -38642
  43. package/dist/engine-r-qHfsLd.cjs +0 -370
package/README.md CHANGED
@@ -1,29 +1,29 @@
1
- # Raptor
1
+ # Embedded Raptor
2
2
 
3
- [![CI](https://img.shields.io/github/actions/workflow/status/artmann/raptor/ci.yml?branch=main&label=CI&logo=github)](https://github.com/artmann/raptor/actions/workflows/ci.yml)
4
- [![npm version](https://img.shields.io/npm/v/raptor.svg?logo=npm)](https://www.npmjs.com/package/raptor)
5
- [![npm downloads](https://img.shields.io/npm/dm/raptor.svg)](https://www.npmjs.com/package/raptor)
3
+ [![CI](https://img.shields.io/github/actions/workflow/status/artmann/embedded-raptor/ci.yml?branch=main&label=CI&logo=github)](https://github.com/artmann/embedded-raptor/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/embedded-raptor.svg?logo=npm)](https://www.npmjs.com/package/embedded-raptor)
5
+ [![npm downloads](https://img.shields.io/npm/dm/embedded-raptor.svg)](https://www.npmjs.com/package/embedded-raptor)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg?logo=typescript)](https://www.typescriptlang.org/)
8
8
 
9
9
  > A lightweight semantic search database with text embeddings for Node.js and
10
10
  > Bun
11
11
 
12
- Raptor lets you build semantic search into your applications with just a few
13
- lines of code. Store text, search by meaning, and find similar content—perfect
14
- for RAG systems, chatbots, and recommendation engines.
12
+ Embedded Raptor lets you build semantic search into your applications with just
13
+ a few lines of code. Store text, search by meaning, and find similar
14
+ content—perfect for RAG systems, chatbots, and recommendation engines.
15
15
 
16
- ## What is Raptor?
16
+ ## What is Embedded Raptor?
17
17
 
18
- Raptor is an embedding database that automatically converts text into vector
19
- embeddings and stores them in an efficient binary format. Instead of searching
20
- by exact keywords, you can search by semantic similarity—finding documents that
21
- mean the same thing, even if they use different words.
18
+ Embedded Raptor is an embedding database that automatically converts text into
19
+ vector embeddings and stores them in an efficient binary format. Instead of
20
+ searching by exact keywords, you can search by semantic similarity—finding
21
+ documents that mean the same thing, even if they use different words.
22
22
 
23
23
  **Example:** Search for "how to reset password" and find results like "forgot my
24
24
  login credentials" or "change account password".
25
25
 
26
- ## Why Raptor?
26
+ ## Why Embedded Raptor?
27
27
 
28
28
  - **Simple API** - No complex setup, just store and search
29
29
  - **Semantic Search** - Find content by meaning, not just keywords
@@ -44,10 +44,10 @@ login credentials" or "change account password".
44
44
 
45
45
  ```bash
46
46
  # Using npm
47
- npm install raptor
47
+ npm install embedded-raptor
48
48
 
49
49
  # Using bun
50
- bun add raptor
50
+ bun add embedded-raptor
51
51
  ```
52
52
 
53
53
  ## Quick Start
@@ -55,7 +55,7 @@ bun add raptor
55
55
  ### Programmatic API
56
56
 
57
57
  ```typescript
58
- import { EmbeddingEngine } from 'raptor'
58
+ import { EmbeddingEngine } from 'embedded-raptor'
59
59
 
60
60
  const engine = new EmbeddingEngine({
61
61
  storePath: './my-database.raptor'
@@ -203,12 +203,12 @@ raptor store key1 "Some text" --storePath ./data/custom.raptor
203
203
 
204
204
  ## How It Works
205
205
 
206
- 1. **Text → Embeddings**: Raptor uses the BGE-Base-EN model to convert text into
207
- 768-dimensional vector embeddings
206
+ 1. **Text → Embeddings**: Embedded Raptor uses the BGE-Base-EN model to convert
207
+ text into 768-dimensional vector embeddings
208
208
  2. **Storage**: Embeddings are stored in an efficient binary format (.raptor
209
209
  files)
210
- 3. **Search**: When you search, Raptor compares your query embedding against all
211
- stored embeddings using cosine similarity
210
+ 3. **Search**: When you search, Embedded Raptor compares your query embedding
211
+ against all stored embeddings using cosine similarity
212
212
  4. **Results**: Returns the most similar results ranked by similarity score
213
213
 
214
214
  **Embedding Model**:
package/dist/cli.cjs CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- const require_engine = require('./engine-KhnrAv7v.cjs');
3
- let node_fs = require("node:fs");
4
- node_fs = require_engine.__toESM(node_fs);
2
+ const require_engine = require('./engine-DLM7PWhV.cjs');
5
3
  let node_path = require("node:path");
6
4
  node_path = require_engine.__toESM(node_path);
5
+ let node_fs = require("node:fs");
6
+ node_fs = require_engine.__toESM(node_fs);
7
7
  let cleye = require("cleye");
8
8
  cleye = require_engine.__toESM(cleye);
9
9
  let node_url = require("node:url");
@@ -89,6 +89,27 @@ const search = (0, cleye.command)({
89
89
  }
90
90
  });
91
91
 
92
+ //#endregion
93
+ //#region src/commands/delete.ts
94
+ const deleteCmd = (0, cleye.command)({
95
+ name: "delete",
96
+ description: "Delete an embedding entry by key",
97
+ parameters: ["<key>"],
98
+ flags: { ...sharedFlags }
99
+ }, async (argv) => {
100
+ const engine = new require_engine.EmbeddingEngine({ storePath: argv.flags.storePath });
101
+ try {
102
+ const [key] = argv._;
103
+ if (await engine.delete(key)) console.log(`Deleted key "${key}"`);
104
+ else {
105
+ console.log(`Key "${key}" not found`);
106
+ process.exit(1);
107
+ }
108
+ } finally {
109
+ await engine.dispose();
110
+ }
111
+ });
112
+
92
113
  //#endregion
93
114
  //#region src/cli.ts
94
115
  const __dirname$1 = (0, node_path.dirname)((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
@@ -100,7 +121,8 @@ function main() {
100
121
  commands: [
101
122
  store,
102
123
  get,
103
- search
124
+ search,
125
+ deleteCmd
104
126
  ]
105
127
  }, () => {});
106
128
  }
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import { t as EmbeddingEngine } from "./engine-DISO9uFr.mjs";
3
- import { readFileSync } from "node:fs";
2
+ import { t as EmbeddingEngine } from "./engine-Cuz0P5Od.mjs";
4
3
  import { dirname, resolve } from "node:path";
4
+ import { readFileSync } from "node:fs";
5
5
  import { cli, command } from "cleye";
6
6
  import { fileURLToPath } from "node:url";
7
7
 
@@ -85,6 +85,27 @@ const search = command({
85
85
  }
86
86
  });
87
87
 
88
+ //#endregion
89
+ //#region src/commands/delete.ts
90
+ const deleteCmd = command({
91
+ name: "delete",
92
+ description: "Delete an embedding entry by key",
93
+ parameters: ["<key>"],
94
+ flags: { ...sharedFlags }
95
+ }, async (argv) => {
96
+ const engine = new EmbeddingEngine({ storePath: argv.flags.storePath });
97
+ try {
98
+ const [key] = argv._;
99
+ if (await engine.delete(key)) console.log(`Deleted key "${key}"`);
100
+ else {
101
+ console.log(`Key "${key}" not found`);
102
+ process.exit(1);
103
+ }
104
+ } finally {
105
+ await engine.dispose();
106
+ }
107
+ });
108
+
88
109
  //#endregion
89
110
  //#region src/cli.ts
90
111
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -96,7 +117,8 @@ function main() {
96
117
  commands: [
97
118
  store,
98
119
  get,
99
- search
120
+ search,
121
+ deleteCmd
100
122
  ]
101
123
  }, () => {});
102
124
  }
@@ -0,0 +1,41 @@
1
+ export declare const deleteCmd: import("cleye").Command<{
2
+ name: "delete";
3
+ description: string;
4
+ parameters: "<key>"[];
5
+ flags: {
6
+ storePath: {
7
+ readonly type: StringConstructor;
8
+ readonly description: "Path to the embeddings store file";
9
+ readonly default: "./database.raptor";
10
+ readonly alias: "s";
11
+ };
12
+ };
13
+ }, {
14
+ command: "delete";
15
+ } & import("type-flag").TypeFlag<{
16
+ storePath: {
17
+ readonly type: StringConstructor;
18
+ readonly description: "Path to the embeddings store file";
19
+ readonly default: "./database.raptor";
20
+ readonly alias: "s";
21
+ };
22
+ } & {
23
+ help: BooleanConstructor;
24
+ }> & {
25
+ _: {
26
+ key: string;
27
+ };
28
+ showHelp: (options?: {
29
+ version?: string;
30
+ description?: string;
31
+ usage?: false | string | string[];
32
+ examples?: string | string[];
33
+ render?: (nodes: {
34
+ id?: string;
35
+ type: keyof import("cleye").Renderers;
36
+ data: any;
37
+ }[], renderers: import("cleye").Renderers) => string;
38
+ }) => void;
39
+ showVersion: () => void;
40
+ }>;
41
+ //# sourceMappingURL=delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../src/commands/delete.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;sBA6B2kM,CAAC;;;;;;;;;;;;EADjmM,CAAA"}
@@ -1,4 +1,5 @@
1
1
  export { store } from './store';
2
2
  export { get } from './get';
3
3
  export { search } from './search';
4
+ export { deleteCmd } from './delete';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAC3B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAC/B,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAC3B,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA"}
@@ -1,4 +1,4 @@
1
- import { EmbeddingModel, FlagEmbedding } from "fastembed";
1
+ import { getLlama, resolveModelFile } from "node-llama-cpp";
2
2
  import { existsSync } from "node:fs";
3
3
  import { appendFile, mkdir, open, stat, writeFile } from "node:fs/promises";
4
4
  import { dirname } from "node:path";
@@ -221,22 +221,64 @@ var CandidateSetEntry = class {
221
221
 
222
222
  //#endregion
223
223
  //#region src/engine.ts
224
+ const DEFAULT_MODEL_URI = "hf:CompendiumLabs/bge-small-en-v1.5-gguf/bge-small-en-v1.5-q8_0.gguf";
225
+ const DEFAULT_CACHE_DIR = "./.cache/models";
224
226
  var EmbeddingEngine = class {
225
227
  fileReader;
226
228
  storePath;
229
+ cacheDir;
230
+ llama;
231
+ model;
232
+ embeddingContext;
233
+ initPromise;
227
234
  constructor(options) {
228
235
  this.storePath = options.storePath;
229
236
  this.fileReader = new BinaryFileReader(options.storePath);
237
+ this.cacheDir = options.cacheDir ?? DEFAULT_CACHE_DIR;
230
238
  }
231
239
  /**
232
- * Generates embedding from text using FastEmbed BGE-Base-EN model
240
+ * Gets or initializes the embedding model
241
+ * Caches the model instance to avoid repeated initialization overhead
242
+ */
243
+ async ensureModelLoaded() {
244
+ if (this.embeddingContext) return;
245
+ if (this.initPromise) return this.initPromise;
246
+ this.initPromise = this.initializeModel();
247
+ await this.initPromise;
248
+ }
249
+ async initializeModel() {
250
+ this.llama = await getLlama();
251
+ const modelPath = await resolveModelFile(DEFAULT_MODEL_URI, this.cacheDir);
252
+ this.model = await this.llama.loadModel({ modelPath });
253
+ this.embeddingContext = await this.model.createEmbeddingContext();
254
+ }
255
+ /**
256
+ * Truncates text to fit within the model's context size
257
+ * Uses the model's tokenizer for accurate token counting
258
+ * BGE-small supports 512 tokens, we use 500 to leave room for special tokens
259
+ */
260
+ truncateToContextSize(text) {
261
+ if (!this.model) {
262
+ const maxChars = 300 * 3;
263
+ return text.length <= maxChars ? text : text.slice(0, maxChars);
264
+ }
265
+ const maxTokens = 500;
266
+ const tokens = this.model.tokenize(text);
267
+ if (tokens.length <= maxTokens) return text;
268
+ const truncatedTokens = tokens.slice(0, maxTokens);
269
+ return this.model.detokenize(truncatedTokens);
270
+ }
271
+ /**
272
+ * Generates embedding from text using node-llama-cpp with bge-small-en-v1.5 model
233
273
  * @param text - Text to embed
234
- * @returns 768-dimensional embedding vector
274
+ * @returns 384-dimensional embedding vector (normalized)
235
275
  */
236
276
  async generateEmbedding(text) {
237
- const embeddings = (await FlagEmbedding.init({ model: EmbeddingModel.BGEBaseEN })).embed([text]);
238
- for await (const batch of embeddings) return Array.from(batch[0]);
239
- return [];
277
+ await this.ensureModelLoaded();
278
+ invariant(this.embeddingContext, "Embedding context not initialized");
279
+ const truncatedText = this.truncateToContextSize(text);
280
+ const embedding = await this.embeddingContext.getEmbeddingFor(truncatedText);
281
+ return Array.from(embedding.vector);
240
282
  }
241
283
  /**
242
284
  * Retrieves an embedding entry by key
@@ -290,16 +332,20 @@ var EmbeddingEngine = class {
290
332
  /**
291
333
  * Stores multiple text embeddings in batch
292
334
  * More efficient than calling store() multiple times
293
- * Generates embeddings in a single batch and writes all records at once
335
+ * Generates embeddings in parallel and writes all records at once
294
336
  * @param items - Array of {key, text} objects to store
295
337
  */
296
338
  async storeMany(items) {
297
339
  invariant(items.length > 0, "Items array must not be empty.");
298
- const texts = items.map((item) => item.text);
299
- const embeddings = (await FlagEmbedding.init({ model: EmbeddingModel.BGEBaseEN })).embed(texts);
300
- const embeddingsList = [];
301
- for await (const batch of embeddings) for (let i = 0; i < batch.length; i++) embeddingsList.push(Array.from(batch[i]));
302
- invariant(embeddingsList.length === items.length, "Number of embeddings must match number of items.");
340
+ await this.ensureModelLoaded();
341
+ const embeddingContext = this.embeddingContext;
342
+ invariant(embeddingContext, "Embedding context not initialized");
343
+ const embeddingPromises = items.map(async (item) => {
344
+ const truncatedText = this.truncateToContextSize(item.text);
345
+ const embedding = await embeddingContext.getEmbeddingFor(truncatedText);
346
+ return Array.from(embedding.vector);
347
+ });
348
+ const embeddingsList = await Promise.all(embeddingPromises);
303
349
  await mkdir(dirname(this.storePath), { recursive: true });
304
350
  if (!existsSync(this.storePath)) await writeHeader(this.storePath, embeddingsList[0].length);
305
351
  const records = items.map((item, index) => ({
@@ -329,6 +375,22 @@ var EmbeddingEngine = class {
329
375
  if (magnitudeA === 0 || magnitudeB === 0) return 0;
330
376
  return dotProduct / (magnitudeA * magnitudeB);
331
377
  }
378
+ /**
379
+ * Disposes of the cached embedding model and releases resources
380
+ * Call this when you're done using the engine to free up memory
381
+ */
382
+ async dispose() {
383
+ if (this.embeddingContext) {
384
+ await this.embeddingContext.dispose();
385
+ this.embeddingContext = void 0;
386
+ }
387
+ if (this.model) {
388
+ await this.model.dispose();
389
+ this.model = void 0;
390
+ }
391
+ this.llama = void 0;
392
+ this.initPromise = void 0;
393
+ }
332
394
  };
333
395
 
334
396
  //#endregion