code-graph-context 2.12.6 → 2.12.8
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
CHANGED
|
@@ -190,7 +190,7 @@ If you prefer to edit the config files directly:
|
|
|
190
190
|
| `NEO4J_USER` | No | `neo4j` | Neo4j username |
|
|
191
191
|
| `NEO4J_PASSWORD` | No | `PASSWORD` | Neo4j password |
|
|
192
192
|
| `EMBEDDING_MODEL` | No | `codesage/codesage-base-v2` | Local embedding model (see [Embedding Configuration](#embedding-configuration)) |
|
|
193
|
-
| `EMBEDDING_BATCH_SIZE` | No | `
|
|
193
|
+
| `EMBEDDING_BATCH_SIZE` | No | `8` | Texts per embedding batch (lower = less memory, higher = faster) |
|
|
194
194
|
| `EMBEDDING_SIDECAR_PORT` | No | `8787` | Port for local embedding server |
|
|
195
195
|
| `EMBEDDING_DEVICE` | No | auto (`mps`/`cpu`) | Device for embeddings. Auto-detects MPS on Apple Silicon |
|
|
196
196
|
| `EMBEDDING_HALF_PRECISION` | No | `false` | Set `true` for float16 (uses ~0.5x memory) |
|
|
@@ -175,7 +175,9 @@ export class EmbeddingSidecar {
|
|
|
175
175
|
}
|
|
176
176
|
return false;
|
|
177
177
|
}
|
|
178
|
-
catch {
|
|
178
|
+
catch (err) {
|
|
179
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
180
|
+
console.error(`[embedding-sidecar] Health check failed: ${msg}`);
|
|
179
181
|
return false;
|
|
180
182
|
}
|
|
181
183
|
}
|
|
@@ -186,6 +188,7 @@ export class EmbeddingSidecar {
|
|
|
186
188
|
await this.start();
|
|
187
189
|
const controller = new AbortController();
|
|
188
190
|
const timeout = setTimeout(() => controller.abort(), this.config.requestTimeoutMs);
|
|
191
|
+
const startTime = Date.now();
|
|
189
192
|
try {
|
|
190
193
|
const res = await fetch(`${this.baseUrl}/embed`, {
|
|
191
194
|
method: 'POST',
|
|
@@ -202,21 +205,24 @@ export class EmbeddingSidecar {
|
|
|
202
205
|
console.error('[embedding-sidecar] OOM detected, restarting sidecar to reclaim GPU memory');
|
|
203
206
|
await this.stop();
|
|
204
207
|
}
|
|
208
|
+
console.error(`[embedding-sidecar] Embed failed after ${Date.now() - startTime}ms: status=${res.status}, texts=${texts.length}, oom=${isOOM}, detail=${detail}`);
|
|
205
209
|
throw new Error(`Sidecar embed failed (${res.status}): ${detail}`);
|
|
206
210
|
}
|
|
207
211
|
const data = (await res.json());
|
|
208
212
|
if (data.dimensions)
|
|
209
213
|
this._dimensions = data.dimensions;
|
|
214
|
+
console.error(`[embedding-sidecar] Embedded ${texts.length} texts in ${Date.now() - startTime}ms (dims=${data.dimensions})`);
|
|
210
215
|
this.resetIdleTimer();
|
|
211
216
|
return data.embeddings;
|
|
212
217
|
}
|
|
213
218
|
catch (err) {
|
|
214
219
|
if (err instanceof Error && err.name === 'AbortError') {
|
|
215
|
-
|
|
216
|
-
console.error('[embedding-sidecar] Request timed out, restarting sidecar');
|
|
220
|
+
console.error(`[embedding-sidecar] Request timed out after ${Date.now() - startTime}ms (limit=${this.config.requestTimeoutMs}ms, texts=${texts.length}), restarting sidecar`);
|
|
217
221
|
await this.stop();
|
|
218
222
|
throw new Error(`Embedding request timed out after ${this.config.requestTimeoutMs}ms`);
|
|
219
223
|
}
|
|
224
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
225
|
+
console.error(`[embedding-sidecar] Embed error after ${Date.now() - startTime}ms: ${msg} (url=${this.baseUrl}, running=${this.isRunning}, texts=${texts.length})`);
|
|
220
226
|
throw err;
|
|
221
227
|
}
|
|
222
228
|
finally {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { debugLog } from '../../mcp/utils.js';
|
|
7
7
|
import { getEmbeddingSidecar } from './embedding-sidecar.js';
|
|
8
8
|
const BATCH_CONFIG = {
|
|
9
|
-
maxBatchSize: parseInt(process.env.EMBEDDING_BATCH_SIZE ?? '', 10) ||
|
|
9
|
+
maxBatchSize: parseInt(process.env.EMBEDDING_BATCH_SIZE ?? '', 10) || 8,
|
|
10
10
|
};
|
|
11
11
|
export class LocalEmbeddingsService {
|
|
12
12
|
async embedText(text) {
|
|
@@ -28,15 +28,23 @@ export class LocalEmbeddingsService {
|
|
|
28
28
|
const totalBatches = Math.ceil(texts.length / safeBatchSize);
|
|
29
29
|
for (let i = 0; i < texts.length; i += safeBatchSize) {
|
|
30
30
|
const batch = texts.slice(i, i + safeBatchSize);
|
|
31
|
-
const batchIndex = Math.floor(i /
|
|
31
|
+
const batchIndex = Math.floor(i / safeBatchSize) + 1;
|
|
32
|
+
console.error(`[embedding] Batch ${batchIndex}/${totalBatches} (${batch.length} texts)`);
|
|
32
33
|
await debugLog('Embedding batch progress', {
|
|
33
34
|
provider: 'local',
|
|
34
35
|
batchIndex,
|
|
35
36
|
totalBatches,
|
|
36
37
|
batchSize: batch.length,
|
|
37
38
|
});
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
try {
|
|
40
|
+
const batchResults = await sidecar.embed(batch);
|
|
41
|
+
results.push(...batchResults);
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
45
|
+
console.error(`[embedding] Batch ${batchIndex}/${totalBatches} FAILED (${batch.length} texts, batchSize=${safeBatchSize}): ${msg}`);
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
40
48
|
}
|
|
41
49
|
return results;
|
|
42
50
|
}
|
|
@@ -132,11 +132,17 @@ export class GraphGeneratorHandler {
|
|
|
132
132
|
// Batch embed all texts that need it
|
|
133
133
|
if (nodesNeedingEmbedding.length > 0) {
|
|
134
134
|
const texts = nodesNeedingEmbedding.map((n) => n.text);
|
|
135
|
+
const effectiveBatchSize = parseInt(process.env.EMBEDDING_BATCH_SIZE ?? '', 10) || EMBEDDING_BATCH_CONFIG.maxBatchSize;
|
|
136
|
+
const totalBatches = Math.ceil(texts.length / effectiveBatchSize);
|
|
137
|
+
console.error(`[embedding] Starting ${texts.length} texts in ~${totalBatches} batches (effective_batch_size=${effectiveBatchSize}, config_max=${EMBEDDING_BATCH_CONFIG.maxBatchSize})`);
|
|
135
138
|
try {
|
|
136
139
|
const embeddings = await this.embeddingsService.embedTextsInBatches(texts, EMBEDDING_BATCH_CONFIG.maxBatchSize);
|
|
137
140
|
// Map embeddings back to their nodes
|
|
141
|
+
let embeddedCount = 0;
|
|
138
142
|
nodesNeedingEmbedding.forEach((item, i) => {
|
|
139
143
|
const embedding = embeddings[i];
|
|
144
|
+
if (embedding)
|
|
145
|
+
embeddedCount++;
|
|
140
146
|
nodeResults[item.index] = {
|
|
141
147
|
...item.node,
|
|
142
148
|
labels: embedding ? [...item.node.labels, GraphGeneratorHandler.EMBEDDED_LABEL] : item.node.labels,
|
|
@@ -146,15 +152,17 @@ export class GraphGeneratorHandler {
|
|
|
146
152
|
},
|
|
147
153
|
};
|
|
148
154
|
});
|
|
155
|
+
console.error(`[embedding] Done: ${embeddedCount}/${texts.length} nodes embedded`);
|
|
149
156
|
await debugLog('Batch embedding completed', {
|
|
150
157
|
totalNodes: nodes.length,
|
|
151
|
-
nodesEmbedded:
|
|
152
|
-
batchesUsed:
|
|
158
|
+
nodesEmbedded: embeddedCount,
|
|
159
|
+
batchesUsed: totalBatches,
|
|
153
160
|
});
|
|
154
161
|
}
|
|
155
162
|
catch (error) {
|
|
156
|
-
|
|
157
|
-
|
|
163
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
164
|
+
console.error(`[embedding] FAILED: ${msg}`);
|
|
165
|
+
await debugLog('Embedding failed', { error: msg });
|
|
158
166
|
throw error;
|
|
159
167
|
}
|
|
160
168
|
}
|
package/package.json
CHANGED