@soulcraft/brainy 0.47.0 → 0.49.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 +268 -554
- package/dist/brainyData.d.ts +83 -2
- package/dist/brainyData.js +536 -66
- package/dist/brainyData.js.map +1 -1
- package/dist/coreTypes.d.ts +74 -12
- package/dist/distributed/configManager.d.ts +9 -0
- package/dist/distributed/configManager.js +129 -10
- package/dist/distributed/configManager.js.map +1 -1
- package/dist/hnsw/hnswIndex.d.ts +2 -2
- package/dist/hnsw/hnswIndex.js +48 -29
- package/dist/hnsw/hnswIndex.js.map +1 -1
- package/dist/hnsw/optimizedHNSWIndex.d.ts +1 -1
- package/dist/hnsw/optimizedHNSWIndex.js +3 -3
- package/dist/hnsw/optimizedHNSWIndex.js.map +1 -1
- package/dist/storage/adapters/baseStorageAdapter.d.ts +18 -2
- package/dist/storage/adapters/baseStorageAdapter.js +69 -4
- package/dist/storage/adapters/baseStorageAdapter.js.map +1 -1
- package/dist/storage/adapters/fileSystemStorage.d.ts +14 -8
- package/dist/storage/adapters/fileSystemStorage.js +90 -22
- package/dist/storage/adapters/fileSystemStorage.js.map +1 -1
- package/dist/storage/adapters/memoryStorage.d.ts +0 -8
- package/dist/storage/adapters/memoryStorage.js +26 -45
- package/dist/storage/adapters/memoryStorage.js.map +1 -1
- package/dist/storage/adapters/opfsStorage.d.ts +40 -8
- package/dist/storage/adapters/opfsStorage.js +195 -44
- package/dist/storage/adapters/opfsStorage.js.map +1 -1
- package/dist/storage/adapters/optimizedS3Search.js +4 -3
- package/dist/storage/adapters/optimizedS3Search.js.map +1 -1
- package/dist/storage/adapters/s3CompatibleStorage.d.ts +3 -10
- package/dist/storage/adapters/s3CompatibleStorage.js +41 -44
- package/dist/storage/adapters/s3CompatibleStorage.js.map +1 -1
- package/dist/storage/backwardCompatibility.d.ts +84 -0
- package/dist/storage/backwardCompatibility.js +141 -0
- package/dist/storage/backwardCompatibility.js.map +1 -0
- package/dist/storage/baseStorage.d.ts +33 -19
- package/dist/storage/baseStorage.js +116 -195
- package/dist/storage/baseStorage.js.map +1 -1
- package/dist/utils/distance.d.ts +4 -4
- package/dist/utils/distance.js +4 -4
- package/dist/utils/embedding.d.ts +10 -0
- package/dist/utils/embedding.js +81 -9
- package/dist/utils/embedding.js.map +1 -1
- package/dist/utils/metadataFilter.d.ts +79 -0
- package/dist/utils/metadataFilter.js +229 -0
- package/dist/utils/metadataFilter.js.map +1 -0
- package/dist/utils/metadataIndex.d.ts +148 -0
- package/dist/utils/metadataIndex.js +639 -0
- package/dist/utils/metadataIndex.js.map +1 -0
- package/dist/utils/metadataIndexCache.d.ts +60 -0
- package/dist/utils/metadataIndexCache.js +119 -0
- package/dist/utils/metadataIndexCache.js.map +1 -0
- package/package.json +4 -4
package/dist/utils/embedding.js
CHANGED
|
@@ -4,6 +4,51 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { isBrowser } from './environment.js';
|
|
6
6
|
import { pipeline, env } from '@huggingface/transformers';
|
|
7
|
+
/**
|
|
8
|
+
* Detect the best available GPU device for the current environment
|
|
9
|
+
*/
|
|
10
|
+
export async function detectBestDevice() {
|
|
11
|
+
// Browser environment - check for WebGPU support
|
|
12
|
+
if (isBrowser()) {
|
|
13
|
+
if (typeof navigator !== 'undefined' && 'gpu' in navigator) {
|
|
14
|
+
try {
|
|
15
|
+
const adapter = await navigator.gpu?.requestAdapter();
|
|
16
|
+
if (adapter) {
|
|
17
|
+
return 'webgpu';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
// WebGPU not available or failed to initialize
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return 'cpu';
|
|
25
|
+
}
|
|
26
|
+
// Node.js environment - check for CUDA support
|
|
27
|
+
try {
|
|
28
|
+
// Check if ONNX Runtime GPU packages are available
|
|
29
|
+
// This is a simple heuristic - in production you might want more sophisticated detection
|
|
30
|
+
const hasGpu = process.env.CUDA_VISIBLE_DEVICES !== undefined ||
|
|
31
|
+
process.env.ONNXRUNTIME_GPU_ENABLED === 'true';
|
|
32
|
+
return hasGpu ? 'cuda' : 'cpu';
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
return 'cpu';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Resolve device string to actual device configuration
|
|
40
|
+
*/
|
|
41
|
+
export async function resolveDevice(device = 'auto') {
|
|
42
|
+
if (device === 'auto') {
|
|
43
|
+
return await detectBestDevice();
|
|
44
|
+
}
|
|
45
|
+
// Map 'gpu' to appropriate GPU type for current environment
|
|
46
|
+
if (device === 'gpu') {
|
|
47
|
+
const detected = await detectBestDevice();
|
|
48
|
+
return detected === 'cpu' ? 'cpu' : detected;
|
|
49
|
+
}
|
|
50
|
+
return device;
|
|
51
|
+
}
|
|
7
52
|
export class TransformerEmbedding {
|
|
8
53
|
/**
|
|
9
54
|
* Create a new TransformerEmbedding instance
|
|
@@ -16,9 +61,10 @@ export class TransformerEmbedding {
|
|
|
16
61
|
this.options = {
|
|
17
62
|
model: options.model || 'Xenova/all-MiniLM-L6-v2',
|
|
18
63
|
verbose: this.verbose,
|
|
19
|
-
cacheDir: options.cacheDir ||
|
|
64
|
+
cacheDir: options.cacheDir || './models', // Will be resolved async in init()
|
|
20
65
|
localFilesOnly: options.localFilesOnly !== undefined ? options.localFilesOnly : !isBrowser(),
|
|
21
|
-
dtype: options.dtype || 'fp32'
|
|
66
|
+
dtype: options.dtype || 'fp32',
|
|
67
|
+
device: options.device || 'auto'
|
|
22
68
|
};
|
|
23
69
|
// Configure transformers.js environment
|
|
24
70
|
if (!isBrowser()) {
|
|
@@ -42,7 +88,7 @@ export class TransformerEmbedding {
|
|
|
42
88
|
/**
|
|
43
89
|
* Get the default cache directory for models
|
|
44
90
|
*/
|
|
45
|
-
getDefaultCacheDir() {
|
|
91
|
+
async getDefaultCacheDir() {
|
|
46
92
|
if (isBrowser()) {
|
|
47
93
|
return './models'; // Browser default
|
|
48
94
|
}
|
|
@@ -60,6 +106,9 @@ export class TransformerEmbedding {
|
|
|
60
106
|
// Check if we're in Node.js and try to find the bundled models
|
|
61
107
|
if (typeof process !== 'undefined' && process.versions?.node) {
|
|
62
108
|
try {
|
|
109
|
+
// Use dynamic import instead of require for ES modules compatibility
|
|
110
|
+
const { createRequire } = await import('module');
|
|
111
|
+
const require = createRequire(import.meta.url);
|
|
63
112
|
const path = require('path');
|
|
64
113
|
const fs = require('fs');
|
|
65
114
|
// Try to resolve the package location
|
|
@@ -85,7 +134,7 @@ export class TransformerEmbedding {
|
|
|
85
134
|
}
|
|
86
135
|
}
|
|
87
136
|
catch (error) {
|
|
88
|
-
|
|
137
|
+
// Silently fall back to default path if module detection fails
|
|
89
138
|
}
|
|
90
139
|
}
|
|
91
140
|
// Fallback to default cache directory
|
|
@@ -115,19 +164,42 @@ export class TransformerEmbedding {
|
|
|
115
164
|
}
|
|
116
165
|
// Always use real implementation - no mocking
|
|
117
166
|
try {
|
|
118
|
-
|
|
167
|
+
// Resolve device configuration and cache directory
|
|
168
|
+
const device = await resolveDevice(this.options.device);
|
|
169
|
+
const cacheDir = this.options.cacheDir === './models'
|
|
170
|
+
? await this.getDefaultCacheDir()
|
|
171
|
+
: this.options.cacheDir;
|
|
172
|
+
this.logger('log', `Loading Transformer model: ${this.options.model} on device: ${device}`);
|
|
119
173
|
const startTime = Date.now();
|
|
120
|
-
// Load the feature extraction pipeline
|
|
121
|
-
// In browsers, never use local_files_only to avoid conflicts
|
|
174
|
+
// Load the feature extraction pipeline with GPU support
|
|
122
175
|
const pipelineOptions = {
|
|
123
|
-
cache_dir:
|
|
176
|
+
cache_dir: cacheDir,
|
|
124
177
|
local_files_only: isBrowser() ? false : this.options.localFilesOnly,
|
|
125
178
|
dtype: this.options.dtype
|
|
126
179
|
};
|
|
180
|
+
// Add device configuration for GPU acceleration
|
|
181
|
+
if (device !== 'cpu') {
|
|
182
|
+
pipelineOptions.device = device;
|
|
183
|
+
this.logger('log', `🚀 GPU acceleration enabled: ${device}`);
|
|
184
|
+
}
|
|
127
185
|
if (this.verbose) {
|
|
128
186
|
this.logger('log', `Pipeline options: ${JSON.stringify(pipelineOptions)}`);
|
|
129
187
|
}
|
|
130
|
-
|
|
188
|
+
try {
|
|
189
|
+
this.extractor = await pipeline('feature-extraction', this.options.model, pipelineOptions);
|
|
190
|
+
}
|
|
191
|
+
catch (gpuError) {
|
|
192
|
+
// Fallback to CPU if GPU initialization fails
|
|
193
|
+
if (device !== 'cpu') {
|
|
194
|
+
this.logger('warn', `GPU initialization failed, falling back to CPU: ${gpuError?.message || gpuError}`);
|
|
195
|
+
const cpuOptions = { ...pipelineOptions };
|
|
196
|
+
delete cpuOptions.device;
|
|
197
|
+
this.extractor = await pipeline('feature-extraction', this.options.model, cpuOptions);
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
throw gpuError;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
131
203
|
const loadTime = Date.now() - startTime;
|
|
132
204
|
this.logger('log', `✅ Model loaded successfully in ${loadTime}ms`);
|
|
133
205
|
this.initialized = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"embedding.js","sourceRoot":"","sources":["../../src/utils/embedding.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAA;
|
|
1
|
+
{"version":3,"file":"embedding.js","sourceRoot":"","sources":["../../src/utils/embedding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart metadata filtering for vector search
|
|
3
|
+
* Filters DURING search to ensure relevant results
|
|
4
|
+
* Simple API that just works without configuration
|
|
5
|
+
*/
|
|
6
|
+
import { SearchResult, HNSWNoun } from '../coreTypes.js';
|
|
7
|
+
/**
|
|
8
|
+
* MongoDB-style query operators
|
|
9
|
+
*/
|
|
10
|
+
export interface QueryOperators {
|
|
11
|
+
$eq?: any;
|
|
12
|
+
$ne?: any;
|
|
13
|
+
$gt?: any;
|
|
14
|
+
$gte?: any;
|
|
15
|
+
$lt?: any;
|
|
16
|
+
$lte?: any;
|
|
17
|
+
$in?: any[];
|
|
18
|
+
$nin?: any[];
|
|
19
|
+
$exists?: boolean;
|
|
20
|
+
$regex?: string | RegExp;
|
|
21
|
+
$includes?: any;
|
|
22
|
+
$all?: any[];
|
|
23
|
+
$size?: number;
|
|
24
|
+
$and?: MetadataFilter[];
|
|
25
|
+
$or?: MetadataFilter[];
|
|
26
|
+
$not?: MetadataFilter;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Metadata filter definition
|
|
30
|
+
*/
|
|
31
|
+
export interface MetadataFilter {
|
|
32
|
+
[key: string]: any | QueryOperators;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Options for metadata filtering
|
|
36
|
+
*/
|
|
37
|
+
export interface MetadataFilterOptions {
|
|
38
|
+
metadata?: MetadataFilter;
|
|
39
|
+
scoring?: {
|
|
40
|
+
vectorWeight?: number;
|
|
41
|
+
metadataWeight?: number;
|
|
42
|
+
metadataBoosts?: Record<string, number | ((value: any, query: any) => number)>;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Check if metadata matches the filter
|
|
47
|
+
*/
|
|
48
|
+
export declare function matchesMetadataFilter(metadata: any, filter: MetadataFilter): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Calculate metadata boost score
|
|
51
|
+
*/
|
|
52
|
+
export declare function calculateMetadataScore(metadata: any, filter: MetadataFilter, scoring?: MetadataFilterOptions['scoring']): number;
|
|
53
|
+
/**
|
|
54
|
+
* Apply compound scoring to search results
|
|
55
|
+
*/
|
|
56
|
+
export declare function applyCompoundScoring<T>(results: SearchResult<T>[], filter: MetadataFilter, scoring?: MetadataFilterOptions['scoring']): SearchResult<T>[];
|
|
57
|
+
/**
|
|
58
|
+
* Filter search results by metadata
|
|
59
|
+
*/
|
|
60
|
+
export declare function filterSearchResultsByMetadata<T>(results: SearchResult<T>[], filter: MetadataFilter): SearchResult<T>[];
|
|
61
|
+
/**
|
|
62
|
+
* Filter nouns by metadata before search
|
|
63
|
+
*/
|
|
64
|
+
export declare function filterNounsByMetadata(nouns: HNSWNoun[], filter: MetadataFilter): HNSWNoun[];
|
|
65
|
+
/**
|
|
66
|
+
* Aggregate search results for faceted search
|
|
67
|
+
*/
|
|
68
|
+
export interface FacetConfig {
|
|
69
|
+
field: string;
|
|
70
|
+
limit?: number;
|
|
71
|
+
}
|
|
72
|
+
export interface FacetResult {
|
|
73
|
+
[value: string]: number;
|
|
74
|
+
}
|
|
75
|
+
export interface AggregationResult<T> {
|
|
76
|
+
results: SearchResult<T>[];
|
|
77
|
+
facets: Record<string, FacetResult>;
|
|
78
|
+
}
|
|
79
|
+
export declare function aggregateSearchResults<T>(results: SearchResult<T>[], facets: Record<string, FacetConfig>): AggregationResult<T>;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart metadata filtering for vector search
|
|
3
|
+
* Filters DURING search to ensure relevant results
|
|
4
|
+
* Simple API that just works without configuration
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Check if a value matches a query with operators
|
|
8
|
+
*/
|
|
9
|
+
function matchesQuery(value, query) {
|
|
10
|
+
// Direct equality check
|
|
11
|
+
if (typeof query !== 'object' || query === null || Array.isArray(query)) {
|
|
12
|
+
return value === query;
|
|
13
|
+
}
|
|
14
|
+
// Check for MongoDB-style operators
|
|
15
|
+
for (const [op, operand] of Object.entries(query)) {
|
|
16
|
+
switch (op) {
|
|
17
|
+
case '$eq':
|
|
18
|
+
if (value !== operand)
|
|
19
|
+
return false;
|
|
20
|
+
break;
|
|
21
|
+
case '$ne':
|
|
22
|
+
if (value === operand)
|
|
23
|
+
return false;
|
|
24
|
+
break;
|
|
25
|
+
case '$gt':
|
|
26
|
+
if (typeof value !== 'number' || typeof operand !== 'number' || !(value > operand))
|
|
27
|
+
return false;
|
|
28
|
+
break;
|
|
29
|
+
case '$gte':
|
|
30
|
+
if (typeof value !== 'number' || typeof operand !== 'number' || !(value >= operand))
|
|
31
|
+
return false;
|
|
32
|
+
break;
|
|
33
|
+
case '$lt':
|
|
34
|
+
if (typeof value !== 'number' || typeof operand !== 'number' || !(value < operand))
|
|
35
|
+
return false;
|
|
36
|
+
break;
|
|
37
|
+
case '$lte':
|
|
38
|
+
if (typeof value !== 'number' || typeof operand !== 'number' || !(value <= operand))
|
|
39
|
+
return false;
|
|
40
|
+
break;
|
|
41
|
+
case '$in':
|
|
42
|
+
if (!Array.isArray(operand) || !operand.includes(value))
|
|
43
|
+
return false;
|
|
44
|
+
break;
|
|
45
|
+
case '$nin':
|
|
46
|
+
if (!Array.isArray(operand) || operand.includes(value))
|
|
47
|
+
return false;
|
|
48
|
+
break;
|
|
49
|
+
case '$exists':
|
|
50
|
+
if ((value !== undefined) !== operand)
|
|
51
|
+
return false;
|
|
52
|
+
break;
|
|
53
|
+
case '$regex':
|
|
54
|
+
const regex = typeof operand === 'string' ? new RegExp(operand) : operand;
|
|
55
|
+
if (!(regex instanceof RegExp) || !regex.test(String(value)))
|
|
56
|
+
return false;
|
|
57
|
+
break;
|
|
58
|
+
case '$includes':
|
|
59
|
+
if (!Array.isArray(value) || !value.includes(operand))
|
|
60
|
+
return false;
|
|
61
|
+
break;
|
|
62
|
+
case '$all':
|
|
63
|
+
if (!Array.isArray(value) || !Array.isArray(operand))
|
|
64
|
+
return false;
|
|
65
|
+
for (const item of operand) {
|
|
66
|
+
if (!value.includes(item))
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
case '$size':
|
|
71
|
+
if (!Array.isArray(value) || value.length !== operand)
|
|
72
|
+
return false;
|
|
73
|
+
break;
|
|
74
|
+
default:
|
|
75
|
+
// Unknown operator, treat as field name
|
|
76
|
+
if (!matchesFieldQuery(value, op, operand))
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Check if a field matches a query
|
|
84
|
+
*/
|
|
85
|
+
function matchesFieldQuery(obj, field, query) {
|
|
86
|
+
const value = getNestedValue(obj, field);
|
|
87
|
+
return matchesQuery(value, query);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get nested value from object using dot notation
|
|
91
|
+
*/
|
|
92
|
+
function getNestedValue(obj, path) {
|
|
93
|
+
const parts = path.split('.');
|
|
94
|
+
let current = obj;
|
|
95
|
+
for (const part of parts) {
|
|
96
|
+
if (current === null || current === undefined) {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
current = current[part];
|
|
100
|
+
}
|
|
101
|
+
return current;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Check if metadata matches the filter
|
|
105
|
+
*/
|
|
106
|
+
export function matchesMetadataFilter(metadata, filter) {
|
|
107
|
+
if (!filter || Object.keys(filter).length === 0) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
for (const [key, query] of Object.entries(filter)) {
|
|
111
|
+
// Handle logical operators
|
|
112
|
+
if (key === '$and') {
|
|
113
|
+
if (!Array.isArray(query))
|
|
114
|
+
return false;
|
|
115
|
+
for (const subFilter of query) {
|
|
116
|
+
if (!matchesMetadataFilter(metadata, subFilter))
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (key === '$or') {
|
|
122
|
+
if (!Array.isArray(query))
|
|
123
|
+
return false;
|
|
124
|
+
let matched = false;
|
|
125
|
+
for (const subFilter of query) {
|
|
126
|
+
if (matchesMetadataFilter(metadata, subFilter)) {
|
|
127
|
+
matched = true;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (!matched)
|
|
132
|
+
return false;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (key === '$not') {
|
|
136
|
+
if (matchesMetadataFilter(metadata, query))
|
|
137
|
+
return false;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
// Handle field queries
|
|
141
|
+
const value = getNestedValue(metadata, key);
|
|
142
|
+
if (!matchesQuery(value, query)) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Calculate metadata boost score
|
|
150
|
+
*/
|
|
151
|
+
export function calculateMetadataScore(metadata, filter, scoring) {
|
|
152
|
+
if (!scoring || !scoring.metadataBoosts) {
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
let score = 0;
|
|
156
|
+
for (const [field, boost] of Object.entries(scoring.metadataBoosts)) {
|
|
157
|
+
const value = getNestedValue(metadata, field);
|
|
158
|
+
if (typeof boost === 'function') {
|
|
159
|
+
score += boost(value, filter);
|
|
160
|
+
}
|
|
161
|
+
else if (value !== undefined) {
|
|
162
|
+
// Check if the field matches the filter
|
|
163
|
+
const fieldFilter = filter[field];
|
|
164
|
+
if (fieldFilter && matchesQuery(value, fieldFilter)) {
|
|
165
|
+
score += boost;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return score;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Apply compound scoring to search results
|
|
173
|
+
*/
|
|
174
|
+
export function applyCompoundScoring(results, filter, scoring) {
|
|
175
|
+
if (!scoring || (!scoring.vectorWeight && !scoring.metadataWeight)) {
|
|
176
|
+
return results;
|
|
177
|
+
}
|
|
178
|
+
const vectorWeight = scoring.vectorWeight ?? 1.0;
|
|
179
|
+
const metadataWeight = scoring.metadataWeight ?? 0.0;
|
|
180
|
+
return results.map(result => {
|
|
181
|
+
const metadataScore = calculateMetadataScore(result.metadata, filter, scoring);
|
|
182
|
+
const combinedScore = (result.score * vectorWeight) + (metadataScore * metadataWeight);
|
|
183
|
+
return {
|
|
184
|
+
...result,
|
|
185
|
+
score: combinedScore
|
|
186
|
+
};
|
|
187
|
+
}).sort((a, b) => b.score - a.score); // Re-sort by combined score
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Filter search results by metadata
|
|
191
|
+
*/
|
|
192
|
+
export function filterSearchResultsByMetadata(results, filter) {
|
|
193
|
+
if (!filter || Object.keys(filter).length === 0) {
|
|
194
|
+
return results;
|
|
195
|
+
}
|
|
196
|
+
return results.filter(result => matchesMetadataFilter(result.metadata, filter));
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Filter nouns by metadata before search
|
|
200
|
+
*/
|
|
201
|
+
export function filterNounsByMetadata(nouns, filter) {
|
|
202
|
+
if (!filter || Object.keys(filter).length === 0) {
|
|
203
|
+
return nouns;
|
|
204
|
+
}
|
|
205
|
+
return nouns.filter(noun => matchesMetadataFilter(noun.metadata, filter));
|
|
206
|
+
}
|
|
207
|
+
export function aggregateSearchResults(results, facets) {
|
|
208
|
+
const facetResults = {};
|
|
209
|
+
for (const [facetName, config] of Object.entries(facets)) {
|
|
210
|
+
const counts = {};
|
|
211
|
+
for (const result of results) {
|
|
212
|
+
const value = getNestedValue(result.metadata, config.field);
|
|
213
|
+
if (value !== undefined) {
|
|
214
|
+
const key = String(value);
|
|
215
|
+
counts[key] = (counts[key] || 0) + 1;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// Sort by count and apply limit
|
|
219
|
+
const sorted = Object.entries(counts)
|
|
220
|
+
.sort((a, b) => b[1] - a[1])
|
|
221
|
+
.slice(0, config.limit || 10);
|
|
222
|
+
facetResults[facetName] = Object.fromEntries(sorted);
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
results,
|
|
226
|
+
facets: facetResults
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=metadataFilter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadataFilter.js","sourceRoot":"","sources":["../../src/utils/metadataFilter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata Index System
|
|
3
|
+
* Maintains inverted indexes for fast metadata filtering
|
|
4
|
+
* Automatically updates indexes when data changes
|
|
5
|
+
*/
|
|
6
|
+
import { StorageAdapter } from '../coreTypes.js';
|
|
7
|
+
export interface MetadataIndexEntry {
|
|
8
|
+
field: string;
|
|
9
|
+
value: string | number | boolean;
|
|
10
|
+
ids: Set<string>;
|
|
11
|
+
lastUpdated: number;
|
|
12
|
+
}
|
|
13
|
+
export interface FieldIndexData {
|
|
14
|
+
values: Record<string, number>;
|
|
15
|
+
lastUpdated: number;
|
|
16
|
+
}
|
|
17
|
+
export interface MetadataIndexStats {
|
|
18
|
+
totalEntries: number;
|
|
19
|
+
totalIds: number;
|
|
20
|
+
fieldsIndexed: string[];
|
|
21
|
+
lastRebuild: number;
|
|
22
|
+
indexSize: number;
|
|
23
|
+
}
|
|
24
|
+
export interface MetadataIndexConfig {
|
|
25
|
+
maxIndexSize?: number;
|
|
26
|
+
rebuildThreshold?: number;
|
|
27
|
+
autoOptimize?: boolean;
|
|
28
|
+
indexedFields?: string[];
|
|
29
|
+
excludeFields?: string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Manages metadata indexes for fast filtering
|
|
33
|
+
* Maintains inverted indexes: field+value -> list of IDs
|
|
34
|
+
*/
|
|
35
|
+
export declare class MetadataIndexManager {
|
|
36
|
+
private storage;
|
|
37
|
+
private config;
|
|
38
|
+
private indexCache;
|
|
39
|
+
private dirtyEntries;
|
|
40
|
+
private isRebuilding;
|
|
41
|
+
private metadataCache;
|
|
42
|
+
private fieldIndexes;
|
|
43
|
+
private dirtyFields;
|
|
44
|
+
private lastFlushTime;
|
|
45
|
+
private autoFlushThreshold;
|
|
46
|
+
constructor(storage: StorageAdapter, config?: MetadataIndexConfig);
|
|
47
|
+
/**
|
|
48
|
+
* Get index key for field and value
|
|
49
|
+
*/
|
|
50
|
+
private getIndexKey;
|
|
51
|
+
/**
|
|
52
|
+
* Generate field index filename for filter discovery
|
|
53
|
+
*/
|
|
54
|
+
private getFieldIndexFilename;
|
|
55
|
+
/**
|
|
56
|
+
* Generate value chunk filename for scalable storage
|
|
57
|
+
*/
|
|
58
|
+
private getValueChunkFilename;
|
|
59
|
+
/**
|
|
60
|
+
* Make a value safe for use in filenames
|
|
61
|
+
*/
|
|
62
|
+
private makeSafeFilename;
|
|
63
|
+
/**
|
|
64
|
+
* Normalize value for consistent indexing
|
|
65
|
+
*/
|
|
66
|
+
private normalizeValue;
|
|
67
|
+
/**
|
|
68
|
+
* Create a short hash for long values to avoid filesystem filename limits
|
|
69
|
+
*/
|
|
70
|
+
private hashValue;
|
|
71
|
+
/**
|
|
72
|
+
* Check if field should be indexed
|
|
73
|
+
*/
|
|
74
|
+
private shouldIndexField;
|
|
75
|
+
/**
|
|
76
|
+
* Extract indexable field-value pairs from metadata
|
|
77
|
+
*/
|
|
78
|
+
private extractIndexableFields;
|
|
79
|
+
/**
|
|
80
|
+
* Add item to metadata indexes
|
|
81
|
+
*/
|
|
82
|
+
addToIndex(id: string, metadata: any, skipFlush?: boolean): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Update field index with value count
|
|
85
|
+
*/
|
|
86
|
+
private updateFieldIndex;
|
|
87
|
+
/**
|
|
88
|
+
* Remove item from metadata indexes
|
|
89
|
+
*/
|
|
90
|
+
removeFromIndex(id: string, metadata?: any): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Get IDs for a specific field-value combination with caching
|
|
93
|
+
*/
|
|
94
|
+
getIds(field: string, value: any): Promise<string[]>;
|
|
95
|
+
/**
|
|
96
|
+
* Get all available values for a field (for filter discovery)
|
|
97
|
+
*/
|
|
98
|
+
getFilterValues(field: string): Promise<string[]>;
|
|
99
|
+
/**
|
|
100
|
+
* Get all indexed fields (for filter discovery)
|
|
101
|
+
*/
|
|
102
|
+
getFilterFields(): Promise<string[]>;
|
|
103
|
+
/**
|
|
104
|
+
* Convert MongoDB-style filter to simple field-value criteria for indexing
|
|
105
|
+
*/
|
|
106
|
+
private convertFilterToCriteria;
|
|
107
|
+
/**
|
|
108
|
+
* Get IDs matching MongoDB-style metadata filter using indexes where possible
|
|
109
|
+
*/
|
|
110
|
+
getIdsForFilter(filter: any): Promise<string[]>;
|
|
111
|
+
/**
|
|
112
|
+
* Get IDs matching multiple criteria (intersection) - LEGACY METHOD
|
|
113
|
+
* @deprecated Use getIdsForFilter instead
|
|
114
|
+
*/
|
|
115
|
+
getIdsForCriteria(criteria: Record<string, any>): Promise<string[]>;
|
|
116
|
+
/**
|
|
117
|
+
* Flush dirty entries to storage
|
|
118
|
+
*/
|
|
119
|
+
flush(): Promise<void>;
|
|
120
|
+
/**
|
|
121
|
+
* Load field index from storage
|
|
122
|
+
*/
|
|
123
|
+
private loadFieldIndex;
|
|
124
|
+
/**
|
|
125
|
+
* Save field index to storage
|
|
126
|
+
*/
|
|
127
|
+
private saveFieldIndex;
|
|
128
|
+
/**
|
|
129
|
+
* Get index statistics
|
|
130
|
+
*/
|
|
131
|
+
getStats(): Promise<MetadataIndexStats>;
|
|
132
|
+
/**
|
|
133
|
+
* Rebuild entire index from scratch using pagination
|
|
134
|
+
*/
|
|
135
|
+
rebuild(): Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* Load index entry from storage using safe filenames
|
|
138
|
+
*/
|
|
139
|
+
private loadIndexEntry;
|
|
140
|
+
/**
|
|
141
|
+
* Save index entry to storage using safe filenames
|
|
142
|
+
*/
|
|
143
|
+
private saveIndexEntry;
|
|
144
|
+
/**
|
|
145
|
+
* Delete index entry from storage using safe filenames
|
|
146
|
+
*/
|
|
147
|
+
private deleteIndexEntry;
|
|
148
|
+
}
|