@hazeljs/kag 0.0.0-stage → 2.0.9
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 +122 -2
- package/dist/adapters/graphrag.adapter.d.ts +47 -0
- package/dist/adapters/graphrag.adapter.d.ts.map +1 -0
- package/dist/adapters/graphrag.adapter.js +111 -0
- package/dist/confidence.d.ts +7 -0
- package/dist/confidence.d.ts.map +1 -0
- package/dist/confidence.js +40 -0
- package/dist/errors/kag.error.d.ts +42 -0
- package/dist/errors/kag.error.d.ts.map +1 -0
- package/dist/errors/kag.error.js +80 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/ingestion/ingest.d.ts +24 -0
- package/dist/ingestion/ingest.d.ts.map +1 -0
- package/dist/ingestion/ingest.js +61 -0
- package/dist/kag.module.d.ts +29 -0
- package/dist/kag.module.d.ts.map +1 -0
- package/dist/kag.module.js +58 -0
- package/dist/kag.service.d.ts +66 -0
- package/dist/kag.service.d.ts.map +1 -0
- package/dist/kag.service.js +92 -0
- package/dist/knowledge-graph.d.ts +50 -0
- package/dist/knowledge-graph.d.ts.map +1 -0
- package/dist/knowledge-graph.js +290 -0
- package/dist/planner/heuristic-query-planner.d.ts +36 -0
- package/dist/planner/heuristic-query-planner.d.ts.map +1 -0
- package/dist/planner/heuristic-query-planner.js +67 -0
- package/dist/planner/industry-profiles.d.ts +34 -0
- package/dist/planner/industry-profiles.d.ts.map +1 -0
- package/dist/planner/industry-profiles.js +83 -0
- package/dist/resolution/entity-resolver.d.ts +21 -0
- package/dist/resolution/entity-resolver.d.ts.map +1 -0
- package/dist/resolution/entity-resolver.js +123 -0
- package/dist/security/authorizer.d.ts +27 -0
- package/dist/security/authorizer.d.ts.map +1 -0
- package/dist/security/authorizer.js +57 -0
- package/dist/stores/in-memory-knowledge.store.d.ts +22 -0
- package/dist/stores/in-memory-knowledge.store.d.ts.map +1 -0
- package/dist/stores/in-memory-knowledge.store.js +186 -0
- package/dist/temporal.d.ts +7 -0
- package/dist/temporal.d.ts.map +1 -0
- package/dist/temporal.js +63 -0
- package/dist/types.d.ts +207 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +15 -0
- package/package.json +78 -4
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
var KagModule_1;
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.KagModule = void 0;
|
|
14
|
+
const core_1 = require("@hazeljs/core");
|
|
15
|
+
const core_2 = __importDefault(require("@hazeljs/core"));
|
|
16
|
+
const kag_service_1 = require("./kag.service");
|
|
17
|
+
const types_1 = require("./types");
|
|
18
|
+
let KagModule = KagModule_1 = class KagModule {
|
|
19
|
+
static forRoot(options = {}) {
|
|
20
|
+
core_2.default.info('Configuring KAG module...');
|
|
21
|
+
const service = new kag_service_1.KagService(options);
|
|
22
|
+
return {
|
|
23
|
+
module: KagModule_1,
|
|
24
|
+
providers: [
|
|
25
|
+
{ provide: types_1.KAG_OPTIONS, useValue: options },
|
|
26
|
+
{ provide: kag_service_1.KagService, useValue: service },
|
|
27
|
+
],
|
|
28
|
+
exports: [kag_service_1.KagService],
|
|
29
|
+
global: true,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
static forRootAsync(options) {
|
|
33
|
+
return {
|
|
34
|
+
module: KagModule_1,
|
|
35
|
+
providers: [
|
|
36
|
+
{
|
|
37
|
+
provide: types_1.KAG_OPTIONS,
|
|
38
|
+
useFactory: options.useFactory,
|
|
39
|
+
inject: options.inject,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
provide: kag_service_1.KagService,
|
|
43
|
+
useFactory: (...args) => new kag_service_1.KagService(args[0]),
|
|
44
|
+
inject: [types_1.KAG_OPTIONS],
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
exports: [kag_service_1.KagService],
|
|
48
|
+
global: true,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
exports.KagModule = KagModule;
|
|
53
|
+
exports.KagModule = KagModule = KagModule_1 = __decorate([
|
|
54
|
+
(0, core_1.HazelModule)({
|
|
55
|
+
providers: [],
|
|
56
|
+
exports: [],
|
|
57
|
+
})
|
|
58
|
+
], KagModule);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { AskOptions, ContextContribution, ContextContributor, KagModuleOptions, KnowledgeAnswer, EntityResolutionResult, KnowledgeEntity, KnowledgeFact, KnowledgeRelation, ObservationPromotion, TraversalResult } from './types';
|
|
2
|
+
import { KnowledgeGraph } from './knowledge-graph';
|
|
3
|
+
import { type IngestBatch, type IngestResult } from './ingestion/ingest';
|
|
4
|
+
import { type GraphStoreLike } from './adapters/graphrag.adapter';
|
|
5
|
+
export declare class KagService implements ContextContributor {
|
|
6
|
+
readonly kind: "kag";
|
|
7
|
+
private readonly graphs;
|
|
8
|
+
private readonly options;
|
|
9
|
+
constructor(options?: KagModuleOptions);
|
|
10
|
+
forTenant(tenantId: string, graph?: string): KnowledgeGraph;
|
|
11
|
+
private graphOrThrow;
|
|
12
|
+
entity(input: KnowledgeEntity, opts?: {
|
|
13
|
+
tenantId?: string;
|
|
14
|
+
graph?: string;
|
|
15
|
+
}): Promise<KnowledgeEntity>;
|
|
16
|
+
relate(input: Omit<KnowledgeRelation, 'id'> & {
|
|
17
|
+
id?: string;
|
|
18
|
+
}, opts?: {
|
|
19
|
+
tenantId?: string;
|
|
20
|
+
graph?: string;
|
|
21
|
+
}): Promise<KnowledgeRelation>;
|
|
22
|
+
fact(input: KnowledgeFact, opts?: {
|
|
23
|
+
tenantId?: string;
|
|
24
|
+
graph?: string;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
fact: KnowledgeFact;
|
|
27
|
+
contradictions: KnowledgeFact[];
|
|
28
|
+
}>;
|
|
29
|
+
ingest(batch: IngestBatch, opts?: {
|
|
30
|
+
tenantId?: string;
|
|
31
|
+
graph?: string;
|
|
32
|
+
raw?: unknown;
|
|
33
|
+
}): Promise<IngestResult>;
|
|
34
|
+
traverse(seedIds: string[], options?: {
|
|
35
|
+
depth?: number;
|
|
36
|
+
asOf?: Date | string;
|
|
37
|
+
tenantId?: string;
|
|
38
|
+
graph?: string;
|
|
39
|
+
}): Promise<TraversalResult>;
|
|
40
|
+
ask(question: string, options?: AskOptions & {
|
|
41
|
+
tenantId?: string;
|
|
42
|
+
}): Promise<KnowledgeAnswer>;
|
|
43
|
+
resolve(candidate: KnowledgeEntity, opts?: {
|
|
44
|
+
tenantId?: string;
|
|
45
|
+
graph?: string;
|
|
46
|
+
}): Promise<EntityResolutionResult>;
|
|
47
|
+
promoteObservation(observation: ObservationPromotion, opts?: {
|
|
48
|
+
tenantId?: string;
|
|
49
|
+
graph?: string;
|
|
50
|
+
}): Promise<KnowledgeFact | null>;
|
|
51
|
+
importGraphRag(graphStore: GraphStoreLike, opts?: {
|
|
52
|
+
tenantId?: string;
|
|
53
|
+
graph?: string;
|
|
54
|
+
}): Promise<{
|
|
55
|
+
entities: number;
|
|
56
|
+
relations: number;
|
|
57
|
+
}>;
|
|
58
|
+
contribute(request: {
|
|
59
|
+
query: string;
|
|
60
|
+
tenantId: string;
|
|
61
|
+
namespace?: string;
|
|
62
|
+
agentId?: string;
|
|
63
|
+
}): Promise<ContextContribution>;
|
|
64
|
+
private key;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=kag.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kag.service.d.ts","sourceRoot":"","sources":["../src/kag.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.KagService = void 0;
|
|
13
|
+
const core_1 = require("@hazeljs/core");
|
|
14
|
+
const knowledge_graph_1 = require("./knowledge-graph");
|
|
15
|
+
const kag_error_1 = require("./errors/kag.error");
|
|
16
|
+
const ingest_1 = require("./ingestion/ingest");
|
|
17
|
+
const graphrag_adapter_1 = require("./adapters/graphrag.adapter");
|
|
18
|
+
let KagService = class KagService {
|
|
19
|
+
constructor(options = {}) {
|
|
20
|
+
this.kind = 'kag';
|
|
21
|
+
this.graphs = new Map();
|
|
22
|
+
this.options = options;
|
|
23
|
+
if (options.tenantId) {
|
|
24
|
+
this.graphs.set(this.key(options.tenantId, options.graph), new knowledge_graph_1.KnowledgeGraph({
|
|
25
|
+
...options,
|
|
26
|
+
tenantId: options.tenantId,
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
forTenant(tenantId, graph) {
|
|
31
|
+
const k = this.key(tenantId, graph ?? this.options.graph);
|
|
32
|
+
let g = this.graphs.get(k);
|
|
33
|
+
if (!g) {
|
|
34
|
+
g = new knowledge_graph_1.KnowledgeGraph({
|
|
35
|
+
...this.options,
|
|
36
|
+
tenantId,
|
|
37
|
+
graph: graph ?? this.options.graph,
|
|
38
|
+
});
|
|
39
|
+
this.graphs.set(k, g);
|
|
40
|
+
}
|
|
41
|
+
return g;
|
|
42
|
+
}
|
|
43
|
+
graphOrThrow(tenantId, graph) {
|
|
44
|
+
const tid = tenantId ?? this.options.tenantId;
|
|
45
|
+
if (!tid) {
|
|
46
|
+
throw kag_error_1.KagError.tenantRequired();
|
|
47
|
+
}
|
|
48
|
+
return this.forTenant(tid, graph);
|
|
49
|
+
}
|
|
50
|
+
async entity(input, opts) {
|
|
51
|
+
return this.graphOrThrow(opts?.tenantId, opts?.graph).entity(input);
|
|
52
|
+
}
|
|
53
|
+
async relate(input, opts) {
|
|
54
|
+
return this.graphOrThrow(opts?.tenantId, opts?.graph).relate(input);
|
|
55
|
+
}
|
|
56
|
+
async fact(input, opts) {
|
|
57
|
+
return this.graphOrThrow(opts?.tenantId, opts?.graph).fact(input);
|
|
58
|
+
}
|
|
59
|
+
async ingest(batch, opts) {
|
|
60
|
+
const g = this.graphOrThrow(opts?.tenantId, opts?.graph);
|
|
61
|
+
return (0, ingest_1.ingestKnowledge)(g, batch, {
|
|
62
|
+
extractor: this.options.extractor,
|
|
63
|
+
raw: opts?.raw,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async traverse(seedIds, options) {
|
|
67
|
+
return this.graphOrThrow(options?.tenantId, options?.graph).traverse(seedIds, options);
|
|
68
|
+
}
|
|
69
|
+
async ask(question, options = {}) {
|
|
70
|
+
return this.graphOrThrow(options.tenantId, options.graph).ask(question, options);
|
|
71
|
+
}
|
|
72
|
+
async resolve(candidate, opts) {
|
|
73
|
+
return this.graphOrThrow(opts?.tenantId, opts?.graph).resolve(candidate);
|
|
74
|
+
}
|
|
75
|
+
async promoteObservation(observation, opts) {
|
|
76
|
+
return this.graphOrThrow(opts?.tenantId, opts?.graph).promoteObservation(observation);
|
|
77
|
+
}
|
|
78
|
+
async importGraphRag(graphStore, opts) {
|
|
79
|
+
return (0, graphrag_adapter_1.importGraph)(this.graphOrThrow(opts?.tenantId, opts?.graph), graphStore);
|
|
80
|
+
}
|
|
81
|
+
async contribute(request) {
|
|
82
|
+
return this.forTenant(request.tenantId, request.namespace).contribute(request);
|
|
83
|
+
}
|
|
84
|
+
key(tenantId, graph) {
|
|
85
|
+
return `${tenantId}::${graph ?? 'default'}`;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
exports.KagService = KagService;
|
|
89
|
+
exports.KagService = KagService = __decorate([
|
|
90
|
+
(0, core_1.Service)(),
|
|
91
|
+
__metadata("design:paramtypes", [Object])
|
|
92
|
+
], KagService);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { AskOptions, ContextContribution, ContextContributor, EntityResolutionResult, KagModuleOptions, KnowledgeAnswer, KnowledgeEntity, KnowledgeFact, KnowledgeRelation, KnowledgeScope, KnowledgeStore, ObservationPromotion, TraversalResult } from './types';
|
|
2
|
+
export interface KnowledgeGraphOptions extends KagModuleOptions {
|
|
3
|
+
store?: KnowledgeStore;
|
|
4
|
+
tenantId: string;
|
|
5
|
+
graph?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Primary KAG facade for scripts and tests (similar to GraphRAGPipeline).
|
|
9
|
+
*/
|
|
10
|
+
export declare class KnowledgeGraph implements ContextContributor {
|
|
11
|
+
readonly kind: "kag";
|
|
12
|
+
private readonly store;
|
|
13
|
+
private readonly scope;
|
|
14
|
+
private readonly resolver;
|
|
15
|
+
private readonly planner;
|
|
16
|
+
private readonly authorizer;
|
|
17
|
+
private readonly retriever?;
|
|
18
|
+
private readonly llm?;
|
|
19
|
+
private readonly confidenceAggregation;
|
|
20
|
+
private readonly externalEmitter?;
|
|
21
|
+
private readonly localEmitter;
|
|
22
|
+
constructor(options: KnowledgeGraphOptions);
|
|
23
|
+
on(event: string, listener: (...args: unknown[]) => void): this;
|
|
24
|
+
getScope(): KnowledgeScope;
|
|
25
|
+
entity(input: KnowledgeEntity): Promise<KnowledgeEntity>;
|
|
26
|
+
relate(input: Omit<KnowledgeRelation, 'id'> & {
|
|
27
|
+
id?: string;
|
|
28
|
+
}): Promise<KnowledgeRelation>;
|
|
29
|
+
fact(input: KnowledgeFact): Promise<{
|
|
30
|
+
fact: KnowledgeFact;
|
|
31
|
+
contradictions: KnowledgeFact[];
|
|
32
|
+
}>;
|
|
33
|
+
resolve(candidate: KnowledgeEntity): Promise<EntityResolutionResult>;
|
|
34
|
+
traverse(seedIds: string[], options?: {
|
|
35
|
+
depth?: number;
|
|
36
|
+
asOf?: Date | string;
|
|
37
|
+
}): Promise<TraversalResult>;
|
|
38
|
+
ask(question: string, options?: AskOptions): Promise<KnowledgeAnswer>;
|
|
39
|
+
promoteObservation(observation: ObservationPromotion): Promise<KnowledgeFact | null>;
|
|
40
|
+
changes(from: Date | string, to: Date | string): Promise<KnowledgeFact[]>;
|
|
41
|
+
currentFacts(subject?: string): Promise<KnowledgeFact[]>;
|
|
42
|
+
contribute(request: {
|
|
43
|
+
query: string;
|
|
44
|
+
tenantId: string;
|
|
45
|
+
namespace?: string;
|
|
46
|
+
agentId?: string;
|
|
47
|
+
}): Promise<ContextContribution>;
|
|
48
|
+
private emit;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=knowledge-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"knowledge-graph.d.ts","sourceRoot":"","sources":["../src/knowledge-graph.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EAEf,eAAe,EAEf,aAAa,EAEb,iBAAiB,EAEjB,cAAc,EAEd,cAAc,EACd,oBAAoB,EACpB,eAAe,EAChB,MAAM,SAAS,CAAC;AAUjB,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,cAAe,YAAW,kBAAkB;IACvD,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAE/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiB;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsB;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAqB;IAChD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAA0B;IAC/C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAyD;IAC/F,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAmC;IACpE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;gBAEvC,OAAO,EAAE,qBAAqB;IAuB1C,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAK/D,QAAQ,IAAI,cAAc;IAIpB,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IAmBxD,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAe1F,IAAI,CACR,KAAK,EAAE,aAAa,GACnB,OAAO,CAAC;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,cAAc,EAAE,aAAa,EAAE,CAAA;KAAE,CAAC;IAa9D,OAAO,CAAC,SAAS,EAAE,eAAe,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAKpE,QAAQ,CACZ,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,IAAI,GAAG,MAAM,CAAA;KAAE,GACjD,OAAO,CAAC,eAAe,CAAC;IAKrB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IA+GzE,kBAAkB,CAAC,WAAW,EAAE,oBAAoB,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAqBpF,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,EAAE,EAAE,EAAE,IAAI,GAAG,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAKzE,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAQxD,UAAU,CAAC,OAAO,EAAE;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAYhC,OAAO,CAAC,IAAI;CAIb"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.KnowledgeGraph = void 0;
|
|
7
|
+
const eventemitter3_1 = __importDefault(require("eventemitter3"));
|
|
8
|
+
const crypto_1 = require("crypto");
|
|
9
|
+
const types_1 = require("./types");
|
|
10
|
+
const in_memory_knowledge_store_1 = require("./stores/in-memory-knowledge.store");
|
|
11
|
+
const entity_resolver_1 = require("./resolution/entity-resolver");
|
|
12
|
+
const heuristic_query_planner_1 = require("./planner/heuristic-query-planner");
|
|
13
|
+
const authorizer_1 = require("./security/authorizer");
|
|
14
|
+
const kag_error_1 = require("./errors/kag.error");
|
|
15
|
+
const confidence_1 = require("./confidence");
|
|
16
|
+
const temporal_1 = require("./temporal");
|
|
17
|
+
/**
|
|
18
|
+
* Primary KAG facade for scripts and tests (similar to GraphRAGPipeline).
|
|
19
|
+
*/
|
|
20
|
+
class KnowledgeGraph {
|
|
21
|
+
constructor(options) {
|
|
22
|
+
this.kind = 'kag';
|
|
23
|
+
this.localEmitter = new eventemitter3_1.default();
|
|
24
|
+
if (!options.tenantId) {
|
|
25
|
+
throw kag_error_1.KagError.tenantRequired();
|
|
26
|
+
}
|
|
27
|
+
this.store = options.store ?? new in_memory_knowledge_store_1.InMemoryKnowledgeStore(options.contradictionPolicy ?? 'rank');
|
|
28
|
+
this.scope = { tenantId: options.tenantId, graph: options.graph };
|
|
29
|
+
this.resolver = new entity_resolver_1.EntityResolver({
|
|
30
|
+
mergeThreshold: options.mergeThreshold ?? 0.9,
|
|
31
|
+
embed: options.embed,
|
|
32
|
+
strategies: options.embed ? ['exact', 'normalized', 'semantic'] : ['exact', 'normalized'],
|
|
33
|
+
});
|
|
34
|
+
this.planner =
|
|
35
|
+
options.planner ??
|
|
36
|
+
new heuristic_query_planner_1.HeuristicQueryPlanner({
|
|
37
|
+
industry: options.industry,
|
|
38
|
+
});
|
|
39
|
+
this.authorizer = options.authorizer ?? new authorizer_1.TenantKnowledgeAuthorizer(options.tenantId);
|
|
40
|
+
this.retriever = options.retriever;
|
|
41
|
+
this.llm = options.llm;
|
|
42
|
+
this.confidenceAggregation = options.confidenceAggregation ?? 'min';
|
|
43
|
+
this.externalEmitter = options.eventEmitter;
|
|
44
|
+
}
|
|
45
|
+
on(event, listener) {
|
|
46
|
+
this.localEmitter.on(event, listener);
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
getScope() {
|
|
50
|
+
return { ...this.scope };
|
|
51
|
+
}
|
|
52
|
+
async entity(input) {
|
|
53
|
+
await (0, authorizer_1.assertAuthorized)(this.authorizer, this.scope, 'write', {
|
|
54
|
+
kind: 'entity',
|
|
55
|
+
id: input.id,
|
|
56
|
+
type: input.type,
|
|
57
|
+
});
|
|
58
|
+
const existing = await this.store.listEntities(this.scope);
|
|
59
|
+
const resolution = await this.resolver.resolve(input, existing);
|
|
60
|
+
const toWrite = resolution.merged
|
|
61
|
+
? { ...resolution.merged, id: resolution.merged.id }
|
|
62
|
+
: { ...input, confidence: input.confidence ?? 1 };
|
|
63
|
+
const prior = await this.store.getEntity(this.scope, toWrite.id);
|
|
64
|
+
await this.store.upsertEntity(this.scope, toWrite);
|
|
65
|
+
this.emit(prior ? types_1.KAG_EVENTS.ENTITY_UPDATED : types_1.KAG_EVENTS.ENTITY_CREATED, toWrite);
|
|
66
|
+
return toWrite;
|
|
67
|
+
}
|
|
68
|
+
async relate(input) {
|
|
69
|
+
await (0, authorizer_1.assertAuthorized)(this.authorizer, this.scope, 'write', {
|
|
70
|
+
kind: 'relation',
|
|
71
|
+
type: input.type,
|
|
72
|
+
});
|
|
73
|
+
const relation = {
|
|
74
|
+
...input,
|
|
75
|
+
id: input.id ?? `${input.from}:${input.type}:${input.to}`,
|
|
76
|
+
confidence: input.confidence ?? 1,
|
|
77
|
+
};
|
|
78
|
+
await this.store.upsertRelation(this.scope, relation);
|
|
79
|
+
this.emit(types_1.KAG_EVENTS.RELATION_CREATED, relation);
|
|
80
|
+
return relation;
|
|
81
|
+
}
|
|
82
|
+
async fact(input) {
|
|
83
|
+
await (0, authorizer_1.assertAuthorized)(this.authorizer, this.scope, 'write', {
|
|
84
|
+
kind: 'fact',
|
|
85
|
+
id: input.subject,
|
|
86
|
+
});
|
|
87
|
+
const { contradictions } = await this.store.upsertFact(this.scope, input);
|
|
88
|
+
if (contradictions.length > 0) {
|
|
89
|
+
this.emit(types_1.KAG_EVENTS.CONTRADICTION_DETECTED, { fact: input, contradictions });
|
|
90
|
+
}
|
|
91
|
+
this.emit(types_1.KAG_EVENTS.FACT_ADDED, input);
|
|
92
|
+
return { fact: input, contradictions };
|
|
93
|
+
}
|
|
94
|
+
async resolve(candidate) {
|
|
95
|
+
const existing = await this.store.listEntities(this.scope);
|
|
96
|
+
return this.resolver.resolve(candidate, existing);
|
|
97
|
+
}
|
|
98
|
+
async traverse(seedIds, options) {
|
|
99
|
+
await (0, authorizer_1.assertAuthorized)(this.authorizer, this.scope, 'read', { kind: 'entity' });
|
|
100
|
+
return this.store.traverse(this.scope, seedIds, options);
|
|
101
|
+
}
|
|
102
|
+
async ask(question, options = {}) {
|
|
103
|
+
await (0, authorizer_1.assertAuthorized)(this.authorizer, this.scope, 'read', { kind: 'entity' });
|
|
104
|
+
const entities = await this.store.listEntities(this.scope);
|
|
105
|
+
const plan = await this.planner.plan(question, { scope: this.scope, entities });
|
|
106
|
+
const seeds = plan.seedIds.length > 0 ? plan.seedIds : entities.slice(0, 5).map((e) => e.id);
|
|
107
|
+
const traversal = await this.store.traverse(this.scope, seeds, {
|
|
108
|
+
depth: options.depth ?? plan.depth,
|
|
109
|
+
relationTypes: plan.relationTypes,
|
|
110
|
+
asOf: options.asOf,
|
|
111
|
+
});
|
|
112
|
+
const evidence = [];
|
|
113
|
+
for (const rel of traversal.relations) {
|
|
114
|
+
evidence.push({
|
|
115
|
+
entity: rel.from,
|
|
116
|
+
relation: rel.type,
|
|
117
|
+
entity2: rel.to,
|
|
118
|
+
source: rel.source,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
for (const f of traversal.facts) {
|
|
122
|
+
evidence.push({ fact: f, source: f.source, entity: f.subject });
|
|
123
|
+
}
|
|
124
|
+
let alternatives;
|
|
125
|
+
const subjectIds = [
|
|
126
|
+
...new Set([
|
|
127
|
+
...seeds,
|
|
128
|
+
...traversal.entities.map((e) => e.id),
|
|
129
|
+
...traversal.facts.map((f) => f.subject),
|
|
130
|
+
]),
|
|
131
|
+
];
|
|
132
|
+
const query = await this.store.query(this.scope, {
|
|
133
|
+
entityIds: subjectIds.length > 0 ? subjectIds : undefined,
|
|
134
|
+
asOf: options.asOf,
|
|
135
|
+
});
|
|
136
|
+
if (query.contradictions && query.contradictions.length > 0) {
|
|
137
|
+
alternatives = query.contradictions.flat();
|
|
138
|
+
const winners = query.contradictions.map((group) => (0, confidence_1.rankFacts)(group)[0]);
|
|
139
|
+
for (const w of winners) {
|
|
140
|
+
if (!evidence.some((e) => e.fact?.id === w.id)) {
|
|
141
|
+
evidence.push({ fact: w, source: w.source, entity: w.subject });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (options.rag && this.retriever) {
|
|
146
|
+
const passages = await this.retriever.search(question, {
|
|
147
|
+
topK: 5,
|
|
148
|
+
tenantId: this.scope.tenantId,
|
|
149
|
+
});
|
|
150
|
+
for (const p of passages) {
|
|
151
|
+
evidence.push({
|
|
152
|
+
source: { type: 'rag', id: p.id },
|
|
153
|
+
fact: {
|
|
154
|
+
subject: '_rag',
|
|
155
|
+
predicate: 'passage',
|
|
156
|
+
object: p.content,
|
|
157
|
+
confidence: p.score ?? 0.7,
|
|
158
|
+
source: { type: 'rag', id: p.id },
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const sources = [];
|
|
164
|
+
for (const e of evidence) {
|
|
165
|
+
if (e.source)
|
|
166
|
+
sources.push(e.source);
|
|
167
|
+
if (e.fact?.source)
|
|
168
|
+
sources.push(e.fact.source);
|
|
169
|
+
}
|
|
170
|
+
const confidence = (0, confidence_1.aggregateConfidence)([
|
|
171
|
+
traversal.confidence,
|
|
172
|
+
...traversal.facts.map((f) => f.confidence ?? 1),
|
|
173
|
+
...traversal.relations.map((r) => r.confidence ?? 1),
|
|
174
|
+
], this.confidenceAggregation);
|
|
175
|
+
const explanation = options.explain
|
|
176
|
+
? formatExplanation(evidence, confidence, plan.template)
|
|
177
|
+
: undefined;
|
|
178
|
+
let answer;
|
|
179
|
+
if (this.llm) {
|
|
180
|
+
const prompt = `Answer using ONLY the following evidence. Do not invent facts.\n` +
|
|
181
|
+
`Question: ${question}\n` +
|
|
182
|
+
`Evidence:\n${JSON.stringify(evidence, null, 2)}\n` +
|
|
183
|
+
`Confidence: ${confidence.toFixed(2)}`;
|
|
184
|
+
answer = await this.llm(prompt);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
answer = explanation ?? summarizeEvidence(evidence);
|
|
188
|
+
}
|
|
189
|
+
const result = {
|
|
190
|
+
answer,
|
|
191
|
+
evidence,
|
|
192
|
+
sources: dedupeSources(sources),
|
|
193
|
+
confidence,
|
|
194
|
+
alternatives,
|
|
195
|
+
explanation,
|
|
196
|
+
};
|
|
197
|
+
this.emit(types_1.KAG_EVENTS.QUERY_COMPLETED, { question, confidence, evidenceCount: evidence.length });
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
async promoteObservation(observation) {
|
|
201
|
+
if (!observation.validated) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
if (observation.confidence === undefined || observation.confidence < 0) {
|
|
205
|
+
throw kag_error_1.KagError.validationError('Validated observations require a confidence score.');
|
|
206
|
+
}
|
|
207
|
+
const fact = {
|
|
208
|
+
id: (0, crypto_1.randomUUID)(),
|
|
209
|
+
subject: observation.subject,
|
|
210
|
+
predicate: observation.predicate,
|
|
211
|
+
object: observation.object,
|
|
212
|
+
confidence: observation.confidence,
|
|
213
|
+
source: observation.source ?? { type: 'memory', id: 'promotion' },
|
|
214
|
+
validFrom: observation.validFrom,
|
|
215
|
+
validUntil: observation.validUntil,
|
|
216
|
+
};
|
|
217
|
+
await this.fact(fact);
|
|
218
|
+
return fact;
|
|
219
|
+
}
|
|
220
|
+
async changes(from, to) {
|
|
221
|
+
const result = await this.store.query(this.scope, {});
|
|
222
|
+
return (0, temporal_1.changesBetween)(result.facts, from, to);
|
|
223
|
+
}
|
|
224
|
+
async currentFacts(subject) {
|
|
225
|
+
const result = await this.store.query(this.scope, {
|
|
226
|
+
entityIds: subject ? [subject] : undefined,
|
|
227
|
+
currentOnly: true,
|
|
228
|
+
});
|
|
229
|
+
return result.facts.filter((f) => (0, temporal_1.isFactValidAt)(f));
|
|
230
|
+
}
|
|
231
|
+
async contribute(request) {
|
|
232
|
+
if (request.tenantId !== this.scope.tenantId) {
|
|
233
|
+
throw kag_error_1.KagError.accessDenied('tenant');
|
|
234
|
+
}
|
|
235
|
+
const answer = await this.ask(request.query, { explain: true });
|
|
236
|
+
return {
|
|
237
|
+
text: answer.answer ?? answer.explanation ?? '',
|
|
238
|
+
evidence: answer.evidence,
|
|
239
|
+
fingerprint: `${this.scope.tenantId}:${answer.confidence}:${answer.evidence.length}`,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
emit(event, payload) {
|
|
243
|
+
this.localEmitter.emit(event, payload);
|
|
244
|
+
this.externalEmitter?.emit(event, payload);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
exports.KnowledgeGraph = KnowledgeGraph;
|
|
248
|
+
function formatExplanation(evidence, confidence, template) {
|
|
249
|
+
const lines = evidence.map((e) => {
|
|
250
|
+
if (e.relation && e.entity && e.entity2) {
|
|
251
|
+
return `${e.entity} -[${e.relation}]-> ${e.entity2}`;
|
|
252
|
+
}
|
|
253
|
+
if (e.fact) {
|
|
254
|
+
return (`${e.fact.subject}.${e.fact.predicate} = ${JSON.stringify(e.fact.object)}` +
|
|
255
|
+
(e.fact.source
|
|
256
|
+
? ` (source: ${e.fact.source.type}${e.fact.source.id ? ':' + e.fact.source.id : ''})`
|
|
257
|
+
: ''));
|
|
258
|
+
}
|
|
259
|
+
return JSON.stringify(e);
|
|
260
|
+
});
|
|
261
|
+
const header = template ? `Template: ${template}\n` : '';
|
|
262
|
+
return `${header}Evidence path (confidence ${confidence.toFixed(2)}):\n` + lines.join('\n');
|
|
263
|
+
}
|
|
264
|
+
function summarizeEvidence(evidence) {
|
|
265
|
+
if (evidence.length === 0)
|
|
266
|
+
return 'No knowledge evidence found.';
|
|
267
|
+
return evidence
|
|
268
|
+
.slice(0, 8)
|
|
269
|
+
.map((e) => {
|
|
270
|
+
if (e.relation)
|
|
271
|
+
return `${e.entity} ${e.relation} ${e.entity2}`;
|
|
272
|
+
if (e.fact)
|
|
273
|
+
return `${e.fact.subject} ${e.fact.predicate} ${JSON.stringify(e.fact.object)}`;
|
|
274
|
+
return '';
|
|
275
|
+
})
|
|
276
|
+
.filter(Boolean)
|
|
277
|
+
.join('; ');
|
|
278
|
+
}
|
|
279
|
+
function dedupeSources(sources) {
|
|
280
|
+
const seen = new Set();
|
|
281
|
+
const out = [];
|
|
282
|
+
for (const s of sources) {
|
|
283
|
+
const key = `${s.type}:${s.id ?? ''}`;
|
|
284
|
+
if (seen.has(key))
|
|
285
|
+
continue;
|
|
286
|
+
seen.add(key);
|
|
287
|
+
out.push(s);
|
|
288
|
+
}
|
|
289
|
+
return out;
|
|
290
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { KnowledgeEntity, KnowledgeQueryPlanner, KnowledgeScope } from '../types';
|
|
2
|
+
import { type IndustryProfile, type QueryTemplate } from './industry-profiles';
|
|
3
|
+
export interface HeuristicQueryPlannerOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Industry / domain profile(s). Defaults to GENERIC_INDUSTRY_PROFILE
|
|
6
|
+
* (no commerce-specific relation filters).
|
|
7
|
+
*/
|
|
8
|
+
industry?: IndustryProfile | IndustryProfile[];
|
|
9
|
+
/** Extra templates layered on top of the industry profile. */
|
|
10
|
+
templates?: QueryTemplate[];
|
|
11
|
+
/** Override default BFS depth when no template matches. */
|
|
12
|
+
defaultDepth?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* V1 planner: seed entities from the question + optional industry templates.
|
|
16
|
+
*
|
|
17
|
+
* Core behavior is industry-agnostic. Pass `COMMERCE_INDUSTRY_PROFILE` (or a
|
|
18
|
+
* custom profile) when your graph uses domain-specific relation types.
|
|
19
|
+
*/
|
|
20
|
+
export declare class HeuristicQueryPlanner implements KnowledgeQueryPlanner {
|
|
21
|
+
private readonly templates;
|
|
22
|
+
private readonly defaultDepth;
|
|
23
|
+
private readonly industryId;
|
|
24
|
+
constructor(options?: HeuristicQueryPlannerOptions);
|
|
25
|
+
getIndustryId(): string;
|
|
26
|
+
plan(question: string, context: {
|
|
27
|
+
scope: KnowledgeScope;
|
|
28
|
+
entities: KnowledgeEntity[];
|
|
29
|
+
}): Promise<{
|
|
30
|
+
seedIds: string[];
|
|
31
|
+
depth: number;
|
|
32
|
+
relationTypes?: string[];
|
|
33
|
+
template?: string;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=heuristic-query-planner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heuristic-query-planner.d.ts","sourceRoot":"","sources":["../../src/planner/heuristic-query-planner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACvF,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,WAAW,4BAA4B;IAC3C;;;OAGG;IACH,QAAQ,CAAC,EAAE,eAAe,GAAG,eAAe,EAAE,CAAC;IAC/C,8DAA8D;IAC9D,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;IAC5B,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,qBAAa,qBAAsB,YAAW,qBAAqB;IACjE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;IAC5C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;gBAExB,OAAO,GAAE,4BAAiC;IAYtD,aAAa,IAAI,MAAM;IAIjB,IAAI,CACR,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;QAAE,KAAK,EAAE,cAAc,CAAC;QAAC,QAAQ,EAAE,eAAe,EAAE,CAAA;KAAE,GAC9D,OAAO,CAAC;QACT,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CAuCH"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HeuristicQueryPlanner = void 0;
|
|
4
|
+
const industry_profiles_1 = require("./industry-profiles");
|
|
5
|
+
/**
|
|
6
|
+
* V1 planner: seed entities from the question + optional industry templates.
|
|
7
|
+
*
|
|
8
|
+
* Core behavior is industry-agnostic. Pass `COMMERCE_INDUSTRY_PROFILE` (or a
|
|
9
|
+
* custom profile) when your graph uses domain-specific relation types.
|
|
10
|
+
*/
|
|
11
|
+
class HeuristicQueryPlanner {
|
|
12
|
+
constructor(options = {}) {
|
|
13
|
+
const industries = normalizeIndustries(options.industry);
|
|
14
|
+
const fromIndustry = industries.flatMap((p) => p.templates);
|
|
15
|
+
this.templates = [...fromIndustry, ...(options.templates ?? [])];
|
|
16
|
+
this.defaultDepth =
|
|
17
|
+
options.defaultDepth ??
|
|
18
|
+
industries.map((p) => p.defaultDepth).find((d) => d !== undefined) ??
|
|
19
|
+
industry_profiles_1.GENERIC_INDUSTRY_PROFILE.defaultDepth ??
|
|
20
|
+
3;
|
|
21
|
+
this.industryId = industries.map((p) => p.id).join('+') || 'generic';
|
|
22
|
+
}
|
|
23
|
+
getIndustryId() {
|
|
24
|
+
return this.industryId;
|
|
25
|
+
}
|
|
26
|
+
async plan(question, context) {
|
|
27
|
+
const lower = question.toLowerCase();
|
|
28
|
+
const seeds = [];
|
|
29
|
+
for (const entity of context.entities) {
|
|
30
|
+
const names = [
|
|
31
|
+
entity.id.toLowerCase(),
|
|
32
|
+
String(entity.properties.name ?? '').toLowerCase(),
|
|
33
|
+
...(entity.aliases ?? []).map((a) => a.toLowerCase()),
|
|
34
|
+
].filter(Boolean);
|
|
35
|
+
for (const name of names) {
|
|
36
|
+
if (name.length >= 3 && lower.includes(name)) {
|
|
37
|
+
seeds.push(entity.id);
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Match entity type tokens in the question (domain-agnostic).
|
|
43
|
+
if (seeds.length === 0) {
|
|
44
|
+
for (const entity of context.entities) {
|
|
45
|
+
if (lower.includes(entity.type.toLowerCase())) {
|
|
46
|
+
seeds.push(entity.id);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const matches = this.templates.filter((t) => t.pattern.test(question));
|
|
51
|
+
// Prefer domain templates that constrain relation types over generic intents.
|
|
52
|
+
const template = matches.find((t) => t.relationTypes && t.relationTypes.length > 0) ?? matches[0];
|
|
53
|
+
return {
|
|
54
|
+
seedIds: [...new Set(seeds)].slice(0, 20),
|
|
55
|
+
depth: template?.depth ?? this.defaultDepth,
|
|
56
|
+
relationTypes: template?.relationTypes,
|
|
57
|
+
template: template?.name,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.HeuristicQueryPlanner = HeuristicQueryPlanner;
|
|
62
|
+
function normalizeIndustries(industry) {
|
|
63
|
+
if (!industry) {
|
|
64
|
+
return [industry_profiles_1.GENERIC_INDUSTRY_PROFILE];
|
|
65
|
+
}
|
|
66
|
+
return Array.isArray(industry) ? industry : [industry];
|
|
67
|
+
}
|