@neuledge/graph-memory-registry 0.2.0 → 0.3.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/README.md +5 -1
- package/dist/memory.d.ts +8 -4
- package/dist/memory.js +94 -48
- package/dist/memory.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -41,10 +41,14 @@ import { openai } from "@ai-sdk/openai";
|
|
|
41
41
|
|
|
42
42
|
const registry = new NeuledgeGraphMemoryRegistry({
|
|
43
43
|
model: openai.embedding("text-embedding-3-small"),
|
|
44
|
+
|
|
45
|
+
// (optional) useful for persistence across restarts and serverless cold starts
|
|
46
|
+
// commit this file to your repo or store in a shared volume
|
|
47
|
+
cacheFile: "./embedding-cache.json",
|
|
44
48
|
});
|
|
45
49
|
|
|
46
50
|
// Register a data source
|
|
47
|
-
|
|
51
|
+
registry.register({
|
|
48
52
|
template: "weather.{city}",
|
|
49
53
|
resolver: async ({ city }) => {
|
|
50
54
|
// fetch weather for the matched city
|
package/dist/memory.d.ts
CHANGED
|
@@ -3,16 +3,21 @@ import { type NeuledgeGraphRegistry, type NeuledgeGraphResolver, type NeuledgeGr
|
|
|
3
3
|
import { type EmbeddingModel } from "ai";
|
|
4
4
|
export declare class NeuledgeGraphMemoryRegistry implements NeuledgeGraphRegistry {
|
|
5
5
|
private embeddingModel;
|
|
6
|
+
private cacheFile?;
|
|
6
7
|
private registry;
|
|
7
|
-
private
|
|
8
|
-
private registerPromise?;
|
|
8
|
+
private embeddingPromise?;
|
|
9
9
|
private defaultTrashhold;
|
|
10
10
|
private defaultLimit;
|
|
11
11
|
constructor(options: {
|
|
12
12
|
model: EmbeddingModel;
|
|
13
|
+
cacheFile?: string;
|
|
13
14
|
defaultTrashhold?: number;
|
|
14
15
|
defaultLimit?: number;
|
|
15
16
|
});
|
|
17
|
+
private loadCache;
|
|
18
|
+
private saveCache;
|
|
19
|
+
private ensureEmbeddings;
|
|
20
|
+
private ensureReady;
|
|
16
21
|
match(args: {
|
|
17
22
|
path: string;
|
|
18
23
|
}): Promise<NeuledgeGraphMatch | null>;
|
|
@@ -20,8 +25,7 @@ export declare class NeuledgeGraphMemoryRegistry implements NeuledgeGraphRegistr
|
|
|
20
25
|
register<Template extends string, Value extends object>(args: {
|
|
21
26
|
template: Template;
|
|
22
27
|
resolver: NeuledgeGraphResolver<Template, Value>;
|
|
23
|
-
}):
|
|
24
|
-
private registerAsync;
|
|
28
|
+
}): void;
|
|
25
29
|
suggestions(args: {
|
|
26
30
|
path: string;
|
|
27
31
|
trashhold?: number;
|
package/dist/memory.js
CHANGED
|
@@ -1,18 +1,99 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
1
2
|
import { NeuledgeGraphMatcher, } from "@neuledge/graph-router";
|
|
2
3
|
import { cosineSimilarity, embed, embedMany, } from "ai";
|
|
3
4
|
export class NeuledgeGraphMemoryRegistry {
|
|
4
5
|
embeddingModel;
|
|
6
|
+
cacheFile;
|
|
5
7
|
registry;
|
|
6
|
-
|
|
7
|
-
registerPromise;
|
|
8
|
+
embeddingPromise;
|
|
8
9
|
defaultTrashhold;
|
|
9
10
|
defaultLimit;
|
|
10
11
|
constructor(options) {
|
|
11
12
|
this.embeddingModel = options.model;
|
|
13
|
+
this.cacheFile = options.cacheFile;
|
|
12
14
|
this.registry = {};
|
|
13
|
-
this.registerQueue = {};
|
|
14
15
|
this.defaultTrashhold = options.defaultTrashhold ?? 0;
|
|
15
16
|
this.defaultLimit = options.defaultLimit ?? 10;
|
|
17
|
+
setTimeout(() => {
|
|
18
|
+
void this.ensureReady().catch(() => { });
|
|
19
|
+
}, 1);
|
|
20
|
+
}
|
|
21
|
+
async loadCache() {
|
|
22
|
+
if (!this.cacheFile)
|
|
23
|
+
return;
|
|
24
|
+
const exists = await fs
|
|
25
|
+
.access(this.cacheFile, fs.constants.F_OK)
|
|
26
|
+
.then(() => true)
|
|
27
|
+
.catch(() => false);
|
|
28
|
+
if (!exists) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const data = await fs.readFile(this.cacheFile, "utf8");
|
|
33
|
+
const cache = JSON.parse(data);
|
|
34
|
+
for (const [template, embedding] of Object.entries(cache)) {
|
|
35
|
+
if (this.registry[template]) {
|
|
36
|
+
this.registry[template].embedding = embedding;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
throw new Error(`Failed to load cache file: ${error}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async saveCache() {
|
|
45
|
+
if (!this.cacheFile)
|
|
46
|
+
return;
|
|
47
|
+
const cache = {};
|
|
48
|
+
for (const [template, entry] of Object.entries(this.registry)) {
|
|
49
|
+
if (entry.embedding) {
|
|
50
|
+
cache[template] = entry.embedding;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
await fs.writeFile(this.cacheFile, JSON.stringify(cache), "utf8");
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
throw new Error(`Failed to save cache file: ${error}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async ensureEmbeddings() {
|
|
61
|
+
let missing = Object.keys(this.registry).filter((template) => !this.registry[template]?.embedding);
|
|
62
|
+
if (!missing.length)
|
|
63
|
+
return;
|
|
64
|
+
await this.loadCache();
|
|
65
|
+
let needsSaving = false;
|
|
66
|
+
while (true) {
|
|
67
|
+
missing = Object.keys(this.registry).filter((template) => !this.registry[template]?.embedding);
|
|
68
|
+
if (!missing.length)
|
|
69
|
+
break;
|
|
70
|
+
const { embeddings } = await embedMany({
|
|
71
|
+
model: this.embeddingModel,
|
|
72
|
+
values: missing,
|
|
73
|
+
});
|
|
74
|
+
if (embeddings.length !== missing.length) {
|
|
75
|
+
throw new Error("Unexpected number of embedding vectors return from `embedMany`");
|
|
76
|
+
}
|
|
77
|
+
for (let i = 0; i < missing.length; ++i) {
|
|
78
|
+
// biome-ignore lint/style/noNonNullAssertion: already checked length
|
|
79
|
+
this.registry[missing[i]].embedding = embeddings[i];
|
|
80
|
+
}
|
|
81
|
+
needsSaving = true;
|
|
82
|
+
}
|
|
83
|
+
if (needsSaving) {
|
|
84
|
+
await this.saveCache();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async ensureReady() {
|
|
88
|
+
if (!this.embeddingPromise) {
|
|
89
|
+
this.embeddingPromise = this.ensureEmbeddings();
|
|
90
|
+
void this.embeddingPromise
|
|
91
|
+
.catch(() => { })
|
|
92
|
+
.then(() => {
|
|
93
|
+
this.embeddingPromise = undefined;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
await this.embeddingPromise;
|
|
16
97
|
}
|
|
17
98
|
async match(args) {
|
|
18
99
|
for (const { matcher } of Object.values(this.registry)) {
|
|
@@ -29,61 +110,26 @@ export class NeuledgeGraphMemoryRegistry {
|
|
|
29
110
|
}
|
|
30
111
|
return entry.resolver(match.params);
|
|
31
112
|
}
|
|
32
|
-
|
|
33
|
-
this.
|
|
113
|
+
register(args) {
|
|
114
|
+
this.registry[args.template] = {
|
|
34
115
|
matcher: new NeuledgeGraphMatcher(args.template),
|
|
35
116
|
resolver: args.resolver,
|
|
36
117
|
};
|
|
37
|
-
if (!this.registerPromise) {
|
|
38
|
-
this.registerPromise = this.registerAsync();
|
|
39
|
-
this.registerPromise
|
|
40
|
-
.catch(() => { })
|
|
41
|
-
.then(() => {
|
|
42
|
-
this.registerPromise = undefined;
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
return this.registerPromise;
|
|
46
118
|
}
|
|
47
|
-
registerAsync = async () => {
|
|
48
|
-
let queue = this.registerQueue;
|
|
49
|
-
this.registerQueue = {};
|
|
50
|
-
let templates = Object.keys(queue);
|
|
51
|
-
do {
|
|
52
|
-
const { embeddings } = await embedMany({
|
|
53
|
-
model: this.embeddingModel,
|
|
54
|
-
values: templates,
|
|
55
|
-
});
|
|
56
|
-
if (embeddings.length !== templates.length) {
|
|
57
|
-
throw new Error("Unexpected number of embedding vectors return from `embedMany`");
|
|
58
|
-
}
|
|
59
|
-
for (let i = 0; i < templates.length; ++i) {
|
|
60
|
-
// biome-ignore lint/style/noNonNullAssertion: loop
|
|
61
|
-
const template = templates[i];
|
|
62
|
-
// biome-ignore lint/style/noNonNullAssertion: already verified
|
|
63
|
-
const embedding = embeddings[i];
|
|
64
|
-
// biome-ignore lint/style/noNonNullAssertion: already verified
|
|
65
|
-
const entry = queue[template];
|
|
66
|
-
this.registry[template] = {
|
|
67
|
-
matcher: entry.matcher,
|
|
68
|
-
resolver: entry.resolver,
|
|
69
|
-
embedding,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
queue = this.registerQueue;
|
|
73
|
-
this.registerQueue = {};
|
|
74
|
-
templates = Object.keys(queue);
|
|
75
|
-
} while (templates.length);
|
|
76
|
-
};
|
|
77
119
|
async suggestions(args) {
|
|
78
|
-
const { embedding } = await
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
120
|
+
const [{ embedding }] = await Promise.all([
|
|
121
|
+
embed({
|
|
122
|
+
model: this.embeddingModel,
|
|
123
|
+
value: args.path,
|
|
124
|
+
}),
|
|
125
|
+
this.ensureReady(),
|
|
126
|
+
]);
|
|
82
127
|
const trashhold = args.trashhold ?? this.defaultTrashhold;
|
|
83
128
|
const limit = args.limit ?? this.defaultLimit;
|
|
84
129
|
return Object.entries(this.registry)
|
|
85
130
|
.map(([template, entry]) => ({
|
|
86
131
|
template,
|
|
132
|
+
// biome-ignore lint/style/noNonNullAssertion: ensured by `ensureReady`
|
|
87
133
|
similarity: cosineSimilarity(entry.embedding, embedding),
|
|
88
134
|
}))
|
|
89
135
|
.filter((s) => s.similarity >= trashhold)
|
package/dist/memory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neuledge/graph-memory-registry",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "In-memory embedding registry for intelligent query routing with semantic similarity matching.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -49,10 +49,10 @@
|
|
|
49
49
|
"typescript": "^5.9.3",
|
|
50
50
|
"vite-tsconfig-paths": "^5.1.4",
|
|
51
51
|
"vitest": "^4.0.3",
|
|
52
|
-
"@neuledge/graph-router": "0.
|
|
52
|
+
"@neuledge/graph-router": "0.3.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"@neuledge/graph-router": "^0.
|
|
55
|
+
"@neuledge/graph-router": "^0.3.0",
|
|
56
56
|
"ai": ">=5.0.0"
|
|
57
57
|
},
|
|
58
58
|
"tsx": {
|