Skip to content

Commit 1843188

Browse files
committed
Add configurable embedding batchSize and bump version to 1.0.3
Splits embedBatch into mini-batches (default 1) to control memory usage. New `batchSize` field in embedding config, configurable per graph/project.
1 parent 508adde commit 1843188

6 files changed

Lines changed: 23 additions & 12 deletions

File tree

graph-memory.yaml.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ server:
3131
# dtype: "q8" # Quantization: fp32, fp16, q8, q4
3232
# queryPrefix: "" # Prefix prepended to search queries
3333
# documentPrefix: "" # Prefix prepended to documents during indexing
34+
# batchSize: 1 # Texts per ONNX forward pass (increase for faster indexing, more memory)
3435

3536
# ---------------------------------------------------------------------------
3637
# Projects

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mcp-graph-memory",
3-
"version": "1.0.0",
3+
"version": "1.0.3",
44
"description": "MCP server for semantic graph memory from markdown files",
55
"main": "dist/cli/index.js",
66
"bin": {

src/lib/embedder.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,17 @@ export async function embedBatch(
8181
const texts = inputs.map(({ title, content }) =>
8282
`${config.documentPrefix}${title}\n${content}`.slice(0, _maxChars),
8383
);
84-
const tensor = await pipe._call(texts, { pooling: config.pooling, normalize: config.normalize });
85-
const dim = tensor.dims[1];
86-
const data = tensor.data as Float32Array;
84+
85+
const batchSize = config.batchSize;
8786
const result: number[][] = [];
88-
for (let i = 0; i < inputs.length; i++) {
89-
result.push(Array.from(data.slice(i * dim, (i + 1) * dim)));
87+
for (let start = 0; start < texts.length; start += batchSize) {
88+
const chunk = texts.slice(start, start + batchSize);
89+
const tensor = await pipe._call(chunk, { pooling: config.pooling, normalize: config.normalize });
90+
const dim = tensor.dims[1];
91+
const data = tensor.data as Float32Array;
92+
for (let i = 0; i < chunk.length; i++) {
93+
result.push(Array.from(data.slice(i * dim, (i + 1) * dim)));
94+
}
9095
}
9196
return result;
9297
}

src/lib/multi-config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const embeddingConfigSchema = z.object({
2222
dtype: z.string().optional(),
2323
queryPrefix: z.string().optional(),
2424
documentPrefix: z.string().optional(),
25+
batchSize: z.number().int().positive().optional(),
2526
});
2627

2728
const graphEmbeddingOverridesSchema = z.object({
@@ -98,6 +99,7 @@ export interface EmbeddingConfig {
9899
dtype?: string;
99100
queryPrefix: string;
100101
documentPrefix: string;
102+
batchSize: number;
101103
}
102104

103105
/**
@@ -175,6 +177,7 @@ const EMBEDDING_DEFAULTS: EmbeddingConfig = {
175177
normalize: true,
176178
queryPrefix: '',
177179
documentPrefix: '',
180+
batchSize: 1,
178181
};
179182

180183
const SERVER_DEFAULTS: Omit<ServerConfig, 'embedding'> & { embedding: EmbeddingConfig } = {
@@ -214,6 +217,7 @@ function mergeEmbeddingConfig(
214217
dtype: override.dtype ?? base.dtype,
215218
queryPrefix: override.queryPrefix ?? base.queryPrefix,
216219
documentPrefix: override.documentPrefix ?? base.documentPrefix,
220+
batchSize: override.batchSize ?? base.batchSize,
217221
};
218222
}
219223

@@ -233,6 +237,7 @@ function resolveEmbeddingConfig(
233237
dtype: raw.dtype ?? fallback.dtype,
234238
queryPrefix: raw.queryPrefix ?? fallback.queryPrefix,
235239
documentPrefix: raw.documentPrefix ?? fallback.documentPrefix,
240+
batchSize: raw.batchSize ?? fallback.batchSize,
236241
};
237242
}
238243

src/tests/rest-api.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ function createTestProject(): ProjectInstance {
4343
chunkDepth: 4,
4444
maxTokensDefault: 4000,
4545
embedMaxChars: 2000,
46-
embedding: { model: 'test', pooling: 'mean' as const, normalize: true, queryPrefix: '', documentPrefix: '' },
46+
embedding: { model: 'test', pooling: 'mean' as const, normalize: true, queryPrefix: '', documentPrefix: '', batchSize: 1 },
4747
graphEmbeddings: Object.fromEntries(
48-
['docs', 'code', 'knowledge', 'tasks', 'files', 'skills'].map(g => [g, { model: 'test', pooling: 'mean' as const, normalize: true, queryPrefix: '', documentPrefix: '' }]),
48+
['docs', 'code', 'knowledge', 'tasks', 'files', 'skills'].map(g => [g, { model: 'test', pooling: 'mean' as const, normalize: true, queryPrefix: '', documentPrefix: '', batchSize: 1 }]),
4949
) as any,
5050
author: { name: '', email: '' },
5151
},
@@ -482,9 +482,9 @@ describe('Attachment REST endpoints', () => {
482482
chunkDepth: 4,
483483
maxTokensDefault: 4000,
484484
embedMaxChars: 2000,
485-
embedding: { model: 'test', pooling: 'mean' as const, normalize: true, queryPrefix: '', documentPrefix: '' },
485+
embedding: { model: 'test', pooling: 'mean' as const, normalize: true, queryPrefix: '', documentPrefix: '', batchSize: 1 },
486486
graphEmbeddings: Object.fromEntries(
487-
['docs', 'code', 'knowledge', 'tasks', 'files', 'skills'].map(g => [g, { model: 'test', pooling: 'mean' as const, normalize: true, queryPrefix: '', documentPrefix: '' }]),
487+
['docs', 'code', 'knowledge', 'tasks', 'files', 'skills'].map(g => [g, { model: 'test', pooling: 'mean' as const, normalize: true, queryPrefix: '', documentPrefix: '', batchSize: 1 }]),
488488
) as any,
489489
author: { name: '', email: '' },
490490
},

0 commit comments

Comments
 (0)