@carlonicora/nestjs-neo4jsonapi 2.14.10 → 2.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/dist/agents/contextualiser/contexts/contextualiser.context.d.ts +41 -0
  2. package/dist/agents/contextualiser/contexts/contextualiser.context.d.ts.map +1 -1
  3. package/dist/agents/contextualiser/contexts/contextualiser.context.js +17 -0
  4. package/dist/agents/contextualiser/contexts/contextualiser.context.js.map +1 -1
  5. package/dist/agents/contextualiser/contexts/notebook.context.d.ts +22 -0
  6. package/dist/agents/contextualiser/contexts/notebook.context.d.ts.map +1 -1
  7. package/dist/agents/contextualiser/contexts/notebook.context.js +14 -0
  8. package/dist/agents/contextualiser/contexts/notebook.context.js.map +1 -1
  9. package/dist/agents/contextualiser/factories/contextualiser.context.factory.d.ts.map +1 -1
  10. package/dist/agents/contextualiser/factories/contextualiser.context.factory.js +2 -0
  11. package/dist/agents/contextualiser/factories/contextualiser.context.factory.js.map +1 -1
  12. package/dist/agents/contextualiser/nodes/atomicfacts.node.service.d.ts.map +1 -1
  13. package/dist/agents/contextualiser/nodes/atomicfacts.node.service.js +17 -5
  14. package/dist/agents/contextualiser/nodes/atomicfacts.node.service.js.map +1 -1
  15. package/dist/agents/contextualiser/nodes/chunk.node.service.d.ts +1 -14
  16. package/dist/agents/contextualiser/nodes/chunk.node.service.d.ts.map +1 -1
  17. package/dist/agents/contextualiser/nodes/chunk.node.service.js +56 -206
  18. package/dist/agents/contextualiser/nodes/chunk.node.service.js.map +1 -1
  19. package/dist/agents/contextualiser/nodes/chunk.vector.node.service.d.ts +3 -12
  20. package/dist/agents/contextualiser/nodes/chunk.vector.node.service.d.ts.map +1 -1
  21. package/dist/agents/contextualiser/nodes/chunk.vector.node.service.js +44 -133
  22. package/dist/agents/contextualiser/nodes/chunk.vector.node.service.js.map +1 -1
  23. package/dist/agents/contextualiser/nodes/keyconcepts.node.service.d.ts +1 -2
  24. package/dist/agents/contextualiser/nodes/keyconcepts.node.service.d.ts.map +1 -1
  25. package/dist/agents/contextualiser/nodes/keyconcepts.node.service.js +60 -60
  26. package/dist/agents/contextualiser/nodes/keyconcepts.node.service.js.map +1 -1
  27. package/dist/agents/contextualiser/nodes/question.refiner.node.service.d.ts.map +1 -1
  28. package/dist/agents/contextualiser/nodes/question.refiner.node.service.js +7 -2
  29. package/dist/agents/contextualiser/nodes/question.refiner.node.service.js.map +1 -1
  30. package/dist/agents/contextualiser/nodes/rational.node.service.js +2 -1
  31. package/dist/agents/contextualiser/nodes/rational.node.service.js.map +1 -1
  32. package/dist/agents/contextualiser/services/contextualiser.service.d.ts.map +1 -1
  33. package/dist/agents/contextualiser/services/contextualiser.service.js +30 -22
  34. package/dist/agents/contextualiser/services/contextualiser.service.js.map +1 -1
  35. package/dist/agents/prompts/index.d.ts +0 -2
  36. package/dist/agents/prompts/index.d.ts.map +1 -1
  37. package/dist/agents/prompts/index.js +7 -5
  38. package/dist/agents/prompts/index.js.map +1 -1
  39. package/dist/agents/responder/contexts/responder.context.d.ts +96 -0
  40. package/dist/agents/responder/contexts/responder.context.d.ts.map +1 -1
  41. package/dist/agents/responder/interfaces/unified.trace.interface.d.ts +9 -0
  42. package/dist/agents/responder/interfaces/unified.trace.interface.d.ts.map +1 -1
  43. package/dist/agents/responder/nodes/__tests__/helpers/answer-node.harness.d.ts +38 -0
  44. package/dist/agents/responder/nodes/__tests__/helpers/answer-node.harness.d.ts.map +1 -0
  45. package/dist/agents/responder/nodes/__tests__/helpers/answer-node.harness.js +36 -0
  46. package/dist/agents/responder/nodes/__tests__/helpers/answer-node.harness.js.map +1 -0
  47. package/dist/agents/responder/nodes/graph.node.service.d.ts.map +1 -1
  48. package/dist/agents/responder/nodes/graph.node.service.js +18 -3
  49. package/dist/agents/responder/nodes/graph.node.service.js.map +1 -1
  50. package/dist/agents/responder/nodes/planner.node.service.d.ts.map +1 -1
  51. package/dist/agents/responder/nodes/planner.node.service.js +9 -0
  52. package/dist/agents/responder/nodes/planner.node.service.js.map +1 -1
  53. package/dist/agents/responder/nodes/responder.answer.node.service.d.ts +26 -1
  54. package/dist/agents/responder/nodes/responder.answer.node.service.d.ts.map +1 -1
  55. package/dist/agents/responder/nodes/responder.answer.node.service.js +127 -13
  56. package/dist/agents/responder/nodes/responder.answer.node.service.js.map +1 -1
  57. package/dist/agents/responder/services/responder.service.d.ts.map +1 -1
  58. package/dist/agents/responder/services/responder.service.js +4 -0
  59. package/dist/agents/responder/services/responder.service.js.map +1 -1
  60. package/dist/common/utils/settled.d.ts +33 -0
  61. package/dist/common/utils/settled.d.ts.map +1 -0
  62. package/dist/common/utils/settled.js +66 -0
  63. package/dist/common/utils/settled.js.map +1 -0
  64. package/dist/config/interfaces/config.prompts.interface.d.ts +12 -0
  65. package/dist/config/interfaces/config.prompts.interface.d.ts.map +1 -1
  66. package/dist/core/llm/services/model.service.d.ts.map +1 -1
  67. package/dist/core/llm/services/model.service.js +5 -2
  68. package/dist/core/llm/services/model.service.js.map +1 -1
  69. package/dist/core/llm/services/reasoning-content-fetch.d.ts +41 -0
  70. package/dist/core/llm/services/reasoning-content-fetch.d.ts.map +1 -0
  71. package/dist/core/llm/services/reasoning-content-fetch.js +143 -0
  72. package/dist/core/llm/services/reasoning-content-fetch.js.map +1 -0
  73. package/dist/eval/retrieval/end-to-end-sweep.service.d.ts +52 -0
  74. package/dist/eval/retrieval/end-to-end-sweep.service.d.ts.map +1 -0
  75. package/dist/eval/retrieval/end-to-end-sweep.service.js +194 -0
  76. package/dist/eval/retrieval/end-to-end-sweep.service.js.map +1 -0
  77. package/dist/eval/retrieval/evidence.matcher.d.ts +23 -0
  78. package/dist/eval/retrieval/evidence.matcher.d.ts.map +1 -0
  79. package/dist/eval/retrieval/evidence.matcher.js +38 -0
  80. package/dist/eval/retrieval/evidence.matcher.js.map +1 -0
  81. package/dist/eval/retrieval/index.d.ts +10 -0
  82. package/dist/eval/retrieval/index.d.ts.map +1 -0
  83. package/dist/eval/retrieval/index.js +35 -0
  84. package/dist/eval/retrieval/index.js.map +1 -0
  85. package/dist/eval/retrieval/question-set.loader.d.ts +16 -0
  86. package/dist/eval/retrieval/question-set.loader.d.ts.map +1 -0
  87. package/dist/eval/retrieval/question-set.loader.js +73 -0
  88. package/dist/eval/retrieval/question-set.loader.js.map +1 -0
  89. package/dist/eval/retrieval/retrieval-eval.module.d.ts +14 -0
  90. package/dist/eval/retrieval/retrieval-eval.module.d.ts.map +1 -0
  91. package/dist/eval/retrieval/retrieval-eval.module.js +48 -0
  92. package/dist/eval/retrieval/retrieval-eval.module.js.map +1 -0
  93. package/dist/eval/retrieval/retrieval-eval.types.d.ts +84 -0
  94. package/dist/eval/retrieval/retrieval-eval.types.d.ts.map +1 -0
  95. package/dist/eval/retrieval/retrieval-eval.types.js +25 -0
  96. package/dist/eval/retrieval/retrieval-eval.types.js.map +1 -0
  97. package/dist/eval/retrieval/retrieval-sweep.service.d.ts +35 -0
  98. package/dist/eval/retrieval/retrieval-sweep.service.d.ts.map +1 -0
  99. package/dist/eval/retrieval/retrieval-sweep.service.js +93 -0
  100. package/dist/eval/retrieval/retrieval-sweep.service.js.map +1 -0
  101. package/dist/eval/retrieval/rubric-judge.service.d.ts +30 -0
  102. package/dist/eval/retrieval/rubric-judge.service.d.ts.map +1 -0
  103. package/dist/eval/retrieval/rubric-judge.service.js +138 -0
  104. package/dist/eval/retrieval/rubric-judge.service.js.map +1 -0
  105. package/dist/eval/retrieval/sweep-report.d.ts +11 -0
  106. package/dist/eval/retrieval/sweep-report.d.ts.map +1 -0
  107. package/dist/eval/retrieval/sweep-report.js +79 -0
  108. package/dist/eval/retrieval/sweep-report.js.map +1 -0
  109. package/dist/eval/retrieval/token-accounting.check.d.ts +39 -0
  110. package/dist/eval/retrieval/token-accounting.check.d.ts.map +1 -0
  111. package/dist/eval/retrieval/token-accounting.check.js +75 -0
  112. package/dist/eval/retrieval/token-accounting.check.js.map +1 -0
  113. package/dist/foundations/atomicfact/repositories/atomicfact.repository.d.ts.map +1 -1
  114. package/dist/foundations/atomicfact/repositories/atomicfact.repository.js +7 -0
  115. package/dist/foundations/atomicfact/repositories/atomicfact.repository.js.map +1 -1
  116. package/dist/foundations/chunk/repositories/chunk.repository.d.ts +87 -1
  117. package/dist/foundations/chunk/repositories/chunk.repository.d.ts.map +1 -1
  118. package/dist/foundations/chunk/repositories/chunk.repository.js +239 -50
  119. package/dist/foundations/chunk/repositories/chunk.repository.js.map +1 -1
  120. package/dist/foundations/chunk/repositories/retrieval.constants.d.ts +69 -0
  121. package/dist/foundations/chunk/repositories/retrieval.constants.d.ts.map +1 -0
  122. package/dist/foundations/chunk/repositories/retrieval.constants.js +72 -0
  123. package/dist/foundations/chunk/repositories/retrieval.constants.js.map +1 -0
  124. package/dist/foundations/keyconcept/repositories/keyconcept.repository.d.ts +2 -0
  125. package/dist/foundations/keyconcept/repositories/keyconcept.repository.d.ts.map +1 -1
  126. package/dist/foundations/keyconcept/repositories/keyconcept.repository.js +9 -5
  127. package/dist/foundations/keyconcept/repositories/keyconcept.repository.js.map +1 -1
  128. package/package.json +1 -1
@@ -8,245 +8,95 @@ 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
- };
14
11
  var ChunkNodeService_1;
15
12
  Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.ChunkNodeService = exports.defaultChunkPrompt = void 0;
13
+ exports.ChunkNodeService = void 0;
17
14
  const common_1 = require("@nestjs/common");
18
- const config_1 = require("@nestjs/config");
19
- const nestjs_cls_1 = require("nestjs-cls");
20
- const zod_1 = require("zod");
21
- const llm_service_1 = require("../../../core/llm/services/llm.service");
22
- const websocket_service_1 = require("../../../core/websocket/services/websocket.service");
23
15
  const chunk_repository_1 = require("../../../foundations/chunk/repositories/chunk.repository");
24
- const retrieval_source_interface_1 = require("../interfaces/retrieval.source.interface");
25
- const usage_attribution_1 = require("../../common/usage-attribution");
26
- exports.defaultChunkPrompt = `
27
- As an intelligent assistant, your primary objective is to assess a specific **text chunk** and determine whether the available information suffices to answer the question.
28
-
29
- Given the **question**, and the **rational plan** to answer the question you have to:
30
- 1. Analyse the text and determine if it is relevant to answer the user question
31
- - The text chunk should be examined for key information that directly relates to the question being asked.
32
-
33
- 2. Write an note summarizing the key points from the current text chunk that are relevant to the question
34
- - The note should contain all the information required to provide a detailed answer
35
- - The note should be a comprehensive summary that can be used to generate a precise, contextualised response to the question, containing all the required details enough to cover all relevant aspects.
36
-
37
- 3. Write a reason describing how the text chunk is relevant to the question
38
- - The reason should explain why the text chunk is relevant or not to answer the question.
39
-
40
- 4. Select the appropriate next action to take based on your assessment of the current information.
41
- - **queuePreviousChunk**: Choose this action if you feel that the current chunk of text might have relevant information in a previous text chunk that would **significantly** enhance your answer. Do not select this action if you believe the current chunk is either sufficient or completely irrelevant.
42
- - **queueNextChunk**: Choose this action if you feel that the current chunk of text might have relevant information in a subsequent text chunk that would **significantly** enhance your answer. Do not select this action if you believe the current chunk is either sufficient or completely irrelevant.
43
- - **readNeighbouringNodes**: Choose this action if you believe that this text chunk does not contain relevant information and that exploring neighbouring chunks could provide valuable context.
44
- - **answer**: Choose this action if you believe that the information in this text chunk is sufficient to provide a **comprehensive and accurate** answer to the question.
45
- - **skip**: Choose this action if you believe that the current chunk of text is not relevant to the question and that you want to move on to the next chunk without taking any further action.
46
-
47
- 5. **Provide a Status Message**:
48
- - Write a **short, friendly message** (maximum 40 characters) about your action.
49
- - **Avoid technical terms** such as "nodes", "atomic facts", or "key concepts".
50
- - The status message should make the user understand the action being taken
51
- - The status message **MUST** contain clear information contextualised to the current question and the gathered information.
52
- - The status message should be specific to the context and clearly convey the next steps or actions being taken.
53
- - The status message **MUST NOT** be something unrelated to the text, such as "success", "sufficient information", "insufficient information", "chunk analysed", "chunk processed" or similar generic messages.
54
-
55
- ### Important Notes:
56
- - **Proceed to Answer When Appropriate**: If the current information is sufficient to provide a reliable answer, do not hesitate to proceed to select **answer** as the next step.
57
- - **Gather More Information When Needed**: If you identify gaps or uncertainties that could be addressed by additional information, choose the appropriate action to gather that information.
58
- - **Use Judgment in Decision-Making**: Apply thoughtful consideration to decide whether additional information is necessary.
59
- - If the content contains acronyms and their definition, include the definition of the acronym in your answer.
60
-
61
- ### **Please strictly follow the above instructions and format. Let's begin.**
62
- `;
63
- const outputSchema = zod_1.z.object({
64
- status: zod_1.z
65
- .string()
66
- .describe(`Write a short, friendly message (max 40 characters) about your action, avoiding technical terms such as "nodes" or "atomic facts" or "key concepts". Give flavour to the message and avoid repeating the same message.`),
67
- note: zod_1.z
68
- .object({
69
- content: zod_1.z.string().describe("The new insights and findings about the question from current text"),
70
- reason: zod_1.z.string().describe("The reason describing how the text chunk is relevant to the question"),
71
- })
72
- .describe("The note summarizing the key points from the current text chunk that are relevant to the question"),
73
- chosenAction: zod_1.z.string()
74
- .describe(`This is the action you have decided to do in the next step. You **MUST** pick one of the following actions:
75
- - **queuePreviousChunk**: Choose this action if you feel that the previous text chunk contains valuable information for answering the question. Do not select this action if you believe the current chunk is either sufficient or completely irrelevant.
76
- - **queueNextChunk**: Choose this action if you feel that the subsequent text chunk contains valuable information for answering the question. Do not select this action if you believe the current chunk is either sufficient or completely irrelevant.
77
- - **readNeighbouringNodes**: Choose this action if you feel that the current text contains valuable, but somewhat incomplete information that could be clarified by exploring related concepts.
78
- - **answer**: Choose this action if you believe that the information you have currently obtained is enough to answer the question. This will allow you to summarize the gathered information and provide a final answer.
79
- - **skip**: Choose this action if you believe that the current chunk of text is not relevant to the question and that you want to move on to the next chunk without taking any further action.
80
- `),
81
- });
82
- const inputSchema = zod_1.z.object({
83
- question: zod_1.z.string().describe("The question asked by the user"),
84
- rationalPlan: zod_1.z
85
- .string()
86
- .describe("The rational plan you designed to provide a comprehensive answer to the user question"),
87
- text: zod_1.z.string().describe("The content of the text you must analyse to provide an answer to the user question"),
88
- });
16
+ /**
17
+ * How many chunks either side of a retrieved chunk are read with it. The same
18
+ * value, for the same reason, as in `chunk.vector.node.service.ts`: a chunk
19
+ * boundary is an artefact of the splitter, not of the document, so the sentence
20
+ * that completes a fact often sits one chunk away. Duplicating one integer is
21
+ * cheaper than a shared import across two node files; the value is documented
22
+ * in both.
23
+ */
24
+ const NEIGHBOR_WINDOW = 1;
89
25
  let ChunkNodeService = ChunkNodeService_1 = class ChunkNodeService {
90
- constructor(llmService, chunkRepository, webSocketService, clsService, configService, contributedTools) {
91
- this.llmService = llmService;
26
+ constructor(chunkRepository) {
92
27
  this.chunkRepository = chunkRepository;
93
- this.webSocketService = webSocketService;
94
- this.clsService = clsService;
95
- this.configService = configService;
96
- this.contributedTools = contributedTools;
97
28
  this.logger = new common_1.Logger(ChunkNodeService_1.name);
98
- const prompts = this.configService.get("prompts");
99
- this.systemPrompt = prompts?.contextualiser?.chunk ?? exports.defaultChunkPrompt;
100
29
  }
101
30
  async execute(params) {
102
31
  if (params.state.queuedChunks.length === 0) {
103
32
  this.logger.warn(`chunks → ${params.state.neighbouringAlreadyExplored ? "answer" : "neighbouring_nodes"} ` +
104
33
  `(no queued chunks): processedChunks=${params.state.processedChunks.length}`);
105
34
  return {
35
+ llmCalls: 0,
106
36
  nextStep: params.state.neighbouringAlreadyExplored ? "answer" : "neighbouring_nodes",
107
37
  };
108
38
  }
109
- const chunks = [];
110
39
  const chunkIdsToProcess = params.state.queuedChunks.filter((chunkId) => !params.state.processedChunks.includes(chunkId));
111
- const queuedCount = chunkIdsToProcess.length;
112
- while (chunkIdsToProcess.length > 0) {
113
- const chunkId = chunkIdsToProcess.shift();
114
- const chunk = await this.chunkRepository.findChunkById({
115
- chunkId: chunkId,
116
- dataLimits: params.state.limits,
117
- });
118
- if (chunk)
119
- chunks.push(chunk);
120
- }
121
- this.logger.log(`chunk lookup → ${chunks.length}/${queuedCount} chunks found by id ` + `(missing=${queuedCount - chunks.length})`);
122
- if (chunks.length === 0) {
40
+ const fetched = await this.chunkRepository.findChunksByIds({
41
+ chunkIds: chunkIdsToProcess,
42
+ dataLimits: params.state.limits,
43
+ queryEmbedding: params.state.questionEmbedding,
44
+ });
45
+ this.logger.log(`chunk lookup → ${fetched.length}/${chunkIdsToProcess.length} chunks found by id ` +
46
+ `(missing=${chunkIdsToProcess.length - fetched.length})`);
47
+ if (fetched.length === 0) {
123
48
  this.logger.warn(`chunks → ${params.state.neighbouringAlreadyExplored ? "answer" : "neighbouring_nodes"} ` +
124
- `(0 chunks resolved from ${queuedCount} ids — chunkIds may belong to deleted HowTos or company-scoped MATCH failed)`);
49
+ `(0 chunks resolved from ${chunkIdsToProcess.length} ids — chunkIds may belong to deleted HowTos or company-scoped MATCH failed)`);
125
50
  return {
126
51
  queuedChunks: [],
52
+ llmCalls: 0,
127
53
  nextStep: params.state.neighbouringAlreadyExplored ? "answer" : "neighbouring_nodes",
128
54
  };
129
55
  }
130
- const llmResponses = (await Promise.all(chunks.map(async (chunk) => {
131
- if (!chunk.content || chunk.content.trim() === "")
132
- return null;
133
- const inputParams = {
134
- rationalPlan: params.state.rationalPlan,
135
- question: params.state.question,
136
- text: chunk.content,
137
- };
138
- const llmResponse = await this.llmService.call({
139
- inputSchema: inputSchema,
140
- inputParams: inputParams,
141
- outputSchema: outputSchema,
142
- systemPrompts: [this.systemPrompt],
143
- temperature: 0.1,
144
- ...(this.contributedTools?.length ? { tools: this.contributedTools } : {}),
145
- // Billed to the CALLING agent: its ledger category, its entity. Spread
146
- // LAST so nothing above can overwrite the attribution.
147
- ...(0, usage_attribution_1.buildInheritedAttribution)(params.state),
148
- });
149
- if (params.state.contentType === "Conversation")
150
- await this.webSocketService.sendMessageToUser(this.clsService.get("userId"), "contextualiser", {
151
- message: llmResponse.status,
152
- conversationId: params.state.contentId,
153
- });
56
+ // Every fetched chunk is kept. Filtering by score was measured to be
57
+ // either inert (the relative bar admits everything on this corpus) or
58
+ // lossy (a count cap of 8 loses required evidence), so the notebook
59
+ // character budget in responder.answer.node.service.ts is what decides
60
+ // what reaches the answer. Ordering is how the budget knows what to drop.
61
+ const kept = [...fetched].sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
62
+ // Neighbour-window widening: each chunk is carried into the notebook
63
+ // together with the chunks immediately before/after it, so the answer node
64
+ // reads continuous prose instead of a splitter's arbitrary slice. This is
65
+ // the automatic replacement for the per-chunk LLM decision that used to
66
+ // queue a previous/next chunk for another round.
67
+ const neighborRecords = await this.chunkRepository.findChunkNeighbors({
68
+ chunkIds: kept.map((chunk) => chunk.id),
69
+ window: NEIGHBOR_WINDOW,
70
+ });
71
+ const neighborById = new Map(neighborRecords.map((neighbour) => [neighbour.chunkId, neighbour]));
72
+ const newNotebookEntries = kept
73
+ .filter((chunk) => chunk.content && chunk.content.trim() !== "")
74
+ .map((chunk) => {
75
+ const neighbours = neighborById.get(chunk.id);
154
76
  return {
155
77
  chunkId: chunk.id,
156
- status: llmResponse.chosenAction === "answer" ? llmResponse.status : undefined,
157
- note: {
158
- content: llmResponse.note?.content ?? "",
159
- reason: llmResponse.note?.reason ?? "",
160
- },
161
- chosenAction: llmResponse.chosenAction,
162
- tokens: llmResponse.tokenUsage,
78
+ content: neighbours ? [...neighbours.before, chunk.content, ...neighbours.after].join("\n\n") : chunk.content,
79
+ reason: "",
80
+ sourceLayer: "case",
81
+ metadata: undefined,
82
+ score: chunk.score,
83
+ coreContent: chunk.content,
163
84
  };
164
- })));
165
- const tokenUsed = {
166
- input: 0,
167
- output: 0,
168
- };
169
- const newNotebookEntries = [];
170
- const statuses = [];
171
- for (const llmResponse of llmResponses.filter((response) => !!response)) {
172
- tokenUsed.input += llmResponse.tokens.input;
173
- tokenUsed.output += llmResponse.tokens.output;
174
- if (llmResponse.chosenAction !== "skip")
175
- newNotebookEntries.push({
176
- chunkId: llmResponse.chunkId,
177
- content: llmResponse.note.content,
178
- reason: llmResponse.note.reason,
179
- sourceLayer: "case",
180
- metadata: undefined,
181
- });
182
- if (!statuses.includes(llmResponse.status) && !params.state.status.includes(llmResponse.status))
183
- statuses.push(llmResponse.status);
184
- }
185
- const newChunksToQuery = [];
186
- await Promise.all(llmResponses
187
- .filter((response) => !!response)
188
- .map(async (llmResponse) => {
189
- switch (llmResponse.chosenAction) {
190
- case "queueNextChunk":
191
- const nextChunk = await this.chunkRepository.findSubsequentChunkId({
192
- chunkId: llmResponse.chunkId,
193
- });
194
- if (nextChunk)
195
- newChunksToQuery.push(nextChunk.id);
196
- break;
197
- case "queuePreviousChunk":
198
- const previousChunk = await this.chunkRepository.findPreviousChunkId({
199
- chunkId: llmResponse.chunkId,
200
- });
201
- if (previousChunk)
202
- newChunksToQuery.push(previousChunk.id);
203
- break;
204
- }
205
- }));
206
- let nextStep;
207
- if (newChunksToQuery.length > 0) {
208
- nextStep = "chunks";
209
- }
210
- else if (llmResponses.filter((response) => !!response).some((llmResponse) => llmResponse.chosenAction === "answer") ===
211
- true) {
212
- nextStep = "answer";
213
- }
214
- else {
215
- if (params.state.neighbouringAlreadyExplored)
216
- nextStep = "answer";
217
- else
218
- nextStep = "neighbouring_nodes";
219
- }
220
- // Safety checks to prevent excessive looping:
221
- // 1. Local check: If we've gone through chunks more than 3 times
222
- // 2. Global check: If we're approaching the maxHops limit (typically 20, leave 5 hop buffer)
223
- const approachingMaxHops = params.state.hops >= 15;
224
- if (params.state.chunkLevel > 3 || approachingMaxHops) {
225
- newChunksToQuery.length = 0;
226
- nextStep = "answer";
227
- }
228
- const returnedHops = params.state.hops + 1;
85
+ });
229
86
  return {
230
- hops: returnedHops,
87
+ hops: params.state.hops + 1,
88
+ llmCalls: 0,
231
89
  notebook: newNotebookEntries,
232
- chunkLevel: params.state.chunkLevel + 1,
233
- processedChunks: chunks.map((c) => c.id),
234
- queuedChunks: newChunksToQuery,
235
- nextStep: nextStep,
236
- status: statuses.filter((status) => status),
237
- tokens: tokenUsed,
90
+ processedChunks: fetched.map((chunk) => chunk.id),
91
+ queuedChunks: [],
92
+ nextStep: params.state.neighbouringAlreadyExplored ? "answer" : "neighbouring_nodes",
93
+ tokens: { input: 0, output: 0 },
238
94
  };
239
95
  }
240
96
  };
241
97
  exports.ChunkNodeService = ChunkNodeService;
242
98
  exports.ChunkNodeService = ChunkNodeService = ChunkNodeService_1 = __decorate([
243
99
  (0, common_1.Injectable)(),
244
- __param(5, (0, common_1.Optional)()),
245
- __param(5, (0, common_1.Inject)(retrieval_source_interface_1.CONTEXTUALISER_TOOLS)),
246
- __metadata("design:paramtypes", [llm_service_1.LLMService,
247
- chunk_repository_1.ChunkRepository,
248
- websocket_service_1.WebSocketService,
249
- nestjs_cls_1.ClsService,
250
- config_1.ConfigService, Array])
100
+ __metadata("design:paramtypes", [chunk_repository_1.ChunkRepository])
251
101
  ], ChunkNodeService);
252
102
  //# sourceMappingURL=chunk.node.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chunk.node.service.js","sourceRoot":"","sources":["../../../../src/agents/contextualiser/nodes/chunk.node.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chunk.node.service.js","sourceRoot":"","sources":["../../../../src/agents/contextualiser/nodes/chunk.node.service.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,13 @@
1
- import { ConfigService } from "@nestjs/config";
2
- import { ClsService } from "nestjs-cls";
3
- import { BaseConfigInterface } from "../../../config/interfaces";
4
- import { LLMService } from "../../../core/llm/services/llm.service";
5
- import { WebSocketService } from "../../../core/websocket/services/websocket.service";
1
+ import { EmbedderService } from "../../../core/llm/services/embedder.service";
6
2
  import { ChunkRepository } from "../../../foundations/chunk/repositories/chunk.repository";
7
3
  import { ContextualiserContext, ContextualiserContextState } from "../../contextualiser/contexts/contextualiser.context";
8
4
  import { RetrievalSourceContribution } from "../interfaces/retrieval.source.interface";
9
- export declare const defaultChunkVectorPrompt = "\nAs an intelligent assistant, your primary objective is to assess a specific **text chunk** and determine whether the available information suffices to answer the question.\n\nGiven the **question**, and the **rational plan** to answer the question you have to:\n1. Write a note summarizing the key points from the current text chunk that are relevant to the question. This must be used as context to answer the question.\n - The note should contain all the information required to provide a detailed answer\n - It should be a comprehensive note that can be used to generate a precise, contextualise reponse to the question, containing all the required details enough to cover all relevant aspects.\n\n2. Write a reason describing how the text chunk is relevant to the question\n - The reason should explain why the text chunk is relevant or not to answer the question.\n\n3. Select the appropriate next action to take based on your assessment of the current information.\n - **queuePreviousChunk**: Choose this action if you feel that the current chunk of text might have relevant information in a previous text chunk that would **significantly** enhance your answer.\n - **queueNextChunk**: Choose this action if you feel that the current chunk of text might have relevant information in a subsequent text chunk that would **significantly** enhance your answer.\n - **readNeighbouringNodes**: Choose this action if you believe that this text chunk does not contain relevant information and that exploring neighbouring chunks could provide valuable context.\n - **answer**: Choose this action if you believe that the information in this text chunk is sufficient to provide a **comprehensive and accurate** answer to the question.\n\n 4. **Provide a Status Message**:\n - Write a **short, friendly message** (maximum 40 characters) about your action.\n - **Avoid technical terms** such as \"nodes\", \"atomic facts\", or \"key concepts\".\n - The status message should make the user understand the action being taken\n - The status message **MUST** contain clear information contextualised to the current question and the gathered information.\n - The status message should be specific to the context and clearly convey the next steps or actions being taken.\n - The status message **MUST NOT** be something unrelated to the text, such as \"success\", \"sufficient information\", \"insufficient information\", \"chunk analysed\", \"chunk processed\" or similar generic messages.\n \n ### Important Notes:\n - **Proceed to Answer When Appropriate**: If the current information is sufficient to provide a reliable answer, do not hesitate to proceed to select **answer** as the next step.\n - **Gather More Information When Needed**: If you identify gaps or uncertainties that could be addressed by additional information, choose the appropriate action to gather that information.\n - **Use Judgment in Decision-Making**: Apply thoughtful consideration to decide whether additional information is necessary.\n - If the content contains acronyms and their definition, include the definition of the acronym in your answer.\n \n### **Please strictly follow the above instructions and format. Let's begin.**\n";
10
5
  export declare class ChunkVectorNodeService {
11
- private readonly llmService;
12
6
  private readonly chunkRepository;
13
- private readonly webSocketService;
14
- private readonly clsService;
15
- private readonly configService;
7
+ private readonly embedderService;
16
8
  private readonly retrievalSources?;
17
9
  private readonly logger;
18
- private readonly systemPrompt;
19
- constructor(llmService: LLMService, chunkRepository: ChunkRepository, webSocketService: WebSocketService, clsService: ClsService, configService: ConfigService<BaseConfigInterface>, retrievalSources?: RetrievalSourceContribution[]);
10
+ constructor(chunkRepository: ChunkRepository, embedderService: EmbedderService, retrievalSources?: RetrievalSourceContribution[]);
20
11
  execute(params: {
21
12
  state: typeof ContextualiserContext.State;
22
13
  }): Promise<Partial<ContextualiserContextState>>;
@@ -1 +1 @@
1
- {"version":3,"file":"chunk.vector.node.service.d.ts","sourceRoot":"","sources":["../../../../src/agents/contextualiser/nodes/chunk.vector.node.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGxC,OAAO,EAAE,mBAAmB,EAA0B,MAAM,4BAA4B,CAAC;AACzF,OAAO,EAAE,UAAU,EAAE,MAAM,wCAAwC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oDAAoD,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,MAAM,0DAA0D,CAAC;AAE3F,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,sDAAsD,CAAC;AAE9D,OAAO,EAAqB,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AAI1G,eAAO,MAAM,wBAAwB,6pGAgCpC,CAAC;AA+BF,qBACa,sBAAsB;IAK/B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAG9B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAXpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2C;IAClE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAGnB,UAAU,EAAE,UAAU,EACtB,eAAe,EAAE,eAAe,EAChC,gBAAgB,EAAE,gBAAgB,EAClC,UAAU,EAAE,UAAU,EACtB,aAAa,EAAE,aAAa,CAAC,mBAAmB,CAAC,EAGjD,gBAAgB,CAAC,EAAE,2BAA2B,EAAE;IAM7D,OAAO,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,OAAO,qBAAqB,CAAC,KAAK,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;CAiJnH"}
1
+ {"version":3,"file":"chunk.vector.node.service.d.ts","sourceRoot":"","sources":["../../../../src/agents/contextualiser/nodes/chunk.vector.node.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,6CAA6C,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,0DAA0D,CAAC;AAE3F,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC3B,MAAM,sDAAsD,CAAC;AAE9D,OAAO,EAAqB,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AAI1G,qBACa,sBAAsB;IAI/B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAGhC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;IAPpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2C;gBAG/C,eAAe,EAAE,eAAe,EAChC,eAAe,EAAE,eAAe,EAGhC,gBAAgB,CAAC,EAAE,2BAA2B,EAAE;IAG7D,OAAO,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,OAAO,qBAAqB,CAAC,KAAK,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;CA8GnH"}
@@ -13,92 +13,39 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
13
13
  };
14
14
  var ChunkVectorNodeService_1;
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.ChunkVectorNodeService = exports.defaultChunkVectorPrompt = void 0;
16
+ exports.ChunkVectorNodeService = void 0;
17
17
  const common_1 = require("@nestjs/common");
18
- const config_1 = require("@nestjs/config");
19
- const nestjs_cls_1 = require("nestjs-cls");
20
- const zod_1 = require("zod");
21
- const llm_service_1 = require("../../../core/llm/services/llm.service");
22
- const websocket_service_1 = require("../../../core/websocket/services/websocket.service");
18
+ const embedder_service_1 = require("../../../core/llm/services/embedder.service");
23
19
  const chunk_repository_1 = require("../../../foundations/chunk/repositories/chunk.repository");
24
20
  const usage_attribution_1 = require("../../common/usage-attribution");
25
21
  const retrieval_source_interface_1 = require("../interfaces/retrieval.source.interface");
26
22
  const NEIGHBOR_WINDOW = 1;
27
- exports.defaultChunkVectorPrompt = `
28
- As an intelligent assistant, your primary objective is to assess a specific **text chunk** and determine whether the available information suffices to answer the question.
29
-
30
- Given the **question**, and the **rational plan** to answer the question you have to:
31
- 1. Write a note summarizing the key points from the current text chunk that are relevant to the question. This must be used as context to answer the question.
32
- - The note should contain all the information required to provide a detailed answer
33
- - It should be a comprehensive note that can be used to generate a precise, contextualise reponse to the question, containing all the required details enough to cover all relevant aspects.
34
-
35
- 2. Write a reason describing how the text chunk is relevant to the question
36
- - The reason should explain why the text chunk is relevant or not to answer the question.
37
-
38
- 3. Select the appropriate next action to take based on your assessment of the current information.
39
- - **queuePreviousChunk**: Choose this action if you feel that the current chunk of text might have relevant information in a previous text chunk that would **significantly** enhance your answer.
40
- - **queueNextChunk**: Choose this action if you feel that the current chunk of text might have relevant information in a subsequent text chunk that would **significantly** enhance your answer.
41
- - **readNeighbouringNodes**: Choose this action if you believe that this text chunk does not contain relevant information and that exploring neighbouring chunks could provide valuable context.
42
- - **answer**: Choose this action if you believe that the information in this text chunk is sufficient to provide a **comprehensive and accurate** answer to the question.
43
-
44
- 4. **Provide a Status Message**:
45
- - Write a **short, friendly message** (maximum 40 characters) about your action.
46
- - **Avoid technical terms** such as "nodes", "atomic facts", or "key concepts".
47
- - The status message should make the user understand the action being taken
48
- - The status message **MUST** contain clear information contextualised to the current question and the gathered information.
49
- - The status message should be specific to the context and clearly convey the next steps or actions being taken.
50
- - The status message **MUST NOT** be something unrelated to the text, such as "success", "sufficient information", "insufficient information", "chunk analysed", "chunk processed" or similar generic messages.
51
-
52
- ### Important Notes:
53
- - **Proceed to Answer When Appropriate**: If the current information is sufficient to provide a reliable answer, do not hesitate to proceed to select **answer** as the next step.
54
- - **Gather More Information When Needed**: If you identify gaps or uncertainties that could be addressed by additional information, choose the appropriate action to gather that information.
55
- - **Use Judgment in Decision-Making**: Apply thoughtful consideration to decide whether additional information is necessary.
56
- - If the content contains acronyms and their definition, include the definition of the acronym in your answer.
57
-
58
- ### **Please strictly follow the above instructions and format. Let's begin.**
59
- `;
60
- const outputSchema = zod_1.z.object({
61
- status: zod_1.z
62
- .string()
63
- .describe(`Write a short, friendly message (max 40 characters) about your action, avoiding technical terms such as "nodes" or "atomic facts" or "key concepts". Give flavour to the message and avoid repeating the same message.`),
64
- note: zod_1.z
65
- .object({
66
- content: zod_1.z.string().describe("The new insights and findings about the question from current text"),
67
- reason: zod_1.z.string().describe("The reason describing how the text chunk is relevant to the question"),
68
- })
69
- .describe("The note summarizing the key points from the current text chunk that are relevant to the question"),
70
- chosenAction: zod_1.z.string()
71
- .describe(`This is the action you have decided to do in the next step. You **MUST** pick one of the following actions:
72
- - **queuePreviousChunk**: Choose this action if you feel that the previous text chunk contains valuable information for answering the question.
73
- - **queueNextChunk**: Choose this action if you feel that the subsequent text chunk contains valuable information for answering the question.
74
- - **readNeighbouringNodes**: Choose this action if you feel that the current text contains valuable, but somewhat incomplete information that could be clarified by exploring related concepts.
75
- - **answer**: Choose this action if you believe that the information you have currently obtained is enough to answer the question. This will allow you to summarize the gathered information and provide a final answer.
76
- `),
77
- });
78
- const inputSchema = zod_1.z.object({
79
- question: zod_1.z.string().describe("The question asked by the user"),
80
- rationalPlan: zod_1.z
81
- .string()
82
- .describe("The rational plan you designed to provide a comprehensive answer to the user question"),
83
- text: zod_1.z.string().describe("The content of the text you must analyse to provide an answer to the user question"),
84
- });
85
23
  let ChunkVectorNodeService = ChunkVectorNodeService_1 = class ChunkVectorNodeService {
86
- constructor(llmService, chunkRepository, webSocketService, clsService, configService, retrievalSources) {
87
- this.llmService = llmService;
24
+ constructor(chunkRepository, embedderService, retrievalSources) {
88
25
  this.chunkRepository = chunkRepository;
89
- this.webSocketService = webSocketService;
90
- this.clsService = clsService;
91
- this.configService = configService;
26
+ this.embedderService = embedderService;
92
27
  this.retrievalSources = retrievalSources;
93
28
  this.logger = new common_1.Logger(ChunkVectorNodeService_1.name);
94
- const prompts = this.configService.get("prompts");
95
- this.systemPrompt = prompts?.contextualiser?.chunkVector ?? exports.defaultChunkVectorPrompt;
96
29
  }
97
30
  async execute(params) {
31
+ // ONE embedding per turn. findPotentialChunks and findPotentialKeyConcepts
32
+ // were each embedding the identical question string, costing two provider
33
+ // round trips and two ledger rows for one question.
34
+ const queryEmbedding = params.state.questionEmbedding ??
35
+ (await this.embedderService.vectoriseText({
36
+ text: params.state.question,
37
+ attribution: (0, usage_attribution_1.buildRetrievalAttribution)({
38
+ contentId: params.state.contentId,
39
+ contentType: params.state.contentType,
40
+ dataLimits: params.state.limits,
41
+ scope: params.state,
42
+ }),
43
+ }));
98
44
  const [chunks, contributed] = await Promise.all([
99
45
  this.chunkRepository.findPotentialChunks({
100
46
  question: params.state.question,
101
47
  dataLimits: params.state.limits,
48
+ queryEmbedding,
102
49
  // The question embedding is billed to the scope this retrieval searches.
103
50
  // Task 10 threaded the CALLING agent's own attribution through this
104
51
  // state, and it is now the first branch of the derivation: when another
@@ -123,8 +70,9 @@ let ChunkVectorNodeService = ChunkVectorNodeService_1 = class ChunkVectorNodeSer
123
70
  return [];
124
71
  }))).then((lists) => lists.flat()),
125
72
  ]);
126
- // Neighbour-window widening: each retrieved chunk is analysed together with the
127
- // chunks immediately before/after it, so the LLM sees continuous prose.
73
+ // Neighbour-window widening: each retrieved chunk carries the chunks
74
+ // immediately before/after it, so what reaches the notebook is continuous
75
+ // prose rather than a sentence cut at both ends.
128
76
  const allRetrievedIds = chunks.map((c) => c.id);
129
77
  const neighborRecords = allRetrievedIds.length
130
78
  ? await this.chunkRepository.findChunkNeighbors({ chunkIds: allRetrievedIds, window: NEIGHBOR_WINDOW })
@@ -138,63 +86,26 @@ let ChunkVectorNodeService = ChunkVectorNodeService_1 = class ChunkVectorNodeSer
138
86
  };
139
87
  if (chunks.length === 0 && contributed.length === 0) {
140
88
  this.logger.log("chunk_vector: no results — continuing per rational plan routing");
141
- return {};
89
+ // Nothing to analyse: this path makes no provider call.
90
+ return { llmCalls: 0, questionEmbedding: queryEmbedding };
142
91
  }
143
- const llmResponses = (await Promise.all(chunks.map(async (chunk) => {
144
- if (!chunk.content || chunk.content.trim() === "")
145
- return null;
146
- const inputParams = {
147
- rationalPlan: params.state.rationalPlan,
148
- question: params.state.question,
149
- text: widen(chunk.id, chunk.content),
150
- };
151
- const llmResponse = await this.llmService.call({
152
- inputSchema: inputSchema,
153
- inputParams: inputParams,
154
- outputSchema: outputSchema,
155
- systemPrompts: [this.systemPrompt],
156
- temperature: 0.1,
157
- // Billed to the CALLING agent: its ledger category, its entity. Spread
158
- // LAST so nothing above can overwrite the attribution.
159
- ...(0, usage_attribution_1.buildInheritedAttribution)(params.state),
160
- });
161
- if (params.state.contentType === "Conversation")
162
- await this.webSocketService.sendMessageToUser(this.clsService.get("userId"), "contextualiser", {
163
- message: llmResponse.status,
164
- conversationId: params.state.contentId,
165
- });
166
- return {
167
- chunkId: chunk.id,
168
- status: llmResponse.status,
169
- note: {
170
- content: llmResponse.note?.content ?? "",
171
- reason: llmResponse.note?.reason ?? "",
172
- },
173
- chosenAction: llmResponse.chosenAction,
174
- tokens: llmResponse.tokenUsage,
175
- };
176
- })));
177
- const tokenUsed = {
178
- input: 0,
179
- output: 0,
180
- };
92
+ // No per-chunk LLM call. It filtered nothing — the notebook push was
93
+ // unconditional and its paraphrase REPLACED the chunk, so the answer node
94
+ // never saw text it could quote. The widened source text goes through
95
+ // instead, ordered and budgeted downstream (responder.answer.node.service).
181
96
  const newNotebookEntries = [];
182
- const statuses = [];
183
- for (const llmResponse of llmResponses.filter((response) => !!response)) {
184
- tokenUsed.input += llmResponse.tokens.input;
185
- tokenUsed.output += llmResponse.tokens.output;
97
+ for (const chunk of chunks) {
98
+ if (!chunk.content || chunk.content.trim() === "")
99
+ continue;
186
100
  newNotebookEntries.push({
187
- chunkId: llmResponse.chunkId,
188
- content: llmResponse.note.content,
189
- reason: llmResponse.note.reason,
101
+ chunkId: chunk.id,
102
+ content: widen(chunk.id, chunk.content),
103
+ reason: "",
190
104
  sourceLayer: "case",
191
105
  metadata: undefined,
106
+ score: chunk.score,
107
+ coreContent: chunk.content,
192
108
  });
193
- if (llmResponse.status &&
194
- !statuses.includes(llmResponse.status) &&
195
- !params.state.status.includes(llmResponse.status)) {
196
- statuses.push(llmResponse.status);
197
- }
198
109
  }
199
110
  for (const entry of contributed) {
200
111
  newNotebookEntries.push({
@@ -203,26 +114,26 @@ let ChunkVectorNodeService = ChunkVectorNodeService_1 = class ChunkVectorNodeSer
203
114
  reason: entry.reason,
204
115
  sourceLayer: entry.sourceLayer ?? "case",
205
116
  metadata: entry.metadata,
117
+ score: undefined,
118
+ coreContent: undefined,
206
119
  });
207
120
  }
208
121
  return {
209
122
  hops: params.state.hops + 1,
123
+ llmCalls: 0,
210
124
  processedChunks: chunks.map((c) => c.id),
211
125
  notebook: newNotebookEntries,
212
- status: statuses,
213
- tokens: tokenUsed,
126
+ questionEmbedding: queryEmbedding,
127
+ tokens: { input: 0, output: 0 },
214
128
  };
215
129
  }
216
130
  };
217
131
  exports.ChunkVectorNodeService = ChunkVectorNodeService;
218
132
  exports.ChunkVectorNodeService = ChunkVectorNodeService = ChunkVectorNodeService_1 = __decorate([
219
133
  (0, common_1.Injectable)(),
220
- __param(5, (0, common_1.Optional)()),
221
- __param(5, (0, common_1.Inject)(retrieval_source_interface_1.RETRIEVAL_SOURCES)),
222
- __metadata("design:paramtypes", [llm_service_1.LLMService,
223
- chunk_repository_1.ChunkRepository,
224
- websocket_service_1.WebSocketService,
225
- nestjs_cls_1.ClsService,
226
- config_1.ConfigService, Array])
134
+ __param(2, (0, common_1.Optional)()),
135
+ __param(2, (0, common_1.Inject)(retrieval_source_interface_1.RETRIEVAL_SOURCES)),
136
+ __metadata("design:paramtypes", [chunk_repository_1.ChunkRepository,
137
+ embedder_service_1.EmbedderService, Array])
227
138
  ], ChunkVectorNodeService);
228
139
  //# sourceMappingURL=chunk.vector.node.service.js.map