@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
package/src/specs/prune.test.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
// src/specs/prune.test.ts
|
|
2
2
|
import { config } from 'dotenv';
|
|
3
3
|
config();
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
HumanMessage,
|
|
6
|
+
AIMessage,
|
|
7
|
+
SystemMessage,
|
|
8
|
+
BaseMessage,
|
|
9
|
+
ToolMessage,
|
|
10
|
+
} from '@langchain/core/messages';
|
|
5
11
|
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
6
12
|
import type { UsageMetadata } from '@langchain/core/messages';
|
|
7
13
|
import type * as t from '@/types';
|
|
@@ -15,7 +21,10 @@ const createTestTokenCounter = (): t.TokenCounter => {
|
|
|
15
21
|
// This simple token counter just counts characters as tokens for predictable testing
|
|
16
22
|
return (message: BaseMessage): number => {
|
|
17
23
|
// Use type assertion to help TypeScript understand the type
|
|
18
|
-
const content = message.content as
|
|
24
|
+
const content = message.content as
|
|
25
|
+
| string
|
|
26
|
+
| Array<t.MessageContentComplex | string>
|
|
27
|
+
| undefined;
|
|
19
28
|
|
|
20
29
|
// Handle string content
|
|
21
30
|
if (typeof content === 'string') {
|
|
@@ -57,7 +66,7 @@ function calculateTotalTokens(usage: Partial<UsageMetadata>): UsageMetadata {
|
|
|
57
66
|
return {
|
|
58
67
|
input_tokens: totalInputTokens,
|
|
59
68
|
output_tokens: totalOutputTokens,
|
|
60
|
-
total_tokens: totalInputTokens + totalOutputTokens
|
|
69
|
+
total_tokens: totalInputTokens + totalOutputTokens,
|
|
61
70
|
};
|
|
62
71
|
}
|
|
63
72
|
|
|
@@ -81,15 +90,21 @@ function getMessagesWithinTokenLimit({
|
|
|
81
90
|
// start with 3 tokens for the label after all messages have been counted.
|
|
82
91
|
let summaryIndex = -1;
|
|
83
92
|
let currentTokenCount = 3;
|
|
84
|
-
const instructions =
|
|
85
|
-
|
|
93
|
+
const instructions =
|
|
94
|
+
_messages[0]?.getType() === 'system' ? _messages[0] : undefined;
|
|
95
|
+
const instructionsTokenCount =
|
|
96
|
+
instructions != null ? indexTokenCountMap[0] : 0;
|
|
86
97
|
let remainingContextTokens = maxContextTokens - instructionsTokenCount;
|
|
87
98
|
const messages = [..._messages];
|
|
88
99
|
const context: BaseMessage[] = [];
|
|
89
100
|
|
|
90
101
|
if (currentTokenCount < remainingContextTokens) {
|
|
91
102
|
let currentIndex = messages.length;
|
|
92
|
-
while (
|
|
103
|
+
while (
|
|
104
|
+
messages.length > 0 &&
|
|
105
|
+
currentTokenCount < remainingContextTokens &&
|
|
106
|
+
currentIndex > 1
|
|
107
|
+
) {
|
|
93
108
|
currentIndex--;
|
|
94
109
|
if (messages.length === 1 && instructions) {
|
|
95
110
|
break;
|
|
@@ -99,7 +114,7 @@ function getMessagesWithinTokenLimit({
|
|
|
99
114
|
|
|
100
115
|
const tokenCount = indexTokenCountMap[currentIndex] || 0;
|
|
101
116
|
|
|
102
|
-
if (
|
|
117
|
+
if (currentTokenCount + tokenCount <= remainingContextTokens) {
|
|
103
118
|
context.push(poppedMessage);
|
|
104
119
|
currentTokenCount += tokenCount;
|
|
105
120
|
} else {
|
|
@@ -109,8 +124,10 @@ function getMessagesWithinTokenLimit({
|
|
|
109
124
|
}
|
|
110
125
|
|
|
111
126
|
// If startType is specified, discard messages until we find one of the required type
|
|
112
|
-
if (startType && context.length > 0) {
|
|
113
|
-
const requiredTypeIndex = context.findIndex(
|
|
127
|
+
if (startType != null && startType && context.length > 0) {
|
|
128
|
+
const requiredTypeIndex = context.findIndex(
|
|
129
|
+
(msg) => msg.getType() === startType
|
|
130
|
+
);
|
|
114
131
|
|
|
115
132
|
if (requiredTypeIndex > 0) {
|
|
116
133
|
// If we found a message of the required type, discard all messages before it
|
|
@@ -152,8 +169,8 @@ describe('Prune Messages Tests', () => {
|
|
|
152
169
|
output_tokens: 50,
|
|
153
170
|
input_token_details: {
|
|
154
171
|
cache_creation: 10,
|
|
155
|
-
cache_read: 5
|
|
156
|
-
}
|
|
172
|
+
cache_read: 5,
|
|
173
|
+
},
|
|
157
174
|
};
|
|
158
175
|
|
|
159
176
|
const result = calculateTotalTokens(usage);
|
|
@@ -166,7 +183,7 @@ describe('Prune Messages Tests', () => {
|
|
|
166
183
|
it('should handle missing fields gracefully', () => {
|
|
167
184
|
const usage: Partial<UsageMetadata> = {
|
|
168
185
|
input_tokens: 100,
|
|
169
|
-
output_tokens: 50
|
|
186
|
+
output_tokens: 50,
|
|
170
187
|
};
|
|
171
188
|
|
|
172
189
|
const result = calculateTotalTokens(usage);
|
|
@@ -192,19 +209,19 @@ describe('Prune Messages Tests', () => {
|
|
|
192
209
|
const messages = [
|
|
193
210
|
new SystemMessage('System instruction'),
|
|
194
211
|
new HumanMessage('Hello'),
|
|
195
|
-
new AIMessage('Hi there')
|
|
212
|
+
new AIMessage('Hi there'),
|
|
196
213
|
];
|
|
197
214
|
|
|
198
215
|
const indexTokenCountMap = {
|
|
199
216
|
0: 17, // "System instruction"
|
|
200
|
-
1: 5,
|
|
201
|
-
2: 8
|
|
217
|
+
1: 5, // "Hello"
|
|
218
|
+
2: 8, // "Hi there"
|
|
202
219
|
};
|
|
203
220
|
|
|
204
221
|
const result = getMessagesWithinTokenLimit({
|
|
205
222
|
messages,
|
|
206
223
|
maxContextTokens: 100,
|
|
207
|
-
indexTokenCountMap
|
|
224
|
+
indexTokenCountMap,
|
|
208
225
|
});
|
|
209
226
|
|
|
210
227
|
expect(result.context.length).toBe(3);
|
|
@@ -220,22 +237,22 @@ describe('Prune Messages Tests', () => {
|
|
|
220
237
|
new HumanMessage('Message 1'),
|
|
221
238
|
new AIMessage('Response 1'),
|
|
222
239
|
new HumanMessage('Message 2'),
|
|
223
|
-
new AIMessage('Response 2')
|
|
240
|
+
new AIMessage('Response 2'),
|
|
224
241
|
];
|
|
225
242
|
|
|
226
243
|
const indexTokenCountMap = {
|
|
227
244
|
0: 17, // "System instruction"
|
|
228
|
-
1: 9,
|
|
245
|
+
1: 9, // "Message 1"
|
|
229
246
|
2: 10, // "Response 1"
|
|
230
|
-
3: 9,
|
|
231
|
-
4: 10
|
|
247
|
+
3: 9, // "Message 2"
|
|
248
|
+
4: 10, // "Response 2"
|
|
232
249
|
};
|
|
233
250
|
|
|
234
251
|
// Set a limit that can only fit the system message and the last two messages
|
|
235
252
|
const result = getMessagesWithinTokenLimit({
|
|
236
253
|
messages,
|
|
237
254
|
maxContextTokens: 40,
|
|
238
|
-
indexTokenCountMap
|
|
255
|
+
indexTokenCountMap,
|
|
239
256
|
});
|
|
240
257
|
|
|
241
258
|
// Should include system message and the last two messages
|
|
@@ -255,20 +272,20 @@ describe('Prune Messages Tests', () => {
|
|
|
255
272
|
const messages = [
|
|
256
273
|
new SystemMessage('System instruction'),
|
|
257
274
|
new HumanMessage('Hello'),
|
|
258
|
-
new AIMessage('Hi there')
|
|
275
|
+
new AIMessage('Hi there'),
|
|
259
276
|
];
|
|
260
277
|
|
|
261
278
|
const indexTokenCountMap = {
|
|
262
279
|
0: 17, // "System instruction"
|
|
263
|
-
1: 5,
|
|
264
|
-
2: 8
|
|
280
|
+
1: 5, // "Hello"
|
|
281
|
+
2: 8, // "Hi there"
|
|
265
282
|
};
|
|
266
283
|
|
|
267
284
|
// Set a limit that can only fit the system message
|
|
268
285
|
const result = getMessagesWithinTokenLimit({
|
|
269
286
|
messages,
|
|
270
287
|
maxContextTokens: 20,
|
|
271
|
-
indexTokenCountMap
|
|
288
|
+
indexTokenCountMap,
|
|
272
289
|
});
|
|
273
290
|
|
|
274
291
|
expect(result.context.length).toBe(1);
|
|
@@ -283,7 +300,7 @@ describe('Prune Messages Tests', () => {
|
|
|
283
300
|
new AIMessage('AI message 1'),
|
|
284
301
|
new HumanMessage('Human message 1'),
|
|
285
302
|
new AIMessage('AI message 2'),
|
|
286
|
-
new HumanMessage('Human message 2')
|
|
303
|
+
new HumanMessage('Human message 2'),
|
|
287
304
|
];
|
|
288
305
|
|
|
289
306
|
const indexTokenCountMap = {
|
|
@@ -291,7 +308,7 @@ describe('Prune Messages Tests', () => {
|
|
|
291
308
|
1: 12, // "AI message 1"
|
|
292
309
|
2: 15, // "Human message 1"
|
|
293
310
|
3: 12, // "AI message 2"
|
|
294
|
-
4: 15
|
|
311
|
+
4: 15, // "Human message 2"
|
|
295
312
|
};
|
|
296
313
|
|
|
297
314
|
// Set a limit that can fit all messages
|
|
@@ -299,7 +316,7 @@ describe('Prune Messages Tests', () => {
|
|
|
299
316
|
messages,
|
|
300
317
|
maxContextTokens: 100,
|
|
301
318
|
indexTokenCountMap,
|
|
302
|
-
startType: 'human'
|
|
319
|
+
startType: 'human',
|
|
303
320
|
});
|
|
304
321
|
|
|
305
322
|
// All messages should be included since we're under the token limit
|
|
@@ -318,13 +335,13 @@ describe('Prune Messages Tests', () => {
|
|
|
318
335
|
const messages = [
|
|
319
336
|
new SystemMessage('System instruction'),
|
|
320
337
|
new AIMessage('AI message 1'),
|
|
321
|
-
new AIMessage('AI message 2')
|
|
338
|
+
new AIMessage('AI message 2'),
|
|
322
339
|
];
|
|
323
340
|
|
|
324
341
|
const indexTokenCountMap = {
|
|
325
342
|
0: 17, // "System instruction"
|
|
326
343
|
1: 12, // "AI message 1"
|
|
327
|
-
2: 12
|
|
344
|
+
2: 12, // "AI message 2"
|
|
328
345
|
};
|
|
329
346
|
|
|
330
347
|
// Set a limit that can fit all messages
|
|
@@ -332,7 +349,7 @@ describe('Prune Messages Tests', () => {
|
|
|
332
349
|
messages,
|
|
333
350
|
maxContextTokens: 100,
|
|
334
351
|
indexTokenCountMap,
|
|
335
|
-
startType: 'human'
|
|
352
|
+
startType: 'human',
|
|
336
353
|
});
|
|
337
354
|
|
|
338
355
|
// Should include all messages since no human messages exist to start from
|
|
@@ -373,20 +390,20 @@ describe('Prune Messages Tests', () => {
|
|
|
373
390
|
const messages = [
|
|
374
391
|
new SystemMessage('System instruction'),
|
|
375
392
|
new HumanMessage('Hello'),
|
|
376
|
-
new AIMessage('Hi there')
|
|
393
|
+
new AIMessage('Hi there'),
|
|
377
394
|
];
|
|
378
395
|
|
|
379
396
|
const indexTokenCountMap = {
|
|
380
397
|
0: tokenCounter(messages[0]),
|
|
381
398
|
1: tokenCounter(messages[1]),
|
|
382
|
-
2: tokenCounter(messages[2])
|
|
399
|
+
2: tokenCounter(messages[2]),
|
|
383
400
|
};
|
|
384
401
|
|
|
385
402
|
const pruneMessages = createPruneMessages({
|
|
386
403
|
maxTokens: 100,
|
|
387
404
|
startIndex: 0,
|
|
388
405
|
tokenCounter,
|
|
389
|
-
indexTokenCountMap
|
|
406
|
+
indexTokenCountMap,
|
|
390
407
|
});
|
|
391
408
|
|
|
392
409
|
const result = pruneMessages({ messages });
|
|
@@ -402,7 +419,7 @@ describe('Prune Messages Tests', () => {
|
|
|
402
419
|
new HumanMessage('Message 1'),
|
|
403
420
|
new AIMessage('Response 1'),
|
|
404
421
|
new HumanMessage('Message 2'),
|
|
405
|
-
new AIMessage('Response 2')
|
|
422
|
+
new AIMessage('Response 2'),
|
|
406
423
|
];
|
|
407
424
|
|
|
408
425
|
const indexTokenCountMap = {
|
|
@@ -410,7 +427,7 @@ describe('Prune Messages Tests', () => {
|
|
|
410
427
|
1: tokenCounter(messages[1]),
|
|
411
428
|
2: tokenCounter(messages[2]),
|
|
412
429
|
3: tokenCounter(messages[3]),
|
|
413
|
-
4: tokenCounter(messages[4])
|
|
430
|
+
4: tokenCounter(messages[4]),
|
|
414
431
|
};
|
|
415
432
|
|
|
416
433
|
// Set a limit that can only fit the system message and the last two messages
|
|
@@ -418,7 +435,7 @@ describe('Prune Messages Tests', () => {
|
|
|
418
435
|
maxTokens: 40,
|
|
419
436
|
startIndex: 0,
|
|
420
437
|
tokenCounter,
|
|
421
|
-
indexTokenCountMap
|
|
438
|
+
indexTokenCountMap,
|
|
422
439
|
});
|
|
423
440
|
|
|
424
441
|
const result = pruneMessages({ messages });
|
|
@@ -437,7 +454,7 @@ describe('Prune Messages Tests', () => {
|
|
|
437
454
|
new AIMessage('AI message 1'),
|
|
438
455
|
new HumanMessage('Human message 1'),
|
|
439
456
|
new AIMessage('AI message 2'),
|
|
440
|
-
new HumanMessage('Human message 2')
|
|
457
|
+
new HumanMessage('Human message 2'),
|
|
441
458
|
];
|
|
442
459
|
|
|
443
460
|
const indexTokenCountMap = {
|
|
@@ -445,7 +462,7 @@ describe('Prune Messages Tests', () => {
|
|
|
445
462
|
1: tokenCounter(messages[1]),
|
|
446
463
|
2: tokenCounter(messages[2]),
|
|
447
464
|
3: tokenCounter(messages[3]),
|
|
448
|
-
4: tokenCounter(messages[4])
|
|
465
|
+
4: tokenCounter(messages[4]),
|
|
449
466
|
};
|
|
450
467
|
|
|
451
468
|
// Set a limit that can fit all messages
|
|
@@ -453,12 +470,12 @@ describe('Prune Messages Tests', () => {
|
|
|
453
470
|
maxTokens: 100,
|
|
454
471
|
startIndex: 0,
|
|
455
472
|
tokenCounter,
|
|
456
|
-
indexTokenCountMap: { ...indexTokenCountMap }
|
|
473
|
+
indexTokenCountMap: { ...indexTokenCountMap },
|
|
457
474
|
});
|
|
458
475
|
|
|
459
476
|
const result = pruneMessages({
|
|
460
477
|
messages,
|
|
461
|
-
startType: 'human'
|
|
478
|
+
startType: 'human',
|
|
462
479
|
});
|
|
463
480
|
|
|
464
481
|
// All messages should be included since we're under the token limit
|
|
@@ -475,39 +492,42 @@ describe('Prune Messages Tests', () => {
|
|
|
475
492
|
const messages = [
|
|
476
493
|
new SystemMessage('System instruction'),
|
|
477
494
|
new HumanMessage('Hello'),
|
|
478
|
-
new AIMessage('Hi there')
|
|
495
|
+
new AIMessage('Hi there'),
|
|
479
496
|
];
|
|
480
497
|
|
|
481
498
|
const indexTokenCountMap = {
|
|
482
499
|
0: tokenCounter(messages[0]),
|
|
483
500
|
1: tokenCounter(messages[1]),
|
|
484
|
-
2: tokenCounter(messages[2])
|
|
501
|
+
2: tokenCounter(messages[2]),
|
|
485
502
|
};
|
|
486
503
|
|
|
487
504
|
const pruneMessages = createPruneMessages({
|
|
488
505
|
maxTokens: 100,
|
|
489
506
|
startIndex: 0,
|
|
490
507
|
tokenCounter,
|
|
491
|
-
indexTokenCountMap: { ...indexTokenCountMap }
|
|
508
|
+
indexTokenCountMap: { ...indexTokenCountMap },
|
|
492
509
|
});
|
|
493
510
|
|
|
494
511
|
// Provide usage metadata that indicates different token counts
|
|
495
512
|
const usageMetadata: Partial<UsageMetadata> = {
|
|
496
513
|
input_tokens: 50,
|
|
497
514
|
output_tokens: 25,
|
|
498
|
-
total_tokens: 75
|
|
515
|
+
total_tokens: 75,
|
|
499
516
|
};
|
|
500
517
|
|
|
501
518
|
const result = pruneMessages({
|
|
502
519
|
messages,
|
|
503
|
-
usageMetadata
|
|
520
|
+
usageMetadata,
|
|
504
521
|
});
|
|
505
522
|
|
|
506
523
|
// The function should have updated the indexTokenCountMap based on the usage metadata
|
|
507
524
|
expect(result.indexTokenCountMap).not.toEqual(indexTokenCountMap);
|
|
508
525
|
|
|
509
526
|
// The total of all values in indexTokenCountMap should equal the total_tokens from usageMetadata
|
|
510
|
-
const totalTokens = Object.values(result.indexTokenCountMap).reduce(
|
|
527
|
+
const totalTokens = Object.values(result.indexTokenCountMap).reduce(
|
|
528
|
+
(a = 0, b = 0) => a + b,
|
|
529
|
+
0
|
|
530
|
+
);
|
|
511
531
|
expect(totalTokens).toBe(75);
|
|
512
532
|
});
|
|
513
533
|
});
|
|
@@ -520,7 +540,7 @@ describe('Prune Messages Tests', () => {
|
|
|
520
540
|
new AIMessage('AI message 1'),
|
|
521
541
|
new ToolMessage({ content: 'Tool result 1', tool_call_id: 'tool1' }),
|
|
522
542
|
new AIMessage('AI message 2'),
|
|
523
|
-
new ToolMessage({ content: 'Tool result 2', tool_call_id: 'tool2' })
|
|
543
|
+
new ToolMessage({ content: 'Tool result 2', tool_call_id: 'tool2' }),
|
|
524
544
|
];
|
|
525
545
|
|
|
526
546
|
const indexTokenCountMap = {
|
|
@@ -528,7 +548,7 @@ describe('Prune Messages Tests', () => {
|
|
|
528
548
|
1: 12, // AI message 1
|
|
529
549
|
2: 13, // Tool result 1
|
|
530
550
|
3: 12, // AI message 2
|
|
531
|
-
4: 13
|
|
551
|
+
4: 13, // Tool result 2
|
|
532
552
|
};
|
|
533
553
|
|
|
534
554
|
// Create a pruneMessages function with a token limit that will only include the last few messages
|
|
@@ -536,7 +556,7 @@ describe('Prune Messages Tests', () => {
|
|
|
536
556
|
maxTokens: 58, // Only enough for system + last 3 messages + 3, but should not include a parent-less tool message
|
|
537
557
|
startIndex: 0,
|
|
538
558
|
tokenCounter,
|
|
539
|
-
indexTokenCountMap: { ...indexTokenCountMap }
|
|
559
|
+
indexTokenCountMap: { ...indexTokenCountMap },
|
|
540
560
|
});
|
|
541
561
|
|
|
542
562
|
const result = pruneMessages({ messages });
|
|
@@ -557,7 +577,7 @@ describe('Prune Messages Tests', () => {
|
|
|
557
577
|
new AIMessage('AI message 1'),
|
|
558
578
|
new ToolMessage({ content: 'Tool result 1', tool_call_id: 'tool1' }),
|
|
559
579
|
new HumanMessage('Human message 2'),
|
|
560
|
-
new ToolMessage({ content: 'Tool result 2', tool_call_id: 'tool2' })
|
|
580
|
+
new ToolMessage({ content: 'Tool result 2', tool_call_id: 'tool2' }),
|
|
561
581
|
];
|
|
562
582
|
|
|
563
583
|
const indexTokenCountMap = {
|
|
@@ -566,7 +586,7 @@ describe('Prune Messages Tests', () => {
|
|
|
566
586
|
2: 12, // AI message 1
|
|
567
587
|
3: 13, // Tool result 1
|
|
568
588
|
4: 15, // Human message 2
|
|
569
|
-
5: 13
|
|
589
|
+
5: 13, // Tool result 2
|
|
570
590
|
};
|
|
571
591
|
|
|
572
592
|
// Create a pruneMessages function with a token limit that will only include the last few messages
|
|
@@ -574,7 +594,7 @@ describe('Prune Messages Tests', () => {
|
|
|
574
594
|
maxTokens: 48, // Only enough for system + last 2 messages
|
|
575
595
|
startIndex: 0,
|
|
576
596
|
tokenCounter,
|
|
577
|
-
indexTokenCountMap: { ...indexTokenCountMap }
|
|
597
|
+
indexTokenCountMap: { ...indexTokenCountMap },
|
|
578
598
|
});
|
|
579
599
|
|
|
580
600
|
const result = pruneMessages({ messages });
|
|
@@ -594,7 +614,7 @@ describe('Prune Messages Tests', () => {
|
|
|
594
614
|
new HumanMessage('Human message'),
|
|
595
615
|
new AIMessage('AI message with tool use'),
|
|
596
616
|
new ToolMessage({ content: 'Tool result', tool_call_id: 'tool1' }),
|
|
597
|
-
new AIMessage('AI message after tool')
|
|
617
|
+
new AIMessage('AI message after tool'),
|
|
598
618
|
];
|
|
599
619
|
|
|
600
620
|
const indexTokenCountMap = {
|
|
@@ -602,14 +622,14 @@ describe('Prune Messages Tests', () => {
|
|
|
602
622
|
1: 13, // Human message
|
|
603
623
|
2: 22, // AI message with tool use
|
|
604
624
|
3: 11, // Tool result
|
|
605
|
-
4: 19
|
|
625
|
+
4: 19, // AI message after tool
|
|
606
626
|
};
|
|
607
627
|
|
|
608
628
|
const pruneMessages = createPruneMessages({
|
|
609
629
|
maxTokens: 50,
|
|
610
630
|
startIndex: 0,
|
|
611
631
|
tokenCounter,
|
|
612
|
-
indexTokenCountMap: { ...indexTokenCountMap }
|
|
632
|
+
indexTokenCountMap: { ...indexTokenCountMap },
|
|
613
633
|
});
|
|
614
634
|
|
|
615
635
|
const result = pruneMessages({ messages });
|
|
@@ -626,7 +646,7 @@ describe('Prune Messages Tests', () => {
|
|
|
626
646
|
new HumanMessage('Human message 1'),
|
|
627
647
|
new AIMessage('AI message with tool use'),
|
|
628
648
|
new ToolMessage({ content: 'Tool result', tool_call_id: 'tool1' }),
|
|
629
|
-
new HumanMessage('Human message 2')
|
|
649
|
+
new HumanMessage('Human message 2'),
|
|
630
650
|
];
|
|
631
651
|
|
|
632
652
|
const indexTokenCountMap = {
|
|
@@ -634,14 +654,14 @@ describe('Prune Messages Tests', () => {
|
|
|
634
654
|
1: 15, // Human message 1
|
|
635
655
|
2: 22, // AI message with tool use
|
|
636
656
|
3: 11, // Tool result
|
|
637
|
-
4: 15
|
|
657
|
+
4: 15, // Human message 2
|
|
638
658
|
};
|
|
639
659
|
|
|
640
660
|
const pruneMessages = createPruneMessages({
|
|
641
661
|
maxTokens: 46,
|
|
642
662
|
startIndex: 0,
|
|
643
663
|
tokenCounter,
|
|
644
|
-
indexTokenCountMap: { ...indexTokenCountMap }
|
|
664
|
+
indexTokenCountMap: { ...indexTokenCountMap },
|
|
645
665
|
});
|
|
646
666
|
|
|
647
667
|
const result = pruneMessages({ messages });
|
|
@@ -661,7 +681,7 @@ describe('Prune Messages Tests', () => {
|
|
|
661
681
|
new AIMessage('AI message 2 with tool use'),
|
|
662
682
|
new ToolMessage({ content: 'Tool result 2', tool_call_id: 'tool2' }),
|
|
663
683
|
new AIMessage('AI message 3 with tool use'),
|
|
664
|
-
new ToolMessage({ content: 'Tool result 3', tool_call_id: 'tool3' })
|
|
684
|
+
new ToolMessage({ content: 'Tool result 3', tool_call_id: 'tool3' }),
|
|
665
685
|
];
|
|
666
686
|
|
|
667
687
|
const indexTokenCountMap = {
|
|
@@ -672,14 +692,14 @@ describe('Prune Messages Tests', () => {
|
|
|
672
692
|
4: 26, // AI message 2 with tool use
|
|
673
693
|
5: 13, // Tool result 2
|
|
674
694
|
6: 26, // AI message 3 with tool use
|
|
675
|
-
7: 13
|
|
695
|
+
7: 13, // Tool result 3
|
|
676
696
|
};
|
|
677
697
|
|
|
678
698
|
const pruneMessages = createPruneMessages({
|
|
679
699
|
maxTokens: 111,
|
|
680
700
|
startIndex: 0,
|
|
681
701
|
tokenCounter,
|
|
682
|
-
indexTokenCountMap: { ...indexTokenCountMap }
|
|
702
|
+
indexTokenCountMap: { ...indexTokenCountMap },
|
|
683
703
|
});
|
|
684
704
|
|
|
685
705
|
const result = pruneMessages({ messages });
|
|
@@ -712,15 +732,16 @@ describe('Prune Messages Tests', () => {
|
|
|
712
732
|
// Override the model to use a fake LLM
|
|
713
733
|
run.Graph?.overrideTestModel(['This is a test response'], 1);
|
|
714
734
|
|
|
715
|
-
const messages = [
|
|
716
|
-
new HumanMessage('Hello, how are you?')
|
|
717
|
-
];
|
|
735
|
+
const messages = [new HumanMessage('Hello, how are you?')];
|
|
718
736
|
|
|
719
737
|
const indexTokenCountMap = {
|
|
720
|
-
0: tokenCounter(messages[0])
|
|
738
|
+
0: tokenCounter(messages[0]),
|
|
721
739
|
};
|
|
722
740
|
|
|
723
|
-
const config: Partial<RunnableConfig> & {
|
|
741
|
+
const config: Partial<RunnableConfig> & {
|
|
742
|
+
version: 'v1' | 'v2';
|
|
743
|
+
streamMode: string;
|
|
744
|
+
} = {
|
|
724
745
|
configurable: {
|
|
725
746
|
thread_id: 'test-thread',
|
|
726
747
|
},
|
|
@@ -728,15 +749,11 @@ describe('Prune Messages Tests', () => {
|
|
|
728
749
|
version: 'v2' as const,
|
|
729
750
|
};
|
|
730
751
|
|
|
731
|
-
await run.processStream(
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
indexTokenCountMap,
|
|
737
|
-
tokenCounter,
|
|
738
|
-
}
|
|
739
|
-
);
|
|
752
|
+
await run.processStream({ messages }, config, {
|
|
753
|
+
maxContextTokens: 1000,
|
|
754
|
+
indexTokenCountMap,
|
|
755
|
+
tokenCounter,
|
|
756
|
+
});
|
|
740
757
|
|
|
741
758
|
const finalMessages = run.getRunMessages();
|
|
742
759
|
expect(finalMessages).toBeDefined();
|