@memvid/sdk 2.0.143 → 2.0.145
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/dist/index.d.ts +1 -1
- package/dist/index.js +139 -5
- package/dist/types.d.ts +21 -0
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -300,7 +300,7 @@ export declare function create(filename: string, kind?: Kind, apiKeyOrOptions?:
|
|
|
300
300
|
export declare function open(filename: string, kind?: Kind, apiKeyOrOptions?: ApiKey | UseOptions, options?: UseOptions): Promise<Memvid>;
|
|
301
301
|
export declare function verifyMemvid(path: string, options?: UseVerifyOptions): Promise<unknown>;
|
|
302
302
|
export declare function doctorMemvid(path: string, options?: UseDoctorOptions): Promise<unknown>;
|
|
303
|
-
export type { AddMemoryCardsResult, Kind, ApiKey, Memvid, MemoryCard, MemoryCardInput, MemoriesResult, MemoriesStats, LockOptions, UseOptions, UnlockOptions, FindInput, VecSearchInput, AskInput, TimelineInput, PutInput, PutManyInput, PutManyOptions, MemvidErrorCode, MemvidErrorDetails, HeatmapEntry, HeatmapResponse, SessionSummary, SessionReplayResult, SessionActionResult, StatsResult, FindHit, FindResult, VecSearchResult, AskResult, AskStats, AskUsage, AskSource, TimelineEntry, } from "./types";
|
|
303
|
+
export type { AddMemoryCardsResult, Kind, ApiKey, Memvid, MemoryCard, MemoryCardInput, MemoriesResult, MemoriesStats, LockOptions, UseOptions, UnlockOptions, FindInput, VecSearchInput, AskInput, TimelineInput, PutInput, PutManyInput, PutManyOptions, MemvidErrorCode, MemvidErrorDetails, HeatmapEntry, HeatmapResponse, SessionSummary, SessionReplayResult, SessionActionResult, StatsResult, FindHit, FindResult, VecSearchResult, AskResult, AskStats, AskUsage, AskSource, Grounding, FollowUp, TimelineEntry, } from "./types";
|
|
304
304
|
export { MemvidError, CapacityExceededError, TicketInvalidError, TicketReplayError, LexIndexDisabledError, TimeIndexMissingError, VerificationFailedError, LockedError, ApiKeyRequiredError, FileNotFoundError, MemoryAlreadyBoundError, FrameNotFoundError, VecIndexDisabledError, CorruptFileError, VecDimensionMismatchError, EmbeddingFailedError, EncryptionError, QuotaExceededError, getErrorSuggestion, } from "./error";
|
|
305
305
|
export { EmbeddingProvider, OpenAIEmbeddings, OpenAIEmbeddingsConfig, CohereEmbeddings, CohereEmbeddingsConfig, VoyageEmbeddings, VoyageEmbeddingsConfig, NvidiaEmbeddings, NvidiaEmbeddingsConfig, GeminiEmbeddings, GeminiEmbeddingsConfig, MistralEmbeddings, MistralEmbeddingsConfig, getEmbedder, MODEL_DIMENSIONS, LOCAL_EMBEDDING_MODELS, LocalEmbeddingModel, } from "./embeddings";
|
|
306
306
|
export { flush as flushAnalytics, isTelemetryEnabled } from "./analytics";
|
package/dist/index.js
CHANGED
|
@@ -492,6 +492,11 @@ function loadNativeAddon() {
|
|
|
492
492
|
const pkgParts = platformInfo.pkg.split("/");
|
|
493
493
|
const scope = pkgParts[0]; // "@memvid"
|
|
494
494
|
const pkgName = pkgParts[1]; // "sdk-win32-x64-msvc"
|
|
495
|
+
const debug = process.env.MEMVID_DEBUG === "1";
|
|
496
|
+
if (debug) {
|
|
497
|
+
console.log("[memvid] __dirname:", __dirname);
|
|
498
|
+
console.log("[memvid] Looking for platform package:", platformInfo.pkg);
|
|
499
|
+
}
|
|
495
500
|
// Try to find the platform package in various locations
|
|
496
501
|
const possiblePaths = [
|
|
497
502
|
// Sibling in same scope (most common for scoped packages)
|
|
@@ -509,9 +514,16 @@ function loadNativeAddon() {
|
|
|
509
514
|
// Yarn PnP / berry
|
|
510
515
|
path.join(__dirname, "..", "..", ".yarn", "cache", `${scope.replace("@", "")}-${pkgName}`, platformInfo.binary),
|
|
511
516
|
];
|
|
517
|
+
if (debug) {
|
|
518
|
+
console.log("[memvid] Checking paths:");
|
|
519
|
+
possiblePaths.forEach((p, i) => console.log(` [${i}] ${p}`));
|
|
520
|
+
}
|
|
512
521
|
for (const binaryPath of possiblePaths) {
|
|
513
522
|
try {
|
|
514
523
|
fs.statSync(binaryPath);
|
|
524
|
+
if (debug) {
|
|
525
|
+
console.log("[memvid] Found binary at:", binaryPath);
|
|
526
|
+
}
|
|
515
527
|
// Set LD_LIBRARY_PATH/DYLD_LIBRARY_PATH for Tika library
|
|
516
528
|
const binaryDir = path.dirname(binaryPath);
|
|
517
529
|
if (platform === "linux") {
|
|
@@ -526,7 +538,10 @@ function loadNativeAddon() {
|
|
|
526
538
|
}
|
|
527
539
|
return require(binaryPath);
|
|
528
540
|
}
|
|
529
|
-
catch {
|
|
541
|
+
catch (err) {
|
|
542
|
+
if (debug) {
|
|
543
|
+
console.log(`[memvid] Path not found: ${binaryPath}`);
|
|
544
|
+
}
|
|
530
545
|
// Try next path
|
|
531
546
|
}
|
|
532
547
|
}
|
|
@@ -1279,10 +1294,129 @@ class MemvidImpl {
|
|
|
1279
1294
|
}
|
|
1280
1295
|
}
|
|
1281
1296
|
}
|
|
1297
|
+
// Calculate grounding score
|
|
1298
|
+
this.verifyGrounding(response);
|
|
1282
1299
|
// Build follow-up suggestions if confidence is low
|
|
1283
1300
|
return this.buildFollowUp(response);
|
|
1284
1301
|
});
|
|
1285
1302
|
}
|
|
1303
|
+
verifyGrounding(response) {
|
|
1304
|
+
const answer = response.answer || "";
|
|
1305
|
+
const context = response.context || "";
|
|
1306
|
+
// Empty answer = no hallucination
|
|
1307
|
+
if (!answer) {
|
|
1308
|
+
response.grounding = {
|
|
1309
|
+
score: 1.0,
|
|
1310
|
+
label: "HIGH",
|
|
1311
|
+
sentence_count: 0,
|
|
1312
|
+
grounded_sentences: 0,
|
|
1313
|
+
has_warning: false,
|
|
1314
|
+
warning_reason: undefined,
|
|
1315
|
+
};
|
|
1316
|
+
return;
|
|
1317
|
+
}
|
|
1318
|
+
// No context = potential hallucination
|
|
1319
|
+
if (!context) {
|
|
1320
|
+
response.grounding = {
|
|
1321
|
+
score: 0.0,
|
|
1322
|
+
label: "LOW",
|
|
1323
|
+
sentence_count: 1,
|
|
1324
|
+
grounded_sentences: 0,
|
|
1325
|
+
has_warning: true,
|
|
1326
|
+
warning_reason: "No context provided - answer may be hallucinated",
|
|
1327
|
+
};
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
// Normalize context for comparison
|
|
1331
|
+
const contextLower = context.toLowerCase();
|
|
1332
|
+
const contextWords = new Set(contextLower.split(/[^a-zA-Z0-9]+/).filter(w => w.length > 2));
|
|
1333
|
+
// Split answer into sentences
|
|
1334
|
+
const sentences = answer
|
|
1335
|
+
.split(/[.!?]/)
|
|
1336
|
+
.map(s => s.trim())
|
|
1337
|
+
.filter(s => s.length > 10);
|
|
1338
|
+
if (sentences.length === 0) {
|
|
1339
|
+
response.grounding = {
|
|
1340
|
+
score: 0.5,
|
|
1341
|
+
label: "MEDIUM",
|
|
1342
|
+
sentence_count: 0,
|
|
1343
|
+
grounded_sentences: 0,
|
|
1344
|
+
has_warning: false,
|
|
1345
|
+
warning_reason: undefined,
|
|
1346
|
+
};
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
const sentenceScores = [];
|
|
1350
|
+
let groundedCount = 0;
|
|
1351
|
+
for (const sentence of sentences) {
|
|
1352
|
+
const sentenceLower = sentence.toLowerCase();
|
|
1353
|
+
const sentenceWords = new Set(sentenceLower.split(/[^a-zA-Z0-9]+/).filter(w => w.length > 2));
|
|
1354
|
+
if (sentenceWords.size === 0) {
|
|
1355
|
+
sentenceScores.push(0.5);
|
|
1356
|
+
continue;
|
|
1357
|
+
}
|
|
1358
|
+
// Calculate word overlap
|
|
1359
|
+
let overlap = 0;
|
|
1360
|
+
for (const word of sentenceWords) {
|
|
1361
|
+
if (contextWords.has(word))
|
|
1362
|
+
overlap++;
|
|
1363
|
+
}
|
|
1364
|
+
const score = overlap / Math.max(sentenceWords.size, 1);
|
|
1365
|
+
// Add phrase bonus for exact matches
|
|
1366
|
+
let phraseBonus = 0;
|
|
1367
|
+
if (contextLower.includes(sentenceLower)) {
|
|
1368
|
+
phraseBonus = 0.3;
|
|
1369
|
+
}
|
|
1370
|
+
else {
|
|
1371
|
+
// Check for significant substring matches
|
|
1372
|
+
const words = sentenceLower.split(/\s+/);
|
|
1373
|
+
if (words.length >= 3) {
|
|
1374
|
+
const phrase = words.slice(0, 3).join(" ");
|
|
1375
|
+
if (contextLower.includes(phrase)) {
|
|
1376
|
+
phraseBonus = 0.15;
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
const finalScore = Math.min(score + phraseBonus, 1.0);
|
|
1381
|
+
sentenceScores.push(finalScore);
|
|
1382
|
+
if (finalScore >= 0.3) {
|
|
1383
|
+
groundedCount++;
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
const overallScore = sentenceScores.length > 0
|
|
1387
|
+
? sentenceScores.reduce((a, b) => a + b, 0) / sentenceScores.length
|
|
1388
|
+
: 0.5;
|
|
1389
|
+
// Determine warning
|
|
1390
|
+
let hasWarning = false;
|
|
1391
|
+
let warningReason;
|
|
1392
|
+
if (overallScore < 0.2) {
|
|
1393
|
+
hasWarning = true;
|
|
1394
|
+
warningReason = "Answer appears to be poorly grounded in context";
|
|
1395
|
+
}
|
|
1396
|
+
else if (overallScore < 0.4 && groundedCount < Math.floor(sentences.length / 2)) {
|
|
1397
|
+
hasWarning = true;
|
|
1398
|
+
warningReason = "Some statements may not be supported by context";
|
|
1399
|
+
}
|
|
1400
|
+
// Determine label
|
|
1401
|
+
let label;
|
|
1402
|
+
if (overallScore >= 0.7) {
|
|
1403
|
+
label = "HIGH";
|
|
1404
|
+
}
|
|
1405
|
+
else if (overallScore >= 0.4) {
|
|
1406
|
+
label = "MEDIUM";
|
|
1407
|
+
}
|
|
1408
|
+
else {
|
|
1409
|
+
label = "LOW";
|
|
1410
|
+
}
|
|
1411
|
+
response.grounding = {
|
|
1412
|
+
score: overallScore,
|
|
1413
|
+
label,
|
|
1414
|
+
sentence_count: sentences.length,
|
|
1415
|
+
grounded_sentences: groundedCount,
|
|
1416
|
+
has_warning: hasWarning,
|
|
1417
|
+
warning_reason: warningReason,
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
1286
1420
|
async buildFollowUp(response) {
|
|
1287
1421
|
const hits = response.hits || [];
|
|
1288
1422
|
// Check if retrieval has no results
|
|
@@ -1296,10 +1430,10 @@ class MemvidImpl {
|
|
|
1296
1430
|
veryLowRetrieval = true;
|
|
1297
1431
|
}
|
|
1298
1432
|
}
|
|
1299
|
-
// Check grounding if available
|
|
1300
|
-
const grounding = response.grounding
|
|
1301
|
-
const hasGroundingWarning = grounding
|
|
1302
|
-
const lowGrounding = grounding
|
|
1433
|
+
// Check grounding if available
|
|
1434
|
+
const grounding = response.grounding;
|
|
1435
|
+
const hasGroundingWarning = grounding?.has_warning || false;
|
|
1436
|
+
const lowGrounding = grounding?.score !== undefined && grounding.score < 0.3;
|
|
1303
1437
|
// Detect "Not enough information" type answers (primary trigger)
|
|
1304
1438
|
const answer = (response.answer || "").toLowerCase();
|
|
1305
1439
|
const noInfoPhrases = [
|
package/dist/types.d.ts
CHANGED
|
@@ -507,6 +507,21 @@ export interface FollowUp {
|
|
|
507
507
|
available_topics: string[];
|
|
508
508
|
suggestions: string[];
|
|
509
509
|
}
|
|
510
|
+
/** Grounding information for answer quality assessment */
|
|
511
|
+
export interface Grounding {
|
|
512
|
+
/** Overall grounding score (0-1) */
|
|
513
|
+
score: number;
|
|
514
|
+
/** Grounding quality label (LOW, MEDIUM, HIGH) */
|
|
515
|
+
label?: string;
|
|
516
|
+
/** Number of sentences in the answer */
|
|
517
|
+
sentence_count?: number;
|
|
518
|
+
/** Number of sentences grounded in context */
|
|
519
|
+
grounded_sentences?: number;
|
|
520
|
+
/** Whether there's a grounding warning */
|
|
521
|
+
has_warning: boolean;
|
|
522
|
+
/** Reason for the warning if any */
|
|
523
|
+
warning_reason?: string;
|
|
524
|
+
}
|
|
510
525
|
/** Response from ask() method */
|
|
511
526
|
export interface AskResult {
|
|
512
527
|
question: string;
|
|
@@ -521,6 +536,8 @@ export interface AskResult {
|
|
|
521
536
|
stats: AskStats;
|
|
522
537
|
usage: AskUsage;
|
|
523
538
|
model?: string;
|
|
539
|
+
/** Grounding information for answer quality assessment */
|
|
540
|
+
grounding?: Grounding;
|
|
524
541
|
/** Follow-up suggestions when confidence is low */
|
|
525
542
|
follow_up?: FollowUp;
|
|
526
543
|
}
|
|
@@ -548,6 +565,10 @@ export interface Memvid {
|
|
|
548
565
|
vecSearch(query: string, queryEmbedding: number[], opts?: VecSearchInput): Promise<VecSearchResult>;
|
|
549
566
|
/** Ask a question and get an AI-generated answer based on memory contents. */
|
|
550
567
|
ask(question: string, opts?: AskInput): Promise<AskResult>;
|
|
568
|
+
/** Store a correction/ground truth statement with retrieval priority boost. */
|
|
569
|
+
correct(statement: string, options?: CorrectOptions): Promise<string>;
|
|
570
|
+
/** Batch store multiple corrections with retrieval priority boost. */
|
|
571
|
+
correctMany(corrections: CorrectManyInput[]): Promise<string[]>;
|
|
551
572
|
/** Get chronological list of frames. */
|
|
552
573
|
timeline(opts?: TimelineInput): Promise<TimelineEntry[]>;
|
|
553
574
|
/** Get memory statistics including capacity, frame count, and index status. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memvid/sdk",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.145",
|
|
4
4
|
"description": "Single-file AI memory system for Node.js. Store, search, and query documents with built-in RAG.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
"node": ">=18"
|
|
42
42
|
},
|
|
43
43
|
"optionalDependencies": {
|
|
44
|
-
"@memvid/sdk-darwin-arm64": "2.0.
|
|
45
|
-
"@memvid/sdk-darwin-x64": "2.0.
|
|
46
|
-
"@memvid/sdk-linux-x64-gnu": "2.0.
|
|
47
|
-
"@memvid/sdk-win32-x64-msvc": "2.0.
|
|
44
|
+
"@memvid/sdk-darwin-arm64": "2.0.145",
|
|
45
|
+
"@memvid/sdk-darwin-x64": "2.0.145",
|
|
46
|
+
"@memvid/sdk-linux-x64-gnu": "2.0.145",
|
|
47
|
+
"@memvid/sdk-win32-x64-msvc": "2.0.145"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@langchain/core": ">=0.3.0",
|