sxng-cli 1.0.9 → 1.1.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/dist/commands/graph-add.d.ts.map +1 -1
- package/dist/commands/graph-add.js +9 -1
- package/dist/commands/graph-add.js.map +1 -1
- package/dist/commands/graph-drill.d.ts +11 -0
- package/dist/commands/graph-drill.d.ts.map +1 -0
- package/dist/commands/graph-drill.js +26 -0
- package/dist/commands/graph-drill.js.map +1 -0
- package/dist/commands/graph-explore.d.ts +10 -0
- package/dist/commands/graph-explore.d.ts.map +1 -0
- package/dist/commands/graph-explore.js +32 -0
- package/dist/commands/graph-explore.js.map +1 -0
- package/dist/commands/graph-obfuscate.d.ts +17 -0
- package/dist/commands/graph-obfuscate.d.ts.map +1 -0
- package/dist/commands/graph-obfuscate.js +110 -0
- package/dist/commands/graph-obfuscate.js.map +1 -0
- package/dist/commands/graph-search.d.ts +11 -0
- package/dist/commands/graph-search.d.ts.map +1 -0
- package/dist/commands/graph-search.js +19 -0
- package/dist/commands/graph-search.js.map +1 -0
- package/dist/commands/graph-traverse.d.ts +10 -0
- package/dist/commands/graph-traverse.d.ts.map +1 -0
- package/dist/commands/graph-traverse.js +39 -0
- package/dist/commands/graph-traverse.js.map +1 -0
- package/dist/commands/query-graph.d.ts +2 -0
- package/dist/commands/query-graph.d.ts.map +1 -1
- package/dist/commands/query-graph.js +66 -0
- package/dist/commands/query-graph.js.map +1 -1
- package/dist/deep/co-occurrence.d.ts +50 -0
- package/dist/deep/co-occurrence.d.ts.map +1 -0
- package/dist/deep/co-occurrence.js +95 -0
- package/dist/deep/co-occurrence.js.map +1 -0
- package/dist/deep/degree-utils.d.ts +39 -0
- package/dist/deep/degree-utils.d.ts.map +1 -0
- package/dist/deep/degree-utils.js +42 -0
- package/dist/deep/degree-utils.js.map +1 -0
- package/dist/deep/extractor.d.ts +7 -2
- package/dist/deep/extractor.d.ts.map +1 -1
- package/dist/deep/extractor.js +143 -78
- package/dist/deep/extractor.js.map +1 -1
- package/dist/deep/graph-explore.d.ts +115 -0
- package/dist/deep/graph-explore.d.ts.map +1 -0
- package/dist/deep/graph-explore.js +586 -0
- package/dist/deep/graph-explore.js.map +1 -0
- package/dist/deep/graph-obfuscate.d.ts +51 -0
- package/dist/deep/graph-obfuscate.d.ts.map +1 -0
- package/dist/deep/graph-obfuscate.js +226 -0
- package/dist/deep/graph-obfuscate.js.map +1 -0
- package/dist/deep/graph-preprocess.d.ts +41 -0
- package/dist/deep/graph-preprocess.d.ts.map +1 -0
- package/dist/deep/graph-preprocess.js +32 -0
- package/dist/deep/graph-preprocess.js.map +1 -0
- package/dist/deep/graph-sampling.d.ts +51 -0
- package/dist/deep/graph-sampling.d.ts.map +1 -0
- package/dist/deep/graph-sampling.js +409 -0
- package/dist/deep/graph-sampling.js.map +1 -0
- package/dist/deep/graph.d.ts +24 -1
- package/dist/deep/graph.d.ts.map +1 -1
- package/dist/deep/graph.js +42 -1
- package/dist/deep/graph.js.map +1 -1
- package/dist/deep/iteration-data.d.ts +38 -0
- package/dist/deep/iteration-data.d.ts.map +1 -0
- package/dist/deep/iteration-data.js +48 -0
- package/dist/deep/iteration-data.js.map +1 -0
- package/dist/deep/path-extraction.d.ts +53 -0
- package/dist/deep/path-extraction.d.ts.map +1 -0
- package/dist/deep/path-extraction.js +229 -0
- package/dist/deep/path-extraction.js.map +1 -0
- package/dist/deep/quality-assess.d.ts +45 -0
- package/dist/deep/quality-assess.d.ts.map +1 -0
- package/dist/deep/quality-assess.js +125 -0
- package/dist/deep/quality-assess.js.map +1 -0
- package/dist/deep/query-redundancy.d.ts +39 -0
- package/dist/deep/query-redundancy.d.ts.map +1 -0
- package/dist/deep/query-redundancy.js +109 -0
- package/dist/deep/query-redundancy.js.map +1 -0
- package/dist/deep/query-suggest.d.ts +35 -0
- package/dist/deep/query-suggest.d.ts.map +1 -0
- package/dist/deep/query-suggest.js +98 -0
- package/dist/deep/query-suggest.js.map +1 -0
- package/dist/deep/recovery-analysis.d.ts +61 -0
- package/dist/deep/recovery-analysis.d.ts.map +1 -0
- package/dist/deep/recovery-analysis.js +188 -0
- package/dist/deep/recovery-analysis.js.map +1 -0
- package/dist/deep/search-strategy.d.ts +37 -0
- package/dist/deep/search-strategy.d.ts.map +1 -0
- package/dist/deep/search-strategy.js +99 -0
- package/dist/deep/search-strategy.js.map +1 -0
- package/dist/deep/session.d.ts +2 -0
- package/dist/deep/session.d.ts.map +1 -1
- package/dist/deep/session.js +1 -1
- package/dist/deep/session.js.map +1 -1
- package/dist/deep/simhash.d.ts +5 -0
- package/dist/deep/simhash.d.ts.map +1 -1
- package/dist/deep/simhash.js +16 -0
- package/dist/deep/simhash.js.map +1 -1
- package/dist/deep/tfidf.d.ts +38 -0
- package/dist/deep/tfidf.d.ts.map +1 -0
- package/dist/deep/tfidf.js +103 -0
- package/dist/deep/tfidf.js.map +1 -0
- package/dist/runCli.d.ts +3 -1
- package/dist/runCli.d.ts.map +1 -1
- package/dist/runCli.js +762 -307
- package/dist/runCli.js.map +1 -1
- package/package.json +17 -4
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified interface for all deep search iteration data commands.
|
|
3
|
+
*
|
|
4
|
+
* Composes the individual data modules into a single analysis call:
|
|
5
|
+
* - checkQueryRedundancy
|
|
6
|
+
* - assessResultQuality
|
|
7
|
+
* - generateQuerySuggestions
|
|
8
|
+
* - analyzeRecoveryOptions
|
|
9
|
+
* - getStrategyInfo
|
|
10
|
+
*
|
|
11
|
+
* Agent can call getSessionAnalysis() to get a comprehensive snapshot
|
|
12
|
+
* of the session state for decision-making.
|
|
13
|
+
*/
|
|
14
|
+
import { assessResultQuality } from './quality-assess.js';
|
|
15
|
+
import { generateQuerySuggestions } from './query-suggest.js';
|
|
16
|
+
import { getStrategyInfo } from './search-strategy.js';
|
|
17
|
+
import { analyzeRecoveryOptions } from './recovery-analysis.js';
|
|
18
|
+
import { checkQueryRedundancy } from './query-redundancy.js';
|
|
19
|
+
// ── Unified analysis ──────────────────────────────────────────────
|
|
20
|
+
/** Get a comprehensive analysis of the current session state.
|
|
21
|
+
* Combines quality assessment, strategy info, query suggestions,
|
|
22
|
+
* and recovery analysis into a single output for Agent decision-making. */
|
|
23
|
+
export function getSessionAnalysis(graph, sessionResults, options) {
|
|
24
|
+
// Quality assessment
|
|
25
|
+
const quality = assessResultQuality(sessionResults, sessionResults, graph, options?.qualityThresholds);
|
|
26
|
+
// Strategy info
|
|
27
|
+
const strategy = getStrategyInfo(graph, options?.strategyConfig);
|
|
28
|
+
// Query suggestions
|
|
29
|
+
const suggestions = generateQuerySuggestions(graph, sessionResults, strategy.currentStage, quality);
|
|
30
|
+
// Recovery analysis
|
|
31
|
+
const recovery = analyzeRecoveryOptions(graph, sessionResults, quality, options?.strategyConfig);
|
|
32
|
+
return { quality, strategy, suggestions, recovery };
|
|
33
|
+
}
|
|
34
|
+
/** Check a new query for redundancy before execution.
|
|
35
|
+
* Standalone convenience function — also available via query-redundancy.ts. */
|
|
36
|
+
export function checkNewQueryRedundancy(newQuery, graph, config) {
|
|
37
|
+
const history = [];
|
|
38
|
+
graph.forEachNode((_node, attrs) => {
|
|
39
|
+
if (attrs.type === 'query' && attrs.query) {
|
|
40
|
+
history.push(attrs.query);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return checkQueryRedundancy(newQuery, history, {
|
|
44
|
+
jaccardThreshold: config?.jaccardThreshold ?? 0.7,
|
|
45
|
+
action: config?.action ?? 'warn',
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=iteration-data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iteration-data.js","sourceRoot":"","sources":["../../src/deep/iteration-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,EAAmC,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC3F,OAAO,EAAoC,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAChG,OAAO,EAAgC,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,EAAoB,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAClF,OAAO,EAAsC,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAWjG,qEAAqE;AAErE;;4EAE4E;AAC5E,MAAM,UAAU,kBAAkB,CAC9B,KAAoD,EACpD,cAA+B,EAC/B,OAGC;IAED,qBAAqB;IACrB,MAAM,OAAO,GAAG,mBAAmB,CAC/B,cAAc,EACd,cAAc,EACd,KAAK,EACL,OAAO,EAAE,iBAAiB,CAC7B,CAAC;IAEF,gBAAgB;IAChB,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;IAEjE,oBAAoB;IACpB,MAAM,WAAW,GAAG,wBAAwB,CACxC,KAAK,EACL,cAAc,EACd,QAAQ,CAAC,YAAY,EACrB,OAAO,CACV,CAAC;IAEF,oBAAoB;IACpB,MAAM,QAAQ,GAAG,sBAAsB,CACnC,KAAK,EACL,cAAc,EACd,OAAO,EACP,OAAO,EAAE,cAAc,CAC1B,CAAC;IAEF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;AACxD,CAAC;AAED;gFACgF;AAChF,MAAM,UAAU,uBAAuB,CACnC,QAAgB,EAChB,KAAoD,EACpD,MAAkC;IAElC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,CAAC,WAAW,CAAC,CAAC,KAAa,EAAE,KAAqB,EAAE,EAAE;QACvD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC9B,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,oBAAoB,CAAC,QAAQ,EAAE,OAAO,EAAE;QAC3C,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,IAAI,GAAG;QACjD,MAAM,EAAE,MAAM,EAAE,MAAM,IAAI,MAAM;KACnC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reasoning path extraction from knowledge graphs.
|
|
3
|
+
*
|
|
4
|
+
* Detects structured reasoning patterns:
|
|
5
|
+
* - composition_chain: e₁→(r₁)→e₂→(r₂)→e₃→... (sequential chain)
|
|
6
|
+
* - conjunction: e₁→e₃←e₂ (two seeds converging on a shared target)
|
|
7
|
+
*
|
|
8
|
+
* Creates path: nodes in the graph with ordered entity IDs.
|
|
9
|
+
*/
|
|
10
|
+
import { DirectedGraph } from 'graphology';
|
|
11
|
+
import { GraphNodeAttrs, GraphEdgeAttrs } from './graph.js';
|
|
12
|
+
export interface CompositionChain {
|
|
13
|
+
id: string;
|
|
14
|
+
entities: string[];
|
|
15
|
+
hops: number;
|
|
16
|
+
relations: string[];
|
|
17
|
+
}
|
|
18
|
+
export interface ConjunctionPath {
|
|
19
|
+
id: string;
|
|
20
|
+
seed1: string;
|
|
21
|
+
seed2: string;
|
|
22
|
+
bridge: string;
|
|
23
|
+
hops: number;
|
|
24
|
+
}
|
|
25
|
+
export interface PathExtractionResult {
|
|
26
|
+
compositionChains: CompositionChain[];
|
|
27
|
+
conjunctions: ConjunctionPath[];
|
|
28
|
+
totalPaths: number;
|
|
29
|
+
}
|
|
30
|
+
export interface PathExtractionConfig {
|
|
31
|
+
/** Min chain length (hops). Default: 2 */
|
|
32
|
+
minChainHops?: number;
|
|
33
|
+
/** Max chain length (hops). Default: 5 */
|
|
34
|
+
maxChainHops?: number;
|
|
35
|
+
/** Max BFS depth for conjunction search. Default: 3 */
|
|
36
|
+
maxConjunctionDepth?: number;
|
|
37
|
+
/** Deduplicate paths that share the same entity set. Default: true */
|
|
38
|
+
dedup?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Detect composition chains: sequences of entity→entity edges forming a path.
|
|
42
|
+
* Walks the graph from each entity, following entity→entity edges up to maxHops.
|
|
43
|
+
* Avoids revisiting nodes (cycle detection).
|
|
44
|
+
*/
|
|
45
|
+
export declare function detectCompositionChains(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, config?: PathExtractionConfig): CompositionChain[];
|
|
46
|
+
/**
|
|
47
|
+
* Detect conjunction patterns: e₁→e₃←e₂
|
|
48
|
+
* Two entities that both have edges pointing to a shared target entity.
|
|
49
|
+
*/
|
|
50
|
+
export declare function detectConjunctions(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, config?: PathExtractionConfig): ConjunctionPath[];
|
|
51
|
+
/** Extract all reasoning paths from a graph. Creates path: nodes. */
|
|
52
|
+
export declare function extractPaths(graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, config?: PathExtractionConfig): PathExtractionResult;
|
|
53
|
+
//# sourceMappingURL=path-extraction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-extraction.d.ts","sourceRoot":"","sources":["../../src/deep/path-extraction.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAwB,MAAM,YAAY,CAAC;AAKlF,MAAM,WAAW,gBAAgB;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACjC,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IACtC,YAAY,EAAE,eAAe,EAAE,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACjC,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,sEAAsE;IACtE,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAID;;;;GAIG;AACH,wBAAgB,uBAAuB,CACnC,KAAK,EAAE,aAAa,CAAC,cAAc,EAAE,cAAc,CAAC,EACpD,MAAM,CAAC,EAAE,oBAAoB,GAC9B,gBAAgB,EAAE,CA0CpB;AA4ED;;;GAGG;AACH,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,aAAa,CAAC,cAAc,EAAE,cAAc,CAAC,EACpD,MAAM,CAAC,EAAE,oBAAoB,GAC9B,eAAe,EAAE,CAkDnB;AA+BD,qEAAqE;AACrE,wBAAgB,YAAY,CACxB,KAAK,EAAE,aAAa,CAAC,cAAc,EAAE,cAAc,CAAC,EACpD,MAAM,CAAC,EAAE,oBAAoB,GAC9B,oBAAoB,CA4CtB"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reasoning path extraction from knowledge graphs.
|
|
3
|
+
*
|
|
4
|
+
* Detects structured reasoning patterns:
|
|
5
|
+
* - composition_chain: e₁→(r₁)→e₂→(r₂)→e₃→... (sequential chain)
|
|
6
|
+
* - conjunction: e₁→e₃←e₂ (two seeds converging on a shared target)
|
|
7
|
+
*
|
|
8
|
+
* Creates path: nodes in the graph with ordered entity IDs.
|
|
9
|
+
*/
|
|
10
|
+
import { nextPathId } from './graph.js';
|
|
11
|
+
import { getEntityDegree } from './degree-utils.js';
|
|
12
|
+
// ── Composition Chain Detection ───────────────────────────────────
|
|
13
|
+
/**
|
|
14
|
+
* Detect composition chains: sequences of entity→entity edges forming a path.
|
|
15
|
+
* Walks the graph from each entity, following entity→entity edges up to maxHops.
|
|
16
|
+
* Avoids revisiting nodes (cycle detection).
|
|
17
|
+
*/
|
|
18
|
+
export function detectCompositionChains(graph, config) {
|
|
19
|
+
const minHops = config?.minChainHops ?? 2;
|
|
20
|
+
const maxHops = config?.maxChainHops ?? 5;
|
|
21
|
+
const dedup = config?.dedup ?? true;
|
|
22
|
+
const chains = [];
|
|
23
|
+
const seenEntitySets = new Set();
|
|
24
|
+
// Get all entity nodes
|
|
25
|
+
const entityNodes = [];
|
|
26
|
+
graph.forEachNode((node, attrs) => {
|
|
27
|
+
if (attrs.type === 'entity')
|
|
28
|
+
entityNodes.push(node);
|
|
29
|
+
});
|
|
30
|
+
// Sort by degree descending — start from high-degree hubs
|
|
31
|
+
entityNodes.sort((a, b) => getEntityDegree(graph, b) - getEntityDegree(graph, a));
|
|
32
|
+
for (const startNode of entityNodes) {
|
|
33
|
+
// DFS from startNode, following entity-to-entity edges
|
|
34
|
+
const paths = dfsEntityChains(graph, startNode, maxHops);
|
|
35
|
+
for (const path of paths) {
|
|
36
|
+
if (path.entities.length - 1 < minHops)
|
|
37
|
+
continue;
|
|
38
|
+
if (dedup) {
|
|
39
|
+
const key = path.entities.join('|');
|
|
40
|
+
const reverseKey = [...path.entities].reverse().join('|');
|
|
41
|
+
if (seenEntitySets.has(key) || seenEntitySets.has(reverseKey))
|
|
42
|
+
continue;
|
|
43
|
+
seenEntitySets.add(key);
|
|
44
|
+
}
|
|
45
|
+
const id = nextPathId(graph, 'composition_chain');
|
|
46
|
+
chains.push({
|
|
47
|
+
id,
|
|
48
|
+
entities: path.entities,
|
|
49
|
+
hops: path.entities.length - 1,
|
|
50
|
+
relations: path.relations,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return chains;
|
|
55
|
+
}
|
|
56
|
+
/** DFS from a start entity, collecting all chains up to maxHops. */
|
|
57
|
+
function dfsEntityChains(graph, start, maxHops) {
|
|
58
|
+
const results = [];
|
|
59
|
+
function dfs(current, path, relations, visited) {
|
|
60
|
+
if (path.length - 1 >= maxHops) {
|
|
61
|
+
if (path.length - 1 >= 2) {
|
|
62
|
+
results.push({ entities: [...path], relations: [...relations] });
|
|
63
|
+
}
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// Follow outgoing entity→entity edges
|
|
67
|
+
const outEdges = graph.outEdges(current);
|
|
68
|
+
let extended = false;
|
|
69
|
+
for (const edge of outEdges) {
|
|
70
|
+
const target = graph.target(edge);
|
|
71
|
+
if (visited.has(target))
|
|
72
|
+
continue;
|
|
73
|
+
if (graph.getNodeAttributes(target).type !== 'entity')
|
|
74
|
+
continue;
|
|
75
|
+
const attrs = graph.getEdgeAttributes(current, target);
|
|
76
|
+
visited.add(target);
|
|
77
|
+
path.push(target);
|
|
78
|
+
relations.push(attrs.relation);
|
|
79
|
+
dfs(target, path, relations, visited);
|
|
80
|
+
extended = true;
|
|
81
|
+
path.pop();
|
|
82
|
+
relations.pop();
|
|
83
|
+
visited.delete(target);
|
|
84
|
+
}
|
|
85
|
+
// Also follow incoming entity→entity edges
|
|
86
|
+
const inEdges = graph.inEdges(current);
|
|
87
|
+
for (const edge of inEdges) {
|
|
88
|
+
const source = graph.source(edge);
|
|
89
|
+
if (visited.has(source))
|
|
90
|
+
continue;
|
|
91
|
+
if (graph.getNodeAttributes(source).type !== 'entity')
|
|
92
|
+
continue;
|
|
93
|
+
const attrs = graph.getEdgeAttributes(source, current);
|
|
94
|
+
visited.add(source);
|
|
95
|
+
path.push(source);
|
|
96
|
+
relations.push(attrs.relation);
|
|
97
|
+
dfs(source, path, relations, visited);
|
|
98
|
+
extended = true;
|
|
99
|
+
path.pop();
|
|
100
|
+
relations.pop();
|
|
101
|
+
visited.delete(source);
|
|
102
|
+
}
|
|
103
|
+
// Record this path if it's long enough (even if not at maxHops)
|
|
104
|
+
if (!extended && path.length - 1 >= 2) {
|
|
105
|
+
results.push({ entities: [...path], relations: [...relations] });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
dfs(start, [start], [], new Set([start]));
|
|
109
|
+
return results;
|
|
110
|
+
}
|
|
111
|
+
// ── Conjunction Detection ─────────────────────────────────────────
|
|
112
|
+
/**
|
|
113
|
+
* Detect conjunction patterns: e₁→e₃←e₂
|
|
114
|
+
* Two entities that both have edges pointing to a shared target entity.
|
|
115
|
+
*/
|
|
116
|
+
export function detectConjunctions(graph, config) {
|
|
117
|
+
const maxDepth = config?.maxConjunctionDepth ?? 3;
|
|
118
|
+
const dedup = config?.dedup ?? true;
|
|
119
|
+
const conjunctions = [];
|
|
120
|
+
const seenPairs = new Set();
|
|
121
|
+
// Get all entity nodes
|
|
122
|
+
const entityNodes = [];
|
|
123
|
+
graph.forEachNode((node, attrs) => {
|
|
124
|
+
if (attrs.type === 'entity')
|
|
125
|
+
entityNodes.push(node);
|
|
126
|
+
});
|
|
127
|
+
// For each entity, find its targets within maxDepth
|
|
128
|
+
const reachability = new Map();
|
|
129
|
+
for (const entity of entityNodes) {
|
|
130
|
+
reachability.set(entity, bfsEntityReachable(graph, entity, maxDepth));
|
|
131
|
+
}
|
|
132
|
+
// Find pairs of entities that share a common target
|
|
133
|
+
for (let i = 0; i < entityNodes.length; i++) {
|
|
134
|
+
for (let j = i + 1; j < entityNodes.length; j++) {
|
|
135
|
+
const e1 = entityNodes[i];
|
|
136
|
+
const e2 = entityNodes[j];
|
|
137
|
+
const reach1 = reachability.get(e1);
|
|
138
|
+
const reach2 = reachability.get(e2);
|
|
139
|
+
// Find common reachable entities
|
|
140
|
+
for (const [target, d1] of reach1) {
|
|
141
|
+
const d2 = reach2.get(target);
|
|
142
|
+
if (d2 === undefined)
|
|
143
|
+
continue;
|
|
144
|
+
if (target === e1 || target === e2)
|
|
145
|
+
continue;
|
|
146
|
+
const pairKey = [e1, e2].sort().join('|') + '→' + target;
|
|
147
|
+
if (dedup && seenPairs.has(pairKey))
|
|
148
|
+
continue;
|
|
149
|
+
seenPairs.add(pairKey);
|
|
150
|
+
const id = nextPathId(graph, 'conjunction');
|
|
151
|
+
conjunctions.push({
|
|
152
|
+
id,
|
|
153
|
+
seed1: e1,
|
|
154
|
+
seed2: e2,
|
|
155
|
+
bridge: target,
|
|
156
|
+
hops: Math.max(d1, d2),
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return conjunctions;
|
|
162
|
+
}
|
|
163
|
+
/** BFS from an entity, returning reachable entity nodes within maxDepth. */
|
|
164
|
+
function bfsEntityReachable(graph, start, maxDepth) {
|
|
165
|
+
const dist = new Map();
|
|
166
|
+
const queue = [{ id: start, d: 0 }];
|
|
167
|
+
dist.set(start, 0);
|
|
168
|
+
while (queue.length > 0) {
|
|
169
|
+
const { id, d } = queue.shift();
|
|
170
|
+
if (d >= maxDepth)
|
|
171
|
+
continue;
|
|
172
|
+
// Follow both directions
|
|
173
|
+
graph.forEachNeighbor(id, (neighbor) => {
|
|
174
|
+
if (dist.has(neighbor))
|
|
175
|
+
return;
|
|
176
|
+
if (graph.getNodeAttributes(neighbor).type !== 'entity')
|
|
177
|
+
return;
|
|
178
|
+
dist.set(neighbor, d + 1);
|
|
179
|
+
queue.push({ id: neighbor, d: d + 1 });
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
dist.delete(start); // don't include self
|
|
183
|
+
return dist;
|
|
184
|
+
}
|
|
185
|
+
// ── Combined extraction ───────────────────────────────────────────
|
|
186
|
+
/** Extract all reasoning paths from a graph. Creates path: nodes. */
|
|
187
|
+
export function extractPaths(graph, config) {
|
|
188
|
+
const chains = detectCompositionChains(graph, config);
|
|
189
|
+
const conjunctions = detectConjunctions(graph, config);
|
|
190
|
+
// Create path: nodes in the graph
|
|
191
|
+
for (const chain of chains) {
|
|
192
|
+
graph.mergeNode(chain.id, {
|
|
193
|
+
type: 'path',
|
|
194
|
+
label: `Chain: ${chain.entities.map(e => graph.getNodeAttributes(e)?.label ?? e).join(' → ')}`,
|
|
195
|
+
pathType: 'composition_chain',
|
|
196
|
+
hops: chain.hops,
|
|
197
|
+
entities: chain.entities,
|
|
198
|
+
});
|
|
199
|
+
// Add includes edges from path to each entity
|
|
200
|
+
for (const entityId of chain.entities) {
|
|
201
|
+
if (graph.hasNode(entityId) && !graph.hasEdge(chain.id, entityId)) {
|
|
202
|
+
graph.addEdge(chain.id, entityId, { relation: 'includes', weight: 1 });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
for (const conj of conjunctions) {
|
|
207
|
+
const e1Label = graph.getNodeAttributes(conj.seed1)?.label ?? conj.seed1;
|
|
208
|
+
const e2Label = graph.getNodeAttributes(conj.seed2)?.label ?? conj.seed2;
|
|
209
|
+
const bridgeLabel = graph.getNodeAttributes(conj.bridge)?.label ?? conj.bridge;
|
|
210
|
+
graph.mergeNode(conj.id, {
|
|
211
|
+
type: 'path',
|
|
212
|
+
label: `Conj: ${e1Label} + ${e2Label} → ${bridgeLabel}`,
|
|
213
|
+
pathType: 'conjunction',
|
|
214
|
+
hops: conj.hops,
|
|
215
|
+
entities: [conj.seed1, conj.seed2, conj.bridge],
|
|
216
|
+
});
|
|
217
|
+
for (const entityId of [conj.seed1, conj.seed2, conj.bridge]) {
|
|
218
|
+
if (graph.hasNode(entityId) && !graph.hasEdge(conj.id, entityId)) {
|
|
219
|
+
graph.addEdge(conj.id, entityId, { relation: 'includes', weight: 1 });
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
compositionChains: chains,
|
|
225
|
+
conjunctions,
|
|
226
|
+
totalPaths: chains.length + conjunctions.length,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=path-extraction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-extraction.js","sourceRoot":"","sources":["../../src/deep/path-extraction.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAkC,UAAU,EAAY,MAAM,YAAY,CAAC;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAoCpD,qEAAqE;AAErE;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACnC,KAAoD,EACpD,MAA6B;IAE7B,MAAM,OAAO,GAAG,MAAM,EAAE,YAAY,IAAI,CAAC,CAAC;IAC1C,MAAM,OAAO,GAAG,MAAM,EAAE,YAAY,IAAI,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,MAAM,EAAE,KAAK,IAAI,IAAI,CAAC;IAEpC,MAAM,MAAM,GAAuB,EAAE,CAAC;IACtC,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;IAEzC,uBAAuB;IACvB,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAY,EAAE,KAAqB,EAAE,EAAE;QACtD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,0DAA0D;IAC1D,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,eAAe,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IAElF,KAAK,MAAM,SAAS,IAAI,WAAW,EAAE,CAAC;QAClC,uDAAuD;QACvD,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAEzD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,GAAG,OAAO;gBAAE,SAAS;YAEjD,IAAI,KAAK,EAAE,CAAC;gBACR,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACpC,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC1D,IAAI,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC;oBAAE,SAAS;gBACxE,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC5B,CAAC;YAED,MAAM,EAAE,GAAG,UAAU,CAAC,KAAK,EAAE,mBAAmB,CAAC,CAAC;YAClD,MAAM,CAAC,IAAI,CAAC;gBACR,EAAE;gBACF,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;gBAC9B,SAAS,EAAE,IAAI,CAAC,SAAS;aAC5B,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAOD,oEAAoE;AACpE,SAAS,eAAe,CACpB,KAAoD,EACpD,KAAa,EACb,OAAe;IAEf,MAAM,OAAO,GAAsB,EAAE,CAAC;IAEtC,SAAS,GAAG,CAAC,OAAe,EAAE,IAAc,EAAE,SAAmB,EAAE,OAAoB;QACnF,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;YACrE,CAAC;YACD,OAAO;QACX,CAAC;QAED,sCAAsC;QACtC,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACzC,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,SAAS;YAClC,IAAI,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,QAAQ;gBAAE,SAAS;YAEhE,MAAM,KAAK,GAAG,KAAK,CAAC,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAClB,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAE/B,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YACtC,QAAQ,GAAG,IAAI,CAAC;YAEhB,IAAI,CAAC,GAAG,EAAE,CAAC;YACX,SAAS,CAAC,GAAG,EAAE,CAAC;YAChB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;QAED,2CAA2C;QAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvC,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,SAAS;YAClC,IAAI,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,QAAQ;gBAAE,SAAS;YAEhE,MAAM,KAAK,GAAG,KAAK,CAAC,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAClB,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAE/B,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YACtC,QAAQ,GAAG,IAAI,CAAC;YAEhB,IAAI,CAAC,GAAG,EAAE,CAAC;YACX,SAAS,CAAC,GAAG,EAAE,CAAC;YAChB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;QAED,gEAAgE;QAChE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;QACrE,CAAC;IACL,CAAC;IAED,GAAG,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1C,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,qEAAqE;AAErE;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAC9B,KAAoD,EACpD,MAA6B;IAE7B,MAAM,QAAQ,GAAG,MAAM,EAAE,mBAAmB,IAAI,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,MAAM,EAAE,KAAK,IAAI,IAAI,CAAC;IAEpC,MAAM,YAAY,GAAsB,EAAE,CAAC;IAC3C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpC,uBAAuB;IACvB,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAY,EAAE,KAAqB,EAAE,EAAE;QACtD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,oDAAoD;IACpD,MAAM,YAAY,GAAG,IAAI,GAAG,EAA+B,CAAC;IAC5D,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;QAC/B,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,oDAAoD;IACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9C,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC;YACrC,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC;YAErC,iCAAiC;YACjC,KAAK,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,MAAM,EAAE,CAAC;gBAChC,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC9B,IAAI,EAAE,KAAK,SAAS;oBAAE,SAAS;gBAC/B,IAAI,MAAM,KAAK,EAAE,IAAI,MAAM,KAAK,EAAE;oBAAE,SAAS;gBAE7C,MAAM,OAAO,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,MAAM,CAAC;gBACzD,IAAI,KAAK,IAAI,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC;oBAAE,SAAS;gBAC9C,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAEvB,MAAM,EAAE,GAAG,UAAU,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;gBAC5C,YAAY,CAAC,IAAI,CAAC;oBACd,EAAE;oBACF,KAAK,EAAE,EAAE;oBACT,KAAK,EAAE,EAAE;oBACT,MAAM,EAAE,MAAM;oBACd,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC;iBACzB,CAAC,CAAC;YACP,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,YAAY,CAAC;AACxB,CAAC;AAED,4EAA4E;AAC5E,SAAS,kBAAkB,CACvB,KAAoD,EACpD,KAAa,EACb,QAAgB;IAEhB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,MAAM,KAAK,GAAqC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACtE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAEnB,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;QACjC,IAAI,CAAC,IAAI,QAAQ;YAAE,SAAS;QAE5B,yBAAyB;QACzB,KAAK,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC,QAAgB,EAAE,EAAE;YAC3C,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAAE,OAAO;YAC/B,IAAI,KAAK,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAO;YAChE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACP,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,qBAAqB;IACzC,OAAO,IAAI,CAAC;AAChB,CAAC;AAED,qEAAqE;AAErE,qEAAqE;AACrE,MAAM,UAAU,YAAY,CACxB,KAAoD,EACpD,MAA6B;IAE7B,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAEvD,kCAAkC;IAClC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACzB,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE;YACtB,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,UAAU,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YAC9F,QAAQ,EAAE,mBAAmB;YAC7B,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;SAC3B,CAAC,CAAC;QACH,8CAA8C;QAC9C,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACpC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC;gBAChE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;YAC3E,CAAC;QACL,CAAC;IACL,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;QACzE,MAAM,OAAO,GAAG,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;QACzE,MAAM,WAAW,GAAG,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;QAC/E,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,EAAE;YACrB,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,SAAS,OAAO,MAAM,OAAO,MAAM,WAAW,EAAE;YACvD,QAAQ,EAAE,aAAa;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC;SAClD,CAAC,CAAC;QACH,KAAK,MAAM,QAAQ,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3D,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,CAAC;gBAC/D,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;YAC1E,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO;QACH,iBAAiB,EAAE,MAAM;QACzB,YAAY;QACZ,UAAU,EAAE,MAAM,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM;KAClD,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result quality assessment for deep search sessions.
|
|
3
|
+
*
|
|
4
|
+
* After each search round, compute quality indicators independently.
|
|
5
|
+
* Each indicator has its own threshold — no weighted sum.
|
|
6
|
+
*
|
|
7
|
+
* Verdict logic:
|
|
8
|
+
* - good: all indicators pass
|
|
9
|
+
* - acceptable: ≤2 indicators fail
|
|
10
|
+
* - poor: ≥3 indicators fail
|
|
11
|
+
*
|
|
12
|
+
* Novelty uses SimHash similarity < 0.7 as "not similar" threshold
|
|
13
|
+
* (paired with dedup threshold of 0.85).
|
|
14
|
+
*/
|
|
15
|
+
import { DirectedGraph } from 'graphology';
|
|
16
|
+
import { SessionResult } from './session.js';
|
|
17
|
+
import { GraphNodeAttrs, GraphEdgeAttrs } from './graph.js';
|
|
18
|
+
export interface IndicatorResult {
|
|
19
|
+
value: number;
|
|
20
|
+
threshold: number;
|
|
21
|
+
pass: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface QualityBreakdown {
|
|
24
|
+
resultCount: IndicatorResult;
|
|
25
|
+
contentDepth: IndicatorResult;
|
|
26
|
+
entityRichness: IndicatorResult;
|
|
27
|
+
sourceDiversity: IndicatorResult;
|
|
28
|
+
novelty: IndicatorResult;
|
|
29
|
+
}
|
|
30
|
+
export interface QualityScore {
|
|
31
|
+
verdict: 'good' | 'acceptable' | 'poor';
|
|
32
|
+
breakdown: QualityBreakdown;
|
|
33
|
+
failedIndicators: string[];
|
|
34
|
+
}
|
|
35
|
+
export interface QualityThresholds {
|
|
36
|
+
resultCount: number;
|
|
37
|
+
contentDepth: number;
|
|
38
|
+
entityRichness: number;
|
|
39
|
+
sourceDiversity: number;
|
|
40
|
+
novelty: number;
|
|
41
|
+
}
|
|
42
|
+
/** Assess the quality of new search results against session context.
|
|
43
|
+
* All indicators use independent thresholds — no weighted sum. */
|
|
44
|
+
export declare function assessResultQuality(newResults: SessionResult[], sessionResults: SessionResult[], graph: DirectedGraph<GraphNodeAttrs, GraphEdgeAttrs>, thresholds?: Partial<QualityThresholds>): QualityScore;
|
|
45
|
+
//# sourceMappingURL=quality-assess.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-assess.d.ts","sourceRoot":"","sources":["../../src/deep/quality-assess.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAI5D,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC7B,WAAW,EAAE,eAAe,CAAC;IAC7B,YAAY,EAAE,eAAe,CAAC;IAC9B,cAAc,EAAE,eAAe,CAAC;IAChC,eAAe,EAAE,eAAe,CAAC;IACjC,OAAO,EAAE,eAAe,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY;IACzB,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,MAAM,CAAC;IACxC,SAAS,EAAE,gBAAgB,CAAC;IAC5B,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACnB;AAwGD;mEACmE;AACnE,wBAAgB,mBAAmB,CAC/B,UAAU,EAAE,aAAa,EAAE,EAC3B,cAAc,EAAE,aAAa,EAAE,EAC/B,KAAK,EAAE,aAAa,CAAC,cAAc,EAAE,cAAc,CAAC,EACpD,UAAU,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GACxC,YAAY,CAyBd"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result quality assessment for deep search sessions.
|
|
3
|
+
*
|
|
4
|
+
* After each search round, compute quality indicators independently.
|
|
5
|
+
* Each indicator has its own threshold — no weighted sum.
|
|
6
|
+
*
|
|
7
|
+
* Verdict logic:
|
|
8
|
+
* - good: all indicators pass
|
|
9
|
+
* - acceptable: ≤2 indicators fail
|
|
10
|
+
* - poor: ≥3 indicators fail
|
|
11
|
+
*
|
|
12
|
+
* Novelty uses SimHash similarity < 0.7 as "not similar" threshold
|
|
13
|
+
* (paired with dedup threshold of 0.85).
|
|
14
|
+
*/
|
|
15
|
+
import { SimHash } from './simhash.js';
|
|
16
|
+
const DEFAULT_THRESHOLDS = {
|
|
17
|
+
resultCount: 5,
|
|
18
|
+
contentDepth: 150,
|
|
19
|
+
entityRichness: 2,
|
|
20
|
+
sourceDiversity: 3,
|
|
21
|
+
novelty: 0.3,
|
|
22
|
+
};
|
|
23
|
+
// ── Indicator computations ────────────────────────────────────────
|
|
24
|
+
/** Extract domain from URL */
|
|
25
|
+
function extractDomain(url) {
|
|
26
|
+
try {
|
|
27
|
+
return new URL(url).hostname;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return '';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Compute result count indicator */
|
|
34
|
+
function computeResultCount(newResults, threshold) {
|
|
35
|
+
const value = newResults.length;
|
|
36
|
+
return { value, threshold, pass: value >= threshold };
|
|
37
|
+
}
|
|
38
|
+
/** Compute content depth indicator — average content length of extracted results only */
|
|
39
|
+
function computeContentDepth(newResults, threshold) {
|
|
40
|
+
const extracted = newResults.filter(r => r.content && r.content.length > 0);
|
|
41
|
+
if (extracted.length === 0) {
|
|
42
|
+
return { value: 0, threshold, pass: false };
|
|
43
|
+
}
|
|
44
|
+
const totalLength = extracted.reduce((sum, r) => sum + (r.content?.length ?? 0), 0);
|
|
45
|
+
const value = totalLength / extracted.length;
|
|
46
|
+
return { value, threshold, pass: value >= threshold };
|
|
47
|
+
}
|
|
48
|
+
/** Compute entity richness indicator — count of Agent-added entities in the graph */
|
|
49
|
+
function computeEntityRichness(graph, threshold) {
|
|
50
|
+
let entityCount = 0;
|
|
51
|
+
graph.forEachNode((_node, attrs) => {
|
|
52
|
+
if (attrs.type === 'entity')
|
|
53
|
+
entityCount++;
|
|
54
|
+
});
|
|
55
|
+
return { value: entityCount, threshold, pass: entityCount >= threshold };
|
|
56
|
+
}
|
|
57
|
+
/** Compute source diversity indicator — number of distinct domains */
|
|
58
|
+
function computeSourceDiversity(newResults, threshold) {
|
|
59
|
+
const domains = new Set();
|
|
60
|
+
for (const r of newResults) {
|
|
61
|
+
const domain = extractDomain(r.url);
|
|
62
|
+
if (domain)
|
|
63
|
+
domains.add(domain);
|
|
64
|
+
}
|
|
65
|
+
const value = domains.size;
|
|
66
|
+
return { value, threshold, pass: value >= threshold };
|
|
67
|
+
}
|
|
68
|
+
/** Compute novelty indicator — fraction of new results not similar to existing session results.
|
|
69
|
+
* Uses SimHash similarity < 0.7 as "not similar" threshold.
|
|
70
|
+
* Caches SimHash results for performance. */
|
|
71
|
+
function computeNovelty(newResults, sessionResults, threshold) {
|
|
72
|
+
if (newResults.length === 0) {
|
|
73
|
+
return { value: 0, threshold, pass: false };
|
|
74
|
+
}
|
|
75
|
+
if (sessionResults.length === 0) {
|
|
76
|
+
// No prior results → everything is novel
|
|
77
|
+
return { value: 1, threshold, pass: true };
|
|
78
|
+
}
|
|
79
|
+
const simhash = new SimHash();
|
|
80
|
+
// Cache existing hashes to avoid recomputation
|
|
81
|
+
const existingHashes = sessionResults.map(r => simhash.hash(`${r.title} ${r.content || ''}`));
|
|
82
|
+
let novelCount = 0;
|
|
83
|
+
for (const r of newResults) {
|
|
84
|
+
const h = simhash.hash(`${r.title} ${r.content || ''}`);
|
|
85
|
+
let isSimilar = false;
|
|
86
|
+
for (const existing of existingHashes) {
|
|
87
|
+
if (simhash.similarity(h, existing) >= 0.7) {
|
|
88
|
+
isSimilar = true;
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (!isSimilar)
|
|
93
|
+
novelCount++;
|
|
94
|
+
}
|
|
95
|
+
const value = novelCount / newResults.length;
|
|
96
|
+
return { value, threshold, pass: value >= threshold };
|
|
97
|
+
}
|
|
98
|
+
// ── Main assessment ───────────────────────────────────────────────
|
|
99
|
+
/** Assess the quality of new search results against session context.
|
|
100
|
+
* All indicators use independent thresholds — no weighted sum. */
|
|
101
|
+
export function assessResultQuality(newResults, sessionResults, graph, thresholds) {
|
|
102
|
+
const t = { ...DEFAULT_THRESHOLDS, ...thresholds };
|
|
103
|
+
const breakdown = {
|
|
104
|
+
resultCount: computeResultCount(newResults, t.resultCount),
|
|
105
|
+
contentDepth: computeContentDepth(newResults, t.contentDepth),
|
|
106
|
+
entityRichness: computeEntityRichness(graph, t.entityRichness),
|
|
107
|
+
sourceDiversity: computeSourceDiversity(newResults, t.sourceDiversity),
|
|
108
|
+
novelty: computeNovelty(newResults, sessionResults, t.novelty),
|
|
109
|
+
};
|
|
110
|
+
const failedIndicators = Object.entries(breakdown)
|
|
111
|
+
.filter(([, v]) => !v.pass)
|
|
112
|
+
.map(([k]) => k);
|
|
113
|
+
let verdict;
|
|
114
|
+
if (failedIndicators.length === 0) {
|
|
115
|
+
verdict = 'good';
|
|
116
|
+
}
|
|
117
|
+
else if (failedIndicators.length <= 2) {
|
|
118
|
+
verdict = 'acceptable';
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
verdict = 'poor';
|
|
122
|
+
}
|
|
123
|
+
return { verdict, breakdown, failedIndicators };
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=quality-assess.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-assess.js","sourceRoot":"","sources":["../../src/deep/quality-assess.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Query redundancy detection via Jaccard similarity.
|
|
3
|
+
*
|
|
4
|
+
* Before executing a new query, compare it against all historical queries
|
|
5
|
+
* in the session. If similarity exceeds a threshold, take action:
|
|
6
|
+
* - warn: output warning, proceed with search
|
|
7
|
+
* - adjust: auto-remove overlapping terms, add differentiation
|
|
8
|
+
* - skip: skip redundant query entirely
|
|
9
|
+
*
|
|
10
|
+
* Short queries (≤3 words) use character-level bigram Jaccard to avoid
|
|
11
|
+
* low similarity from minor word differences. Longer queries use word-level Jaccard.
|
|
12
|
+
*/
|
|
13
|
+
export interface RedundancyConfig {
|
|
14
|
+
jaccardThreshold: number;
|
|
15
|
+
action: 'warn' | 'adjust' | 'skip';
|
|
16
|
+
}
|
|
17
|
+
export interface RedundancyResult {
|
|
18
|
+
isRedundant: boolean;
|
|
19
|
+
maxSimilarity: number;
|
|
20
|
+
similarQueries: Array<{
|
|
21
|
+
query: string;
|
|
22
|
+
similarity: number;
|
|
23
|
+
}>;
|
|
24
|
+
adjustedQuery?: string;
|
|
25
|
+
action: RedundancyConfig['action'];
|
|
26
|
+
}
|
|
27
|
+
/** Compute Jaccard similarity between two queries.
|
|
28
|
+
* - ≤2 words: character-level bigram Jaccard (case-insensitive)
|
|
29
|
+
* - >2 words: word-level Jaccard (case-insensitive) */
|
|
30
|
+
export declare function computeJaccard(a: string, b: string): number;
|
|
31
|
+
/** Adjust a redundant query by removing overlapping terms and adding differentiation.
|
|
32
|
+
* Returns the adjusted query string, or the original if no adjustment is possible. */
|
|
33
|
+
export declare function adjustQuery(newQuery: string, similarQueries: Array<{
|
|
34
|
+
query: string;
|
|
35
|
+
similarity: number;
|
|
36
|
+
}>): string;
|
|
37
|
+
/** Check a new query against session history for redundancy. */
|
|
38
|
+
export declare function checkQueryRedundancy(newQuery: string, sessionHistory: string[], config: RedundancyConfig): RedundancyResult;
|
|
39
|
+
//# sourceMappingURL=query-redundancy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-redundancy.d.ts","sourceRoot":"","sources":["../../src/deep/query-redundancy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,WAAW,gBAAgB;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;CACtC;AA6BD;;wDAEwD;AACxD,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAkB3D;AAID;uFACuF;AACvF,wBAAgB,WAAW,CACvB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,GAC7D,MAAM,CAwBR;AAID,gEAAgE;AAChE,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,EAAE,EACxB,MAAM,EAAE,gBAAgB,GACzB,gBAAgB,CA4BlB"}
|