@danielsimonjr/memoryjs 1.0.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.
Files changed (295) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +266 -0
  3. package/dist/core/EntityManager.d.ts +268 -0
  4. package/dist/core/EntityManager.d.ts.map +1 -0
  5. package/dist/core/EntityManager.js +512 -0
  6. package/dist/core/EntityManager.js.map +1 -0
  7. package/dist/core/GraphEventEmitter.d.ts +202 -0
  8. package/dist/core/GraphEventEmitter.d.ts.map +1 -0
  9. package/dist/core/GraphEventEmitter.js +347 -0
  10. package/dist/core/GraphEventEmitter.js.map +1 -0
  11. package/dist/core/GraphStorage.d.ts +395 -0
  12. package/dist/core/GraphStorage.d.ts.map +1 -0
  13. package/dist/core/GraphStorage.js +786 -0
  14. package/dist/core/GraphStorage.js.map +1 -0
  15. package/dist/core/GraphTraversal.d.ts +141 -0
  16. package/dist/core/GraphTraversal.d.ts.map +1 -0
  17. package/dist/core/GraphTraversal.js +574 -0
  18. package/dist/core/GraphTraversal.js.map +1 -0
  19. package/dist/core/HierarchyManager.d.ts +111 -0
  20. package/dist/core/HierarchyManager.d.ts.map +1 -0
  21. package/dist/core/HierarchyManager.js +225 -0
  22. package/dist/core/HierarchyManager.js.map +1 -0
  23. package/dist/core/ManagerContext.d.ts +76 -0
  24. package/dist/core/ManagerContext.d.ts.map +1 -0
  25. package/dist/core/ManagerContext.js +129 -0
  26. package/dist/core/ManagerContext.js.map +1 -0
  27. package/dist/core/ObservationManager.d.ts +85 -0
  28. package/dist/core/ObservationManager.d.ts.map +1 -0
  29. package/dist/core/ObservationManager.js +124 -0
  30. package/dist/core/ObservationManager.js.map +1 -0
  31. package/dist/core/RelationManager.d.ts +131 -0
  32. package/dist/core/RelationManager.d.ts.map +1 -0
  33. package/dist/core/RelationManager.js +212 -0
  34. package/dist/core/RelationManager.js.map +1 -0
  35. package/dist/core/SQLiteStorage.d.ts +354 -0
  36. package/dist/core/SQLiteStorage.d.ts.map +1 -0
  37. package/dist/core/SQLiteStorage.js +919 -0
  38. package/dist/core/SQLiteStorage.js.map +1 -0
  39. package/dist/core/StorageFactory.d.ts +45 -0
  40. package/dist/core/StorageFactory.d.ts.map +1 -0
  41. package/dist/core/StorageFactory.js +65 -0
  42. package/dist/core/StorageFactory.js.map +1 -0
  43. package/dist/core/TransactionManager.d.ts +464 -0
  44. package/dist/core/TransactionManager.d.ts.map +1 -0
  45. package/dist/core/TransactionManager.js +869 -0
  46. package/dist/core/TransactionManager.js.map +1 -0
  47. package/dist/core/index.d.ts +17 -0
  48. package/dist/core/index.d.ts.map +1 -0
  49. package/dist/core/index.js +20 -0
  50. package/dist/core/index.js.map +1 -0
  51. package/dist/features/AnalyticsManager.d.ts +44 -0
  52. package/dist/features/AnalyticsManager.d.ts.map +1 -0
  53. package/dist/features/AnalyticsManager.js +224 -0
  54. package/dist/features/AnalyticsManager.js.map +1 -0
  55. package/dist/features/ArchiveManager.d.ts +133 -0
  56. package/dist/features/ArchiveManager.d.ts.map +1 -0
  57. package/dist/features/ArchiveManager.js +282 -0
  58. package/dist/features/ArchiveManager.js.map +1 -0
  59. package/dist/features/CompressionManager.d.ts +119 -0
  60. package/dist/features/CompressionManager.d.ts.map +1 -0
  61. package/dist/features/CompressionManager.js +470 -0
  62. package/dist/features/CompressionManager.js.map +1 -0
  63. package/dist/features/IOManager.d.ts +225 -0
  64. package/dist/features/IOManager.d.ts.map +1 -0
  65. package/dist/features/IOManager.js +1093 -0
  66. package/dist/features/IOManager.js.map +1 -0
  67. package/dist/features/KeywordExtractor.d.ts +61 -0
  68. package/dist/features/KeywordExtractor.d.ts.map +1 -0
  69. package/dist/features/KeywordExtractor.js +127 -0
  70. package/dist/features/KeywordExtractor.js.map +1 -0
  71. package/dist/features/ObservationNormalizer.d.ts +90 -0
  72. package/dist/features/ObservationNormalizer.d.ts.map +1 -0
  73. package/dist/features/ObservationNormalizer.js +194 -0
  74. package/dist/features/ObservationNormalizer.js.map +1 -0
  75. package/dist/features/StreamingExporter.d.ts +128 -0
  76. package/dist/features/StreamingExporter.d.ts.map +1 -0
  77. package/dist/features/StreamingExporter.js +212 -0
  78. package/dist/features/StreamingExporter.js.map +1 -0
  79. package/dist/features/TagManager.d.ts +147 -0
  80. package/dist/features/TagManager.d.ts.map +1 -0
  81. package/dist/features/TagManager.js +211 -0
  82. package/dist/features/TagManager.js.map +1 -0
  83. package/dist/features/index.d.ts +14 -0
  84. package/dist/features/index.d.ts.map +1 -0
  85. package/dist/features/index.js +15 -0
  86. package/dist/features/index.js.map +1 -0
  87. package/dist/index.d.ts +15 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +20 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/search/BM25Search.d.ts +148 -0
  92. package/dist/search/BM25Search.d.ts.map +1 -0
  93. package/dist/search/BM25Search.js +340 -0
  94. package/dist/search/BM25Search.js.map +1 -0
  95. package/dist/search/BasicSearch.d.ts +51 -0
  96. package/dist/search/BasicSearch.d.ts.map +1 -0
  97. package/dist/search/BasicSearch.js +138 -0
  98. package/dist/search/BasicSearch.js.map +1 -0
  99. package/dist/search/BooleanSearch.d.ts +98 -0
  100. package/dist/search/BooleanSearch.d.ts.map +1 -0
  101. package/dist/search/BooleanSearch.js +431 -0
  102. package/dist/search/BooleanSearch.js.map +1 -0
  103. package/dist/search/EarlyTerminationManager.d.ts +140 -0
  104. package/dist/search/EarlyTerminationManager.d.ts.map +1 -0
  105. package/dist/search/EarlyTerminationManager.js +280 -0
  106. package/dist/search/EarlyTerminationManager.js.map +1 -0
  107. package/dist/search/EmbeddingCache.d.ts +175 -0
  108. package/dist/search/EmbeddingCache.d.ts.map +1 -0
  109. package/dist/search/EmbeddingCache.js +247 -0
  110. package/dist/search/EmbeddingCache.js.map +1 -0
  111. package/dist/search/EmbeddingService.d.ts +277 -0
  112. package/dist/search/EmbeddingService.d.ts.map +1 -0
  113. package/dist/search/EmbeddingService.js +531 -0
  114. package/dist/search/EmbeddingService.js.map +1 -0
  115. package/dist/search/FuzzySearch.d.ts +118 -0
  116. package/dist/search/FuzzySearch.d.ts.map +1 -0
  117. package/dist/search/FuzzySearch.js +313 -0
  118. package/dist/search/FuzzySearch.js.map +1 -0
  119. package/dist/search/HybridScorer.d.ts +181 -0
  120. package/dist/search/HybridScorer.d.ts.map +1 -0
  121. package/dist/search/HybridScorer.js +258 -0
  122. package/dist/search/HybridScorer.js.map +1 -0
  123. package/dist/search/HybridSearchManager.d.ts +80 -0
  124. package/dist/search/HybridSearchManager.d.ts.map +1 -0
  125. package/dist/search/HybridSearchManager.js +188 -0
  126. package/dist/search/HybridSearchManager.js.map +1 -0
  127. package/dist/search/IncrementalIndexer.d.ts +201 -0
  128. package/dist/search/IncrementalIndexer.d.ts.map +1 -0
  129. package/dist/search/IncrementalIndexer.js +343 -0
  130. package/dist/search/IncrementalIndexer.js.map +1 -0
  131. package/dist/search/OptimizedInvertedIndex.d.ts +163 -0
  132. package/dist/search/OptimizedInvertedIndex.d.ts.map +1 -0
  133. package/dist/search/OptimizedInvertedIndex.js +359 -0
  134. package/dist/search/OptimizedInvertedIndex.js.map +1 -0
  135. package/dist/search/ParallelSearchExecutor.d.ts +172 -0
  136. package/dist/search/ParallelSearchExecutor.d.ts.map +1 -0
  137. package/dist/search/ParallelSearchExecutor.js +310 -0
  138. package/dist/search/ParallelSearchExecutor.js.map +1 -0
  139. package/dist/search/QuantizedVectorStore.d.ts +171 -0
  140. package/dist/search/QuantizedVectorStore.d.ts.map +1 -0
  141. package/dist/search/QuantizedVectorStore.js +308 -0
  142. package/dist/search/QuantizedVectorStore.js.map +1 -0
  143. package/dist/search/QueryAnalyzer.d.ts +76 -0
  144. package/dist/search/QueryAnalyzer.d.ts.map +1 -0
  145. package/dist/search/QueryAnalyzer.js +228 -0
  146. package/dist/search/QueryAnalyzer.js.map +1 -0
  147. package/dist/search/QueryCostEstimator.d.ts +244 -0
  148. package/dist/search/QueryCostEstimator.d.ts.map +1 -0
  149. package/dist/search/QueryCostEstimator.js +653 -0
  150. package/dist/search/QueryCostEstimator.js.map +1 -0
  151. package/dist/search/QueryPlanCache.d.ts +220 -0
  152. package/dist/search/QueryPlanCache.d.ts.map +1 -0
  153. package/dist/search/QueryPlanCache.js +380 -0
  154. package/dist/search/QueryPlanCache.js.map +1 -0
  155. package/dist/search/QueryPlanner.d.ts +58 -0
  156. package/dist/search/QueryPlanner.d.ts.map +1 -0
  157. package/dist/search/QueryPlanner.js +138 -0
  158. package/dist/search/QueryPlanner.js.map +1 -0
  159. package/dist/search/RankedSearch.d.ts +71 -0
  160. package/dist/search/RankedSearch.d.ts.map +1 -0
  161. package/dist/search/RankedSearch.js +239 -0
  162. package/dist/search/RankedSearch.js.map +1 -0
  163. package/dist/search/ReflectionManager.d.ts +120 -0
  164. package/dist/search/ReflectionManager.d.ts.map +1 -0
  165. package/dist/search/ReflectionManager.js +232 -0
  166. package/dist/search/ReflectionManager.js.map +1 -0
  167. package/dist/search/SavedSearchManager.d.ts +79 -0
  168. package/dist/search/SavedSearchManager.d.ts.map +1 -0
  169. package/dist/search/SavedSearchManager.js +147 -0
  170. package/dist/search/SavedSearchManager.js.map +1 -0
  171. package/dist/search/SearchFilterChain.d.ts +120 -0
  172. package/dist/search/SearchFilterChain.d.ts.map +1 -0
  173. package/dist/search/SearchFilterChain.js +186 -0
  174. package/dist/search/SearchFilterChain.js.map +1 -0
  175. package/dist/search/SearchManager.d.ts +326 -0
  176. package/dist/search/SearchManager.d.ts.map +1 -0
  177. package/dist/search/SearchManager.js +454 -0
  178. package/dist/search/SearchManager.js.map +1 -0
  179. package/dist/search/SearchSuggestions.d.ts +27 -0
  180. package/dist/search/SearchSuggestions.d.ts.map +1 -0
  181. package/dist/search/SearchSuggestions.js +58 -0
  182. package/dist/search/SearchSuggestions.js.map +1 -0
  183. package/dist/search/SemanticSearch.d.ts +149 -0
  184. package/dist/search/SemanticSearch.d.ts.map +1 -0
  185. package/dist/search/SemanticSearch.js +324 -0
  186. package/dist/search/SemanticSearch.js.map +1 -0
  187. package/dist/search/SymbolicSearch.d.ts +61 -0
  188. package/dist/search/SymbolicSearch.d.ts.map +1 -0
  189. package/dist/search/SymbolicSearch.js +164 -0
  190. package/dist/search/SymbolicSearch.js.map +1 -0
  191. package/dist/search/TFIDFEventSync.d.ts +85 -0
  192. package/dist/search/TFIDFEventSync.d.ts.map +1 -0
  193. package/dist/search/TFIDFEventSync.js +134 -0
  194. package/dist/search/TFIDFEventSync.js.map +1 -0
  195. package/dist/search/TFIDFIndexManager.d.ts +151 -0
  196. package/dist/search/TFIDFIndexManager.d.ts.map +1 -0
  197. package/dist/search/TFIDFIndexManager.js +433 -0
  198. package/dist/search/TFIDFIndexManager.js.map +1 -0
  199. package/dist/search/VectorStore.d.ts +235 -0
  200. package/dist/search/VectorStore.d.ts.map +1 -0
  201. package/dist/search/VectorStore.js +312 -0
  202. package/dist/search/VectorStore.js.map +1 -0
  203. package/dist/search/index.d.ts +35 -0
  204. package/dist/search/index.d.ts.map +1 -0
  205. package/dist/search/index.js +53 -0
  206. package/dist/search/index.js.map +1 -0
  207. package/dist/types/index.d.ts +13 -0
  208. package/dist/types/index.d.ts.map +1 -0
  209. package/dist/types/index.js +13 -0
  210. package/dist/types/index.js.map +1 -0
  211. package/dist/types/types.d.ts +1811 -0
  212. package/dist/types/types.d.ts.map +1 -0
  213. package/dist/types/types.js +10 -0
  214. package/dist/types/types.js.map +1 -0
  215. package/dist/utils/BatchProcessor.d.ts +271 -0
  216. package/dist/utils/BatchProcessor.d.ts.map +1 -0
  217. package/dist/utils/BatchProcessor.js +377 -0
  218. package/dist/utils/BatchProcessor.js.map +1 -0
  219. package/dist/utils/MemoryMonitor.d.ts +176 -0
  220. package/dist/utils/MemoryMonitor.d.ts.map +1 -0
  221. package/dist/utils/MemoryMonitor.js +306 -0
  222. package/dist/utils/MemoryMonitor.js.map +1 -0
  223. package/dist/utils/WorkerPoolManager.d.ts +233 -0
  224. package/dist/utils/WorkerPoolManager.d.ts.map +1 -0
  225. package/dist/utils/WorkerPoolManager.js +421 -0
  226. package/dist/utils/WorkerPoolManager.js.map +1 -0
  227. package/dist/utils/compressedCache.d.ts +221 -0
  228. package/dist/utils/compressedCache.d.ts.map +1 -0
  229. package/dist/utils/compressedCache.js +349 -0
  230. package/dist/utils/compressedCache.js.map +1 -0
  231. package/dist/utils/compressionUtil.d.ts +214 -0
  232. package/dist/utils/compressionUtil.d.ts.map +1 -0
  233. package/dist/utils/compressionUtil.js +248 -0
  234. package/dist/utils/compressionUtil.js.map +1 -0
  235. package/dist/utils/constants.d.ts +245 -0
  236. package/dist/utils/constants.d.ts.map +1 -0
  237. package/dist/utils/constants.js +253 -0
  238. package/dist/utils/constants.js.map +1 -0
  239. package/dist/utils/entityUtils.d.ts +379 -0
  240. package/dist/utils/entityUtils.d.ts.map +1 -0
  241. package/dist/utils/entityUtils.js +649 -0
  242. package/dist/utils/entityUtils.js.map +1 -0
  243. package/dist/utils/errors.d.ts +95 -0
  244. package/dist/utils/errors.d.ts.map +1 -0
  245. package/dist/utils/errors.js +146 -0
  246. package/dist/utils/errors.js.map +1 -0
  247. package/dist/utils/formatters.d.ts +145 -0
  248. package/dist/utils/formatters.d.ts.map +1 -0
  249. package/dist/utils/formatters.js +133 -0
  250. package/dist/utils/formatters.js.map +1 -0
  251. package/dist/utils/index.d.ts +26 -0
  252. package/dist/utils/index.d.ts.map +1 -0
  253. package/dist/utils/index.js +88 -0
  254. package/dist/utils/index.js.map +1 -0
  255. package/dist/utils/indexes.d.ts +270 -0
  256. package/dist/utils/indexes.d.ts.map +1 -0
  257. package/dist/utils/indexes.js +527 -0
  258. package/dist/utils/indexes.js.map +1 -0
  259. package/dist/utils/logger.d.ts +31 -0
  260. package/dist/utils/logger.d.ts.map +1 -0
  261. package/dist/utils/logger.js +41 -0
  262. package/dist/utils/logger.js.map +1 -0
  263. package/dist/utils/operationUtils.d.ts +124 -0
  264. package/dist/utils/operationUtils.d.ts.map +1 -0
  265. package/dist/utils/operationUtils.js +176 -0
  266. package/dist/utils/operationUtils.js.map +1 -0
  267. package/dist/utils/parallelUtils.d.ts +76 -0
  268. package/dist/utils/parallelUtils.d.ts.map +1 -0
  269. package/dist/utils/parallelUtils.js +192 -0
  270. package/dist/utils/parallelUtils.js.map +1 -0
  271. package/dist/utils/schemas.d.ts +556 -0
  272. package/dist/utils/schemas.d.ts.map +1 -0
  273. package/dist/utils/schemas.js +485 -0
  274. package/dist/utils/schemas.js.map +1 -0
  275. package/dist/utils/searchAlgorithms.d.ts +99 -0
  276. package/dist/utils/searchAlgorithms.d.ts.map +1 -0
  277. package/dist/utils/searchAlgorithms.js +168 -0
  278. package/dist/utils/searchAlgorithms.js.map +1 -0
  279. package/dist/utils/searchCache.d.ts +108 -0
  280. package/dist/utils/searchCache.d.ts.map +1 -0
  281. package/dist/utils/searchCache.js +210 -0
  282. package/dist/utils/searchCache.js.map +1 -0
  283. package/dist/utils/taskScheduler.d.ts +294 -0
  284. package/dist/utils/taskScheduler.d.ts.map +1 -0
  285. package/dist/utils/taskScheduler.js +487 -0
  286. package/dist/utils/taskScheduler.js.map +1 -0
  287. package/dist/workers/index.d.ts +12 -0
  288. package/dist/workers/index.d.ts.map +1 -0
  289. package/dist/workers/index.js +10 -0
  290. package/dist/workers/index.js.map +1 -0
  291. package/dist/workers/levenshteinWorker.d.ts +60 -0
  292. package/dist/workers/levenshteinWorker.d.ts.map +1 -0
  293. package/dist/workers/levenshteinWorker.js +99 -0
  294. package/dist/workers/levenshteinWorker.js.map +1 -0
  295. package/package.json +69 -0
@@ -0,0 +1,258 @@
1
+ /**
2
+ * Hybrid Scorer
3
+ *
4
+ * Combines semantic, lexical, and symbolic search scores with
5
+ * min-max normalization and configurable weights.
6
+ *
7
+ * Phase 12 Sprint 3: Search Algorithm Optimization
8
+ *
9
+ * @module search/HybridScorer
10
+ */
11
+ /**
12
+ * Default weights for hybrid search.
13
+ */
14
+ export const DEFAULT_SCORER_WEIGHTS = {
15
+ semantic: 0.4,
16
+ lexical: 0.4,
17
+ symbolic: 0.2,
18
+ };
19
+ /**
20
+ * HybridScorer combines multiple search signals using min-max normalization.
21
+ *
22
+ * Features:
23
+ * 1. Min-max normalization brings all scores to 0-1 range
24
+ * 2. Configurable weights for each layer
25
+ * 3. Handles missing layers gracefully (redistributes weights)
26
+ * 4. Tracks which layers contributed to each result
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const scorer = new HybridScorer({
31
+ * weights: { semantic: 0.5, lexical: 0.3, symbolic: 0.2 }
32
+ * });
33
+ *
34
+ * const results = scorer.combine(
35
+ * semanticResults,
36
+ * lexicalResults,
37
+ * symbolicResults,
38
+ * entityMap
39
+ * );
40
+ * ```
41
+ */
42
+ export class HybridScorer {
43
+ weights;
44
+ minScore;
45
+ normalizeWeights;
46
+ constructor(options = {}) {
47
+ this.weights = {
48
+ ...DEFAULT_SCORER_WEIGHTS,
49
+ ...options.weights,
50
+ };
51
+ this.minScore = options.minScore ?? 0;
52
+ this.normalizeWeights = options.normalizeWeights ?? true;
53
+ }
54
+ /**
55
+ * Get current weights configuration.
56
+ */
57
+ getWeights() {
58
+ return { ...this.weights };
59
+ }
60
+ /**
61
+ * Update weights configuration.
62
+ */
63
+ setWeights(weights) {
64
+ this.weights = { ...this.weights, ...weights };
65
+ }
66
+ /**
67
+ * Perform min-max normalization on scores.
68
+ *
69
+ * Formula: normalized = (x - min) / (max - min)
70
+ *
71
+ * @param scores - Map of entity name to raw score
72
+ * @returns Map of entity name to normalized score (0-1)
73
+ */
74
+ minMaxNormalize(scores) {
75
+ if (scores.size === 0) {
76
+ return new Map();
77
+ }
78
+ // Find min and max
79
+ let min = Infinity;
80
+ let max = -Infinity;
81
+ for (const score of scores.values()) {
82
+ if (score < min)
83
+ min = score;
84
+ if (score > max)
85
+ max = score;
86
+ }
87
+ // Handle edge case where all scores are the same
88
+ if (max === min) {
89
+ const normalized = new Map();
90
+ for (const name of scores.keys()) {
91
+ // If all scores are zero, keep them zero; otherwise normalize to 1
92
+ normalized.set(name, max === 0 ? 0 : 1);
93
+ }
94
+ return normalized;
95
+ }
96
+ // Normalize
97
+ const range = max - min;
98
+ const normalized = new Map();
99
+ for (const [name, score] of scores) {
100
+ normalized.set(name, (score - min) / range);
101
+ }
102
+ return normalized;
103
+ }
104
+ /**
105
+ * Combine results from all three search layers.
106
+ *
107
+ * @param semanticResults - Results from semantic search
108
+ * @param lexicalResults - Results from lexical search
109
+ * @param symbolicResults - Results from symbolic search
110
+ * @param entityMap - Map of entity names to Entity objects
111
+ * @returns Array of combined results sorted by score
112
+ */
113
+ combine(semanticResults, lexicalResults, symbolicResults, entityMap) {
114
+ // Build score maps
115
+ const semanticScores = new Map();
116
+ for (const result of semanticResults) {
117
+ semanticScores.set(result.entityName, result.similarity);
118
+ }
119
+ const lexicalScores = new Map();
120
+ for (const result of lexicalResults) {
121
+ lexicalScores.set(result.entityName, result.score);
122
+ }
123
+ const symbolicScores = new Map();
124
+ for (const result of symbolicResults) {
125
+ symbolicScores.set(result.entityName, result.score);
126
+ }
127
+ // Normalize scores
128
+ const normalizedSemantic = this.minMaxNormalize(semanticScores);
129
+ const normalizedLexical = this.minMaxNormalize(lexicalScores);
130
+ const normalizedSymbolic = this.minMaxNormalize(symbolicScores);
131
+ // Calculate effective weights
132
+ let effectiveWeights = { ...this.weights };
133
+ if (this.normalizeWeights) {
134
+ effectiveWeights = this.getNormalizedWeights(semanticResults.length > 0, lexicalResults.length > 0, symbolicResults.length > 0);
135
+ }
136
+ // Collect all unique entity names
137
+ const allNames = new Set([
138
+ ...normalizedSemantic.keys(),
139
+ ...normalizedLexical.keys(),
140
+ ...normalizedSymbolic.keys(),
141
+ ]);
142
+ // Calculate combined scores
143
+ const results = [];
144
+ for (const entityName of allNames) {
145
+ const entity = entityMap.get(entityName);
146
+ if (!entity)
147
+ continue;
148
+ const semanticScore = normalizedSemantic.get(entityName) ?? 0;
149
+ const lexicalScore = normalizedLexical.get(entityName) ?? 0;
150
+ const symbolicScore = normalizedSymbolic.get(entityName) ?? 0;
151
+ // Calculate weighted combination
152
+ const combined = semanticScore * effectiveWeights.semantic +
153
+ lexicalScore * effectiveWeights.lexical +
154
+ symbolicScore * effectiveWeights.symbolic;
155
+ // Track matched layers
156
+ const matchedLayers = [];
157
+ const rawScores = {};
158
+ if (semanticScores.has(entityName)) {
159
+ matchedLayers.push('semantic');
160
+ rawScores.semantic = semanticScores.get(entityName);
161
+ }
162
+ if (lexicalScores.has(entityName)) {
163
+ matchedLayers.push('lexical');
164
+ rawScores.lexical = lexicalScores.get(entityName);
165
+ }
166
+ if (symbolicScores.has(entityName)) {
167
+ matchedLayers.push('symbolic');
168
+ rawScores.symbolic = symbolicScores.get(entityName);
169
+ }
170
+ // Skip if below minimum score or no layers matched
171
+ if (combined < this.minScore || matchedLayers.length === 0) {
172
+ continue;
173
+ }
174
+ results.push({
175
+ entityName,
176
+ entity,
177
+ scores: {
178
+ semantic: semanticScore,
179
+ lexical: lexicalScore,
180
+ symbolic: symbolicScore,
181
+ combined,
182
+ },
183
+ matchedLayers,
184
+ rawScores,
185
+ });
186
+ }
187
+ // Sort by combined score descending
188
+ return results.sort((a, b) => b.scores.combined - a.scores.combined);
189
+ }
190
+ /**
191
+ * Get weights normalized to sum to 1, redistributing for missing layers.
192
+ *
193
+ * @param hasSemantic - Whether semantic results are available
194
+ * @param hasLexical - Whether lexical results are available
195
+ * @param hasSymbolic - Whether symbolic results are available
196
+ * @returns Normalized weights
197
+ */
198
+ getNormalizedWeights(hasSemantic, hasLexical, hasSymbolic) {
199
+ let totalActiveWeight = 0;
200
+ if (hasSemantic)
201
+ totalActiveWeight += this.weights.semantic;
202
+ if (hasLexical)
203
+ totalActiveWeight += this.weights.lexical;
204
+ if (hasSymbolic)
205
+ totalActiveWeight += this.weights.symbolic;
206
+ // If no layers are active, return zero weights
207
+ if (totalActiveWeight === 0) {
208
+ return { semantic: 0, lexical: 0, symbolic: 0 };
209
+ }
210
+ // Normalize active weights to sum to 1
211
+ return {
212
+ semantic: hasSemantic ? this.weights.semantic / totalActiveWeight : 0,
213
+ lexical: hasLexical ? this.weights.lexical / totalActiveWeight : 0,
214
+ symbolic: hasSymbolic ? this.weights.symbolic / totalActiveWeight : 0,
215
+ };
216
+ }
217
+ /**
218
+ * Combine scores from maps directly (alternative interface).
219
+ *
220
+ * @param semanticScores - Map of entity name to semantic score
221
+ * @param lexicalScores - Map of entity name to lexical score
222
+ * @param symbolicScores - Map of entity name to symbolic score
223
+ * @param entityMap - Map of entity names to Entity objects
224
+ * @returns Array of combined results sorted by score
225
+ */
226
+ combineFromMaps(semanticScores, lexicalScores, symbolicScores, entityMap) {
227
+ // Convert maps to result arrays
228
+ const semanticResults = [];
229
+ for (const [entityName, similarity] of semanticScores) {
230
+ semanticResults.push({ entityName, similarity });
231
+ }
232
+ const lexicalResults = [];
233
+ for (const [entityName, score] of lexicalScores) {
234
+ lexicalResults.push({ entityName, score });
235
+ }
236
+ const symbolicResults = [];
237
+ for (const [entityName, score] of symbolicScores) {
238
+ symbolicResults.push({ entityName, score });
239
+ }
240
+ return this.combine(semanticResults, lexicalResults, symbolicResults, entityMap);
241
+ }
242
+ /**
243
+ * Calculate combined score for a single entity.
244
+ *
245
+ * Useful for scoring individual results without full normalization.
246
+ *
247
+ * @param semanticScore - Normalized semantic score (0-1)
248
+ * @param lexicalScore - Normalized lexical score (0-1)
249
+ * @param symbolicScore - Normalized symbolic score (0-1)
250
+ * @returns Combined weighted score
251
+ */
252
+ calculateScore(semanticScore, lexicalScore, symbolicScore) {
253
+ return (semanticScore * this.weights.semantic +
254
+ lexicalScore * this.weights.lexical +
255
+ symbolicScore * this.weights.symbolic);
256
+ }
257
+ }
258
+ //# sourceMappingURL=HybridScorer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HybridScorer.js","sourceRoot":"","sources":["../../src/search/HybridScorer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Hybrid Search Manager
3
+ *
4
+ * Phase 11: Orchestrates three-layer hybrid search combining
5
+ * semantic, lexical, and symbolic signals.
6
+ *
7
+ * @module search/HybridSearchManager
8
+ */
9
+ import type { HybridSearchOptions, HybridSearchResult, ReadonlyKnowledgeGraph } from '../types/index.js';
10
+ import type { SemanticSearch } from './SemanticSearch.js';
11
+ import type { RankedSearch } from './RankedSearch.js';
12
+ import { SymbolicSearch } from './SymbolicSearch.js';
13
+ /**
14
+ * Default weights for hybrid search layers.
15
+ */
16
+ export declare const DEFAULT_HYBRID_WEIGHTS: {
17
+ semantic: number;
18
+ lexical: number;
19
+ symbolic: number;
20
+ };
21
+ /**
22
+ * Hybrid Search Manager
23
+ *
24
+ * Combines three search layers:
25
+ * 1. Semantic: Vector similarity via embeddings
26
+ * 2. Lexical: Keyword matching via TF-IDF/BM25
27
+ * 3. Symbolic: Structured metadata filtering
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const hybrid = new HybridSearchManager(semanticSearch, rankedSearch);
32
+ * const results = await hybrid.search(graph, 'machine learning', {
33
+ * semanticWeight: 0.5,
34
+ * lexicalWeight: 0.3,
35
+ * symbolicWeight: 0.2,
36
+ * symbolic: { tags: ['ai'] }
37
+ * });
38
+ * ```
39
+ */
40
+ export declare class HybridSearchManager {
41
+ private semanticSearch;
42
+ private rankedSearch;
43
+ private symbolicSearch;
44
+ constructor(semanticSearch: SemanticSearch | null, rankedSearch: RankedSearch);
45
+ /**
46
+ * Perform hybrid search combining all three layers.
47
+ *
48
+ * @param graph - Knowledge graph to search
49
+ * @param query - Search query text
50
+ * @param options - Hybrid search options with weights
51
+ * @returns Combined and ranked results
52
+ */
53
+ search(graph: ReadonlyKnowledgeGraph, query: string, options?: Partial<HybridSearchOptions>): Promise<HybridSearchResult[]>;
54
+ /**
55
+ * Execute semantic search layer.
56
+ */
57
+ private executeSemanticSearch;
58
+ /**
59
+ * Execute lexical search layer (TF-IDF/BM25).
60
+ */
61
+ private executeLexicalSearch;
62
+ /**
63
+ * Execute symbolic search layer.
64
+ */
65
+ private executeSymbolicSearch;
66
+ /**
67
+ * Merge results from all three layers.
68
+ */
69
+ private mergeResults;
70
+ /**
71
+ * Search with full entity resolution.
72
+ * Alias for search() since we now always resolve entities.
73
+ */
74
+ searchWithEntities(graph: ReadonlyKnowledgeGraph, query: string, options?: Partial<HybridSearchOptions>): Promise<HybridSearchResult[]>;
75
+ /**
76
+ * Get the symbolic search instance for direct access.
77
+ */
78
+ getSymbolicSearch(): SymbolicSearch;
79
+ }
80
+ //# sourceMappingURL=HybridSearchManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HybridSearchManager.d.ts","sourceRoot":"","sources":["../../src/search/HybridSearchManager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAEV,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EAEvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGrD;;GAEG;AACH,eAAO,MAAM,sBAAsB;;;;CAIlC,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,mBAAmB;IAI5B,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,YAAY;IAJtB,OAAO,CAAC,cAAc,CAAiB;gBAG7B,cAAc,EAAE,cAAc,GAAG,IAAI,EACrC,YAAY,EAAE,YAAY;IAKpC;;;;;;;OAOG;IACG,MAAM,CACV,KAAK,EAAE,sBAAsB,EAC7B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,OAAO,CAAC,mBAAmB,CAAM,GACzC,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAuChC;;OAEG;YACW,qBAAqB;IA8BnC;;OAEG;YACW,oBAAoB;IA4BlC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAsB7B;;OAEG;IACH,OAAO,CAAC,YAAY;IAkDpB;;;OAGG;IACG,kBAAkB,CACtB,KAAK,EAAE,sBAAsB,EAC7B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,OAAO,CAAC,mBAAmB,CAAM,GACzC,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAIhC;;OAEG;IACH,iBAAiB,IAAI,cAAc;CAGpC"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Hybrid Search Manager
3
+ *
4
+ * Phase 11: Orchestrates three-layer hybrid search combining
5
+ * semantic, lexical, and symbolic signals.
6
+ *
7
+ * @module search/HybridSearchManager
8
+ */
9
+ import { SymbolicSearch } from './SymbolicSearch.js';
10
+ import { SEMANTIC_SEARCH_LIMITS } from '../utils/constants.js';
11
+ /**
12
+ * Default weights for hybrid search layers.
13
+ */
14
+ export const DEFAULT_HYBRID_WEIGHTS = {
15
+ semantic: 0.5,
16
+ lexical: 0.3,
17
+ symbolic: 0.2,
18
+ };
19
+ /**
20
+ * Hybrid Search Manager
21
+ *
22
+ * Combines three search layers:
23
+ * 1. Semantic: Vector similarity via embeddings
24
+ * 2. Lexical: Keyword matching via TF-IDF/BM25
25
+ * 3. Symbolic: Structured metadata filtering
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const hybrid = new HybridSearchManager(semanticSearch, rankedSearch);
30
+ * const results = await hybrid.search(graph, 'machine learning', {
31
+ * semanticWeight: 0.5,
32
+ * lexicalWeight: 0.3,
33
+ * symbolicWeight: 0.2,
34
+ * symbolic: { tags: ['ai'] }
35
+ * });
36
+ * ```
37
+ */
38
+ export class HybridSearchManager {
39
+ semanticSearch;
40
+ rankedSearch;
41
+ symbolicSearch;
42
+ constructor(semanticSearch, rankedSearch) {
43
+ this.semanticSearch = semanticSearch;
44
+ this.rankedSearch = rankedSearch;
45
+ this.symbolicSearch = new SymbolicSearch();
46
+ }
47
+ /**
48
+ * Perform hybrid search combining all three layers.
49
+ *
50
+ * @param graph - Knowledge graph to search
51
+ * @param query - Search query text
52
+ * @param options - Hybrid search options with weights
53
+ * @returns Combined and ranked results
54
+ */
55
+ async search(graph, query, options = {}) {
56
+ const { semanticWeight = DEFAULT_HYBRID_WEIGHTS.semantic, lexicalWeight = DEFAULT_HYBRID_WEIGHTS.lexical, symbolicWeight = DEFAULT_HYBRID_WEIGHTS.symbolic, semantic = {}, lexical = {}, symbolic = {}, limit = SEMANTIC_SEARCH_LIMITS.DEFAULT_LIMIT, } = options;
57
+ // Normalize weights
58
+ const totalWeight = semanticWeight + lexicalWeight + symbolicWeight;
59
+ const normSemantic = semanticWeight / totalWeight;
60
+ const normLexical = lexicalWeight / totalWeight;
61
+ const normSymbolic = symbolicWeight / totalWeight;
62
+ // Execute searches in parallel
63
+ const [semanticResults, lexicalResults, symbolicResults] = await Promise.all([
64
+ this.executeSemanticSearch(graph, query, semantic, limit * 2),
65
+ this.executeLexicalSearch(query, lexical, limit * 2),
66
+ this.executeSymbolicSearch(graph.entities, symbolic),
67
+ ]);
68
+ // Merge results
69
+ const merged = this.mergeResults(graph.entities, semanticResults, lexicalResults, symbolicResults, { semantic: normSemantic, lexical: normLexical, symbolic: normSymbolic });
70
+ // Sort by combined score and limit
71
+ return merged
72
+ .sort((a, b) => b.scores.combined - a.scores.combined)
73
+ .slice(0, limit);
74
+ }
75
+ /**
76
+ * Execute semantic search layer.
77
+ */
78
+ async executeSemanticSearch(graph, query, options, limit) {
79
+ const results = new Map();
80
+ if (!this.semanticSearch) {
81
+ return results; // Semantic search not available
82
+ }
83
+ try {
84
+ const semanticResults = await this.semanticSearch.search(graph, query, options.topK ?? limit, options.minSimilarity ?? 0);
85
+ for (const result of semanticResults) {
86
+ results.set(result.entity.name, result.similarity);
87
+ }
88
+ }
89
+ catch {
90
+ // Semantic search may fail if not indexed
91
+ }
92
+ return results;
93
+ }
94
+ /**
95
+ * Execute lexical search layer (TF-IDF/BM25).
96
+ */
97
+ async executeLexicalSearch(query, _options, limit) {
98
+ const results = new Map();
99
+ try {
100
+ const lexicalResults = await this.rankedSearch.searchNodesRanked(query, undefined, // tags
101
+ undefined, // minImportance
102
+ undefined, // maxImportance
103
+ limit);
104
+ // Normalize scores to 0-1 range
105
+ const maxScore = Math.max(...lexicalResults.map(r => r.score), 1);
106
+ for (const result of lexicalResults) {
107
+ results.set(result.entity.name, result.score / maxScore);
108
+ }
109
+ }
110
+ catch {
111
+ // Lexical search may fail
112
+ }
113
+ return results;
114
+ }
115
+ /**
116
+ * Execute symbolic search layer.
117
+ */
118
+ executeSymbolicSearch(entities, filters) {
119
+ const results = new Map();
120
+ if (!filters || Object.keys(filters).length === 0) {
121
+ // No symbolic filters, give all entities base score
122
+ for (const entity of entities) {
123
+ results.set(entity.name, 0.5);
124
+ }
125
+ return results;
126
+ }
127
+ const symbolicResults = this.symbolicSearch.search(entities, filters);
128
+ for (const result of symbolicResults) {
129
+ results.set(result.entity.name, result.score);
130
+ }
131
+ return results;
132
+ }
133
+ /**
134
+ * Merge results from all three layers.
135
+ */
136
+ mergeResults(entities, semanticScores, lexicalScores, symbolicScores, weights) {
137
+ // Collect all unique entity names that have at least one non-zero score
138
+ const allNames = new Set([
139
+ ...semanticScores.keys(),
140
+ ...lexicalScores.keys(),
141
+ ...symbolicScores.keys(),
142
+ ]);
143
+ // Create entity lookup map
144
+ const entityMap = new Map(entities.map(e => [e.name, e]));
145
+ const results = [];
146
+ for (const name of allNames) {
147
+ const entity = entityMap.get(name);
148
+ if (!entity)
149
+ continue;
150
+ const semantic = semanticScores.get(name) ?? 0;
151
+ const lexical = lexicalScores.get(name) ?? 0;
152
+ const symbolic = symbolicScores.get(name) ?? 0;
153
+ const combined = semantic * weights.semantic +
154
+ lexical * weights.lexical +
155
+ symbolic * weights.symbolic;
156
+ const matchedLayers = [];
157
+ if (semantic > 0)
158
+ matchedLayers.push('semantic');
159
+ if (lexical > 0)
160
+ matchedLayers.push('lexical');
161
+ if (symbolic > 0)
162
+ matchedLayers.push('symbolic');
163
+ // Skip if no layers matched meaningfully
164
+ if (matchedLayers.length === 0)
165
+ continue;
166
+ results.push({
167
+ entity,
168
+ scores: { semantic, lexical, symbolic, combined },
169
+ matchedLayers,
170
+ });
171
+ }
172
+ return results;
173
+ }
174
+ /**
175
+ * Search with full entity resolution.
176
+ * Alias for search() since we now always resolve entities.
177
+ */
178
+ async searchWithEntities(graph, query, options = {}) {
179
+ return this.search(graph, query, options);
180
+ }
181
+ /**
182
+ * Get the symbolic search instance for direct access.
183
+ */
184
+ getSymbolicSearch() {
185
+ return this.symbolicSearch;
186
+ }
187
+ }
188
+ //# sourceMappingURL=HybridSearchManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HybridSearchManager.js","sourceRoot":"","sources":["../../src/search/HybridSearchManager.ts"],"names":[],"mappings":"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"}