@librechat/agents 2.4.13 → 2.4.14
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/cjs/graphs/Graph.cjs +17 -11
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/messages/prune.cjs +65 -35
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +17 -11
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/messages/prune.mjs +65 -35
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/types/graphs/Graph.d.ts +1 -1
- package/dist/types/messages/prune.d.ts +2 -2
- package/package.json +1 -1
- package/src/graphs/Graph.ts +19 -12
- package/src/messages/prune.ts +158 -61
- package/src/specs/prune.test.ts +93 -76
- package/src/specs/token-distribution-edge-case.test.ts +73 -52
|
@@ -8,10 +8,12 @@ function isIndexInContext(arrayA, arrayB, targetIndex) {
|
|
|
8
8
|
function addThinkingBlock(message, thinkingBlock) {
|
|
9
9
|
const content = Array.isArray(message.content)
|
|
10
10
|
? message.content
|
|
11
|
-
: [
|
|
11
|
+
: [
|
|
12
|
+
{
|
|
12
13
|
type: ContentTypes.TEXT,
|
|
13
14
|
text: message.content,
|
|
14
|
-
}
|
|
15
|
+
},
|
|
16
|
+
];
|
|
15
17
|
/** Edge case, the message already has the thinking block */
|
|
16
18
|
if (content[0].type === thinkingBlock.type) {
|
|
17
19
|
return message;
|
|
@@ -19,7 +21,7 @@ function addThinkingBlock(message, thinkingBlock) {
|
|
|
19
21
|
content.unshift(thinkingBlock);
|
|
20
22
|
return new AIMessage({
|
|
21
23
|
...message,
|
|
22
|
-
content
|
|
24
|
+
content,
|
|
23
25
|
});
|
|
24
26
|
}
|
|
25
27
|
/**
|
|
@@ -37,7 +39,7 @@ function calculateTotalTokens(usage) {
|
|
|
37
39
|
return {
|
|
38
40
|
input_tokens: totalInputTokens,
|
|
39
41
|
output_tokens: totalOutputTokens,
|
|
40
|
-
total_tokens: totalInputTokens + totalOutputTokens
|
|
42
|
+
total_tokens: totalInputTokens + totalOutputTokens,
|
|
41
43
|
};
|
|
42
44
|
}
|
|
43
45
|
/**
|
|
@@ -52,7 +54,7 @@ function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, in
|
|
|
52
54
|
// start with 3 tokens for the label after all messages have been counted.
|
|
53
55
|
let currentTokenCount = 3;
|
|
54
56
|
const instructions = _messages[0]?.getType() === 'system' ? _messages[0] : undefined;
|
|
55
|
-
const instructionsTokenCount = instructions != null ? indexTokenCountMap[0] ?? 0 : 0;
|
|
57
|
+
const instructionsTokenCount = instructions != null ? (indexTokenCountMap[0] ?? 0) : 0;
|
|
56
58
|
const initialContextTokens = maxContextTokens - instructionsTokenCount;
|
|
57
59
|
let remainingContextTokens = initialContextTokens;
|
|
58
60
|
let startType = _startType;
|
|
@@ -77,7 +79,9 @@ function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, in
|
|
|
77
79
|
}
|
|
78
80
|
if (currentTokenCount < remainingContextTokens) {
|
|
79
81
|
let currentIndex = messages.length;
|
|
80
|
-
while (messages.length > 0 &&
|
|
82
|
+
while (messages.length > 0 &&
|
|
83
|
+
currentTokenCount < remainingContextTokens &&
|
|
84
|
+
currentIndex > endIndex) {
|
|
81
85
|
currentIndex--;
|
|
82
86
|
if (messages.length === 1 && instructions) {
|
|
83
87
|
break;
|
|
@@ -86,21 +90,30 @@ function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, in
|
|
|
86
90
|
if (!poppedMessage)
|
|
87
91
|
continue;
|
|
88
92
|
const messageType = poppedMessage.getType();
|
|
89
|
-
if (thinkingEnabled === true &&
|
|
93
|
+
if (thinkingEnabled === true &&
|
|
94
|
+
thinkingEndIndex === -1 &&
|
|
95
|
+
currentIndex === originalLength - 1 &&
|
|
96
|
+
(messageType === 'ai' || messageType === 'tool')) {
|
|
90
97
|
thinkingEndIndex = currentIndex;
|
|
91
98
|
}
|
|
92
|
-
if (thinkingEndIndex > -1 &&
|
|
93
|
-
thinkingBlock
|
|
99
|
+
if (thinkingEndIndex > -1 &&
|
|
100
|
+
!thinkingBlock &&
|
|
101
|
+
thinkingStartIndex < 0 &&
|
|
102
|
+
messageType === 'ai' &&
|
|
103
|
+
Array.isArray(poppedMessage.content)) {
|
|
104
|
+
thinkingBlock = poppedMessage.content.find((content) => content.type === reasoningType);
|
|
94
105
|
thinkingStartIndex = thinkingBlock != null ? currentIndex : -1;
|
|
95
106
|
}
|
|
96
107
|
/** False start, the latest message was not part of a multi-assistant/tool sequence of messages */
|
|
97
|
-
if (thinkingEndIndex > -1
|
|
98
|
-
|
|
99
|
-
|
|
108
|
+
if (thinkingEndIndex > -1 &&
|
|
109
|
+
currentIndex === thinkingEndIndex - 1 &&
|
|
110
|
+
messageType !== 'ai' &&
|
|
111
|
+
messageType !== 'tool') {
|
|
100
112
|
thinkingEndIndex = -1;
|
|
101
113
|
}
|
|
102
114
|
const tokenCount = indexTokenCountMap[currentIndex] ?? 0;
|
|
103
|
-
if (prunedMemory.length === 0 &&
|
|
115
|
+
if (prunedMemory.length === 0 &&
|
|
116
|
+
currentTokenCount + tokenCount <= remainingContextTokens) {
|
|
104
117
|
context.push(poppedMessage);
|
|
105
118
|
currentTokenCount += tokenCount;
|
|
106
119
|
}
|
|
@@ -120,7 +133,9 @@ function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, in
|
|
|
120
133
|
let totalTokens = 0;
|
|
121
134
|
for (let i = context.length - 1; i >= 0; i--) {
|
|
122
135
|
const currentType = context[i]?.getType() ?? '';
|
|
123
|
-
if (Array.isArray(startType)
|
|
136
|
+
if (Array.isArray(startType)
|
|
137
|
+
? startType.includes(currentType)
|
|
138
|
+
: currentType === startType) {
|
|
124
139
|
requiredTypeIndex = i + 1;
|
|
125
140
|
break;
|
|
126
141
|
}
|
|
@@ -146,7 +161,10 @@ function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, in
|
|
|
146
161
|
if (thinkingStartIndex > -1) {
|
|
147
162
|
result.thinkingStartIndex = thinkingStartIndex;
|
|
148
163
|
}
|
|
149
|
-
if (prunedMemory.length === 0 ||
|
|
164
|
+
if (prunedMemory.length === 0 ||
|
|
165
|
+
thinkingEndIndex < 0 ||
|
|
166
|
+
(thinkingStartIndex > -1 &&
|
|
167
|
+
isIndexInContext(_messages, context, thinkingStartIndex))) {
|
|
150
168
|
// we reverse at this step to ensure the context is in the correct order for the model, and we need to work backwards
|
|
151
169
|
result.context = context.reverse();
|
|
152
170
|
return result;
|
|
@@ -191,13 +209,15 @@ function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, in
|
|
|
191
209
|
let newContext = [];
|
|
192
210
|
const secondRoundMessages = [..._messages];
|
|
193
211
|
let currentIndex = secondRoundMessages.length;
|
|
194
|
-
while (secondRoundMessages.length > 0 &&
|
|
212
|
+
while (secondRoundMessages.length > 0 &&
|
|
213
|
+
currentTokenCount < remainingContextTokens &&
|
|
214
|
+
currentIndex > thinkingStartIndex) {
|
|
195
215
|
currentIndex--;
|
|
196
216
|
const poppedMessage = secondRoundMessages.pop();
|
|
197
217
|
if (!poppedMessage)
|
|
198
218
|
continue;
|
|
199
219
|
const tokenCount = indexTokenCountMap[currentIndex] ?? 0;
|
|
200
|
-
if (
|
|
220
|
+
if (currentTokenCount + tokenCount <= remainingContextTokens) {
|
|
201
221
|
newContext.push(poppedMessage);
|
|
202
222
|
currentTokenCount += tokenCount;
|
|
203
223
|
}
|
|
@@ -216,7 +236,9 @@ function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, in
|
|
|
216
236
|
let totalTokens = 0;
|
|
217
237
|
for (let i = newContext.length - 1; i >= 0; i--) {
|
|
218
238
|
const currentType = newContext[i]?.getType() ?? '';
|
|
219
|
-
if (Array.isArray(startType)
|
|
239
|
+
if (Array.isArray(startType)
|
|
240
|
+
? startType.includes(currentType)
|
|
241
|
+
: currentType === startType) {
|
|
220
242
|
requiredTypeIndex = i + 1;
|
|
221
243
|
break;
|
|
222
244
|
}
|
|
@@ -249,31 +271,33 @@ function createPruneMessages(factoryParams) {
|
|
|
249
271
|
const indexTokenCountMap = { ...factoryParams.indexTokenCountMap };
|
|
250
272
|
let lastTurnStartIndex = factoryParams.startIndex;
|
|
251
273
|
let lastCutOffIndex = 0;
|
|
252
|
-
let totalTokens =
|
|
274
|
+
let totalTokens = Object.values(indexTokenCountMap).reduce((a = 0, b = 0) => a + b, 0);
|
|
253
275
|
let runThinkingStartIndex = -1;
|
|
254
276
|
return function pruneMessages(params) {
|
|
255
277
|
let currentUsage;
|
|
256
|
-
if (params.usageMetadata &&
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
278
|
+
if (params.usageMetadata &&
|
|
279
|
+
(checkValidNumber(params.usageMetadata.input_tokens) ||
|
|
280
|
+
(checkValidNumber(params.usageMetadata.input_token_details) &&
|
|
281
|
+
(checkValidNumber(params.usageMetadata.input_token_details.cache_creation) ||
|
|
282
|
+
checkValidNumber(params.usageMetadata.input_token_details.cache_read)))) &&
|
|
283
|
+
checkValidNumber(params.usageMetadata.output_tokens)) {
|
|
260
284
|
currentUsage = calculateTotalTokens(params.usageMetadata);
|
|
261
285
|
totalTokens = currentUsage.total_tokens;
|
|
262
286
|
}
|
|
263
287
|
const newOutputs = new Set();
|
|
264
288
|
for (let i = lastTurnStartIndex; i < params.messages.length; i++) {
|
|
265
289
|
const message = params.messages[i];
|
|
266
|
-
|
|
267
|
-
|
|
290
|
+
if (i === lastTurnStartIndex &&
|
|
291
|
+
indexTokenCountMap[i] === undefined &&
|
|
292
|
+
currentUsage) {
|
|
268
293
|
indexTokenCountMap[i] = currentUsage.output_tokens;
|
|
269
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
270
294
|
}
|
|
271
295
|
else if (indexTokenCountMap[i] === undefined) {
|
|
272
296
|
indexTokenCountMap[i] = factoryParams.tokenCounter(message);
|
|
273
297
|
if (currentUsage) {
|
|
274
298
|
newOutputs.add(i);
|
|
275
299
|
}
|
|
276
|
-
totalTokens += indexTokenCountMap[i];
|
|
300
|
+
totalTokens += indexTokenCountMap[i] ?? 0;
|
|
277
301
|
}
|
|
278
302
|
}
|
|
279
303
|
// If `currentUsage` is defined, we need to distribute the current total tokens to our `indexTokenCountMap`,
|
|
@@ -283,7 +307,7 @@ function createPruneMessages(factoryParams) {
|
|
|
283
307
|
if (currentUsage) {
|
|
284
308
|
let totalIndexTokens = 0;
|
|
285
309
|
if (params.messages[0].getType() === 'system') {
|
|
286
|
-
totalIndexTokens += indexTokenCountMap[0];
|
|
310
|
+
totalIndexTokens += indexTokenCountMap[0] ?? 0;
|
|
287
311
|
}
|
|
288
312
|
for (let i = lastCutOffIndex; i < params.messages.length; i++) {
|
|
289
313
|
if (i === 0 && params.messages[0].getType() === 'system') {
|
|
@@ -292,21 +316,22 @@ function createPruneMessages(factoryParams) {
|
|
|
292
316
|
if (newOutputs.has(i)) {
|
|
293
317
|
continue;
|
|
294
318
|
}
|
|
295
|
-
totalIndexTokens += indexTokenCountMap[i];
|
|
319
|
+
totalIndexTokens += indexTokenCountMap[i] ?? 0;
|
|
296
320
|
}
|
|
297
321
|
// Calculate ratio based only on messages that remain in the context
|
|
298
322
|
const ratio = currentUsage.total_tokens / totalIndexTokens;
|
|
299
323
|
const isRatioSafe = ratio >= 1 / 3 && ratio <= 2.5;
|
|
300
324
|
// Apply the ratio adjustment only to messages at or after lastCutOffIndex, and only if the ratio is safe
|
|
301
325
|
if (isRatioSafe) {
|
|
302
|
-
if (params.messages[0].getType() === 'system' &&
|
|
303
|
-
|
|
326
|
+
if (params.messages[0].getType() === 'system' &&
|
|
327
|
+
lastCutOffIndex !== 0) {
|
|
328
|
+
indexTokenCountMap[0] = Math.round((indexTokenCountMap[0] ?? 0) * ratio);
|
|
304
329
|
}
|
|
305
330
|
for (let i = lastCutOffIndex; i < params.messages.length; i++) {
|
|
306
331
|
if (newOutputs.has(i)) {
|
|
307
332
|
continue;
|
|
308
333
|
}
|
|
309
|
-
indexTokenCountMap[i] = Math.round(indexTokenCountMap[i] * ratio);
|
|
334
|
+
indexTokenCountMap[i] = Math.round((indexTokenCountMap[i] ?? 0) * ratio);
|
|
310
335
|
}
|
|
311
336
|
}
|
|
312
337
|
}
|
|
@@ -321,12 +346,17 @@ function createPruneMessages(factoryParams) {
|
|
|
321
346
|
startType: params.startType,
|
|
322
347
|
thinkingEnabled: factoryParams.thinkingEnabled,
|
|
323
348
|
tokenCounter: factoryParams.tokenCounter,
|
|
324
|
-
reasoningType: factoryParams.provider === Providers.BEDROCK
|
|
325
|
-
|
|
349
|
+
reasoningType: factoryParams.provider === Providers.BEDROCK
|
|
350
|
+
? ContentTypes.REASONING_CONTENT
|
|
351
|
+
: ContentTypes.THINKING,
|
|
352
|
+
thinkingStartIndex: factoryParams.thinkingEnabled === true
|
|
353
|
+
? runThinkingStartIndex
|
|
354
|
+
: undefined,
|
|
326
355
|
});
|
|
327
356
|
runThinkingStartIndex = thinkingStartIndex ?? -1;
|
|
328
357
|
/** The index is the first value of `context`, index relative to `params.messages` */
|
|
329
|
-
lastCutOffIndex = Math.max(params.messages.length -
|
|
358
|
+
lastCutOffIndex = Math.max(params.messages.length -
|
|
359
|
+
(context.length - (context[0]?.getType() === 'system' ? 1 : 0)), 0);
|
|
330
360
|
return { context, indexTokenCountMap };
|
|
331
361
|
};
|
|
332
362
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prune.mjs","sources":["../../../src/messages/prune.ts"],"sourcesContent":["import { AIMessage, BaseMessage, UsageMetadata } from '@langchain/core/messages';\nimport type { ThinkingContentText, MessageContentComplex, ReasoningContentText } from '@/types/stream';\nimport type { TokenCounter } from '@/types/run';\nimport { ContentTypes, Providers } from '@/common';\n\nexport type PruneMessagesFactoryParams = {\n provider?: Providers;\n maxTokens: number;\n startIndex: number;\n tokenCounter: TokenCounter;\n indexTokenCountMap: Record<string, number>;\n thinkingEnabled?: boolean;\n};\nexport type PruneMessagesParams = {\n messages: BaseMessage[];\n usageMetadata?: Partial<UsageMetadata>;\n startType?: ReturnType<BaseMessage['getType']>;\n}\n\nfunction isIndexInContext(arrayA: unknown[], arrayB: unknown[], targetIndex: number): boolean {\n const startingIndexInA = arrayA.length - arrayB.length;\n return targetIndex >= startingIndexInA;\n}\n\nfunction addThinkingBlock(message: AIMessage, thinkingBlock: ThinkingContentText | ReasoningContentText): AIMessage {\n const content: MessageContentComplex[] = Array.isArray(message.content)\n ? message.content as MessageContentComplex[]\n : [{\n type: ContentTypes.TEXT,\n text: message.content,\n }];\n /** Edge case, the message already has the thinking block */\n if (content[0].type === thinkingBlock.type) {\n return message;\n }\n content.unshift(thinkingBlock);\n return new AIMessage({\n ...message,\n content\n });\n}\n\n/**\n * Calculates the total tokens from a single usage object\n *\n * @param usage The usage metadata object containing token information\n * @returns An object containing the total input and output tokens\n */\nexport function calculateTotalTokens(usage: Partial<UsageMetadata>): UsageMetadata {\n const baseInputTokens = Number(usage.input_tokens) || 0;\n const cacheCreation = Number(usage.input_token_details?.cache_creation) || 0;\n const cacheRead = Number(usage.input_token_details?.cache_read) || 0;\n\n const totalInputTokens = baseInputTokens + cacheCreation + cacheRead;\n const totalOutputTokens = Number(usage.output_tokens) || 0;\n\n return {\n input_tokens: totalInputTokens,\n output_tokens: totalOutputTokens,\n total_tokens: totalInputTokens + totalOutputTokens\n };\n}\n\nexport type PruningResult = {\n context: BaseMessage[];\n remainingContextTokens: number;\n messagesToRefine: BaseMessage[];\n thinkingStartIndex?: number;\n};\n\n/**\n * Processes an array of messages and returns a context of messages that fit within a specified token limit.\n * It iterates over the messages from newest to oldest, adding them to the context until the token limit is reached.\n *\n * @param options Configuration options for processing messages\n * @returns Object containing the message context, remaining tokens, messages not included, and summary index\n */\nexport function getMessagesWithinTokenLimit({\n messages: _messages,\n maxContextTokens,\n indexTokenCountMap,\n startType: _startType,\n thinkingEnabled,\n tokenCounter,\n thinkingStartIndex: _thinkingStartIndex = -1,\n reasoningType = ContentTypes.THINKING,\n}: {\n messages: BaseMessage[];\n maxContextTokens: number;\n indexTokenCountMap: Record<string, number | undefined>;\n startType?: string | string[];\n thinkingEnabled?: boolean;\n tokenCounter: TokenCounter;\n thinkingStartIndex?: number;\n reasoningType?: ContentTypes.THINKING | ContentTypes.REASONING_CONTENT;\n}): PruningResult {\n // Every reply is primed with <|start|>assistant<|message|>, so we\n // start with 3 tokens for the label after all messages have been counted.\n let currentTokenCount = 3;\n const instructions = _messages[0]?.getType() === 'system' ? _messages[0] : undefined;\n const instructionsTokenCount = instructions != null ? indexTokenCountMap[0] ?? 0 : 0;\n const initialContextTokens = maxContextTokens - instructionsTokenCount;\n let remainingContextTokens = initialContextTokens;\n let startType = _startType;\n const originalLength = _messages.length;\n const messages = [..._messages];\n /**\n * IMPORTANT: this context array gets reversed at the end, since the latest messages get pushed first.\n *\n * This may be confusing to read, but it is done to ensure the context is in the correct order for the model.\n * */\n let context: Array<BaseMessage | undefined> = [];\n\n let thinkingStartIndex = _thinkingStartIndex;\n let thinkingEndIndex = -1;\n let thinkingBlock: ThinkingContentText | ReasoningContentText | undefined;\n const endIndex = instructions != null ? 1 : 0;\n const prunedMemory: BaseMessage[] = [];\n\n if (_thinkingStartIndex > -1) {\n const thinkingMessageContent = messages[_thinkingStartIndex]?.content;\n if (Array.isArray(thinkingMessageContent)) {\n thinkingBlock = thinkingMessageContent.find((content) => content.type === reasoningType) as ThinkingContentText | undefined;\n }\n }\n\n if (currentTokenCount < remainingContextTokens) {\n let currentIndex = messages.length;\n while (messages.length > 0 && currentTokenCount < remainingContextTokens && currentIndex > endIndex) {\n currentIndex--;\n if (messages.length === 1 && instructions) {\n break;\n }\n const poppedMessage = messages.pop();\n if (!poppedMessage) continue;\n const messageType = poppedMessage.getType();\n if (thinkingEnabled === true && thinkingEndIndex === -1 && (currentIndex === (originalLength - 1)) && (messageType === 'ai' || messageType === 'tool')) {\n thinkingEndIndex = currentIndex;\n }\n if (thinkingEndIndex > -1 && !thinkingBlock && thinkingStartIndex < 0 && messageType === 'ai' && Array.isArray(poppedMessage.content)) {\n thinkingBlock = (poppedMessage.content.find((content) => content.type === reasoningType)) as ThinkingContentText | undefined;\n thinkingStartIndex = thinkingBlock != null ? currentIndex : -1;\n }\n /** False start, the latest message was not part of a multi-assistant/tool sequence of messages */\n if (\n thinkingEndIndex > -1\n && currentIndex === (thinkingEndIndex - 1)\n && (messageType !== 'ai' && messageType !== 'tool')\n ) {\n thinkingEndIndex = -1;\n }\n\n const tokenCount = indexTokenCountMap[currentIndex] ?? 0;\n\n if (prunedMemory.length === 0 && ((currentTokenCount + tokenCount) <= remainingContextTokens)) {\n context.push(poppedMessage);\n currentTokenCount += tokenCount;\n } else {\n prunedMemory.push(poppedMessage);\n if (thinkingEndIndex > -1 && thinkingStartIndex < 0) {\n continue;\n }\n break;\n }\n }\n\n if (context[context.length - 1]?.getType() === 'tool') {\n startType = ['ai', 'human'];\n }\n\n if (startType != null && startType.length > 0 && context.length > 0) {\n let requiredTypeIndex = -1;\n\n let totalTokens = 0;\n for (let i = context.length - 1; i >= 0; i--) {\n const currentType = context[i]?.getType() ?? '';\n if (Array.isArray(startType) ? startType.includes(currentType) : currentType === startType) {\n requiredTypeIndex = i + 1;\n break;\n }\n const originalIndex = originalLength - 1 - i;\n totalTokens += indexTokenCountMap[originalIndex] ?? 0;\n }\n\n if (requiredTypeIndex > 0) {\n currentTokenCount -= totalTokens;\n context = context.slice(0, requiredTypeIndex);\n }\n }\n }\n\n if (instructions && originalLength > 0) {\n context.push(_messages[0] as BaseMessage);\n messages.shift();\n }\n\n remainingContextTokens -= currentTokenCount;\n const result: PruningResult = {\n remainingContextTokens,\n context: [] as BaseMessage[],\n messagesToRefine: prunedMemory,\n };\n\n if (thinkingStartIndex > -1) {\n result.thinkingStartIndex = thinkingStartIndex;\n }\n\n if (prunedMemory.length === 0 || thinkingEndIndex < 0 || (thinkingStartIndex > -1 && isIndexInContext(_messages, context, thinkingStartIndex))) {\n // we reverse at this step to ensure the context is in the correct order for the model, and we need to work backwards\n result.context = context.reverse() as BaseMessage[];\n return result;\n }\n\n if (thinkingEndIndex > -1 && thinkingStartIndex < 0) {\n throw new Error('The payload is malformed. There is a thinking sequence but no \"AI\" messages with thinking blocks.');\n }\n\n if (!thinkingBlock) {\n throw new Error('The payload is malformed. There is a thinking sequence but no thinking block found.');\n }\n\n // Since we have a thinking sequence, we need to find the last assistant message\n // in the latest AI/tool sequence to add the thinking block that falls outside of the current context\n // Latest messages are ordered first.\n let assistantIndex = -1;\n for (let i = 0; i < context.length; i++) {\n const currentMessage = context[i];\n const type = currentMessage?.getType();\n if (type === 'ai') {\n assistantIndex = i;\n }\n if (assistantIndex > -1 && (type === 'human' || type === 'system')) {\n break;\n }\n }\n\n if (assistantIndex === -1) {\n throw new Error('The payload is malformed. There is a thinking sequence but no \"AI\" messages to append thinking blocks to.');\n }\n\n thinkingStartIndex = originalLength - 1 - assistantIndex;\n const thinkingTokenCount = tokenCounter(new AIMessage({ content: [thinkingBlock] }));\n const newRemainingCount = remainingContextTokens - thinkingTokenCount;\n const newMessage = addThinkingBlock(context[assistantIndex] as AIMessage, thinkingBlock);\n context[assistantIndex] = newMessage;\n if (newRemainingCount > 0) {\n result.context = context.reverse() as BaseMessage[];\n return result;\n }\n\n const thinkingMessage: AIMessage = context[assistantIndex] as AIMessage;\n // now we need to an additional round of pruning but making the thinking block fit\n const newThinkingMessageTokenCount = (indexTokenCountMap[thinkingStartIndex] ?? 0) + thinkingTokenCount;\n remainingContextTokens = initialContextTokens - newThinkingMessageTokenCount;\n currentTokenCount = 3;\n let newContext: BaseMessage[] = [];\n const secondRoundMessages = [..._messages];\n let currentIndex = secondRoundMessages.length;\n while (secondRoundMessages.length > 0 && currentTokenCount < remainingContextTokens && currentIndex > thinkingStartIndex) {\n currentIndex--;\n const poppedMessage = secondRoundMessages.pop();\n if (!poppedMessage) continue;\n const tokenCount = indexTokenCountMap[currentIndex] ?? 0;\n if ((currentTokenCount + tokenCount) <= remainingContextTokens) {\n newContext.push(poppedMessage);\n currentTokenCount += tokenCount;\n } else {\n messages.push(poppedMessage);\n break;\n }\n }\n\n const firstMessage: AIMessage = newContext[newContext.length - 1];\n const firstMessageType = newContext[newContext.length - 1].getType();\n if (firstMessageType === 'tool') {\n startType = ['ai', 'human'];\n }\n\n if (startType != null && startType.length > 0 && newContext.length > 0) {\n let requiredTypeIndex = -1;\n\n let totalTokens = 0;\n for (let i = newContext.length - 1; i >= 0; i--) {\n const currentType = newContext[i]?.getType() ?? '';\n if (Array.isArray(startType) ? startType.includes(currentType) : currentType === startType) {\n requiredTypeIndex = i + 1;\n break;\n }\n const originalIndex = originalLength - 1 - i;\n totalTokens += indexTokenCountMap[originalIndex] ?? 0;\n }\n\n if (requiredTypeIndex > 0) {\n currentTokenCount -= totalTokens;\n newContext = newContext.slice(0, requiredTypeIndex);\n }\n }\n\n if (firstMessageType === 'ai') {\n const newMessage = addThinkingBlock(firstMessage, thinkingBlock);\n newContext[newContext.length - 1] = newMessage;\n } else {\n newContext.push(thinkingMessage);\n }\n\n if (instructions && originalLength > 0) {\n newContext.push(_messages[0] as BaseMessage);\n secondRoundMessages.shift();\n }\n\n result.context = newContext.reverse();\n return result;\n}\n\nexport function checkValidNumber(value: unknown): value is number {\n return typeof value === 'number' && !isNaN(value) && value > 0;\n}\n\nexport function createPruneMessages(factoryParams: PruneMessagesFactoryParams) {\n const indexTokenCountMap = { ...factoryParams.indexTokenCountMap };\n let lastTurnStartIndex = factoryParams.startIndex;\n let lastCutOffIndex = 0;\n let totalTokens = (Object.values(indexTokenCountMap)).reduce((a, b) => a + b, 0);\n let runThinkingStartIndex = -1;\n return function pruneMessages(params: PruneMessagesParams): {\n context: BaseMessage[];\n indexTokenCountMap: Record<string, number>;\n } {\n let currentUsage: UsageMetadata | undefined;\n if (params.usageMetadata && (\n checkValidNumber(params.usageMetadata.input_tokens)\n || (\n checkValidNumber(params.usageMetadata.input_token_details)\n && (\n checkValidNumber(params.usageMetadata.input_token_details.cache_creation)\n || checkValidNumber(params.usageMetadata.input_token_details.cache_read)\n )\n )\n ) && checkValidNumber(params.usageMetadata.output_tokens)) {\n currentUsage = calculateTotalTokens(params.usageMetadata);\n totalTokens = currentUsage.total_tokens;\n }\n\n const newOutputs = new Set<number>();\n for (let i = lastTurnStartIndex; i < params.messages.length; i++) {\n const message = params.messages[i];\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (i === lastTurnStartIndex && indexTokenCountMap[i] === undefined && currentUsage) {\n indexTokenCountMap[i] = currentUsage.output_tokens;\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n } else if (indexTokenCountMap[i] === undefined) {\n indexTokenCountMap[i] = factoryParams.tokenCounter(message);\n if (currentUsage) {\n newOutputs.add(i);\n }\n totalTokens += indexTokenCountMap[i];\n }\n }\n\n // If `currentUsage` is defined, we need to distribute the current total tokens to our `indexTokenCountMap`,\n // We must distribute it in a weighted manner, so that the total token count is equal to `currentUsage.total_tokens`,\n // relative the manually counted tokens in `indexTokenCountMap`.\n // EDGE CASE: when the resulting context gets pruned, we should not distribute the usage for messages that are not in the context.\n if (currentUsage) {\n let totalIndexTokens = 0;\n if (params.messages[0].getType() === 'system') {\n totalIndexTokens += indexTokenCountMap[0];\n }\n for (let i = lastCutOffIndex; i < params.messages.length; i++) {\n if (i === 0 && params.messages[0].getType() === 'system') {\n continue;\n }\n if (newOutputs.has(i)) {\n continue;\n }\n totalIndexTokens += indexTokenCountMap[i];\n }\n\n // Calculate ratio based only on messages that remain in the context\n const ratio = currentUsage.total_tokens / totalIndexTokens;\n const isRatioSafe = ratio >= 1/3 && ratio <= 2.5;\n\n // Apply the ratio adjustment only to messages at or after lastCutOffIndex, and only if the ratio is safe\n if (isRatioSafe) {\n if (params.messages[0].getType() === 'system' && lastCutOffIndex !== 0) {\n indexTokenCountMap[0] = Math.round(indexTokenCountMap[0] * ratio);\n }\n\n for (let i = lastCutOffIndex; i < params.messages.length; i++) {\n if (newOutputs.has(i)) {\n continue;\n }\n indexTokenCountMap[i] = Math.round(indexTokenCountMap[i] * ratio);\n }\n }\n }\n\n lastTurnStartIndex = params.messages.length;\n if (lastCutOffIndex === 0 && totalTokens <= factoryParams.maxTokens) {\n return { context: params.messages, indexTokenCountMap };\n }\n\n const { context, thinkingStartIndex } = getMessagesWithinTokenLimit({\n maxContextTokens: factoryParams.maxTokens,\n messages: params.messages,\n indexTokenCountMap,\n startType: params.startType,\n thinkingEnabled: factoryParams.thinkingEnabled,\n tokenCounter: factoryParams.tokenCounter,\n reasoningType: factoryParams.provider === Providers.BEDROCK ? ContentTypes.REASONING_CONTENT : ContentTypes.THINKING,\n thinkingStartIndex: factoryParams.thinkingEnabled === true ? runThinkingStartIndex : undefined,\n });\n runThinkingStartIndex = thinkingStartIndex ?? -1;\n /** The index is the first value of `context`, index relative to `params.messages` */\n lastCutOffIndex = Math.max(params.messages.length - (context.length - (context[0]?.getType() === 'system' ? 1 : 0)), 0);\n\n return { context, indexTokenCountMap };\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"prune.mjs","sources":["../../../src/messages/prune.ts"],"sourcesContent":["import {\n AIMessage,\n BaseMessage,\n UsageMetadata,\n} from '@langchain/core/messages';\nimport type {\n ThinkingContentText,\n MessageContentComplex,\n ReasoningContentText,\n} from '@/types/stream';\nimport type { TokenCounter } from '@/types/run';\nimport { ContentTypes, Providers } from '@/common';\n\nexport type PruneMessagesFactoryParams = {\n provider?: Providers;\n maxTokens: number;\n startIndex: number;\n tokenCounter: TokenCounter;\n indexTokenCountMap: Record<string, number | undefined>;\n thinkingEnabled?: boolean;\n};\nexport type PruneMessagesParams = {\n messages: BaseMessage[];\n usageMetadata?: Partial<UsageMetadata>;\n startType?: ReturnType<BaseMessage['getType']>;\n};\n\nfunction isIndexInContext(\n arrayA: unknown[],\n arrayB: unknown[],\n targetIndex: number\n): boolean {\n const startingIndexInA = arrayA.length - arrayB.length;\n return targetIndex >= startingIndexInA;\n}\n\nfunction addThinkingBlock(\n message: AIMessage,\n thinkingBlock: ThinkingContentText | ReasoningContentText\n): AIMessage {\n const content: MessageContentComplex[] = Array.isArray(message.content)\n ? (message.content as MessageContentComplex[])\n : [\n {\n type: ContentTypes.TEXT,\n text: message.content,\n },\n ];\n /** Edge case, the message already has the thinking block */\n if (content[0].type === thinkingBlock.type) {\n return message;\n }\n content.unshift(thinkingBlock);\n return new AIMessage({\n ...message,\n content,\n });\n}\n\n/**\n * Calculates the total tokens from a single usage object\n *\n * @param usage The usage metadata object containing token information\n * @returns An object containing the total input and output tokens\n */\nexport function calculateTotalTokens(\n usage: Partial<UsageMetadata>\n): UsageMetadata {\n const baseInputTokens = Number(usage.input_tokens) || 0;\n const cacheCreation = Number(usage.input_token_details?.cache_creation) || 0;\n const cacheRead = Number(usage.input_token_details?.cache_read) || 0;\n\n const totalInputTokens = baseInputTokens + cacheCreation + cacheRead;\n const totalOutputTokens = Number(usage.output_tokens) || 0;\n\n return {\n input_tokens: totalInputTokens,\n output_tokens: totalOutputTokens,\n total_tokens: totalInputTokens + totalOutputTokens,\n };\n}\n\nexport type PruningResult = {\n context: BaseMessage[];\n remainingContextTokens: number;\n messagesToRefine: BaseMessage[];\n thinkingStartIndex?: number;\n};\n\n/**\n * Processes an array of messages and returns a context of messages that fit within a specified token limit.\n * It iterates over the messages from newest to oldest, adding them to the context until the token limit is reached.\n *\n * @param options Configuration options for processing messages\n * @returns Object containing the message context, remaining tokens, messages not included, and summary index\n */\nexport function getMessagesWithinTokenLimit({\n messages: _messages,\n maxContextTokens,\n indexTokenCountMap,\n startType: _startType,\n thinkingEnabled,\n tokenCounter,\n thinkingStartIndex: _thinkingStartIndex = -1,\n reasoningType = ContentTypes.THINKING,\n}: {\n messages: BaseMessage[];\n maxContextTokens: number;\n indexTokenCountMap: Record<string, number | undefined>;\n startType?: string | string[];\n thinkingEnabled?: boolean;\n tokenCounter: TokenCounter;\n thinkingStartIndex?: number;\n reasoningType?: ContentTypes.THINKING | ContentTypes.REASONING_CONTENT;\n}): PruningResult {\n // Every reply is primed with <|start|>assistant<|message|>, so we\n // start with 3 tokens for the label after all messages have been counted.\n let currentTokenCount = 3;\n const instructions =\n _messages[0]?.getType() === 'system' ? _messages[0] : undefined;\n const instructionsTokenCount =\n instructions != null ? (indexTokenCountMap[0] ?? 0) : 0;\n const initialContextTokens = maxContextTokens - instructionsTokenCount;\n let remainingContextTokens = initialContextTokens;\n let startType = _startType;\n const originalLength = _messages.length;\n const messages = [..._messages];\n /**\n * IMPORTANT: this context array gets reversed at the end, since the latest messages get pushed first.\n *\n * This may be confusing to read, but it is done to ensure the context is in the correct order for the model.\n * */\n let context: Array<BaseMessage | undefined> = [];\n\n let thinkingStartIndex = _thinkingStartIndex;\n let thinkingEndIndex = -1;\n let thinkingBlock: ThinkingContentText | ReasoningContentText | undefined;\n const endIndex = instructions != null ? 1 : 0;\n const prunedMemory: BaseMessage[] = [];\n\n if (_thinkingStartIndex > -1) {\n const thinkingMessageContent = messages[_thinkingStartIndex]?.content;\n if (Array.isArray(thinkingMessageContent)) {\n thinkingBlock = thinkingMessageContent.find(\n (content) => content.type === reasoningType\n ) as ThinkingContentText | undefined;\n }\n }\n\n if (currentTokenCount < remainingContextTokens) {\n let currentIndex = messages.length;\n while (\n messages.length > 0 &&\n currentTokenCount < remainingContextTokens &&\n currentIndex > endIndex\n ) {\n currentIndex--;\n if (messages.length === 1 && instructions) {\n break;\n }\n const poppedMessage = messages.pop();\n if (!poppedMessage) continue;\n const messageType = poppedMessage.getType();\n if (\n thinkingEnabled === true &&\n thinkingEndIndex === -1 &&\n currentIndex === originalLength - 1 &&\n (messageType === 'ai' || messageType === 'tool')\n ) {\n thinkingEndIndex = currentIndex;\n }\n if (\n thinkingEndIndex > -1 &&\n !thinkingBlock &&\n thinkingStartIndex < 0 &&\n messageType === 'ai' &&\n Array.isArray(poppedMessage.content)\n ) {\n thinkingBlock = poppedMessage.content.find(\n (content) => content.type === reasoningType\n ) as ThinkingContentText | undefined;\n thinkingStartIndex = thinkingBlock != null ? currentIndex : -1;\n }\n /** False start, the latest message was not part of a multi-assistant/tool sequence of messages */\n if (\n thinkingEndIndex > -1 &&\n currentIndex === thinkingEndIndex - 1 &&\n messageType !== 'ai' &&\n messageType !== 'tool'\n ) {\n thinkingEndIndex = -1;\n }\n\n const tokenCount = indexTokenCountMap[currentIndex] ?? 0;\n\n if (\n prunedMemory.length === 0 &&\n currentTokenCount + tokenCount <= remainingContextTokens\n ) {\n context.push(poppedMessage);\n currentTokenCount += tokenCount;\n } else {\n prunedMemory.push(poppedMessage);\n if (thinkingEndIndex > -1 && thinkingStartIndex < 0) {\n continue;\n }\n break;\n }\n }\n\n if (context[context.length - 1]?.getType() === 'tool') {\n startType = ['ai', 'human'];\n }\n\n if (startType != null && startType.length > 0 && context.length > 0) {\n let requiredTypeIndex = -1;\n\n let totalTokens = 0;\n for (let i = context.length - 1; i >= 0; i--) {\n const currentType = context[i]?.getType() ?? '';\n if (\n Array.isArray(startType)\n ? startType.includes(currentType)\n : currentType === startType\n ) {\n requiredTypeIndex = i + 1;\n break;\n }\n const originalIndex = originalLength - 1 - i;\n totalTokens += indexTokenCountMap[originalIndex] ?? 0;\n }\n\n if (requiredTypeIndex > 0) {\n currentTokenCount -= totalTokens;\n context = context.slice(0, requiredTypeIndex);\n }\n }\n }\n\n if (instructions && originalLength > 0) {\n context.push(_messages[0] as BaseMessage);\n messages.shift();\n }\n\n remainingContextTokens -= currentTokenCount;\n const result: PruningResult = {\n remainingContextTokens,\n context: [] as BaseMessage[],\n messagesToRefine: prunedMemory,\n };\n\n if (thinkingStartIndex > -1) {\n result.thinkingStartIndex = thinkingStartIndex;\n }\n\n if (\n prunedMemory.length === 0 ||\n thinkingEndIndex < 0 ||\n (thinkingStartIndex > -1 &&\n isIndexInContext(_messages, context, thinkingStartIndex))\n ) {\n // we reverse at this step to ensure the context is in the correct order for the model, and we need to work backwards\n result.context = context.reverse() as BaseMessage[];\n return result;\n }\n\n if (thinkingEndIndex > -1 && thinkingStartIndex < 0) {\n throw new Error(\n 'The payload is malformed. There is a thinking sequence but no \"AI\" messages with thinking blocks.'\n );\n }\n\n if (!thinkingBlock) {\n throw new Error(\n 'The payload is malformed. There is a thinking sequence but no thinking block found.'\n );\n }\n\n // Since we have a thinking sequence, we need to find the last assistant message\n // in the latest AI/tool sequence to add the thinking block that falls outside of the current context\n // Latest messages are ordered first.\n let assistantIndex = -1;\n for (let i = 0; i < context.length; i++) {\n const currentMessage = context[i];\n const type = currentMessage?.getType();\n if (type === 'ai') {\n assistantIndex = i;\n }\n if (assistantIndex > -1 && (type === 'human' || type === 'system')) {\n break;\n }\n }\n\n if (assistantIndex === -1) {\n throw new Error(\n 'The payload is malformed. There is a thinking sequence but no \"AI\" messages to append thinking blocks to.'\n );\n }\n\n thinkingStartIndex = originalLength - 1 - assistantIndex;\n const thinkingTokenCount = tokenCounter(\n new AIMessage({ content: [thinkingBlock] })\n );\n const newRemainingCount = remainingContextTokens - thinkingTokenCount;\n const newMessage = addThinkingBlock(\n context[assistantIndex] as AIMessage,\n thinkingBlock\n );\n context[assistantIndex] = newMessage;\n if (newRemainingCount > 0) {\n result.context = context.reverse() as BaseMessage[];\n return result;\n }\n\n const thinkingMessage: AIMessage = context[assistantIndex] as AIMessage;\n // now we need to an additional round of pruning but making the thinking block fit\n const newThinkingMessageTokenCount =\n (indexTokenCountMap[thinkingStartIndex] ?? 0) + thinkingTokenCount;\n remainingContextTokens = initialContextTokens - newThinkingMessageTokenCount;\n currentTokenCount = 3;\n let newContext: BaseMessage[] = [];\n const secondRoundMessages = [..._messages];\n let currentIndex = secondRoundMessages.length;\n while (\n secondRoundMessages.length > 0 &&\n currentTokenCount < remainingContextTokens &&\n currentIndex > thinkingStartIndex\n ) {\n currentIndex--;\n const poppedMessage = secondRoundMessages.pop();\n if (!poppedMessage) continue;\n const tokenCount = indexTokenCountMap[currentIndex] ?? 0;\n if (currentTokenCount + tokenCount <= remainingContextTokens) {\n newContext.push(poppedMessage);\n currentTokenCount += tokenCount;\n } else {\n messages.push(poppedMessage);\n break;\n }\n }\n\n const firstMessage: AIMessage = newContext[newContext.length - 1];\n const firstMessageType = newContext[newContext.length - 1].getType();\n if (firstMessageType === 'tool') {\n startType = ['ai', 'human'];\n }\n\n if (startType != null && startType.length > 0 && newContext.length > 0) {\n let requiredTypeIndex = -1;\n\n let totalTokens = 0;\n for (let i = newContext.length - 1; i >= 0; i--) {\n const currentType = newContext[i]?.getType() ?? '';\n if (\n Array.isArray(startType)\n ? startType.includes(currentType)\n : currentType === startType\n ) {\n requiredTypeIndex = i + 1;\n break;\n }\n const originalIndex = originalLength - 1 - i;\n totalTokens += indexTokenCountMap[originalIndex] ?? 0;\n }\n\n if (requiredTypeIndex > 0) {\n currentTokenCount -= totalTokens;\n newContext = newContext.slice(0, requiredTypeIndex);\n }\n }\n\n if (firstMessageType === 'ai') {\n const newMessage = addThinkingBlock(firstMessage, thinkingBlock);\n newContext[newContext.length - 1] = newMessage;\n } else {\n newContext.push(thinkingMessage);\n }\n\n if (instructions && originalLength > 0) {\n newContext.push(_messages[0] as BaseMessage);\n secondRoundMessages.shift();\n }\n\n result.context = newContext.reverse();\n return result;\n}\n\nexport function checkValidNumber(value: unknown): value is number {\n return typeof value === 'number' && !isNaN(value) && value > 0;\n}\n\nexport function createPruneMessages(factoryParams: PruneMessagesFactoryParams) {\n const indexTokenCountMap = { ...factoryParams.indexTokenCountMap };\n let lastTurnStartIndex = factoryParams.startIndex;\n let lastCutOffIndex = 0;\n let totalTokens = Object.values(indexTokenCountMap).reduce(\n (a = 0, b = 0) => a + b,\n 0\n ) as number;\n let runThinkingStartIndex = -1;\n return function pruneMessages(params: PruneMessagesParams): {\n context: BaseMessage[];\n indexTokenCountMap: Record<string, number | undefined>;\n } {\n let currentUsage: UsageMetadata | undefined;\n if (\n params.usageMetadata &&\n (checkValidNumber(params.usageMetadata.input_tokens) ||\n (checkValidNumber(params.usageMetadata.input_token_details) &&\n (checkValidNumber(\n params.usageMetadata.input_token_details.cache_creation\n ) ||\n checkValidNumber(\n params.usageMetadata.input_token_details.cache_read\n )))) &&\n checkValidNumber(params.usageMetadata.output_tokens)\n ) {\n currentUsage = calculateTotalTokens(params.usageMetadata);\n totalTokens = currentUsage.total_tokens;\n }\n\n const newOutputs = new Set<number>();\n for (let i = lastTurnStartIndex; i < params.messages.length; i++) {\n const message = params.messages[i];\n if (\n i === lastTurnStartIndex &&\n indexTokenCountMap[i] === undefined &&\n currentUsage\n ) {\n indexTokenCountMap[i] = currentUsage.output_tokens;\n } else if (indexTokenCountMap[i] === undefined) {\n indexTokenCountMap[i] = factoryParams.tokenCounter(message);\n if (currentUsage) {\n newOutputs.add(i);\n }\n totalTokens += indexTokenCountMap[i] ?? 0;\n }\n }\n\n // If `currentUsage` is defined, we need to distribute the current total tokens to our `indexTokenCountMap`,\n // We must distribute it in a weighted manner, so that the total token count is equal to `currentUsage.total_tokens`,\n // relative the manually counted tokens in `indexTokenCountMap`.\n // EDGE CASE: when the resulting context gets pruned, we should not distribute the usage for messages that are not in the context.\n if (currentUsage) {\n let totalIndexTokens = 0;\n if (params.messages[0].getType() === 'system') {\n totalIndexTokens += indexTokenCountMap[0] ?? 0;\n }\n for (let i = lastCutOffIndex; i < params.messages.length; i++) {\n if (i === 0 && params.messages[0].getType() === 'system') {\n continue;\n }\n if (newOutputs.has(i)) {\n continue;\n }\n totalIndexTokens += indexTokenCountMap[i] ?? 0;\n }\n\n // Calculate ratio based only on messages that remain in the context\n const ratio = currentUsage.total_tokens / totalIndexTokens;\n const isRatioSafe = ratio >= 1 / 3 && ratio <= 2.5;\n\n // Apply the ratio adjustment only to messages at or after lastCutOffIndex, and only if the ratio is safe\n if (isRatioSafe) {\n if (\n params.messages[0].getType() === 'system' &&\n lastCutOffIndex !== 0\n ) {\n indexTokenCountMap[0] = Math.round(\n (indexTokenCountMap[0] ?? 0) * ratio\n );\n }\n\n for (let i = lastCutOffIndex; i < params.messages.length; i++) {\n if (newOutputs.has(i)) {\n continue;\n }\n indexTokenCountMap[i] = Math.round(\n (indexTokenCountMap[i] ?? 0) * ratio\n );\n }\n }\n }\n\n lastTurnStartIndex = params.messages.length;\n if (lastCutOffIndex === 0 && totalTokens <= factoryParams.maxTokens) {\n return { context: params.messages, indexTokenCountMap };\n }\n\n const { context, thinkingStartIndex } = getMessagesWithinTokenLimit({\n maxContextTokens: factoryParams.maxTokens,\n messages: params.messages,\n indexTokenCountMap,\n startType: params.startType,\n thinkingEnabled: factoryParams.thinkingEnabled,\n tokenCounter: factoryParams.tokenCounter,\n reasoningType:\n factoryParams.provider === Providers.BEDROCK\n ? ContentTypes.REASONING_CONTENT\n : ContentTypes.THINKING,\n thinkingStartIndex:\n factoryParams.thinkingEnabled === true\n ? runThinkingStartIndex\n : undefined,\n });\n runThinkingStartIndex = thinkingStartIndex ?? -1;\n /** The index is the first value of `context`, index relative to `params.messages` */\n lastCutOffIndex = Math.max(\n params.messages.length -\n (context.length - (context[0]?.getType() === 'system' ? 1 : 0)),\n 0\n );\n\n return { context, indexTokenCountMap };\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -52,7 +52,7 @@ export declare abstract class Graph<T extends t.BaseGraphState = t.BaseGraphStat
|
|
|
52
52
|
contentIndexMap: Map<string, number>;
|
|
53
53
|
toolCallStepIds: Map<string, string>;
|
|
54
54
|
currentUsage: Partial<UsageMetadata> | undefined;
|
|
55
|
-
indexTokenCountMap: Record<string, number>;
|
|
55
|
+
indexTokenCountMap: Record<string, number | undefined>;
|
|
56
56
|
maxContextTokens: number | undefined;
|
|
57
57
|
pruneMessages?: ReturnType<typeof createPruneMessages>;
|
|
58
58
|
/** The amount of time that should pass before another consecutive API call */
|
|
@@ -6,7 +6,7 @@ export type PruneMessagesFactoryParams = {
|
|
|
6
6
|
maxTokens: number;
|
|
7
7
|
startIndex: number;
|
|
8
8
|
tokenCounter: TokenCounter;
|
|
9
|
-
indexTokenCountMap: Record<string, number>;
|
|
9
|
+
indexTokenCountMap: Record<string, number | undefined>;
|
|
10
10
|
thinkingEnabled?: boolean;
|
|
11
11
|
};
|
|
12
12
|
export type PruneMessagesParams = {
|
|
@@ -47,5 +47,5 @@ export declare function getMessagesWithinTokenLimit({ messages: _messages, maxCo
|
|
|
47
47
|
export declare function checkValidNumber(value: unknown): value is number;
|
|
48
48
|
export declare function createPruneMessages(factoryParams: PruneMessagesFactoryParams): (params: PruneMessagesParams) => {
|
|
49
49
|
context: BaseMessage[];
|
|
50
|
-
indexTokenCountMap: Record<string, number>;
|
|
50
|
+
indexTokenCountMap: Record<string, number | undefined>;
|
|
51
51
|
};
|
package/package.json
CHANGED
package/src/graphs/Graph.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
// src/graphs/Graph.ts
|
|
2
3
|
import { nanoid } from 'nanoid';
|
|
3
4
|
import { concat } from '@langchain/core/utils/stream';
|
|
@@ -114,7 +115,7 @@ export abstract class Graph<
|
|
|
114
115
|
contentIndexMap: Map<string, number> = new Map();
|
|
115
116
|
toolCallStepIds: Map<string, string> = new Map();
|
|
116
117
|
currentUsage: Partial<UsageMetadata> | undefined;
|
|
117
|
-
indexTokenCountMap: Record<string, number> = {};
|
|
118
|
+
indexTokenCountMap: Record<string, number | undefined> = {};
|
|
118
119
|
maxContextTokens: number | undefined;
|
|
119
120
|
pruneMessages?: ReturnType<typeof createPruneMessages>;
|
|
120
121
|
/** The amount of time that should pass before another consecutive API call */
|
|
@@ -168,21 +169,25 @@ export class StandardGraph extends Graph<t.BaseGraphState, GraphNode> {
|
|
|
168
169
|
this.reasoningKey = reasoningKey;
|
|
169
170
|
}
|
|
170
171
|
|
|
171
|
-
let finalInstructions: string | BaseMessageFields
|
|
172
|
+
let finalInstructions: string | BaseMessageFields | undefined =
|
|
173
|
+
instructions;
|
|
172
174
|
if (additional_instructions) {
|
|
173
|
-
finalInstructions =
|
|
174
|
-
|
|
175
|
-
|
|
175
|
+
finalInstructions =
|
|
176
|
+
finalInstructions != null && finalInstructions
|
|
177
|
+
? `${finalInstructions}\n\n${additional_instructions}`
|
|
178
|
+
: additional_instructions;
|
|
176
179
|
}
|
|
177
180
|
|
|
178
181
|
if (
|
|
182
|
+
finalInstructions != null &&
|
|
179
183
|
finalInstructions &&
|
|
180
184
|
provider === Providers.ANTHROPIC &&
|
|
181
|
-
(
|
|
185
|
+
((
|
|
182
186
|
clientOptions as t.AnthropicClientOptions
|
|
183
187
|
).clientOptions?.defaultHeaders?.['anthropic-beta']?.includes(
|
|
184
188
|
'prompt-caching'
|
|
185
|
-
)
|
|
189
|
+
) ??
|
|
190
|
+
false)
|
|
186
191
|
) {
|
|
187
192
|
finalInstructions = {
|
|
188
193
|
content: [
|
|
@@ -195,7 +200,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, GraphNode> {
|
|
|
195
200
|
};
|
|
196
201
|
}
|
|
197
202
|
|
|
198
|
-
if (finalInstructions) {
|
|
203
|
+
if (finalInstructions != null && finalInstructions !== '') {
|
|
199
204
|
this.systemMessage = new SystemMessage(finalInstructions);
|
|
200
205
|
}
|
|
201
206
|
}
|
|
@@ -431,7 +436,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, GraphNode> {
|
|
|
431
436
|
if (
|
|
432
437
|
finalMessage &&
|
|
433
438
|
'usage_metadata' in finalMessage &&
|
|
434
|
-
finalMessage.usage_metadata
|
|
439
|
+
finalMessage.usage_metadata != null
|
|
435
440
|
) {
|
|
436
441
|
this.currentUsage = finalMessage.usage_metadata as Partial<UsageMetadata>;
|
|
437
442
|
}
|
|
@@ -448,7 +453,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, GraphNode> {
|
|
|
448
453
|
throw new Error(`No ${config ? 'provider' : 'config'} provided`);
|
|
449
454
|
}
|
|
450
455
|
if (!config.signal) {
|
|
451
|
-
config.signal = this.signal
|
|
456
|
+
config.signal = this.signal
|
|
457
|
+
? AbortSignal.any([this.signal])
|
|
458
|
+
: undefined;
|
|
452
459
|
}
|
|
453
460
|
this.config = config;
|
|
454
461
|
const { messages } = state;
|
|
@@ -718,9 +725,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, GraphNode> {
|
|
|
718
725
|
|
|
719
726
|
const tool_call: t.ProcessedToolCall = {
|
|
720
727
|
id: data.id,
|
|
721
|
-
name: name
|
|
728
|
+
name: name || '',
|
|
722
729
|
args: typeof args === 'string' ? args : JSON.stringify(args),
|
|
723
|
-
output: `Error processing tool${error?.message ? `: ${error.message}` : ''}`,
|
|
730
|
+
output: `Error processing tool${error?.message != null ? `: ${error.message}` : ''}`,
|
|
724
731
|
progress: 1,
|
|
725
732
|
};
|
|
726
733
|
|