@carlonicora/nestjs-neo4jsonapi 1.104.0 → 1.106.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/agents/graph.creator/services/graph.creator.service.d.ts +1 -1
- package/dist/agents/graph.creator/services/graph.creator.service.d.ts.map +1 -1
- package/dist/agents/graph.creator/services/graph.creator.service.js +14 -0
- package/dist/agents/graph.creator/services/graph.creator.service.js.map +1 -1
- package/dist/bootstrap/app.module.factory.d.ts.map +1 -1
- package/dist/bootstrap/app.module.factory.js +1 -0
- package/dist/bootstrap/app.module.factory.js.map +1 -1
- package/dist/bootstrap/bootstrap.options.d.ts +3 -0
- package/dist/bootstrap/bootstrap.options.d.ts.map +1 -1
- package/dist/common/interfaces/agents/graph.creator.interface.d.ts +4 -0
- package/dist/common/interfaces/agents/graph.creator.interface.d.ts.map +1 -1
- package/dist/common/repositories/ai-source-query.provider.d.ts +19 -0
- package/dist/common/repositories/ai-source-query.provider.d.ts.map +1 -0
- package/dist/common/repositories/ai-source-query.provider.js +5 -0
- package/dist/common/repositories/ai-source-query.provider.js.map +1 -0
- package/dist/common/repositories/default.ai-source-query.provider.d.ts +19 -0
- package/dist/common/repositories/default.ai-source-query.provider.d.ts.map +1 -0
- package/dist/common/repositories/default.ai-source-query.provider.js +36 -0
- package/dist/common/repositories/default.ai-source-query.provider.js.map +1 -0
- package/dist/common/repositories/index.d.ts +2 -0
- package/dist/common/repositories/index.d.ts.map +1 -1
- package/dist/common/repositories/index.js +2 -0
- package/dist/common/repositories/index.js.map +1 -1
- package/dist/common/types/data.limits.d.ts +2 -2
- package/dist/common/types/data.limits.d.ts.map +1 -1
- package/dist/config/base.config.d.ts.map +1 -1
- package/dist/config/base.config.js +5 -0
- package/dist/config/base.config.js.map +1 -1
- package/dist/config/interfaces/base.config.interface.d.ts +4 -0
- package/dist/config/interfaces/base.config.interface.d.ts.map +1 -1
- package/dist/config/interfaces/config.chunker.interface.d.ts +10 -0
- package/dist/config/interfaces/config.chunker.interface.d.ts.map +1 -0
- package/dist/config/interfaces/config.chunker.interface.js +3 -0
- package/dist/config/interfaces/config.chunker.interface.js.map +1 -0
- package/dist/config/interfaces/config.embedding.context.interface.d.ts +18 -0
- package/dist/config/interfaces/config.embedding.context.interface.d.ts.map +1 -0
- package/dist/config/interfaces/config.embedding.context.interface.js +3 -0
- package/dist/config/interfaces/config.embedding.context.interface.js.map +1 -0
- package/dist/config/interfaces/index.d.ts +2 -0
- package/dist/config/interfaces/index.d.ts.map +1 -1
- package/dist/config/interfaces/index.js +2 -0
- package/dist/config/interfaces/index.js.map +1 -1
- package/dist/core/core.module.d.ts +4 -0
- package/dist/core/core.module.d.ts.map +1 -1
- package/dist/core/core.module.js +7 -2
- package/dist/core/core.module.js.map +1 -1
- package/dist/core/llm/services/model.service.d.ts.map +1 -1
- package/dist/core/llm/services/model.service.js +18 -34
- package/dist/core/llm/services/model.service.js.map +1 -1
- package/dist/foundations/atomicfact/repositories/atomicfact.repository.d.ts +3 -8
- package/dist/foundations/atomicfact/repositories/atomicfact.repository.d.ts.map +1 -1
- package/dist/foundations/atomicfact/repositories/atomicfact.repository.js +19 -46
- package/dist/foundations/atomicfact/repositories/atomicfact.repository.js.map +1 -1
- package/dist/foundations/chunk/chunk.module.d.ts +6 -3
- package/dist/foundations/chunk/chunk.module.d.ts.map +1 -1
- package/dist/foundations/chunk/chunk.module.js +25 -5
- package/dist/foundations/chunk/chunk.module.js.map +1 -1
- package/dist/foundations/chunk/controllers/chunk.controller.d.ts +19 -1
- package/dist/foundations/chunk/controllers/chunk.controller.d.ts.map +1 -1
- package/dist/foundations/chunk/controllers/chunk.controller.js +59 -2
- package/dist/foundations/chunk/controllers/chunk.controller.js.map +1 -1
- package/dist/foundations/chunk/entities/chunk.entity.d.ts +8 -0
- package/dist/foundations/chunk/entities/chunk.entity.d.ts.map +1 -1
- package/dist/foundations/chunk/entities/chunk.entity.js +20 -0
- package/dist/foundations/chunk/entities/chunk.entity.js.map +1 -1
- package/dist/foundations/chunk/processors/chunk.embedding.processor.d.ts +21 -0
- package/dist/foundations/chunk/processors/chunk.embedding.processor.d.ts.map +1 -0
- package/dist/foundations/chunk/processors/chunk.embedding.processor.js +98 -0
- package/dist/foundations/chunk/processors/chunk.embedding.processor.js.map +1 -0
- package/dist/foundations/chunk/repositories/chunk.repository.d.ts +36 -8
- package/dist/foundations/chunk/repositories/chunk.repository.d.ts.map +1 -1
- package/dist/foundations/chunk/repositories/chunk.repository.js +184 -50
- package/dist/foundations/chunk/repositories/chunk.repository.js.map +1 -1
- package/dist/foundations/chunk/services/chunk.service.d.ts +9 -0
- package/dist/foundations/chunk/services/chunk.service.d.ts.map +1 -1
- package/dist/foundations/chunk/services/chunk.service.js +87 -0
- package/dist/foundations/chunk/services/chunk.service.js.map +1 -1
- package/dist/foundations/chunk/services/embedding-context.d.ts +19 -0
- package/dist/foundations/chunk/services/embedding-context.d.ts.map +1 -0
- package/dist/foundations/chunk/services/embedding-context.js +27 -0
- package/dist/foundations/chunk/services/embedding-context.js.map +1 -0
- package/dist/foundations/chunk/services/reciprocal-rank-fusion.d.ts +2 -0
- package/dist/foundations/chunk/services/reciprocal-rank-fusion.d.ts.map +1 -0
- package/dist/foundations/chunk/services/reciprocal-rank-fusion.js +13 -0
- package/dist/foundations/chunk/services/reciprocal-rank-fusion.js.map +1 -0
- package/dist/foundations/chunker/chunker.module.d.ts.map +1 -1
- package/dist/foundations/chunker/chunker.module.js +2 -0
- package/dist/foundations/chunker/chunker.module.js.map +1 -1
- package/dist/foundations/chunker/services/chunker.service.d.ts +20 -12
- package/dist/foundations/chunker/services/chunker.service.d.ts.map +1 -1
- package/dist/foundations/chunker/services/chunker.service.js +160 -157
- package/dist/foundations/chunker/services/chunker.service.js.map +1 -1
- package/dist/foundations/chunker/services/types/markdownchunking.service.d.ts +17 -0
- package/dist/foundations/chunker/services/types/markdownchunking.service.d.ts.map +1 -0
- package/dist/foundations/chunker/services/types/markdownchunking.service.js +124 -0
- package/dist/foundations/chunker/services/types/markdownchunking.service.js.map +1 -0
- package/dist/foundations/chunker/services/types/pdf.service.d.ts +4 -0
- package/dist/foundations/chunker/services/types/pdf.service.d.ts.map +1 -1
- package/dist/foundations/chunker/services/types/pdf.service.js +14 -4
- package/dist/foundations/chunker/services/types/pdf.service.js.map +1 -1
- package/dist/foundations/keyconcept/controllers/keyconcept.controller.d.ts +15 -0
- package/dist/foundations/keyconcept/controllers/keyconcept.controller.d.ts.map +1 -0
- package/dist/foundations/keyconcept/controllers/keyconcept.controller.js +56 -0
- package/dist/foundations/keyconcept/controllers/keyconcept.controller.js.map +1 -0
- package/dist/foundations/keyconcept/index.d.ts +2 -0
- package/dist/foundations/keyconcept/index.d.ts.map +1 -1
- package/dist/foundations/keyconcept/index.js +5 -1
- package/dist/foundations/keyconcept/index.js.map +1 -1
- package/dist/foundations/keyconcept/keyconcept.module.d.ts.map +1 -1
- package/dist/foundations/keyconcept/keyconcept.module.js +7 -2
- package/dist/foundations/keyconcept/keyconcept.module.js.map +1 -1
- package/dist/foundations/keyconcept/processors/keyconcept.embedding.processor.d.ts +22 -0
- package/dist/foundations/keyconcept/processors/keyconcept.embedding.processor.d.ts.map +1 -0
- package/dist/foundations/keyconcept/processors/keyconcept.embedding.processor.js +98 -0
- package/dist/foundations/keyconcept/processors/keyconcept.embedding.processor.js.map +1 -0
- package/dist/foundations/keyconcept/repositories/keyconcept.repository.d.ts +9 -15
- package/dist/foundations/keyconcept/repositories/keyconcept.repository.d.ts.map +1 -1
- package/dist/foundations/keyconcept/repositories/keyconcept.repository.js +65 -99
- package/dist/foundations/keyconcept/repositories/keyconcept.repository.js.map +1 -1
- package/dist/foundations/s3/index.d.ts +8 -2
- package/dist/foundations/s3/index.d.ts.map +1 -1
- package/dist/foundations/s3/index.js +22 -5
- package/dist/foundations/s3/index.js.map +1 -1
- package/dist/foundations/s3/services/s3.service.d.ts +11 -1
- package/dist/foundations/s3/services/s3.service.d.ts.map +1 -1
- package/dist/foundations/s3/services/s3.service.js +70 -21
- package/dist/foundations/s3/services/s3.service.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { Entity } from "../../../common";
|
|
2
2
|
import { PolymorphicDiscriminatorData } from "../../../common/interfaces/entity.schema.interface";
|
|
3
|
+
export interface ChunkDate {
|
|
4
|
+
date: string;
|
|
5
|
+
description: string;
|
|
6
|
+
}
|
|
3
7
|
export type Chunk = Entity & {
|
|
4
8
|
content: string;
|
|
5
9
|
position?: number;
|
|
@@ -9,6 +13,10 @@ export type Chunk = Entity & {
|
|
|
9
13
|
aiStatus?: string;
|
|
10
14
|
embedding?: number[];
|
|
11
15
|
source?: unknown;
|
|
16
|
+
heading?: string;
|
|
17
|
+
/** Stored on the node as a JSON string; exposed here parsed via a computed field. */
|
|
18
|
+
dates?: ChunkDate[];
|
|
19
|
+
propagatedDates?: ChunkDate[];
|
|
12
20
|
};
|
|
13
21
|
export declare const ChunkDescriptor: import("../../../common").EntityDescriptor<Chunk, {
|
|
14
22
|
source: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk.entity.d.ts","sourceRoot":"","sources":["../../../../src/foundations/chunk/entities/chunk.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAgB,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,4BAA4B,EAAE,MAAM,oDAAoD,CAAC;AAKlG,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"chunk.entity.d.ts","sourceRoot":"","sources":["../../../../src/foundations/chunk/entities/chunk.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAgB,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,4BAA4B,EAAE,MAAM,oDAAoD,CAAC;AAKlG,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;IACpB,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC;CAC/B,CAAC;AAgBF,eAAO,MAAM,eAAe;;;;;;;;;;kCAwCE,4BAA4B;;;EAUxD,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,OAAO,eAAe,CAAC"}
|
|
@@ -5,6 +5,21 @@ const common_1 = require("../../../common");
|
|
|
5
5
|
const registry_1 = require("../../../common/registries/registry");
|
|
6
6
|
const s3_1 = require("../../s3");
|
|
7
7
|
const chunk_meta_1 = require("./chunk.meta");
|
|
8
|
+
/** Parse a `dates` / `propagatedDates` value that is persisted as a JSON-string blob. */
|
|
9
|
+
const parseChunkDates = (raw) => {
|
|
10
|
+
if (Array.isArray(raw))
|
|
11
|
+
return raw;
|
|
12
|
+
if (typeof raw === "string" && raw.trim()) {
|
|
13
|
+
try {
|
|
14
|
+
const parsed = JSON.parse(raw);
|
|
15
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return [];
|
|
22
|
+
};
|
|
8
23
|
exports.ChunkDescriptor = (0, common_1.defineEntity)()({
|
|
9
24
|
...chunk_meta_1.chunkMeta,
|
|
10
25
|
injectServices: [s3_1.S3Service],
|
|
@@ -14,6 +29,7 @@ exports.ChunkDescriptor = (0, common_1.defineEntity)()({
|
|
|
14
29
|
nodeId: { type: "string", meta: true },
|
|
15
30
|
nodeType: { type: "string", meta: true },
|
|
16
31
|
aiStatus: { type: "string" },
|
|
32
|
+
heading: { type: "string" },
|
|
17
33
|
embedding: { type: "number[]", excludeFromJsonApi: true },
|
|
18
34
|
imagePath: {
|
|
19
35
|
type: "string",
|
|
@@ -27,6 +43,10 @@ exports.ChunkDescriptor = (0, common_1.defineEntity)()({
|
|
|
27
43
|
},
|
|
28
44
|
},
|
|
29
45
|
},
|
|
46
|
+
computed: {
|
|
47
|
+
dates: { compute: (params) => parseChunkDates(params.data?.dates) },
|
|
48
|
+
propagatedDates: { compute: (params) => parseChunkDates(params.data?.propagatedDates) },
|
|
49
|
+
},
|
|
30
50
|
relationships: {
|
|
31
51
|
source: {
|
|
32
52
|
model: chunk_meta_1.chunkMeta, // overridden per-row by polymorphic discriminator
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk.entity.js","sourceRoot":"","sources":["../../../../src/foundations/chunk/entities/chunk.entity.ts"],"names":[],"mappings":";;;AAAA,4CAAuD;AAEvD,kEAAoE;AACpE,iCAAqC;AACrC,6CAAyC;
|
|
1
|
+
{"version":3,"file":"chunk.entity.js","sourceRoot":"","sources":["../../../../src/foundations/chunk/entities/chunk.entity.ts"],"names":[],"mappings":";;;AAAA,4CAAuD;AAEvD,kEAAoE;AACpE,iCAAqC;AACrC,6CAAyC;AAsBzC,yFAAyF;AACzF,MAAM,eAAe,GAAG,CAAC,GAAY,EAAe,EAAE;IACpD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,GAAkB,CAAC;IAClD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC/B,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,MAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC;AAEW,QAAA,eAAe,GAAG,IAAA,qBAAY,GAAS,CAAC;IACnD,GAAG,sBAAS;IAEZ,cAAc,EAAE,CAAC,cAAS,CAAC;IAE3B,MAAM,EAAE;QACN,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC3C,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC5B,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE;QACtC,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE;QACxC,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC5B,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC3B,SAAS,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,kBAAkB,EAAE,IAAI,EAAE;QACzD,SAAS,EAAE;YACT,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;gBAClC,IAAI,CAAC,IAAI,CAAC,SAAS;oBAAE,OAAO,SAAS,CAAC;gBACtC,OAAO,MAAM,QAAQ,CAAC,SAAS,CAAC,iBAAiB,CAAC;oBAChD,GAAG,EAAE,IAAI,CAAC,SAAS;oBACnB,GAAG,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;iBACtB,CAAC,CAAC;YACL,CAAC;SACF;KACF;IAED,QAAQ,EAAE;QACR,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;QACnE,eAAe,EAAE,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,EAAE;KACxF;IAED,aAAa,EAAE;QACb,MAAM,EAAE;YACN,KAAK,EAAE,sBAAS,EAAE,kDAAkD;YACpE,SAAS,EAAE,IAAI;YACf,YAAY,EAAE,WAAW;YACzB,WAAW,EAAE,KAAK;YAClB,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE;gBACX,UAAU,EAAE,EAAE;gBACd,aAAa,EAAE,CAAC,IAAkC,EAAE,EAAE;oBACpD,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;wBAChC,MAAM,KAAK,GAAG,wBAAa,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;wBAClD,IAAI,KAAK;4BAAE,OAAO,KAAK,CAAC;oBAC1B,CAAC;oBACD,MAAM,IAAI,KAAK,CAAC,wDAAwD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACzG,CAAC;aACF;SACF;KACF;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { WorkerHost } from "@nestjs/bullmq";
|
|
2
|
+
import { ConfigService } from "@nestjs/config";
|
|
3
|
+
import { Job } from "bullmq";
|
|
4
|
+
import { ClsService } from "nestjs-cls";
|
|
5
|
+
import { BaseConfigInterface } from "../../../config/interfaces/base.config.interface";
|
|
6
|
+
import { EmbedderService } from "../../../core";
|
|
7
|
+
import { ChunkRepository } from "../repositories/chunk.repository";
|
|
8
|
+
export declare class ChunkEmbeddingProcessor extends WorkerHost {
|
|
9
|
+
private readonly clsService;
|
|
10
|
+
private readonly chunkRepository;
|
|
11
|
+
private readonly embedderService;
|
|
12
|
+
private readonly rebuildChunksJobName;
|
|
13
|
+
constructor(clsService: ClsService, chunkRepository: ChunkRepository, embedderService: EmbedderService, configService: ConfigService<BaseConfigInterface>);
|
|
14
|
+
onActive(job: Job): void;
|
|
15
|
+
onError(job: Job): void;
|
|
16
|
+
onCompleted(job: Job): void;
|
|
17
|
+
process(job: Job): Promise<{
|
|
18
|
+
processed: number;
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=chunk.embedding.processor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk.embedding.processor.d.ts","sourceRoot":"","sources":["../../../../src/foundations/chunk/processors/chunk.embedding.processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kDAAkD,CAAC;AACvF,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAInE,qBACa,uBAAwB,SAAQ,UAAU;IAInD,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe;IALlC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;gBAG3B,UAAU,EAAE,UAAU,EACtB,eAAe,EAAE,eAAe,EAChC,eAAe,EAAE,eAAe,EACjD,aAAa,EAAE,aAAa,CAAC,mBAAmB,CAAC;IAQnD,QAAQ,CAAC,GAAG,EAAE,GAAG;IAKjB,OAAO,CAAC,GAAG,EAAE,GAAG;IAKhB,WAAW,CAAC,GAAG,EAAE,GAAG;IAId,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CA0CxD"}
|
|
@@ -0,0 +1,98 @@
|
|
|
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.ChunkEmbeddingProcessor = void 0;
|
|
13
|
+
const bullmq_1 = require("@nestjs/bullmq");
|
|
14
|
+
const config_1 = require("@nestjs/config");
|
|
15
|
+
const bullmq_2 = require("bullmq");
|
|
16
|
+
const nestjs_cls_1 = require("nestjs-cls");
|
|
17
|
+
const core_1 = require("../../../core");
|
|
18
|
+
const chunk_repository_1 = require("../repositories/chunk.repository");
|
|
19
|
+
const EMBEDDING_CHUNKS_QUEUE = "embedding-chunks";
|
|
20
|
+
let ChunkEmbeddingProcessor = class ChunkEmbeddingProcessor extends bullmq_1.WorkerHost {
|
|
21
|
+
constructor(clsService, chunkRepository, embedderService, configService) {
|
|
22
|
+
super();
|
|
23
|
+
this.clsService = clsService;
|
|
24
|
+
this.chunkRepository = chunkRepository;
|
|
25
|
+
this.embedderService = embedderService;
|
|
26
|
+
this.rebuildChunksJobName =
|
|
27
|
+
configService.get("jobNames", { infer: true })?.process?.rebuild_chunks ?? "embedding:rebuild_chunks";
|
|
28
|
+
}
|
|
29
|
+
onActive(job) {
|
|
30
|
+
console.log(`Processing ${job.name} job`);
|
|
31
|
+
}
|
|
32
|
+
onError(job) {
|
|
33
|
+
console.error(`Error processing ${job.name} job (ID: ${job.id}). Reason: ${job.failedReason}`);
|
|
34
|
+
}
|
|
35
|
+
onCompleted(job) {
|
|
36
|
+
console.log(`Completed ${job.name} job (ID: ${job.id})`);
|
|
37
|
+
}
|
|
38
|
+
async process(job) {
|
|
39
|
+
if (job.name !== this.rebuildChunksJobName) {
|
|
40
|
+
throw new Error(`Job ${job.name} not handled by ChunkEmbeddingProcessor`);
|
|
41
|
+
}
|
|
42
|
+
return await this.clsService.run(async () => {
|
|
43
|
+
this.clsService.set("companyId", job.data.companyId);
|
|
44
|
+
this.clsService.set("userId", job.data.userId);
|
|
45
|
+
this.clsService.set("isAutomatedJob", true);
|
|
46
|
+
// 1. Recreate vector index with new dimensions
|
|
47
|
+
await this.chunkRepository.recreateVectorIndex();
|
|
48
|
+
// 2. Get all chunks
|
|
49
|
+
const allChunks = await this.chunkRepository.findAllChunks();
|
|
50
|
+
const chunksWithContent = allChunks.filter((c) => c.content);
|
|
51
|
+
// 3. Process in batches
|
|
52
|
+
const batchSize = 100;
|
|
53
|
+
let processed = 0;
|
|
54
|
+
for (let i = 0; i < chunksWithContent.length; i += batchSize) {
|
|
55
|
+
const batch = chunksWithContent.slice(i, i + batchSize);
|
|
56
|
+
const texts = batch.map((c) => c.content);
|
|
57
|
+
const embeddings = await this.embedderService.vectoriseTextBatch(texts);
|
|
58
|
+
for (let j = 0; j < batch.length; j++) {
|
|
59
|
+
await this.chunkRepository.updateEmbedding({
|
|
60
|
+
chunkId: batch[j].id,
|
|
61
|
+
embedding: embeddings[j],
|
|
62
|
+
});
|
|
63
|
+
processed++;
|
|
64
|
+
}
|
|
65
|
+
const progress = Math.round((processed / chunksWithContent.length) * 100);
|
|
66
|
+
await job.updateProgress(progress);
|
|
67
|
+
}
|
|
68
|
+
return { processed };
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
exports.ChunkEmbeddingProcessor = ChunkEmbeddingProcessor;
|
|
73
|
+
__decorate([
|
|
74
|
+
(0, bullmq_1.OnWorkerEvent)("active"),
|
|
75
|
+
__metadata("design:type", Function),
|
|
76
|
+
__metadata("design:paramtypes", [bullmq_2.Job]),
|
|
77
|
+
__metadata("design:returntype", void 0)
|
|
78
|
+
], ChunkEmbeddingProcessor.prototype, "onActive", null);
|
|
79
|
+
__decorate([
|
|
80
|
+
(0, bullmq_1.OnWorkerEvent)("failed"),
|
|
81
|
+
__metadata("design:type", Function),
|
|
82
|
+
__metadata("design:paramtypes", [bullmq_2.Job]),
|
|
83
|
+
__metadata("design:returntype", void 0)
|
|
84
|
+
], ChunkEmbeddingProcessor.prototype, "onError", null);
|
|
85
|
+
__decorate([
|
|
86
|
+
(0, bullmq_1.OnWorkerEvent)("completed"),
|
|
87
|
+
__metadata("design:type", Function),
|
|
88
|
+
__metadata("design:paramtypes", [bullmq_2.Job]),
|
|
89
|
+
__metadata("design:returntype", void 0)
|
|
90
|
+
], ChunkEmbeddingProcessor.prototype, "onCompleted", null);
|
|
91
|
+
exports.ChunkEmbeddingProcessor = ChunkEmbeddingProcessor = __decorate([
|
|
92
|
+
(0, bullmq_1.Processor)(EMBEDDING_CHUNKS_QUEUE, { concurrency: 1, lockDuration: 1000 * 60 * 30 }),
|
|
93
|
+
__metadata("design:paramtypes", [nestjs_cls_1.ClsService,
|
|
94
|
+
chunk_repository_1.ChunkRepository,
|
|
95
|
+
core_1.EmbedderService,
|
|
96
|
+
config_1.ConfigService])
|
|
97
|
+
], ChunkEmbeddingProcessor);
|
|
98
|
+
//# sourceMappingURL=chunk.embedding.processor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk.embedding.processor.js","sourceRoot":"","sources":["../../../../src/foundations/chunk/processors/chunk.embedding.processor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { OnModuleInit } from "@nestjs/common";
|
|
2
2
|
import { ClsService } from "nestjs-cls";
|
|
3
3
|
import { AiStatus } from "../../../common/enums/ai.status";
|
|
4
|
+
import { AiSourceQueryProvider } from "../../../common/repositories/ai-source-query.provider";
|
|
4
5
|
import { DataLimits } from "../../../common/types/data.limits";
|
|
5
6
|
import { EmbedderService } from "../../../core";
|
|
6
7
|
import { ModelService } from "../../../core/llm/services/model.service";
|
|
@@ -13,19 +14,24 @@ export declare class ChunkRepository implements OnModuleInit {
|
|
|
13
14
|
private readonly embedderService;
|
|
14
15
|
private readonly clsService;
|
|
15
16
|
private readonly securityService;
|
|
16
|
-
|
|
17
|
+
private readonly aiSourceQuery;
|
|
18
|
+
constructor(neo4j: Neo4jService, modelService: ModelService, embedderService: EmbedderService, clsService: ClsService, securityService: SecurityService, aiSourceQuery: AiSourceQueryProvider);
|
|
17
19
|
onModuleInit(): Promise<void>;
|
|
20
|
+
recreateVectorIndex(): Promise<void>;
|
|
21
|
+
findAllChunks(): Promise<Chunk[]>;
|
|
22
|
+
updateEmbedding(params: {
|
|
23
|
+
chunkId: string;
|
|
24
|
+
embedding: number[];
|
|
25
|
+
}): Promise<void>;
|
|
18
26
|
findPotentialChunks(params: {
|
|
19
27
|
question: string;
|
|
20
28
|
dataLimits: DataLimits;
|
|
21
29
|
}): Promise<Chunk[]>;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
*/
|
|
28
|
-
private findPotentialChunksFromHowTos;
|
|
30
|
+
private findChunksByIdsOrdered;
|
|
31
|
+
findParentName(params: {
|
|
32
|
+
id: string;
|
|
33
|
+
nodeType: string;
|
|
34
|
+
}): Promise<string | undefined>;
|
|
29
35
|
findSubsequentChunkId(params: {
|
|
30
36
|
chunkId: string;
|
|
31
37
|
}): Promise<Chunk>;
|
|
@@ -45,6 +51,7 @@ export declare class ChunkRepository implements OnModuleInit {
|
|
|
45
51
|
nodeType: string;
|
|
46
52
|
previousChunkId?: string;
|
|
47
53
|
content: string;
|
|
54
|
+
heading?: string;
|
|
48
55
|
imagePath?: string;
|
|
49
56
|
position: number;
|
|
50
57
|
}): Promise<void>;
|
|
@@ -52,6 +59,19 @@ export declare class ChunkRepository implements OnModuleInit {
|
|
|
52
59
|
id: string;
|
|
53
60
|
aiStatus: AiStatus;
|
|
54
61
|
}): Promise<void>;
|
|
62
|
+
updateDates(params: {
|
|
63
|
+
chunkId: string;
|
|
64
|
+
dates: string;
|
|
65
|
+
}): Promise<void>;
|
|
66
|
+
enrichContentAndEmbedBatch(items: {
|
|
67
|
+
chunkId: string;
|
|
68
|
+
enrichedContent: string;
|
|
69
|
+
propagatedDates?: string;
|
|
70
|
+
}[]): Promise<void>;
|
|
71
|
+
markChunksCompleted(params: {
|
|
72
|
+
id: string;
|
|
73
|
+
nodeType: string;
|
|
74
|
+
}): Promise<void>;
|
|
55
75
|
getChunksInProgress(params: {
|
|
56
76
|
id: string;
|
|
57
77
|
nodeType: string;
|
|
@@ -68,6 +88,14 @@ export declare class ChunkRepository implements OnModuleInit {
|
|
|
68
88
|
id: string;
|
|
69
89
|
nodeType: string;
|
|
70
90
|
}): Promise<void>;
|
|
91
|
+
findChunkNeighbors(params: {
|
|
92
|
+
chunkIds: string[];
|
|
93
|
+
window: number;
|
|
94
|
+
}): Promise<{
|
|
95
|
+
chunkId: string;
|
|
96
|
+
before: string[];
|
|
97
|
+
after: string[];
|
|
98
|
+
}[]>;
|
|
71
99
|
findChunkByContentIdAndType(params: {
|
|
72
100
|
id: string;
|
|
73
101
|
type: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk.repository.d.ts","sourceRoot":"","sources":["../../../../src/foundations/chunk/repositories/chunk.repository.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"chunk.repository.d.ts","sourceRoot":"","sources":["../../../../src/foundations/chunk/repositories/chunk.repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,24 +8,30 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
8
8
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.ChunkRepository = void 0;
|
|
13
16
|
const common_1 = require("@nestjs/common");
|
|
14
17
|
const nestjs_cls_1 = require("nestjs-cls");
|
|
15
18
|
const ai_status_1 = require("../../../common/enums/ai.status");
|
|
16
|
-
const
|
|
19
|
+
const ai_source_query_provider_1 = require("../../../common/repositories/ai-source-query.provider");
|
|
17
20
|
const core_1 = require("../../../core");
|
|
18
21
|
const model_service_1 = require("../../../core/llm/services/model.service");
|
|
19
22
|
const neo4j_service_1 = require("../../../core/neo4j/services/neo4j.service");
|
|
20
23
|
const security_service_1 = require("../../../core/security/services/security.service");
|
|
21
24
|
const chunk_entity_1 = require("../../chunk/entities/chunk.entity");
|
|
25
|
+
const chunk_meta_1 = require("../entities/chunk.meta");
|
|
26
|
+
const reciprocal_rank_fusion_1 = require("../services/reciprocal-rank-fusion");
|
|
22
27
|
let ChunkRepository = class ChunkRepository {
|
|
23
|
-
constructor(neo4j, modelService, embedderService, clsService, securityService) {
|
|
28
|
+
constructor(neo4j, modelService, embedderService, clsService, securityService, aiSourceQuery) {
|
|
24
29
|
this.neo4j = neo4j;
|
|
25
30
|
this.modelService = modelService;
|
|
26
31
|
this.embedderService = embedderService;
|
|
27
32
|
this.clsService = clsService;
|
|
28
33
|
this.securityService = securityService;
|
|
34
|
+
this.aiSourceQuery = aiSourceQuery;
|
|
29
35
|
}
|
|
30
36
|
async onModuleInit() {
|
|
31
37
|
await this.neo4j.writeOne({
|
|
@@ -43,68 +49,120 @@ let ChunkRepository = class ChunkRepository {
|
|
|
43
49
|
}};
|
|
44
50
|
`,
|
|
45
51
|
});
|
|
52
|
+
await this.neo4j.writeOne({
|
|
53
|
+
query: `CREATE FULLTEXT INDEX chunk_content_search IF NOT EXISTS FOR (chunk:Chunk) ON EACH [chunk.content]`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
async recreateVectorIndex() {
|
|
57
|
+
await this.neo4j.writeOne({
|
|
58
|
+
query: `DROP INDEX chunks IF EXISTS`,
|
|
59
|
+
});
|
|
60
|
+
const dimensions = this.modelService.getEmbedderDimensions();
|
|
61
|
+
await this.neo4j.writeOne({
|
|
62
|
+
query: `
|
|
63
|
+
CREATE VECTOR INDEX chunks IF NOT EXISTS
|
|
64
|
+
FOR (chunk:Chunk)
|
|
65
|
+
ON chunk.embedding
|
|
66
|
+
OPTIONS { indexConfig: {
|
|
67
|
+
\`vector.dimensions\`: ${dimensions},
|
|
68
|
+
\`vector.similarity_function\`: 'cosine'
|
|
69
|
+
}};
|
|
70
|
+
`,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async findAllChunks() {
|
|
74
|
+
const query = this.neo4j.initQuery({ serialiser: chunk_entity_1.ChunkDescriptor.model, fetchAll: true });
|
|
75
|
+
query.query = `
|
|
76
|
+
MATCH (${chunk_meta_1.chunkMeta.nodeName}:${chunk_meta_1.chunkMeta.labelName})
|
|
77
|
+
RETURN ${chunk_meta_1.chunkMeta.nodeName}
|
|
78
|
+
`;
|
|
79
|
+
return this.neo4j.readMany(query);
|
|
80
|
+
}
|
|
81
|
+
async updateEmbedding(params) {
|
|
82
|
+
await this.neo4j.writeOne({
|
|
83
|
+
query: `
|
|
84
|
+
MATCH (chunk:Chunk {id: $chunkId})
|
|
85
|
+
SET chunk.embedding = $embedding, chunk.updatedAt = datetime()
|
|
86
|
+
`,
|
|
87
|
+
queryParams: {
|
|
88
|
+
chunkId: params.chunkId,
|
|
89
|
+
embedding: params.embedding,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
46
92
|
}
|
|
47
93
|
async findPotentialChunks(params) {
|
|
48
|
-
// SECURITY: HowTo retrieval intentionally bypasses company filtering.
|
|
49
|
-
// Dispatch to the private method so the bypass is visible and quarantined here.
|
|
50
|
-
if (params.dataLimits.howToMode || params.dataLimits.limitToHowToId) {
|
|
51
|
-
return this.findPotentialChunksFromHowTos(params);
|
|
52
|
-
}
|
|
53
|
-
const query = this.neo4j.initQuery({ serialiser: chunk_entity_1.ChunkDescriptor.model });
|
|
54
94
|
const queryEmbedding = await this.embedderService.vectoriseText({ text: params.question });
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
95
|
+
// Lucene special-character escape so user questions can't break the fulltext query.
|
|
96
|
+
const term = params.question.replace(/([+\-!(){}\[\]^"~*?:\\\/]|&&|\|\|)/g, "\\$1");
|
|
97
|
+
// The access-scoped id-set both retrieval branches are filtered to.
|
|
98
|
+
const scope = this.aiSourceQuery.build({
|
|
99
|
+
dataLimits: params.dataLimits,
|
|
59
100
|
currentUserId: this.clsService.get("userId"),
|
|
60
101
|
securityService: this.securityService,
|
|
61
|
-
dataLimits: params.dataLimits,
|
|
62
102
|
returnsData: true,
|
|
63
|
-
})
|
|
103
|
+
});
|
|
104
|
+
const scopeQuery = this.neo4j.initQuery();
|
|
105
|
+
scopeQuery.queryParams = { ...scopeQuery.queryParams, ...scope.params };
|
|
106
|
+
scopeQuery.query += `
|
|
107
|
+
${scope.cypher}
|
|
64
108
|
MATCH (chunk:Chunk)<-[:HAS_CHUNK]-(data)
|
|
65
|
-
|
|
66
|
-
|
|
109
|
+
RETURN COLLECT(DISTINCT chunk.id) AS chunkIds
|
|
110
|
+
`;
|
|
111
|
+
const scopeResult = await this.neo4j.read(scopeQuery.query, scopeQuery.queryParams);
|
|
112
|
+
const chunkIds = scopeResult.records[0]?.get("chunkIds") ?? [];
|
|
113
|
+
if (chunkIds.length === 0)
|
|
114
|
+
return [];
|
|
115
|
+
const vectorResult = await this.neo4j.read(`
|
|
67
116
|
CALL db.index.vector.queryNodes('chunks', 1000, $queryEmbedding)
|
|
68
117
|
YIELD node AS candidateChunk, score
|
|
69
|
-
WHERE candidateChunk.id IN chunkIds
|
|
70
|
-
|
|
71
|
-
RETURN candidateChunk AS chunk, score
|
|
118
|
+
WHERE candidateChunk.id IN $chunkIds
|
|
119
|
+
RETURN candidateChunk.id AS id
|
|
72
120
|
ORDER BY score DESC
|
|
73
|
-
LIMIT
|
|
74
|
-
|
|
75
|
-
|
|
121
|
+
LIMIT 50
|
|
122
|
+
`, { queryEmbedding, chunkIds });
|
|
123
|
+
const vectorIds = vectorResult.records.map((record) => record.get("id"));
|
|
124
|
+
let lexicalIds = [];
|
|
125
|
+
if (term.trim()) {
|
|
126
|
+
const lexicalResult = await this.neo4j.read(`
|
|
127
|
+
CALL db.index.fulltext.queryNodes('chunk_content_search', $term)
|
|
128
|
+
YIELD node, score
|
|
129
|
+
WHERE node.id IN $chunkIds
|
|
130
|
+
RETURN node.id AS id
|
|
131
|
+
ORDER BY score DESC
|
|
132
|
+
LIMIT 50
|
|
133
|
+
`, { term, chunkIds });
|
|
134
|
+
lexicalIds = lexicalResult.records.map((record) => record.get("id"));
|
|
135
|
+
}
|
|
136
|
+
const fusedIds = (0, reciprocal_rank_fusion_1.reciprocalRankFusion)([vectorIds, lexicalIds]).slice(0, 20);
|
|
137
|
+
return this.findChunksByIdsOrdered(fusedIds);
|
|
76
138
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
* this repository; `findPotentialChunks` dispatches here based on
|
|
81
|
-
* `dataLimits.howToMode` / `dataLimits.limitToHowToId`.
|
|
82
|
-
*/
|
|
83
|
-
async findPotentialChunksFromHowTos(params) {
|
|
139
|
+
async findChunksByIdsOrdered(ids) {
|
|
140
|
+
if (ids.length === 0)
|
|
141
|
+
return [];
|
|
84
142
|
const query = this.neo4j.initQuery({ serialiser: chunk_entity_1.ChunkDescriptor.model });
|
|
85
|
-
const queryEmbedding = await this.embedderService.vectoriseText({ text: params.question });
|
|
86
143
|
query.queryParams = {
|
|
87
144
|
...query.queryParams,
|
|
88
|
-
|
|
89
|
-
...(params.dataLimits.limitToHowToId ? { limitToHowToId: params.dataLimits.limitToHowToId } : {}),
|
|
145
|
+
ids,
|
|
90
146
|
};
|
|
91
|
-
|
|
147
|
+
query.query += `
|
|
148
|
+
MATCH (chunk:Chunk)
|
|
149
|
+
WHERE chunk.id IN $ids
|
|
150
|
+
RETURN chunk
|
|
151
|
+
`;
|
|
152
|
+
const chunks = await this.neo4j.readMany(query);
|
|
153
|
+
const byId = new Map(chunks.map((chunk) => [chunk.id, chunk]));
|
|
154
|
+
return ids.map((id) => byId.get(id)).filter((chunk) => chunk !== undefined);
|
|
155
|
+
}
|
|
156
|
+
async findParentName(params) {
|
|
157
|
+
const query = this.neo4j.initQuery();
|
|
158
|
+
query.queryParams = { ...query.queryParams, id: params.id };
|
|
92
159
|
query.query = `
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
CALL db.index.vector.queryNodes('chunks', 1000, $queryEmbedding)
|
|
100
|
-
YIELD node AS candidateChunk, score
|
|
101
|
-
WHERE candidateChunk.id IN chunkIds
|
|
102
|
-
|
|
103
|
-
RETURN candidateChunk AS chunk, score
|
|
104
|
-
ORDER BY score DESC
|
|
105
|
-
LIMIT 20
|
|
106
|
-
`;
|
|
107
|
-
return this.neo4j.readMany(query);
|
|
160
|
+
MATCH (n:${params.nodeType} {id: $id})
|
|
161
|
+
RETURN coalesce(n.name, n.title, n.subject, n.number) AS name
|
|
162
|
+
`;
|
|
163
|
+
const result = await this.neo4j.read(query.query, query.queryParams);
|
|
164
|
+
const name = result.records[0]?.get("name");
|
|
165
|
+
return typeof name === "string" && name.trim() ? name : undefined;
|
|
108
166
|
}
|
|
109
167
|
async findSubsequentChunkId(params) {
|
|
110
168
|
const query = this.neo4j.initQuery({ serialiser: chunk_entity_1.ChunkDescriptor.model });
|
|
@@ -162,6 +220,7 @@ let ChunkRepository = class ChunkRepository {
|
|
|
162
220
|
...query.queryParams,
|
|
163
221
|
id: params.id,
|
|
164
222
|
content: params.content,
|
|
223
|
+
heading: params.heading ?? null,
|
|
165
224
|
position: params.position,
|
|
166
225
|
vector: vector,
|
|
167
226
|
imagePath: params.imagePath,
|
|
@@ -175,7 +234,8 @@ let ChunkRepository = class ChunkRepository {
|
|
|
175
234
|
OPTIONAL MATCH (nodeType)-[:BELONGS_TO]->(company)
|
|
176
235
|
CREATE (chunk:Chunk {
|
|
177
236
|
id: $id,
|
|
178
|
-
content: $content,
|
|
237
|
+
content: $content,
|
|
238
|
+
heading: $heading,
|
|
179
239
|
${params.imagePath ? "imagePath: $imagePath," : ""}
|
|
180
240
|
embedding: $vector,
|
|
181
241
|
position: $position,
|
|
@@ -210,6 +270,56 @@ let ChunkRepository = class ChunkRepository {
|
|
|
210
270
|
`;
|
|
211
271
|
await this.neo4j.writeOne(query);
|
|
212
272
|
}
|
|
273
|
+
async updateDates(params) {
|
|
274
|
+
const query = this.neo4j.initQuery();
|
|
275
|
+
query.queryParams = {
|
|
276
|
+
...query.queryParams,
|
|
277
|
+
chunkId: params.chunkId,
|
|
278
|
+
dates: params.dates,
|
|
279
|
+
};
|
|
280
|
+
query.query = `
|
|
281
|
+
MATCH (chunk:Chunk {id: $chunkId})
|
|
282
|
+
SET chunk.dates = $dates, chunk.updatedAt = datetime()
|
|
283
|
+
`;
|
|
284
|
+
await this.neo4j.writeOne(query);
|
|
285
|
+
}
|
|
286
|
+
async enrichContentAndEmbedBatch(items) {
|
|
287
|
+
if (items.length === 0)
|
|
288
|
+
return;
|
|
289
|
+
// One Azure round-trip for the whole set — per-call latency dominates batch size, so
|
|
290
|
+
// embedding chunks individually (vectoriseText per chunk) is far slower than batching.
|
|
291
|
+
// RateLimitedEmbedder.embedDocuments splits internally if the batch exceeds maxBatchTokens.
|
|
292
|
+
const vectors = await this.embedderService.vectoriseTextBatch(items.map((item) => item.enrichedContent));
|
|
293
|
+
const rows = items.map((item, index) => ({
|
|
294
|
+
chunkId: item.chunkId,
|
|
295
|
+
enrichedContent: item.enrichedContent,
|
|
296
|
+
vector: vectors[index],
|
|
297
|
+
propagatedDates: item.propagatedDates ?? null,
|
|
298
|
+
}));
|
|
299
|
+
const query = this.neo4j.initQuery();
|
|
300
|
+
query.queryParams = {
|
|
301
|
+
...query.queryParams,
|
|
302
|
+
rows,
|
|
303
|
+
};
|
|
304
|
+
query.query = `
|
|
305
|
+
UNWIND $rows AS row
|
|
306
|
+
MATCH (chunk:Chunk {id: row.chunkId})
|
|
307
|
+
SET chunk.content = row.enrichedContent,
|
|
308
|
+
chunk.embedding = row.vector,
|
|
309
|
+
chunk.updatedAt = datetime(),
|
|
310
|
+
chunk.propagatedDates = row.propagatedDates
|
|
311
|
+
`;
|
|
312
|
+
await this.neo4j.writeOne(query);
|
|
313
|
+
}
|
|
314
|
+
async markChunksCompleted(params) {
|
|
315
|
+
const query = this.neo4j.initQuery();
|
|
316
|
+
query.queryParams = { ...query.queryParams, id: params.id, aiStatus: ai_status_1.AiStatus.Completed };
|
|
317
|
+
query.query += `
|
|
318
|
+
MATCH (nodeType:${params.nodeType} {id: $id})-[:HAS_CHUNK]->(chunk:Chunk)
|
|
319
|
+
SET chunk.aiStatus = $aiStatus, chunk.updatedAt = datetime()
|
|
320
|
+
`;
|
|
321
|
+
await this.neo4j.writeOne(query);
|
|
322
|
+
}
|
|
213
323
|
async getChunksInProgress(params) {
|
|
214
324
|
const query = this.neo4j.initQuery({ serialiser: chunk_entity_1.ChunkDescriptor.model });
|
|
215
325
|
query.queryParams = {
|
|
@@ -268,6 +378,29 @@ let ChunkRepository = class ChunkRepository {
|
|
|
268
378
|
`;
|
|
269
379
|
await this.neo4j.writeOne(query);
|
|
270
380
|
}
|
|
381
|
+
async findChunkNeighbors(params) {
|
|
382
|
+
if (params.chunkIds.length === 0)
|
|
383
|
+
return [];
|
|
384
|
+
const query = this.neo4j.initQuery();
|
|
385
|
+
query.queryParams = { ...query.queryParams, chunkIds: params.chunkIds, window: params.window };
|
|
386
|
+
query.query = `
|
|
387
|
+
UNWIND $chunkIds AS cid
|
|
388
|
+
MATCH (c:Chunk {id: cid})
|
|
389
|
+
OPTIONAL MATCH pBefore = (b:Chunk)-[:NEXT*1..]->(c)
|
|
390
|
+
WITH cid, c, b, length(pBefore) AS beforeDist ORDER BY beforeDist ASC
|
|
391
|
+
WITH cid, c, [x IN collect(b) WHERE x IS NOT NULL][0..$window] AS befores
|
|
392
|
+
OPTIONAL MATCH pAfter = (c)-[:NEXT*1..]->(a:Chunk)
|
|
393
|
+
WITH cid, befores, a, length(pAfter) AS afterDist ORDER BY afterDist ASC
|
|
394
|
+
WITH cid, befores, [x IN collect(a) WHERE x IS NOT NULL][0..$window] AS afters
|
|
395
|
+
RETURN cid AS chunkId, [x IN befores | x.content] AS before, [x IN afters | x.content] AS after
|
|
396
|
+
`;
|
|
397
|
+
const result = await this.neo4j.read(query.query, query.queryParams);
|
|
398
|
+
return result.records.map((r) => ({
|
|
399
|
+
chunkId: r.get("chunkId"),
|
|
400
|
+
before: r.get("before") ?? [],
|
|
401
|
+
after: r.get("after") ?? [],
|
|
402
|
+
}));
|
|
403
|
+
}
|
|
271
404
|
async findChunkByContentIdAndType(params) {
|
|
272
405
|
const query = this.neo4j.initQuery({ fetchAll: true, serialiser: chunk_entity_1.ChunkDescriptor.model });
|
|
273
406
|
query.queryParams = {
|
|
@@ -284,10 +417,11 @@ let ChunkRepository = class ChunkRepository {
|
|
|
284
417
|
exports.ChunkRepository = ChunkRepository;
|
|
285
418
|
exports.ChunkRepository = ChunkRepository = __decorate([
|
|
286
419
|
(0, common_1.Injectable)(),
|
|
420
|
+
__param(5, (0, common_1.Inject)(ai_source_query_provider_1.AI_SOURCE_QUERY)),
|
|
287
421
|
__metadata("design:paramtypes", [neo4j_service_1.Neo4jService,
|
|
288
422
|
model_service_1.ModelService,
|
|
289
423
|
core_1.EmbedderService,
|
|
290
424
|
nestjs_cls_1.ClsService,
|
|
291
|
-
security_service_1.SecurityService])
|
|
425
|
+
security_service_1.SecurityService, Object])
|
|
292
426
|
], ChunkRepository);
|
|
293
427
|
//# sourceMappingURL=chunk.repository.js.map
|