@danielsimonjr/memory-mcp 9.8.3 → 9.9.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 +360 -1829
- package/dist/core/ManagerContext.d.ts +4 -0
- package/dist/core/ManagerContext.d.ts.map +1 -1
- package/dist/core/ManagerContext.js +6 -0
- package/dist/features/KeywordExtractor.d.ts +61 -0
- package/dist/features/KeywordExtractor.d.ts.map +1 -0
- package/dist/features/KeywordExtractor.js +126 -0
- package/dist/features/ObservationNormalizer.d.ts +90 -0
- package/dist/features/ObservationNormalizer.d.ts.map +1 -0
- package/dist/features/ObservationNormalizer.js +193 -0
- package/dist/features/index.d.ts +2 -0
- package/dist/features/index.d.ts.map +1 -1
- package/dist/features/index.js +3 -0
- package/dist/search/HybridSearchManager.d.ts +80 -0
- package/dist/search/HybridSearchManager.d.ts.map +1 -0
- package/dist/search/HybridSearchManager.js +187 -0
- package/dist/search/QueryAnalyzer.d.ts +76 -0
- package/dist/search/QueryAnalyzer.d.ts.map +1 -0
- package/dist/search/QueryAnalyzer.js +227 -0
- package/dist/search/QueryPlanner.d.ts +58 -0
- package/dist/search/QueryPlanner.d.ts.map +1 -0
- package/dist/search/QueryPlanner.js +137 -0
- package/dist/search/ReflectionManager.d.ts +71 -0
- package/dist/search/ReflectionManager.d.ts.map +1 -0
- package/dist/search/ReflectionManager.js +124 -0
- package/dist/search/SymbolicSearch.d.ts +61 -0
- package/dist/search/SymbolicSearch.d.ts.map +1 -0
- package/dist/search/SymbolicSearch.js +163 -0
- package/dist/search/index.d.ts +5 -0
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +8 -0
- package/dist/server/toolDefinitions.d.ts +1 -1
- package/dist/server/toolDefinitions.d.ts.map +1 -1
- package/dist/server/toolDefinitions.js +141 -1
- package/dist/server/toolHandlers.d.ts.map +1 -1
- package/dist/server/toolHandlers.js +167 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types.d.ts +118 -0
- package/dist/types/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -14,6 +14,7 @@ import { ObservationManager } from './ObservationManager.js';
|
|
|
14
14
|
import { HierarchyManager } from './HierarchyManager.js';
|
|
15
15
|
import { GraphTraversal } from './GraphTraversal.js';
|
|
16
16
|
import { SearchManager } from '../search/SearchManager.js';
|
|
17
|
+
import { RankedSearch } from '../search/RankedSearch.js';
|
|
17
18
|
import { SemanticSearch } from '../search/index.js';
|
|
18
19
|
import { IOManager } from '../features/IOManager.js';
|
|
19
20
|
import { TagManager } from '../features/TagManager.js';
|
|
@@ -35,6 +36,7 @@ export declare class ManagerContext {
|
|
|
35
36
|
private _graphTraversal?;
|
|
36
37
|
private _searchManager?;
|
|
37
38
|
private _semanticSearch?;
|
|
39
|
+
private _rankedSearch?;
|
|
38
40
|
private _ioManager?;
|
|
39
41
|
private _tagManager?;
|
|
40
42
|
private _analyticsManager?;
|
|
@@ -58,6 +60,8 @@ export declare class ManagerContext {
|
|
|
58
60
|
* Returns null if no embedding provider is configured.
|
|
59
61
|
*/
|
|
60
62
|
get semanticSearch(): SemanticSearch | null;
|
|
63
|
+
/** RankedSearch - Phase 11: TF-IDF/BM25 ranked search for hybrid search */
|
|
64
|
+
get rankedSearch(): RankedSearch;
|
|
61
65
|
/** IOManager - Import, export, and backup operations */
|
|
62
66
|
get ioManager(): IOManager;
|
|
63
67
|
/** TagManager - Tag alias management */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ManagerContext.d.ts","sourceRoot":"","sources":["../../src/core/ManagerContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAA6C,MAAM,oBAAoB,CAAC;AAC/F,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAG/D;;;GAGG;AACH,qBAAa,cAAc;IAGzB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAG5C,OAAO,CAAC,cAAc,CAAC,CAAgB;IACvC,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAC3C,OAAO,CAAC,mBAAmB,CAAC,CAAqB;IACjD,OAAO,CAAC,iBAAiB,CAAC,CAAmB;IAC7C,OAAO,CAAC,eAAe,CAAC,CAAiB;IACzC,OAAO,CAAC,cAAc,CAAC,CAAgB;IACvC,OAAO,CAAC,eAAe,CAAC,CAAwB;IAChD,OAAO,CAAC,UAAU,CAAC,CAAY;IAC/B,OAAO,CAAC,WAAW,CAAC,CAAa;IACjC,OAAO,CAAC,iBAAiB,CAAC,CAAmB;IAC7C,OAAO,CAAC,mBAAmB,CAAC,CAAqB;IACjD,OAAO,CAAC,eAAe,CAAC,CAAiB;gBAE7B,cAAc,EAAE,MAAM;IAclC,qDAAqD;IACrD,IAAI,aAAa,IAAI,aAAa,CAEjC;IAED,sCAAsC;IACtC,IAAI,eAAe,IAAI,eAAe,CAErC;IAED,4CAA4C;IAC5C,IAAI,kBAAkB,IAAI,kBAAkB,CAE3C;IAED,qDAAqD;IACrD,IAAI,gBAAgB,IAAI,gBAAgB,CAEvC;IAED,sEAAsE;IACtE,IAAI,cAAc,IAAI,cAAc,CAEnC;IAED,4CAA4C;IAC5C,IAAI,aAAa,IAAI,aAAa,CAEjC;IAED;;;OAGG;IACH,IAAI,cAAc,IAAI,cAAc,GAAG,IAAI,CAa1C;IAED,wDAAwD;IACxD,IAAI,SAAS,IAAI,SAAS,CAEzB;IAED,wCAAwC;IACxC,IAAI,UAAU,IAAI,UAAU,CAE3B;IAED,yDAAyD;IACzD,IAAI,gBAAgB,IAAI,gBAAgB,CAEvC;IAED,kEAAkE;IAClE,IAAI,kBAAkB,IAAI,kBAAkB,CAE3C;IAED,kDAAkD;IAClD,IAAI,cAAc,IAAI,cAAc,CAEnC;CACF"}
|
|
1
|
+
{"version":3,"file":"ManagerContext.d.ts","sourceRoot":"","sources":["../../src/core/ManagerContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,cAAc,EAA6C,MAAM,oBAAoB,CAAC;AAC/F,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAG/D;;;GAGG;AACH,qBAAa,cAAc;IAGzB,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAS;IAC/C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAG5C,OAAO,CAAC,cAAc,CAAC,CAAgB;IACvC,OAAO,CAAC,gBAAgB,CAAC,CAAkB;IAC3C,OAAO,CAAC,mBAAmB,CAAC,CAAqB;IACjD,OAAO,CAAC,iBAAiB,CAAC,CAAmB;IAC7C,OAAO,CAAC,eAAe,CAAC,CAAiB;IACzC,OAAO,CAAC,cAAc,CAAC,CAAgB;IACvC,OAAO,CAAC,eAAe,CAAC,CAAwB;IAChD,OAAO,CAAC,aAAa,CAAC,CAAe;IACrC,OAAO,CAAC,UAAU,CAAC,CAAY;IAC/B,OAAO,CAAC,WAAW,CAAC,CAAa;IACjC,OAAO,CAAC,iBAAiB,CAAC,CAAmB;IAC7C,OAAO,CAAC,mBAAmB,CAAC,CAAqB;IACjD,OAAO,CAAC,eAAe,CAAC,CAAiB;gBAE7B,cAAc,EAAE,MAAM;IAclC,qDAAqD;IACrD,IAAI,aAAa,IAAI,aAAa,CAEjC;IAED,sCAAsC;IACtC,IAAI,eAAe,IAAI,eAAe,CAErC;IAED,4CAA4C;IAC5C,IAAI,kBAAkB,IAAI,kBAAkB,CAE3C;IAED,qDAAqD;IACrD,IAAI,gBAAgB,IAAI,gBAAgB,CAEvC;IAED,sEAAsE;IACtE,IAAI,cAAc,IAAI,cAAc,CAEnC;IAED,4CAA4C;IAC5C,IAAI,aAAa,IAAI,aAAa,CAEjC;IAED;;;OAGG;IACH,IAAI,cAAc,IAAI,cAAc,GAAG,IAAI,CAa1C;IAED,2EAA2E;IAC3E,IAAI,YAAY,IAAI,YAAY,CAE/B;IAED,wDAAwD;IACxD,IAAI,SAAS,IAAI,SAAS,CAEzB;IAED,wCAAwC;IACxC,IAAI,UAAU,IAAI,UAAU,CAE3B;IAED,yDAAyD;IACzD,IAAI,gBAAgB,IAAI,gBAAgB,CAEvC;IAED,kEAAkE;IAClE,IAAI,kBAAkB,IAAI,kBAAkB,CAE3C;IAED,kDAAkD;IAClD,IAAI,cAAc,IAAI,cAAc,CAEnC;CACF"}
|
|
@@ -15,6 +15,7 @@ import { ObservationManager } from './ObservationManager.js';
|
|
|
15
15
|
import { HierarchyManager } from './HierarchyManager.js';
|
|
16
16
|
import { GraphTraversal } from './GraphTraversal.js';
|
|
17
17
|
import { SearchManager } from '../search/SearchManager.js';
|
|
18
|
+
import { RankedSearch } from '../search/RankedSearch.js';
|
|
18
19
|
import { SemanticSearch, createEmbeddingService, createVectorStore } from '../search/index.js';
|
|
19
20
|
import { IOManager } from '../features/IOManager.js';
|
|
20
21
|
import { TagManager } from '../features/TagManager.js';
|
|
@@ -40,6 +41,7 @@ export class ManagerContext {
|
|
|
40
41
|
_graphTraversal;
|
|
41
42
|
_searchManager;
|
|
42
43
|
_semanticSearch;
|
|
44
|
+
_rankedSearch;
|
|
43
45
|
_ioManager;
|
|
44
46
|
_tagManager;
|
|
45
47
|
_analyticsManager;
|
|
@@ -99,6 +101,10 @@ export class ManagerContext {
|
|
|
99
101
|
}
|
|
100
102
|
return this._semanticSearch;
|
|
101
103
|
}
|
|
104
|
+
/** RankedSearch - Phase 11: TF-IDF/BM25 ranked search for hybrid search */
|
|
105
|
+
get rankedSearch() {
|
|
106
|
+
return (this._rankedSearch ??= new RankedSearch(this.storage));
|
|
107
|
+
}
|
|
102
108
|
/** IOManager - Import, export, and backup operations */
|
|
103
109
|
get ioManager() {
|
|
104
110
|
return (this._ioManager ??= new IOManager(this.storage));
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyword Extractor
|
|
3
|
+
*
|
|
4
|
+
* Phase 11: Extracts and scores keywords from text
|
|
5
|
+
* for lexical search enhancement.
|
|
6
|
+
*
|
|
7
|
+
* @module features/KeywordExtractor
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* A keyword with importance score.
|
|
11
|
+
*/
|
|
12
|
+
export interface ScoredKeyword {
|
|
13
|
+
keyword: string;
|
|
14
|
+
score: number;
|
|
15
|
+
positions: number[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Keyword Extractor extracts and scores keywords from text.
|
|
19
|
+
*
|
|
20
|
+
* Features:
|
|
21
|
+
* - Position-based scoring (earlier = more important)
|
|
22
|
+
* - Domain-specific keyword boosting
|
|
23
|
+
* - Length-based scoring (longer words often more specific)
|
|
24
|
+
* - Stopword filtering
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const extractor = new KeywordExtractor();
|
|
29
|
+
* const keywords = extractor.extract('The software project was completed on time');
|
|
30
|
+
* // Returns scored keywords sorted by importance
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare class KeywordExtractor {
|
|
34
|
+
private stopwords;
|
|
35
|
+
private domainBoosts;
|
|
36
|
+
constructor();
|
|
37
|
+
/**
|
|
38
|
+
* Extract keywords with scores from text.
|
|
39
|
+
*/
|
|
40
|
+
extract(text: string): ScoredKeyword[];
|
|
41
|
+
private tokenize;
|
|
42
|
+
private isKeyword;
|
|
43
|
+
private calculateScore;
|
|
44
|
+
/**
|
|
45
|
+
* Extract top N keywords.
|
|
46
|
+
*/
|
|
47
|
+
extractTop(text: string, n: number): string[];
|
|
48
|
+
/**
|
|
49
|
+
* Add custom domain boost for a keyword.
|
|
50
|
+
*/
|
|
51
|
+
addDomainBoost(keyword: string, boost: number): void;
|
|
52
|
+
/**
|
|
53
|
+
* Remove a domain boost.
|
|
54
|
+
*/
|
|
55
|
+
removeDomainBoost(keyword: string): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Get all domain boosts.
|
|
58
|
+
*/
|
|
59
|
+
getDomainBoosts(): Map<string, number>;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=KeywordExtractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KeywordExtractor.d.ts","sourceRoot":"","sources":["../../src/features/KeywordExtractor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,YAAY,CAAsB;;IA2B1C;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE;IAyBtC,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,cAAc;IAiBtB;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;IAM7C;;OAEG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAIpD;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAI3C;;OAEG;IACH,eAAe,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;CAGvC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyword Extractor
|
|
3
|
+
*
|
|
4
|
+
* Phase 11: Extracts and scores keywords from text
|
|
5
|
+
* for lexical search enhancement.
|
|
6
|
+
*
|
|
7
|
+
* @module features/KeywordExtractor
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Keyword Extractor extracts and scores keywords from text.
|
|
11
|
+
*
|
|
12
|
+
* Features:
|
|
13
|
+
* - Position-based scoring (earlier = more important)
|
|
14
|
+
* - Domain-specific keyword boosting
|
|
15
|
+
* - Length-based scoring (longer words often more specific)
|
|
16
|
+
* - Stopword filtering
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const extractor = new KeywordExtractor();
|
|
21
|
+
* const keywords = extractor.extract('The software project was completed on time');
|
|
22
|
+
* // Returns scored keywords sorted by importance
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export class KeywordExtractor {
|
|
26
|
+
stopwords;
|
|
27
|
+
domainBoosts;
|
|
28
|
+
constructor() {
|
|
29
|
+
this.stopwords = new Set([
|
|
30
|
+
'a', 'an', 'the', 'is', 'are', 'was', 'were', 'be', 'been',
|
|
31
|
+
'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would',
|
|
32
|
+
'could', 'should', 'can', 'to', 'of', 'in', 'for', 'on',
|
|
33
|
+
'with', 'at', 'by', 'from', 'as', 'and', 'or', 'but',
|
|
34
|
+
]);
|
|
35
|
+
this.domainBoosts = new Map([
|
|
36
|
+
['project', 1.5],
|
|
37
|
+
['task', 1.5],
|
|
38
|
+
['meeting', 1.3],
|
|
39
|
+
['deadline', 1.4],
|
|
40
|
+
['completed', 1.2],
|
|
41
|
+
['started', 1.2],
|
|
42
|
+
['person', 1.3],
|
|
43
|
+
['company', 1.3],
|
|
44
|
+
['team', 1.3],
|
|
45
|
+
['release', 1.4],
|
|
46
|
+
['feature', 1.3],
|
|
47
|
+
['bug', 1.2],
|
|
48
|
+
['issue', 1.2],
|
|
49
|
+
['milestone', 1.4],
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Extract keywords with scores from text.
|
|
54
|
+
*/
|
|
55
|
+
extract(text) {
|
|
56
|
+
const words = this.tokenize(text);
|
|
57
|
+
const keywordMap = new Map();
|
|
58
|
+
for (let i = 0; i < words.length; i++) {
|
|
59
|
+
const word = words[i].toLowerCase();
|
|
60
|
+
if (this.isKeyword(word)) {
|
|
61
|
+
const existing = keywordMap.get(word);
|
|
62
|
+
if (existing) {
|
|
63
|
+
existing.positions.push(i);
|
|
64
|
+
existing.score += this.calculateScore(word, i, words.length);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
keywordMap.set(word, {
|
|
68
|
+
keyword: word,
|
|
69
|
+
score: this.calculateScore(word, i, words.length),
|
|
70
|
+
positions: [i],
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return Array.from(keywordMap.values())
|
|
76
|
+
.sort((a, b) => b.score - a.score);
|
|
77
|
+
}
|
|
78
|
+
tokenize(text) {
|
|
79
|
+
return text
|
|
80
|
+
.replace(/[^a-zA-Z0-9\s]/g, ' ')
|
|
81
|
+
.split(/\s+/)
|
|
82
|
+
.filter(w => w.length > 0);
|
|
83
|
+
}
|
|
84
|
+
isKeyword(word) {
|
|
85
|
+
return word.length > 2 && !this.stopwords.has(word);
|
|
86
|
+
}
|
|
87
|
+
calculateScore(word, position, totalWords) {
|
|
88
|
+
let score = 1.0;
|
|
89
|
+
// Position boost (earlier = more important)
|
|
90
|
+
const positionFactor = 1 - (position / totalWords) * 0.3;
|
|
91
|
+
score *= positionFactor;
|
|
92
|
+
// Domain boost
|
|
93
|
+
const boost = this.domainBoosts.get(word) ?? 1.0;
|
|
94
|
+
score *= boost;
|
|
95
|
+
// Length boost (longer words often more specific)
|
|
96
|
+
if (word.length > 6)
|
|
97
|
+
score *= 1.1;
|
|
98
|
+
return score;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Extract top N keywords.
|
|
102
|
+
*/
|
|
103
|
+
extractTop(text, n) {
|
|
104
|
+
return this.extract(text)
|
|
105
|
+
.slice(0, n)
|
|
106
|
+
.map(k => k.keyword);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Add custom domain boost for a keyword.
|
|
110
|
+
*/
|
|
111
|
+
addDomainBoost(keyword, boost) {
|
|
112
|
+
this.domainBoosts.set(keyword.toLowerCase(), boost);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Remove a domain boost.
|
|
116
|
+
*/
|
|
117
|
+
removeDomainBoost(keyword) {
|
|
118
|
+
return this.domainBoosts.delete(keyword.toLowerCase());
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Get all domain boosts.
|
|
122
|
+
*/
|
|
123
|
+
getDomainBoosts() {
|
|
124
|
+
return new Map(this.domainBoosts);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observation Normalizer
|
|
3
|
+
*
|
|
4
|
+
* Phase 11: Transforms observations to be self-contained facts
|
|
5
|
+
* through coreference resolution and temporal anchoring.
|
|
6
|
+
*
|
|
7
|
+
* @module features/ObservationNormalizer
|
|
8
|
+
*/
|
|
9
|
+
import type { Entity } from '../types/index.js';
|
|
10
|
+
/**
|
|
11
|
+
* Options for observation normalization.
|
|
12
|
+
*/
|
|
13
|
+
export interface NormalizationOptions {
|
|
14
|
+
/** Resolve pronouns to entity names */
|
|
15
|
+
resolveCoreferences?: boolean;
|
|
16
|
+
/** Convert relative dates to absolute dates */
|
|
17
|
+
anchorTimestamps?: boolean;
|
|
18
|
+
/** Extract and tag keywords */
|
|
19
|
+
extractKeywords?: boolean;
|
|
20
|
+
/** Reference date for relative date conversion (default: now) */
|
|
21
|
+
referenceDate?: Date;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Result of normalizing an observation.
|
|
25
|
+
*/
|
|
26
|
+
export interface NormalizationResult {
|
|
27
|
+
original: string;
|
|
28
|
+
normalized: string;
|
|
29
|
+
changes: string[];
|
|
30
|
+
keywords?: string[];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Observation Normalizer transforms observations to self-contained facts.
|
|
34
|
+
*
|
|
35
|
+
* Applies transformations:
|
|
36
|
+
* 1. Coreference resolution: 'He works' -> 'Alice works'
|
|
37
|
+
* 2. Temporal anchoring: 'yesterday' -> '2026-01-07'
|
|
38
|
+
* 3. Keyword extraction: Identifies important terms
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const normalizer = new ObservationNormalizer();
|
|
43
|
+
* const result = normalizer.normalize(
|
|
44
|
+
* 'He started the project yesterday',
|
|
45
|
+
* { name: 'Bob', entityType: 'person', observations: [] }
|
|
46
|
+
* );
|
|
47
|
+
* // result.normalized = 'Bob started the project on 2026-01-07'
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare class ObservationNormalizer {
|
|
51
|
+
private pronounPatterns;
|
|
52
|
+
private relativeTimePatterns;
|
|
53
|
+
/**
|
|
54
|
+
* Normalize an observation for an entity.
|
|
55
|
+
*/
|
|
56
|
+
normalize(observation: string, entity: Entity, options?: NormalizationOptions): NormalizationResult;
|
|
57
|
+
/**
|
|
58
|
+
* Resolve pronouns to entity name.
|
|
59
|
+
*/
|
|
60
|
+
resolveCoreferences(text: string, entity: Entity): {
|
|
61
|
+
text: string;
|
|
62
|
+
changed: boolean;
|
|
63
|
+
};
|
|
64
|
+
private guessMasculine;
|
|
65
|
+
private guessFeminine;
|
|
66
|
+
/**
|
|
67
|
+
* Convert relative timestamps to absolute dates.
|
|
68
|
+
*/
|
|
69
|
+
anchorTimestamps(text: string, referenceDate: Date): {
|
|
70
|
+
text: string;
|
|
71
|
+
changed: boolean;
|
|
72
|
+
replacements: string[];
|
|
73
|
+
};
|
|
74
|
+
private addDays;
|
|
75
|
+
private addMonths;
|
|
76
|
+
private formatDate;
|
|
77
|
+
private formatMonth;
|
|
78
|
+
/**
|
|
79
|
+
* Extract important keywords from text.
|
|
80
|
+
*/
|
|
81
|
+
extractKeywords(text: string): string[];
|
|
82
|
+
/**
|
|
83
|
+
* Normalize all observations for an entity.
|
|
84
|
+
*/
|
|
85
|
+
normalizeEntity(entity: Entity, options?: NormalizationOptions): {
|
|
86
|
+
entity: Entity;
|
|
87
|
+
results: NormalizationResult[];
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=ObservationNormalizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObservationNormalizer.d.ts","sourceRoot":"","sources":["../../src/features/ObservationNormalizer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,uCAAuC;IACvC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,+CAA+C;IAC/C,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,+BAA+B;IAC/B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iEAAiE;IACjE,aAAa,CAAC,EAAE,IAAI,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,eAAe,CAIrB;IAEF,OAAO,CAAC,oBAAoB,CAU1B;IAEF;;OAEG;IACH,SAAS,CACP,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,oBAAyB,GACjC,mBAAmB;IAuCtB;;OAEG;IACH,mBAAmB,CACjB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE;IAsCrC,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,aAAa;IAKrB;;OAEG;IACH,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,IAAI,GAClB;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,MAAM,EAAE,CAAA;KAAE;IAoB7D,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAwBvC;;OAEG;IACH,eAAe,CACb,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,oBAAyB,GACjC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,mBAAmB,EAAE,CAAA;KAAE;CAatD"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Observation Normalizer
|
|
3
|
+
*
|
|
4
|
+
* Phase 11: Transforms observations to be self-contained facts
|
|
5
|
+
* through coreference resolution and temporal anchoring.
|
|
6
|
+
*
|
|
7
|
+
* @module features/ObservationNormalizer
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Observation Normalizer transforms observations to self-contained facts.
|
|
11
|
+
*
|
|
12
|
+
* Applies transformations:
|
|
13
|
+
* 1. Coreference resolution: 'He works' -> 'Alice works'
|
|
14
|
+
* 2. Temporal anchoring: 'yesterday' -> '2026-01-07'
|
|
15
|
+
* 3. Keyword extraction: Identifies important terms
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const normalizer = new ObservationNormalizer();
|
|
20
|
+
* const result = normalizer.normalize(
|
|
21
|
+
* 'He started the project yesterday',
|
|
22
|
+
* { name: 'Bob', entityType: 'person', observations: [] }
|
|
23
|
+
* );
|
|
24
|
+
* // result.normalized = 'Bob started the project on 2026-01-07'
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export class ObservationNormalizer {
|
|
28
|
+
pronounPatterns = {
|
|
29
|
+
masculine: /\b(he|him|his)\b/gi,
|
|
30
|
+
feminine: /\b(she|her|hers)\b/gi,
|
|
31
|
+
neutral: /\b(they|them|their|theirs)\b/gi,
|
|
32
|
+
};
|
|
33
|
+
relativeTimePatterns = [
|
|
34
|
+
[/\byesterday\b/i, (ref) => this.formatDate(this.addDays(ref, -1))],
|
|
35
|
+
[/\btoday\b/i, (ref) => this.formatDate(ref)],
|
|
36
|
+
[/\btomorrow\b/i, (ref) => this.formatDate(this.addDays(ref, 1))],
|
|
37
|
+
[/\blast week\b/i, (ref) => `week of ${this.formatDate(this.addDays(ref, -7))}`],
|
|
38
|
+
[/\blast month\b/i, (ref) => this.formatMonth(this.addMonths(ref, -1))],
|
|
39
|
+
[/\blast year\b/i, (ref) => `${ref.getFullYear() - 1}`],
|
|
40
|
+
[/\bthis week\b/i, (ref) => `week of ${this.formatDate(ref)}`],
|
|
41
|
+
[/\bthis month\b/i, (ref) => this.formatMonth(ref)],
|
|
42
|
+
[/\bthis year\b/i, (ref) => `${ref.getFullYear()}`],
|
|
43
|
+
];
|
|
44
|
+
/**
|
|
45
|
+
* Normalize an observation for an entity.
|
|
46
|
+
*/
|
|
47
|
+
normalize(observation, entity, options = {}) {
|
|
48
|
+
const { resolveCoreferences = true, anchorTimestamps = true, extractKeywords = false, referenceDate = new Date(), } = options;
|
|
49
|
+
let normalized = observation;
|
|
50
|
+
const changes = [];
|
|
51
|
+
if (resolveCoreferences) {
|
|
52
|
+
const corefResult = this.resolveCoreferences(normalized, entity);
|
|
53
|
+
if (corefResult.changed) {
|
|
54
|
+
normalized = corefResult.text;
|
|
55
|
+
changes.push(`Resolved pronouns to '${entity.name}'`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (anchorTimestamps) {
|
|
59
|
+
const timeResult = this.anchorTimestamps(normalized, referenceDate);
|
|
60
|
+
if (timeResult.changed) {
|
|
61
|
+
normalized = timeResult.text;
|
|
62
|
+
changes.push(...timeResult.replacements);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const keywords = extractKeywords
|
|
66
|
+
? this.extractKeywords(normalized)
|
|
67
|
+
: undefined;
|
|
68
|
+
return {
|
|
69
|
+
original: observation,
|
|
70
|
+
normalized,
|
|
71
|
+
changes,
|
|
72
|
+
keywords,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Resolve pronouns to entity name.
|
|
77
|
+
*/
|
|
78
|
+
resolveCoreferences(text, entity) {
|
|
79
|
+
let result = text;
|
|
80
|
+
let changed = false;
|
|
81
|
+
// Determine gender hint from entity type or name patterns
|
|
82
|
+
const isMasculine = this.guessMasculine(entity);
|
|
83
|
+
const isFeminine = this.guessFeminine(entity);
|
|
84
|
+
// Replace pronouns based on detected gender
|
|
85
|
+
if (isMasculine) {
|
|
86
|
+
const newText = result
|
|
87
|
+
.replace(this.pronounPatterns.masculine, entity.name);
|
|
88
|
+
if (newText !== result) {
|
|
89
|
+
result = newText;
|
|
90
|
+
changed = true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else if (isFeminine) {
|
|
94
|
+
const newText = result
|
|
95
|
+
.replace(this.pronounPatterns.feminine, entity.name);
|
|
96
|
+
if (newText !== result) {
|
|
97
|
+
result = newText;
|
|
98
|
+
changed = true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Always try neutral pronouns for non-person entities
|
|
102
|
+
if (entity.entityType.toLowerCase() !== 'person') {
|
|
103
|
+
const newText = result
|
|
104
|
+
.replace(this.pronounPatterns.neutral, entity.name);
|
|
105
|
+
if (newText !== result) {
|
|
106
|
+
result = newText;
|
|
107
|
+
changed = true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return { text: result, changed };
|
|
111
|
+
}
|
|
112
|
+
guessMasculine(entity) {
|
|
113
|
+
const masculineNames = ['john', 'james', 'bob', 'mike', 'david', 'alex'];
|
|
114
|
+
return masculineNames.some(n => entity.name.toLowerCase().includes(n));
|
|
115
|
+
}
|
|
116
|
+
guessFeminine(entity) {
|
|
117
|
+
const feminineNames = ['alice', 'jane', 'sarah', 'mary', 'emma', 'lisa'];
|
|
118
|
+
return feminineNames.some(n => entity.name.toLowerCase().includes(n));
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Convert relative timestamps to absolute dates.
|
|
122
|
+
*/
|
|
123
|
+
anchorTimestamps(text, referenceDate) {
|
|
124
|
+
let result = text;
|
|
125
|
+
const replacements = [];
|
|
126
|
+
for (const [pattern, resolver] of this.relativeTimePatterns) {
|
|
127
|
+
const match = result.match(pattern);
|
|
128
|
+
if (match) {
|
|
129
|
+
const replacement = resolver(referenceDate);
|
|
130
|
+
result = result.replace(pattern, replacement);
|
|
131
|
+
replacements.push(`'${match[0]}' -> '${replacement}'`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
text: result,
|
|
136
|
+
changed: replacements.length > 0,
|
|
137
|
+
replacements,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
addDays(date, days) {
|
|
141
|
+
const result = new Date(date);
|
|
142
|
+
result.setDate(result.getDate() + days);
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
addMonths(date, months) {
|
|
146
|
+
const result = new Date(date);
|
|
147
|
+
result.setMonth(result.getMonth() + months);
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
formatDate(date) {
|
|
151
|
+
return date.toISOString().split('T')[0];
|
|
152
|
+
}
|
|
153
|
+
formatMonth(date) {
|
|
154
|
+
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Extract important keywords from text.
|
|
158
|
+
*/
|
|
159
|
+
extractKeywords(text) {
|
|
160
|
+
const stopwords = new Set([
|
|
161
|
+
'a', 'an', 'the', 'is', 'are', 'was', 'were', 'be', 'been',
|
|
162
|
+
'being', 'have', 'has', 'had', 'do', 'does', 'did', 'will',
|
|
163
|
+
'would', 'could', 'should', 'may', 'might', 'must', 'shall',
|
|
164
|
+
'can', 'to', 'of', 'in', 'for', 'on', 'with', 'at', 'by',
|
|
165
|
+
'from', 'as', 'into', 'through', 'during', 'before', 'after',
|
|
166
|
+
'above', 'below', 'between', 'under', 'again', 'further',
|
|
167
|
+
'then', 'once', 'here', 'there', 'when', 'where', 'why', 'how',
|
|
168
|
+
'all', 'each', 'few', 'more', 'most', 'other', 'some', 'such',
|
|
169
|
+
'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too',
|
|
170
|
+
'very', 's', 't', 'just', 'don', 'now', 'and', 'but', 'or',
|
|
171
|
+
]);
|
|
172
|
+
const words = text
|
|
173
|
+
.toLowerCase()
|
|
174
|
+
.replace(/[^a-z0-9\s]/g, '')
|
|
175
|
+
.split(/\s+/)
|
|
176
|
+
.filter(w => w.length > 2 && !stopwords.has(w));
|
|
177
|
+
// Return unique keywords
|
|
178
|
+
return [...new Set(words)];
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Normalize all observations for an entity.
|
|
182
|
+
*/
|
|
183
|
+
normalizeEntity(entity, options = {}) {
|
|
184
|
+
const results = entity.observations.map(obs => this.normalize(obs, entity, options));
|
|
185
|
+
return {
|
|
186
|
+
entity: {
|
|
187
|
+
...entity,
|
|
188
|
+
observations: results.map(r => r.normalized),
|
|
189
|
+
},
|
|
190
|
+
results,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
}
|
package/dist/features/index.d.ts
CHANGED
|
@@ -9,4 +9,6 @@ export { AnalyticsManager } from './AnalyticsManager.js';
|
|
|
9
9
|
export { CompressionManager } from './CompressionManager.js';
|
|
10
10
|
export { ArchiveManager, type ArchiveCriteria, type ArchiveOptions, type ArchiveResult, } from './ArchiveManager.js';
|
|
11
11
|
export { StreamingExporter, type StreamResult } from './StreamingExporter.js';
|
|
12
|
+
export { ObservationNormalizer, type NormalizationOptions, type NormalizationResult, } from './ObservationNormalizer.js';
|
|
13
|
+
export { KeywordExtractor, type ScoredKeyword, } from './KeywordExtractor.js';
|
|
12
14
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/features/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EACL,SAAS,EACT,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,UAAU,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EACL,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/features/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EACL,SAAS,EACT,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,UAAU,GAChB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EACL,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG9E,OAAO,EACL,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,GACzB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,gBAAgB,EAChB,KAAK,aAAa,GACnB,MAAM,uBAAuB,CAAC"}
|
package/dist/features/index.js
CHANGED
|
@@ -9,3 +9,6 @@ export { AnalyticsManager } from './AnalyticsManager.js';
|
|
|
9
9
|
export { CompressionManager } from './CompressionManager.js';
|
|
10
10
|
export { ArchiveManager, } from './ArchiveManager.js';
|
|
11
11
|
export { StreamingExporter } from './StreamingExporter.js';
|
|
12
|
+
// Phase 11 Sprint 5: Semantic Compression
|
|
13
|
+
export { ObservationNormalizer, } from './ObservationNormalizer.js';
|
|
14
|
+
export { KeywordExtractor, } from './KeywordExtractor.js';
|
|
@@ -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"}
|