Skip to content

Commit 1d3a043

Browse files
committed
feat: added libsql support in embedJs
1 parent ad01e98 commit 1d3a043

File tree

29 files changed

+544
-46
lines changed

29 files changed

+544
-46
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ acme.json
6464
temp/
6565
storage/
6666
lmdb/
67+
data.db
6768

6869
#env
6970
.env

core/embedjs/src/core/rag-application.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,17 @@ export class RAGApplication {
306306
return this.vectorDatabase.getVectorCount();
307307
}
308308

309+
/**
310+
* The function `deleteConversation` deletes all entries related to a particular conversation from the database
311+
* @param {string} conversationId - The `conversationId` that you want to delete. Pass 'default' to delete
312+
* the default conversation thread that is created and maintained automatically
313+
*/
314+
public async deleteConversation(conversationId: string) {
315+
if (this.store) {
316+
await this.store.deleteConversation(conversationId);
317+
}
318+
}
319+
309320
/**
310321
* The function `deleteLoader` deletes embeddings from a loader after confirming the action.
311322
* @param {string} uniqueLoaderId - The `uniqueLoaderId` parameter is a string that represents the

core/embedjs/src/store/memory-store.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,22 @@ export class MemoryStore implements BaseStore {
5050
const loaderId = <string>this.loaderCustomValues[key].loaderId;
5151

5252
delete this.loaderList[key];
53-
this.loaderCustomValuesMap.set(
54-
loaderId,
55-
this.loaderCustomValuesMap.get(loaderId).filter((k) => k !== key),
56-
);
53+
54+
if (this.loaderCustomValuesMap.has(loaderId)) {
55+
this.loaderCustomValuesMap.set(
56+
loaderId,
57+
this.loaderCustomValuesMap.get(loaderId).filter((k) => k !== key),
58+
);
59+
}
5760
}
5861

5962
async deleteLoaderMetadataAndCustomValues(loaderId: string): Promise<void> {
60-
this.loaderCustomValuesMap.get(loaderId).forEach((key) => {
61-
delete this.loaderCustomValues[key];
62-
});
63+
if (this.loaderCustomValuesMap.has(loaderId)) {
64+
this.loaderCustomValuesMap.get(loaderId).forEach((key) => {
65+
delete this.loaderCustomValues[key];
66+
});
67+
}
68+
6369
this.loaderCustomValuesMap.delete(loaderId);
6470
delete this.loaderList[loaderId];
6571
}

databases/embedjs-libsql/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"description": "Add LibSQL support to embedjs",
55
"dependencies": {
66
"@libsql/client": "^0.14.0",
7+
"@llm-tools/embedjs-utils": "0.1.21",
78
"@llm-tools/embedjs-interfaces": "0.1.21",
89
"debug": "^4.3.7"
910
},
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './libsql-db.js';
2+
export * from './libsql-store.js';

databases/embedjs-libsql/src/libsql-db.ts

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import createDebugMessages from 'debug';
22
import { Client, createClient } from '@libsql/client';
33

44
import { BaseVectorDatabase, ExtractChunkData, InsertChunkData } from '@llm-tools/embedjs-interfaces';
5+
import { truncateCenterString } from '@llm-tools/embedjs-utils';
56

67
export class LibSqlDb implements BaseVectorDatabase {
78
private readonly debug = createDebugMessages('embedjs:vector:LibSqlDb');
@@ -16,46 +17,48 @@ export class LibSqlDb implements BaseVectorDatabase {
1617
}
1718

1819
async init({ dimensions }: { dimensions: number }) {
19-
await this.client.execute(`CREATE TABLE ${this.tableName} (
20-
id TEXT
21-
pageContent TEXT,
22-
uniqueLoaderId TEXT,
23-
source TEXT,
20+
await this.client.execute(`CREATE TABLE IF NOT EXISTS ${this.tableName} (
21+
id TEXT PRIMARY KEY,
22+
pageContent TEXT UNIQUE,
23+
uniqueLoaderId TEXT NOT NULL,
24+
source TEXT NOT NULL,
2425
vector F32_BLOB(${dimensions}),
2526
metadata TEXT
2627
);`);
2728
}
2829

2930
async insertChunks(chunks: InsertChunkData[]): Promise<number> {
30-
const values = chunks.map((chunk) => {
31-
return `('${chunk.metadata.id}', '${chunk.pageContent}', '${chunk.metadata.uniqueLoaderId}',
32-
'${chunk.metadata.source}', vector32('[${chunk.vector.join(',')}]'),
33-
'${JSON.stringify(chunk.metadata)}')`;
31+
const batch = chunks.map((chunk) => {
32+
return {
33+
sql: `INSERT OR IGNORE INTO ${this.tableName} (id, pageContent, uniqueLoaderId, source, vector, metadata)
34+
VALUES (?, ?, ?, ?, vector32('[${chunk.vector.join(',')}]'), ?);`,
35+
args: [
36+
chunk.metadata.id,
37+
chunk.pageContent,
38+
chunk.metadata.uniqueLoaderId,
39+
chunk.metadata.source,
40+
JSON.stringify(chunk.metadata),
41+
],
42+
};
3443
});
3544

36-
const statement = `INSERT INTO ${this.tableName} (id, pageContent, uniqueLoaderId, source, vector, metadata)
37-
VALUES
38-
${values.join(',')}
39-
);`;
40-
41-
this.debug(`Executing statement - ${statement}`);
42-
const result = await this.client.execute(statement);
43-
return result.rowsAffected;
45+
this.debug(`Executing batch - ${truncateCenterString(JSON.stringify(batch), 1000)}`);
46+
const result = await this.client.batch(batch, 'write');
47+
return result.reduce((a, b) => a + b.rowsAffected, 0);
4448
}
4549

4650
async similaritySearch(query: number[], k: number): Promise<ExtractChunkData[]> {
4751
const statement = `SELECT id, pageContent, uniqueLoaderId, source, metadata,
4852
vector_distance_cos(vector, vector32('[${query.join(',')}]'))
4953
FROM ${this.tableName}
50-
ORDER BY vector_distance_cos(vector, vector32('[${query.join(',')}]'))
51-
TOP ${k}
52-
ASC;`;
54+
ORDER BY vector_distance_cos(vector, vector32('[${query.join(',')}]')) ASC
55+
LIMIT ${k};`;
5356

54-
this.debug(`Executing statement - ${statement}`);
57+
this.debug(`Executing statement - ${truncateCenterString(statement, 700)}`);
5558
const results = await this.client.execute(statement);
5659

5760
return results.rows.map((result) => {
58-
const metadata = JSON.parse(<string>result.metadata.toString());
61+
const metadata = JSON.parse(result.metadata.toString());
5962

6063
return {
6164
metadata,
@@ -66,16 +69,21 @@ export class LibSqlDb implements BaseVectorDatabase {
6669
}
6770

6871
async getVectorCount(): Promise<number> {
69-
return 0;
72+
const statement = `SELECT count(id) as count FROM ${this.tableName};`;
73+
74+
this.debug(`Executing statement - ${statement}`);
75+
const results = await this.client.execute(statement);
76+
77+
return Number.parseInt(results.rows[0].count.toString());
7078
}
7179

7280
async deleteKeys(uniqueLoaderId: string): Promise<boolean> {
73-
const statement = `DELETE FROM ${this.tableName} VALUES WHERE
74-
uniqueLoaderId = '${uniqueLoaderId}';`;
75-
76-
await this.client.execute(statement);
81+
await this.client.execute(`DELETE FROM ${this.tableName} WHERE
82+
uniqueLoaderId = '${uniqueLoaderId}';`);
7783
return true;
7884
}
7985

80-
async reset(): Promise<void> {}
86+
async reset(): Promise<void> {
87+
await this.client.execute(`DELETE FROM ${this.tableName};`);
88+
}
8189
}

0 commit comments

Comments
 (0)