@librechat/agents 2.3.0 → 2.3.2
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 +6 -6
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/llm.cjs +7 -7
- package/dist/cjs/llm/anthropic/llm.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +6 -6
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +24 -24
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/fake.cjs.map +1 -1
- package/dist/cjs/llm/text.cjs.map +1 -1
- package/dist/cjs/main.cjs +3 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +5 -5
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +11 -9
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/prune.cjs +155 -181
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/stream.cjs +3 -4
- package/dist/cjs/stream.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +1 -1
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/utils/tokens.cjs +3 -3
- package/dist/cjs/utils/tokens.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +6 -6
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/llm/anthropic/llm.mjs +7 -7
- package/dist/esm/llm/anthropic/llm.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +6 -6
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs +24 -24
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/fake.mjs.map +1 -1
- package/dist/esm/llm/text.mjs.map +1 -1
- package/dist/esm/main.mjs +1 -1
- package/dist/esm/messages/core.mjs +5 -5
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +11 -9
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/prune.mjs +153 -182
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/stream.mjs +3 -4
- package/dist/esm/stream.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +1 -1
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/utils/tokens.mjs +3 -3
- package/dist/esm/utils/tokens.mjs.map +1 -1
- package/dist/types/messages/format.d.ts +1 -2
- package/dist/types/messages/prune.d.ts +31 -2
- package/dist/types/types/stream.d.ts +2 -2
- package/dist/types/utils/tokens.d.ts +1 -1
- package/package.json +4 -3
- package/src/graphs/Graph.ts +8 -8
- package/src/llm/anthropic/llm.ts +7 -8
- package/src/llm/anthropic/types.ts +4 -4
- package/src/llm/anthropic/utils/message_inputs.ts +6 -6
- package/src/llm/anthropic/utils/message_outputs.ts +39 -39
- package/src/llm/fake.ts +2 -2
- package/src/llm/text.ts +1 -1
- package/src/messages/core.ts +6 -6
- package/src/messages/format.ts +43 -42
- package/src/messages/formatAgentMessages.test.ts +35 -35
- package/src/messages/formatAgentMessages.tools.test.ts +30 -30
- package/src/messages/prune.ts +182 -226
- package/src/messages/shiftIndexTokenCountMap.test.ts +18 -18
- package/src/mockStream.ts +1 -1
- package/src/run.ts +2 -2
- package/src/specs/prune.test.ts +89 -89
- package/src/specs/reasoning.test.ts +1 -1
- package/src/specs/thinking-prune.test.ts +291 -243
- package/src/specs/tool-error.test.ts +16 -17
- package/src/stream.ts +13 -14
- package/src/tools/ToolNode.ts +1 -1
- package/src/types/stream.ts +4 -3
- package/src/utils/tokens.ts +12 -12
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
import { concat } from '@langchain/core/utils/stream';
|
|
1
2
|
import { AIMessage } from '@langchain/core/messages';
|
|
3
|
+
import { ContentTypes } from '../common/enum.mjs';
|
|
2
4
|
|
|
5
|
+
function isIndexInContext(arrayA, arrayB, targetIndex) {
|
|
6
|
+
const startingIndexInA = arrayA.length - arrayB.length;
|
|
7
|
+
return targetIndex >= startingIndexInA;
|
|
8
|
+
}
|
|
3
9
|
/**
|
|
4
10
|
* Calculates the total tokens from a single usage object
|
|
5
11
|
*
|
|
@@ -25,19 +31,33 @@ function calculateTotalTokens(usage) {
|
|
|
25
31
|
* @param options Configuration options for processing messages
|
|
26
32
|
* @returns Object containing the message context, remaining tokens, messages not included, and summary index
|
|
27
33
|
*/
|
|
28
|
-
function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, indexTokenCountMap,
|
|
34
|
+
function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, indexTokenCountMap, startType: _startType, thinkingEnabled,
|
|
35
|
+
/** We may need to use this when recalculating */
|
|
36
|
+
tokenCounter, }) {
|
|
29
37
|
// Every reply is primed with <|start|>assistant<|message|>, so we
|
|
30
38
|
// start with 3 tokens for the label after all messages have been counted.
|
|
31
|
-
let summaryIndex = -1;
|
|
32
39
|
let currentTokenCount = 3;
|
|
33
|
-
const instructions = _messages
|
|
34
|
-
const instructionsTokenCount = instructions != null ? indexTokenCountMap[0] : 0;
|
|
35
|
-
|
|
40
|
+
const instructions = _messages[0]?.getType() === 'system' ? _messages[0] : undefined;
|
|
41
|
+
const instructionsTokenCount = instructions != null ? indexTokenCountMap[0] ?? 0 : 0;
|
|
42
|
+
const initialContextTokens = maxContextTokens - instructionsTokenCount;
|
|
43
|
+
let remainingContextTokens = initialContextTokens;
|
|
44
|
+
let startType = _startType;
|
|
45
|
+
const originalLength = _messages.length;
|
|
36
46
|
const messages = [..._messages];
|
|
47
|
+
/**
|
|
48
|
+
* IMPORTANT: this context array gets reversed at the end, since the latest messages get pushed first.
|
|
49
|
+
*
|
|
50
|
+
* This may be confusing to read, but it is done to ensure the context is in the correct order for the model.
|
|
51
|
+
* */
|
|
37
52
|
let context = [];
|
|
53
|
+
let thinkingStartIndex = -1;
|
|
54
|
+
let thinkingEndIndex = -1;
|
|
55
|
+
let thinkingBlock;
|
|
56
|
+
const endIndex = instructions != null ? 1 : 0;
|
|
57
|
+
const prunedMemory = [];
|
|
38
58
|
if (currentTokenCount < remainingContextTokens) {
|
|
39
59
|
let currentIndex = messages.length;
|
|
40
|
-
while (messages.length > 0 && currentTokenCount < remainingContextTokens && currentIndex >
|
|
60
|
+
while (messages.length > 0 && currentTokenCount < remainingContextTokens && currentIndex > endIndex) {
|
|
41
61
|
currentIndex--;
|
|
42
62
|
if (messages.length === 1 && instructions) {
|
|
43
63
|
break;
|
|
@@ -45,195 +65,145 @@ function getMessagesWithinTokenLimit({ messages: _messages, maxContextTokens, in
|
|
|
45
65
|
const poppedMessage = messages.pop();
|
|
46
66
|
if (!poppedMessage)
|
|
47
67
|
continue;
|
|
48
|
-
const
|
|
49
|
-
if ((
|
|
68
|
+
const messageType = poppedMessage.getType();
|
|
69
|
+
if (thinkingEnabled === true && thinkingEndIndex === -1 && (currentIndex === (originalLength - 1)) && (messageType === 'ai' || messageType === 'tool')) {
|
|
70
|
+
thinkingEndIndex = currentIndex;
|
|
71
|
+
}
|
|
72
|
+
if (thinkingEndIndex > -1 && !thinkingBlock && thinkingStartIndex < 0 && messageType === 'ai' && Array.isArray(poppedMessage.content)) {
|
|
73
|
+
thinkingBlock = (poppedMessage.content.find((content) => content.type === ContentTypes.THINKING));
|
|
74
|
+
thinkingStartIndex = thinkingBlock != null ? currentIndex : -1;
|
|
75
|
+
}
|
|
76
|
+
/** False start, the latest message was not part of a multi-assistant/tool sequence of messages */
|
|
77
|
+
if (thinkingEndIndex > -1
|
|
78
|
+
&& currentIndex === (thinkingEndIndex - 1)
|
|
79
|
+
&& (messageType !== 'ai' && messageType !== 'tool')) {
|
|
80
|
+
thinkingEndIndex = -1;
|
|
81
|
+
}
|
|
82
|
+
const tokenCount = indexTokenCountMap[currentIndex] ?? 0;
|
|
83
|
+
if (prunedMemory.length === 0 && ((currentTokenCount + tokenCount) <= remainingContextTokens)) {
|
|
50
84
|
context.push(poppedMessage);
|
|
51
85
|
currentTokenCount += tokenCount;
|
|
52
86
|
}
|
|
53
87
|
else {
|
|
54
|
-
|
|
88
|
+
prunedMemory.push(poppedMessage);
|
|
89
|
+
if (thinkingEndIndex > -1) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
55
92
|
break;
|
|
56
93
|
}
|
|
57
94
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
95
|
+
if (thinkingEndIndex > -1 && context[context.length - 1].getType() === 'tool') {
|
|
96
|
+
startType = 'ai';
|
|
97
|
+
}
|
|
98
|
+
if (startType != null && startType && context.length > 0) {
|
|
99
|
+
const requiredTypeIndex = context.findIndex(msg => msg.getType() === startType);
|
|
61
100
|
if (requiredTypeIndex > 0) {
|
|
62
101
|
context = context.slice(requiredTypeIndex);
|
|
63
102
|
}
|
|
64
103
|
}
|
|
65
|
-
// Add system message if it exists
|
|
66
|
-
if (instructions && _messages.length > 0) {
|
|
67
|
-
context.push(_messages[0]);
|
|
68
|
-
messages.shift();
|
|
69
|
-
}
|
|
70
|
-
// Handle thinking mode requirement for Anthropic
|
|
71
|
-
if (thinkingEnabled && context.length > 0 && tokenCounter) {
|
|
72
|
-
// Check if the latest message is an assistant message
|
|
73
|
-
const latestMessageIsAssistant = _messages.length > 0 && _messages[_messages.length - 1].getType() === 'ai';
|
|
74
|
-
// Process only if we have an assistant message in the context
|
|
75
|
-
const firstAssistantIndex = context.findIndex(msg => msg.getType() === 'ai');
|
|
76
|
-
if (firstAssistantIndex >= 0) {
|
|
77
|
-
const firstAssistantMsg = context[firstAssistantIndex];
|
|
78
|
-
// Check if the first assistant message already has a thinking block
|
|
79
|
-
const hasThinkingBlock = Array.isArray(firstAssistantMsg.content) &&
|
|
80
|
-
firstAssistantMsg.content.some(item => item && typeof item === 'object' && item.type === 'thinking');
|
|
81
|
-
// Only proceed if we need to add thinking blocks
|
|
82
|
-
if (!hasThinkingBlock) {
|
|
83
|
-
// Collect thinking blocks from pruned assistant messages, starting from the most recent
|
|
84
|
-
const thinkingBlocks = [];
|
|
85
|
-
// Look through pruned messages for thinking blocks, starting from the end (most recent)
|
|
86
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
87
|
-
const msg = messages[i];
|
|
88
|
-
if (msg.getType() === 'ai' && Array.isArray(msg.content)) {
|
|
89
|
-
for (const item of msg.content) {
|
|
90
|
-
if (item && typeof item === 'object' && item.type === 'thinking') {
|
|
91
|
-
thinkingBlocks.push(item);
|
|
92
|
-
// We only need one thinking block
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (thinkingBlocks.length > 0)
|
|
97
|
-
break; // Stop after finding one thinking block
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
// If we found thinking blocks, add them to the first assistant message
|
|
101
|
-
if (thinkingBlocks.length > 0) {
|
|
102
|
-
// Calculate token count of original message
|
|
103
|
-
const originalTokenCount = tokenCounter(firstAssistantMsg);
|
|
104
|
-
// Create a new content array with thinking blocks at the beginning
|
|
105
|
-
let newContent;
|
|
106
|
-
if (Array.isArray(firstAssistantMsg.content)) {
|
|
107
|
-
// Keep the original content (excluding any existing thinking blocks)
|
|
108
|
-
const originalContent = firstAssistantMsg.content.filter(item => !(item && typeof item === 'object' && item.type === 'thinking'));
|
|
109
|
-
newContent = [...thinkingBlocks, ...originalContent];
|
|
110
|
-
}
|
|
111
|
-
else if (typeof firstAssistantMsg.content === 'string') {
|
|
112
|
-
newContent = [
|
|
113
|
-
...thinkingBlocks,
|
|
114
|
-
{ type: 'text', text: firstAssistantMsg.content }
|
|
115
|
-
];
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
newContent = thinkingBlocks;
|
|
119
|
-
}
|
|
120
|
-
// Create a new message with the updated content
|
|
121
|
-
const newMessage = new AIMessage({
|
|
122
|
-
content: newContent,
|
|
123
|
-
additional_kwargs: firstAssistantMsg.additional_kwargs,
|
|
124
|
-
response_metadata: firstAssistantMsg.response_metadata,
|
|
125
|
-
});
|
|
126
|
-
// Calculate token count of new message
|
|
127
|
-
const newTokenCount = tokenCounter(newMessage);
|
|
128
|
-
// Adjust current token count
|
|
129
|
-
currentTokenCount += (newTokenCount - originalTokenCount);
|
|
130
|
-
// Replace the first assistant message
|
|
131
|
-
context[firstAssistantIndex] = newMessage;
|
|
132
|
-
// If we've exceeded the token limit, we need to prune more messages
|
|
133
|
-
if (currentTokenCount > remainingContextTokens) {
|
|
134
|
-
// Build a map of tool call IDs to track AI <--> tool message correspondences
|
|
135
|
-
const toolCallIdMap = new Map();
|
|
136
|
-
// Identify tool call IDs in the context
|
|
137
|
-
for (let i = 0; i < context.length; i++) {
|
|
138
|
-
const msg = context[i];
|
|
139
|
-
// Check for tool calls in AI messages
|
|
140
|
-
if (msg.getType() === 'ai' && Array.isArray(msg.content)) {
|
|
141
|
-
for (const item of msg.content) {
|
|
142
|
-
if (item && typeof item === 'object' && item.type === 'tool_use' && item.id) {
|
|
143
|
-
toolCallIdMap.set(item.id, i);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
// Check for tool messages
|
|
148
|
-
if (msg.getType() === 'tool' && 'tool_call_id' in msg && typeof msg.tool_call_id === 'string') {
|
|
149
|
-
toolCallIdMap.set(msg.tool_call_id, i);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
// Track which messages to remove
|
|
153
|
-
const indicesToRemove = new Set();
|
|
154
|
-
// Start removing messages from the end, but preserve AI <--> tool message correspondences
|
|
155
|
-
let i = context.length - 1;
|
|
156
|
-
while (i > firstAssistantIndex && currentTokenCount > remainingContextTokens) {
|
|
157
|
-
const msgToRemove = context[i];
|
|
158
|
-
// Check if this is a tool message or has tool calls
|
|
159
|
-
let canRemove = true;
|
|
160
|
-
if (msgToRemove.getType() === 'tool' && 'tool_call_id' in msgToRemove && typeof msgToRemove.tool_call_id === 'string') {
|
|
161
|
-
// If this is a tool message, check if we need to keep its corresponding AI message
|
|
162
|
-
const aiIndex = toolCallIdMap.get(msgToRemove.tool_call_id);
|
|
163
|
-
if (aiIndex !== undefined && aiIndex !== i && !indicesToRemove.has(aiIndex)) {
|
|
164
|
-
// We need to remove both the tool message and its corresponding AI message
|
|
165
|
-
indicesToRemove.add(i);
|
|
166
|
-
indicesToRemove.add(aiIndex);
|
|
167
|
-
currentTokenCount -= (tokenCounter(msgToRemove) + tokenCounter(context[aiIndex]));
|
|
168
|
-
canRemove = false;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
else if (msgToRemove.getType() === 'ai' && Array.isArray(msgToRemove.content)) {
|
|
172
|
-
// If this is an AI message with tool calls, check if we need to keep its corresponding tool messages
|
|
173
|
-
for (const item of msgToRemove.content) {
|
|
174
|
-
if (item && typeof item === 'object' && item.type === 'tool_use' && item.id) {
|
|
175
|
-
const toolIndex = toolCallIdMap.get(item.id);
|
|
176
|
-
if (toolIndex !== undefined && toolIndex !== i && !indicesToRemove.has(toolIndex)) {
|
|
177
|
-
// We need to remove both the AI message and its corresponding tool message
|
|
178
|
-
indicesToRemove.add(i);
|
|
179
|
-
indicesToRemove.add(toolIndex);
|
|
180
|
-
currentTokenCount -= (tokenCounter(msgToRemove) + tokenCounter(context[toolIndex]));
|
|
181
|
-
canRemove = false;
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
// If we can remove this message individually
|
|
188
|
-
if (canRemove && !indicesToRemove.has(i)) {
|
|
189
|
-
indicesToRemove.add(i);
|
|
190
|
-
currentTokenCount -= tokenCounter(msgToRemove);
|
|
191
|
-
}
|
|
192
|
-
i--;
|
|
193
|
-
}
|
|
194
|
-
// Remove messages in reverse order to avoid index shifting
|
|
195
|
-
const sortedIndices = Array.from(indicesToRemove).sort((a, b) => b - a);
|
|
196
|
-
for (const index of sortedIndices) {
|
|
197
|
-
context.splice(index, 1);
|
|
198
|
-
}
|
|
199
|
-
// Update remainingContextTokens to reflect the new token count
|
|
200
|
-
remainingContextTokens = maxContextTokens - currentTokenCount;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
// If the latest message is an assistant message, ensure an assistant message appears early in the context
|
|
206
|
-
// but maintain system message precedence
|
|
207
|
-
if (latestMessageIsAssistant && context.length > 0) {
|
|
208
|
-
// Find the first assistant message in the context
|
|
209
|
-
const assistantIndex = context.findIndex(msg => msg.getType() === 'ai');
|
|
210
|
-
if (assistantIndex > 0) {
|
|
211
|
-
// Check if there's a system message at the beginning
|
|
212
|
-
const hasSystemFirst = context[0].getType() === 'system';
|
|
213
|
-
// Move the assistant message to the appropriate position
|
|
214
|
-
const assistantMsg = context[assistantIndex];
|
|
215
|
-
context.splice(assistantIndex, 1);
|
|
216
|
-
if (hasSystemFirst) {
|
|
217
|
-
// Insert after the system message
|
|
218
|
-
context.splice(1, 0, assistantMsg);
|
|
219
|
-
}
|
|
220
|
-
else {
|
|
221
|
-
// Insert at the beginning if no system message
|
|
222
|
-
context.unshift(assistantMsg);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
104
|
}
|
|
228
|
-
|
|
229
|
-
|
|
105
|
+
if (instructions && originalLength > 0) {
|
|
106
|
+
context.push(_messages[0]);
|
|
107
|
+
messages.shift();
|
|
108
|
+
}
|
|
230
109
|
remainingContextTokens -= currentTokenCount;
|
|
231
|
-
|
|
232
|
-
summaryIndex,
|
|
110
|
+
const result = {
|
|
233
111
|
remainingContextTokens,
|
|
234
|
-
context:
|
|
112
|
+
context: [],
|
|
235
113
|
messagesToRefine: prunedMemory,
|
|
236
114
|
};
|
|
115
|
+
if (prunedMemory.length === 0 || thinkingEndIndex < 0 || (thinkingStartIndex > -1 && isIndexInContext(_messages, context, thinkingStartIndex))) {
|
|
116
|
+
// we reverse at this step to ensure the context is in the correct order for the model, and we need to work backwards
|
|
117
|
+
result.context = context.reverse();
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
if (thinkingEndIndex > -1 && thinkingStartIndex < 0) {
|
|
121
|
+
throw new Error('The payload is malformed. There is a thinking sequence but no "AI" messages with thinking blocks.');
|
|
122
|
+
}
|
|
123
|
+
if (!thinkingBlock) {
|
|
124
|
+
throw new Error('The payload is malformed. There is a thinking sequence but no thinking block found.');
|
|
125
|
+
}
|
|
126
|
+
// Since we have a thinking sequence, we need to find the last assistant message
|
|
127
|
+
// in the latest AI/tool sequence to add the thinking block that falls outside of the current context
|
|
128
|
+
// Latest messages are ordered first.
|
|
129
|
+
let assistantIndex = -1;
|
|
130
|
+
for (let i = 0; i < context.length; i++) {
|
|
131
|
+
const currentMessage = context[i];
|
|
132
|
+
const type = currentMessage.getType();
|
|
133
|
+
if (type === 'ai') {
|
|
134
|
+
assistantIndex = i;
|
|
135
|
+
}
|
|
136
|
+
if (assistantIndex > -1 && (type === 'human' || type === 'system')) {
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (assistantIndex === -1) {
|
|
141
|
+
throw new Error('The payload is malformed. There is a thinking sequence but no "AI" messages to append thinking blocks to.');
|
|
142
|
+
}
|
|
143
|
+
thinkingStartIndex = originalLength - 1 - assistantIndex;
|
|
144
|
+
const thinkingTokenCount = tokenCounter(new AIMessage({ content: [thinkingBlock] }));
|
|
145
|
+
const newRemainingCount = remainingContextTokens - thinkingTokenCount;
|
|
146
|
+
const content = Array.isArray(context[assistantIndex].content)
|
|
147
|
+
? context[assistantIndex].content
|
|
148
|
+
: [{
|
|
149
|
+
type: ContentTypes.TEXT,
|
|
150
|
+
text: context[assistantIndex].content,
|
|
151
|
+
}];
|
|
152
|
+
content.unshift(thinkingBlock);
|
|
153
|
+
context[assistantIndex].content = content;
|
|
154
|
+
if (newRemainingCount > 0) {
|
|
155
|
+
result.context = context.reverse();
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
const thinkingMessage = context[assistantIndex];
|
|
159
|
+
// now we need to an additional round of pruning but making the thinking block fit
|
|
160
|
+
const newThinkingMessageTokenCount = (indexTokenCountMap[thinkingStartIndex] ?? 0) + thinkingTokenCount;
|
|
161
|
+
remainingContextTokens = initialContextTokens - newThinkingMessageTokenCount;
|
|
162
|
+
currentTokenCount = 3;
|
|
163
|
+
let newContext = [];
|
|
164
|
+
const secondRoundMessages = [..._messages];
|
|
165
|
+
let currentIndex = secondRoundMessages.length;
|
|
166
|
+
while (secondRoundMessages.length > 0 && currentTokenCount < remainingContextTokens && currentIndex > thinkingStartIndex) {
|
|
167
|
+
currentIndex--;
|
|
168
|
+
const poppedMessage = secondRoundMessages.pop();
|
|
169
|
+
if (!poppedMessage)
|
|
170
|
+
continue;
|
|
171
|
+
const tokenCount = indexTokenCountMap[currentIndex] ?? 0;
|
|
172
|
+
if ((currentTokenCount + tokenCount) <= remainingContextTokens) {
|
|
173
|
+
newContext.push(poppedMessage);
|
|
174
|
+
currentTokenCount += tokenCount;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
messages.push(poppedMessage);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const firstMessage = newContext[newContext.length - 1];
|
|
182
|
+
const firstMessageType = newContext[newContext.length - 1].getType();
|
|
183
|
+
if (firstMessageType === 'tool') {
|
|
184
|
+
startType = 'ai';
|
|
185
|
+
}
|
|
186
|
+
if (startType != null && startType && newContext.length > 0) {
|
|
187
|
+
const requiredTypeIndex = newContext.findIndex(msg => msg.getType() === startType);
|
|
188
|
+
if (requiredTypeIndex > 0) {
|
|
189
|
+
newContext = newContext.slice(requiredTypeIndex);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
if (firstMessageType === 'ai') {
|
|
193
|
+
newContext[newContext.length - 1] = new AIMessage({
|
|
194
|
+
content: concat(thinkingMessage.content, newContext[newContext.length - 1].content),
|
|
195
|
+
tool_calls: concat(firstMessage.tool_calls, thinkingMessage.tool_calls),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
newContext.push(thinkingMessage);
|
|
200
|
+
}
|
|
201
|
+
if (instructions && originalLength > 0) {
|
|
202
|
+
newContext.push(_messages[0]);
|
|
203
|
+
secondRoundMessages.shift();
|
|
204
|
+
}
|
|
205
|
+
result.context = newContext.reverse();
|
|
206
|
+
return result;
|
|
237
207
|
}
|
|
238
208
|
function checkValidNumber(value) {
|
|
239
209
|
return typeof value === 'number' && !isNaN(value) && value > 0;
|
|
@@ -253,8 +223,10 @@ function createPruneMessages(factoryParams) {
|
|
|
253
223
|
}
|
|
254
224
|
for (let i = lastTurnStartIndex; i < params.messages.length; i++) {
|
|
255
225
|
const message = params.messages[i];
|
|
226
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
256
227
|
if (i === lastTurnStartIndex && indexTokenCountMap[i] === undefined && currentUsage) {
|
|
257
228
|
indexTokenCountMap[i] = currentUsage.output_tokens;
|
|
229
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
258
230
|
}
|
|
259
231
|
else if (indexTokenCountMap[i] === undefined) {
|
|
260
232
|
indexTokenCountMap[i] = factoryParams.tokenCounter(message);
|
|
@@ -276,12 +248,11 @@ function createPruneMessages(factoryParams) {
|
|
|
276
248
|
if (totalTokens <= factoryParams.maxTokens) {
|
|
277
249
|
return { context: params.messages, indexTokenCountMap };
|
|
278
250
|
}
|
|
279
|
-
// Pass the tokenCounter to getMessagesWithinTokenLimit for token recalculation
|
|
280
251
|
const { context } = getMessagesWithinTokenLimit({
|
|
281
252
|
maxContextTokens: factoryParams.maxTokens,
|
|
282
253
|
messages: params.messages,
|
|
283
254
|
indexTokenCountMap,
|
|
284
|
-
|
|
255
|
+
startType: params.startType,
|
|
285
256
|
thinkingEnabled: factoryParams.thinkingEnabled,
|
|
286
257
|
tokenCounter: factoryParams.tokenCounter,
|
|
287
258
|
});
|
|
@@ -289,5 +260,5 @@ function createPruneMessages(factoryParams) {
|
|
|
289
260
|
};
|
|
290
261
|
}
|
|
291
262
|
|
|
292
|
-
export { createPruneMessages };
|
|
263
|
+
export { calculateTotalTokens, checkValidNumber, createPruneMessages, getMessagesWithinTokenLimit };
|
|
293
264
|
//# sourceMappingURL=prune.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prune.mjs","sources":["../../../src/messages/prune.ts"],"sourcesContent":["import { AIMessage } from '@langchain/core/messages';\nimport type { BaseMessage, UsageMetadata } from '@langchain/core/messages';\nimport type { TokenCounter } from '@/types/run';\nexport type PruneMessagesFactoryParams = {\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 startOnMessageType?: ReturnType<BaseMessage['getType']>;\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 */\nfunction 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\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 */\nfunction getMessagesWithinTokenLimit({\n messages: _messages,\n maxContextTokens,\n indexTokenCountMap,\n startOnMessageType,\n thinkingEnabled,\n tokenCounter,\n}: {\n messages: BaseMessage[];\n maxContextTokens: number;\n indexTokenCountMap: Record<string, number>;\n startOnMessageType?: string;\n thinkingEnabled?: boolean;\n tokenCounter?: TokenCounter;\n}): {\n context: BaseMessage[];\n remainingContextTokens: number;\n messagesToRefine: BaseMessage[];\n summaryIndex: number;\n} {\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 summaryIndex = -1;\n let currentTokenCount = 3;\n const instructions = _messages?.[0]?.getType() === 'system' ? _messages[0] : undefined;\n const instructionsTokenCount = instructions != null ? indexTokenCountMap[0] : 0;\n let remainingContextTokens = maxContextTokens - instructionsTokenCount;\n const messages = [..._messages];\n let context: BaseMessage[] = [];\n\n if (currentTokenCount < remainingContextTokens) {\n let currentIndex = messages.length;\n while (messages.length > 0 && currentTokenCount < remainingContextTokens && currentIndex > 1) {\n currentIndex--;\n if (messages.length === 1 && instructions) {\n break;\n }\n const poppedMessage = messages.pop();\n if (!poppedMessage) continue;\n \n const tokenCount = indexTokenCountMap[currentIndex] || 0;\n\n if ((currentTokenCount + tokenCount) <= remainingContextTokens) {\n context.push(poppedMessage);\n currentTokenCount += tokenCount;\n } else {\n messages.push(poppedMessage);\n break;\n }\n }\n \n // Handle startOnMessageType requirement\n if (startOnMessageType && context.length > 0) {\n const requiredTypeIndex = context.findIndex(msg => msg.getType() === startOnMessageType);\n \n if (requiredTypeIndex > 0) {\n context = context.slice(requiredTypeIndex);\n }\n }\n \n // Add system message if it exists\n if (instructions && _messages.length > 0) {\n context.push(_messages[0] as BaseMessage);\n messages.shift();\n }\n \n // Handle thinking mode requirement for Anthropic\n if (thinkingEnabled && context.length > 0 && tokenCounter) {\n // Check if the latest message is an assistant message\n const latestMessageIsAssistant = _messages.length > 0 && _messages[_messages.length - 1].getType() === 'ai';\n \n // Process only if we have an assistant message in the context\n const firstAssistantIndex = context.findIndex(msg => msg.getType() === 'ai');\n \n if (firstAssistantIndex >= 0) {\n const firstAssistantMsg = context[firstAssistantIndex];\n \n // Check if the first assistant message already has a thinking block\n const hasThinkingBlock = Array.isArray(firstAssistantMsg.content) && \n firstAssistantMsg.content.some(item => \n item && typeof item === 'object' && item.type === 'thinking');\n \n // Only proceed if we need to add thinking blocks\n if (!hasThinkingBlock) {\n // Collect thinking blocks from pruned assistant messages, starting from the most recent\n const thinkingBlocks: any[] = [];\n \n // Look through pruned messages for thinking blocks, starting from the end (most recent)\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (msg.getType() === 'ai' && Array.isArray(msg.content)) {\n for (const item of msg.content) {\n if (item && typeof item === 'object' && item.type === 'thinking') {\n thinkingBlocks.push(item);\n // We only need one thinking block\n break;\n }\n }\n if (thinkingBlocks.length > 0) break; // Stop after finding one thinking block\n }\n }\n \n // If we found thinking blocks, add them to the first assistant message\n if (thinkingBlocks.length > 0) {\n // Calculate token count of original message\n const originalTokenCount = tokenCounter(firstAssistantMsg);\n \n // Create a new content array with thinking blocks at the beginning\n let newContent: any[];\n \n if (Array.isArray(firstAssistantMsg.content)) {\n // Keep the original content (excluding any existing thinking blocks)\n const originalContent = firstAssistantMsg.content.filter(item => \n !(item && typeof item === 'object' && item.type === 'thinking'));\n \n newContent = [...thinkingBlocks, ...originalContent];\n } else if (typeof firstAssistantMsg.content === 'string') {\n newContent = [\n ...thinkingBlocks,\n { type: 'text', text: firstAssistantMsg.content }\n ];\n } else {\n newContent = thinkingBlocks;\n }\n \n // Create a new message with the updated content\n const newMessage = new AIMessage({\n content: newContent,\n additional_kwargs: firstAssistantMsg.additional_kwargs,\n response_metadata: firstAssistantMsg.response_metadata,\n });\n \n // Calculate token count of new message\n const newTokenCount = tokenCounter(newMessage);\n \n // Adjust current token count\n currentTokenCount += (newTokenCount - originalTokenCount);\n \n // Replace the first assistant message\n context[firstAssistantIndex] = newMessage;\n \n // If we've exceeded the token limit, we need to prune more messages\n if (currentTokenCount > remainingContextTokens) {\n // Build a map of tool call IDs to track AI <--> tool message correspondences\n const toolCallIdMap = new Map<string, number>();\n \n // Identify tool call IDs in the context\n for (let i = 0; i < context.length; i++) {\n const msg = context[i];\n \n // Check for tool calls in AI messages\n if (msg.getType() === 'ai' && Array.isArray(msg.content)) {\n for (const item of msg.content) {\n if (item && typeof item === 'object' && item.type === 'tool_use' && item.id) {\n toolCallIdMap.set(item.id, i);\n }\n }\n }\n \n // Check for tool messages\n if (msg.getType() === 'tool' && 'tool_call_id' in msg && typeof msg.tool_call_id === 'string') {\n toolCallIdMap.set(msg.tool_call_id, i);\n }\n }\n \n // Track which messages to remove\n const indicesToRemove = new Set<number>();\n \n // Start removing messages from the end, but preserve AI <--> tool message correspondences\n let i = context.length - 1;\n while (i > firstAssistantIndex && currentTokenCount > remainingContextTokens) {\n const msgToRemove = context[i];\n \n // Check if this is a tool message or has tool calls\n let canRemove = true;\n \n if (msgToRemove.getType() === 'tool' && 'tool_call_id' in msgToRemove && typeof msgToRemove.tool_call_id === 'string') {\n // If this is a tool message, check if we need to keep its corresponding AI message\n const aiIndex = toolCallIdMap.get(msgToRemove.tool_call_id);\n if (aiIndex !== undefined && aiIndex !== i && !indicesToRemove.has(aiIndex)) {\n // We need to remove both the tool message and its corresponding AI message\n indicesToRemove.add(i);\n indicesToRemove.add(aiIndex);\n currentTokenCount -= (tokenCounter(msgToRemove) + tokenCounter(context[aiIndex]));\n canRemove = false;\n }\n } else if (msgToRemove.getType() === 'ai' && Array.isArray(msgToRemove.content)) {\n // If this is an AI message with tool calls, check if we need to keep its corresponding tool messages\n for (const item of msgToRemove.content) {\n if (item && typeof item === 'object' && item.type === 'tool_use' && item.id) {\n const toolIndex = toolCallIdMap.get(item.id as string);\n if (toolIndex !== undefined && toolIndex !== i && !indicesToRemove.has(toolIndex)) {\n // We need to remove both the AI message and its corresponding tool message\n indicesToRemove.add(i);\n indicesToRemove.add(toolIndex);\n currentTokenCount -= (tokenCounter(msgToRemove) + tokenCounter(context[toolIndex]));\n canRemove = false;\n break;\n }\n }\n }\n }\n \n // If we can remove this message individually\n if (canRemove && !indicesToRemove.has(i)) {\n indicesToRemove.add(i);\n currentTokenCount -= tokenCounter(msgToRemove);\n }\n \n i--;\n }\n \n // Remove messages in reverse order to avoid index shifting\n const sortedIndices = Array.from(indicesToRemove).sort((a, b) => b - a);\n for (const index of sortedIndices) {\n context.splice(index, 1);\n }\n \n // Update remainingContextTokens to reflect the new token count\n remainingContextTokens = maxContextTokens - currentTokenCount;\n }\n }\n }\n }\n \n // If the latest message is an assistant message, ensure an assistant message appears early in the context\n // but maintain system message precedence\n if (latestMessageIsAssistant && context.length > 0) {\n // Find the first assistant message in the context\n const assistantIndex = context.findIndex(msg => msg.getType() === 'ai');\n if (assistantIndex > 0) {\n // Check if there's a system message at the beginning\n const hasSystemFirst = context[0].getType() === 'system';\n \n // Move the assistant message to the appropriate position\n const assistantMsg = context[assistantIndex];\n context.splice(assistantIndex, 1);\n \n if (hasSystemFirst) {\n // Insert after the system message\n context.splice(1, 0, assistantMsg);\n } else {\n // Insert at the beginning if no system message\n context.unshift(assistantMsg);\n }\n }\n }\n }\n }\n\n const prunedMemory = messages;\n summaryIndex = prunedMemory.length - 1;\n remainingContextTokens -= currentTokenCount;\n\n return {\n summaryIndex,\n remainingContextTokens,\n context: context.reverse(),\n messagesToRefine: prunedMemory,\n };\n}\n\nfunction 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 totalTokens = (Object.values(indexTokenCountMap)).reduce((a, b) => a + b, 0);\n \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 for (let i = lastTurnStartIndex; i < params.messages.length; i++) {\n const message = params.messages[i];\n if (i === lastTurnStartIndex && indexTokenCountMap[i] === undefined && currentUsage) {\n indexTokenCountMap[i] = currentUsage.output_tokens;\n } else if (indexTokenCountMap[i] === undefined) {\n indexTokenCountMap[i] = factoryParams.tokenCounter(message);\n totalTokens += indexTokenCountMap[i];\n }\n }\n\n // If `currentUsage` is defined, we need to distribute the current total tokensto our `indexTokenCountMap`,\n // for all message index keys before `lastTurnStartIndex`, as it has the most accurate count for those messages.\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 if (currentUsage) {\n const totalIndexTokens = Object.values(indexTokenCountMap).reduce((a, b) => a + b, 0);\n const ratio = currentUsage.total_tokens / totalIndexTokens;\n for (const key in indexTokenCountMap) {\n indexTokenCountMap[key] = Math.round(indexTokenCountMap[key] * ratio);\n }\n }\n\n lastTurnStartIndex = params.messages.length;\n if (totalTokens <= factoryParams.maxTokens) {\n return { context: params.messages, indexTokenCountMap };\n }\n\n // Pass the tokenCounter to getMessagesWithinTokenLimit for token recalculation\n const { context } = getMessagesWithinTokenLimit({\n maxContextTokens: factoryParams.maxTokens,\n messages: params.messages,\n indexTokenCountMap,\n startOnMessageType: params.startOnMessageType,\n thinkingEnabled: factoryParams.thinkingEnabled,\n tokenCounter: factoryParams.tokenCounter,\n });\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 { concat } from '@langchain/core/utils/stream';\nimport { AIMessage, BaseMessage, UsageMetadata } from '@langchain/core/messages';\nimport type { ThinkingContentText, MessageContentComplex } from '@/types/stream';\nimport type { TokenCounter } from '@/types/run';\nimport { ContentTypes } from '@/common';\nexport type PruneMessagesFactoryParams = {\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: BaseMessage[], arrayB: BaseMessage[], targetIndex: number): boolean {\n const startingIndexInA = arrayA.length - arrayB.length;\n return targetIndex >= startingIndexInA;\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\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 /** We may need to use this when recalculating */\n tokenCounter,\n}: {\n messages: BaseMessage[];\n maxContextTokens: number;\n indexTokenCountMap: Record<string, number | undefined>;\n tokenCounter: TokenCounter;\n startType?: string;\n thinkingEnabled?: boolean;\n}): {\n context: BaseMessage[];\n remainingContextTokens: number;\n messagesToRefine: BaseMessage[];\n} {\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: BaseMessage[] = [];\n\n let thinkingStartIndex = -1;\n let thinkingEndIndex = -1;\n let thinkingBlock: ThinkingContentText | undefined;\n const endIndex = instructions != null ? 1 : 0;\n const prunedMemory: BaseMessage[] = [];\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 === ContentTypes.THINKING)) 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) {\n continue;\n }\n break;\n }\n }\n\n if (thinkingEndIndex > -1 && context[context.length - 1].getType() === 'tool') {\n startType = 'ai';\n }\n\n if (startType != null && startType && context.length > 0) {\n const requiredTypeIndex = context.findIndex(msg => msg.getType() === startType);\n\n if (requiredTypeIndex > 0) {\n context = context.slice(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 = {\n remainingContextTokens,\n context: [] as BaseMessage[],\n messagesToRefine: prunedMemory,\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();\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\n const content: MessageContentComplex[] = Array.isArray(context[assistantIndex].content)\n ? context[assistantIndex].content as MessageContentComplex[]\n : [{\n type: ContentTypes.TEXT,\n text: context[assistantIndex].content,\n }];\n content.unshift(thinkingBlock);\n context[assistantIndex].content = content;\n if (newRemainingCount > 0) {\n result.context = context.reverse();\n return result;\n }\n\n const thinkingMessage: AIMessage = context[assistantIndex];\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';\n }\n\n if (startType != null && startType && newContext.length > 0) {\n const requiredTypeIndex = newContext.findIndex(msg => msg.getType() === startType);\n if (requiredTypeIndex > 0) {\n newContext = newContext.slice(requiredTypeIndex);\n }\n }\n\n if (firstMessageType === 'ai') {\n newContext[newContext.length - 1] = new AIMessage({\n content: concat(thinkingMessage.content as MessageContentComplex[], newContext[newContext.length - 1].content as MessageContentComplex[]),\n tool_calls: concat(firstMessage.tool_calls, thinkingMessage.tool_calls),\n });\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 totalTokens = (Object.values(indexTokenCountMap)).reduce((a, b) => a + b, 0);\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 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 totalTokens += indexTokenCountMap[i];\n }\n }\n\n // If `currentUsage` is defined, we need to distribute the current total tokensto our `indexTokenCountMap`,\n // for all message index keys before `lastTurnStartIndex`, as it has the most accurate count for those messages.\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 if (currentUsage) {\n const totalIndexTokens = Object.values(indexTokenCountMap).reduce((a, b) => a + b, 0);\n const ratio = currentUsage.total_tokens / totalIndexTokens;\n for (const key in indexTokenCountMap) {\n indexTokenCountMap[key] = Math.round(indexTokenCountMap[key] * ratio);\n }\n }\n\n lastTurnStartIndex = params.messages.length;\n if (totalTokens <= factoryParams.maxTokens) {\n return { context: params.messages, indexTokenCountMap };\n }\n\n const { context } = getMessagesWithinTokenLimit({\n maxContextTokens: factoryParams.maxTokens,\n messages: params.messages,\n indexTokenCountMap,\n startType: params.startType,\n thinkingEnabled: factoryParams.thinkingEnabled,\n tokenCounter: factoryParams.tokenCounter,\n });\n\n return { context, indexTokenCountMap };\n };\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/run.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.mjs","sources":["../../src/run.ts"],"sourcesContent":["// src/run.ts\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport { PromptTemplate } from '@langchain/core/prompts';\nimport { AzureChatOpenAI, ChatOpenAI } from '@langchain/openai';\nimport { SystemMessage } from '@langchain/core/messages';\nimport type { BaseMessage, MessageContentComplex } from '@langchain/core/messages';\nimport type { ClientCallbacks, SystemCallbacks } from '@/graphs/Graph';\nimport type { RunnableConfig } from '@langchain/core/runnables';\nimport type * as t from '@/types';\nimport { GraphEvents, Providers, Callback } from '@/common';\nimport { manualToolStreamProviders } from '@/llm/providers';\nimport { shiftIndexTokenCountMap } from '@/messages/format';\nimport { createTitleRunnable } from '@/utils/title';\nimport { createTokenCounter } from '@/utils/tokens';\nimport { StandardGraph } from '@/graphs/Graph';\nimport { HandlerRegistry } from '@/events';\nimport { isOpenAILike } from '@/utils/llm';\n\nexport class Run<T extends t.BaseGraphState> {\n graphRunnable?: t.CompiledWorkflow<T, Partial<T>, string>;\n // private collab!: CollabGraph;\n // private taskManager!: TaskManager;\n private handlerRegistry: HandlerRegistry;\n id: string;\n Graph: StandardGraph | undefined;\n provider: Providers | undefined;\n returnContent: boolean = false;\n\n private constructor(config: Partial<t.RunConfig>) {\n const runId = config.runId ?? '';\n if (!runId) {\n throw new Error('Run ID not provided');\n }\n\n this.id = runId;\n\n const handlerRegistry = new HandlerRegistry();\n\n if (config.customHandlers) {\n for (const [eventType, handler] of Object.entries(config.customHandlers)) {\n handlerRegistry.register(eventType, handler);\n }\n }\n\n this.handlerRegistry = handlerRegistry;\n\n if (!config.graphConfig) {\n throw new Error('Graph config not provided');\n }\n\n if (config.graphConfig.type === 'standard' || !config.graphConfig.type) {\n this.provider = config.graphConfig.llmConfig.provider;\n this.graphRunnable = this.createStandardGraph(config.graphConfig) as unknown as t.CompiledWorkflow<T, Partial<T>, string>;\n if (this.Graph) {\n this.Graph.handlerRegistry = handlerRegistry;\n }\n }\n\n this.returnContent = config.returnContent ?? false;\n }\n\n private createStandardGraph(config: t.StandardGraphConfig): t.CompiledWorkflow<t.IState, Partial<t.IState>, string> {\n const { llmConfig, tools = [], ...graphInput } = config;\n const { provider, ...clientOptions } = llmConfig;\n\n const standardGraph = new StandardGraph({\n tools,\n provider,\n clientOptions,\n ...graphInput,\n runId: this.id,\n });\n this.Graph = standardGraph;\n return standardGraph.createWorkflow();\n }\n\n static async create<T extends t.BaseGraphState>(config: t.RunConfig): Promise<Run<T>> {\n return new Run<T>(config);\n }\n\n getRunMessages(): BaseMessage[] | undefined {\n if (!this.Graph) {\n throw new Error('Graph not initialized. Make sure to use Run.create() to instantiate the Run.');\n }\n return this.Graph.getRunMessages();\n }\n\n async processStream(\n inputs: t.IState,\n config: Partial<RunnableConfig> & { version: 'v1' | 'v2'; run_id?: string },\n streamOptions?: t.EventStreamOptions,\n ): Promise<MessageContentComplex[] | undefined> {\n if (!this.graphRunnable) {\n throw new Error('Run not initialized. Make sure to use Run.create() to instantiate the Run.');\n }\n if (!this.Graph) {\n throw new Error('Graph not initialized. Make sure to use Run.create() to instantiate the Run.');\n }\n\n this.Graph.resetValues(streamOptions?.keepContent);\n const provider = this.Graph.provider;\n const hasTools = this.Graph.tools ? this.Graph.tools.length > 0 : false;\n if (streamOptions?.callbacks) {\n /* TODO: conflicts with callback manager */\n const callbacks = config.callbacks as t.ProvidedCallbacks ?? [];\n config.callbacks = callbacks.concat(this.getCallbacks(streamOptions.callbacks));\n }\n\n if (!this.id) {\n throw new Error('Run ID not provided');\n }\n\n const tokenCounter = streamOptions?.tokenCounter ?? (streamOptions?.indexTokenCountMap ? await createTokenCounter() : undefined);\n const toolTokens = tokenCounter ? (this.Graph.tools?.reduce((acc, tool) => {\n if (!tool.schema) {\n return acc;\n }\n \n const jsonSchema = zodToJsonSchema(tool.schema.describe(tool.description ?? ''), tool.name);\n return acc + tokenCounter(new SystemMessage(JSON.stringify(jsonSchema)));\n }, 0) ?? 0) : 0;\n let instructionTokens = toolTokens;\n if (this.Graph.systemMessage && tokenCounter) {\n instructionTokens += tokenCounter(this.Graph.systemMessage);\n }\n if (instructionTokens > 0) {\n this.Graph.indexTokenCountMap = shiftIndexTokenCountMap(streamOptions?.indexTokenCountMap ?? {}, instructionTokens);\n } else {\n this.Graph.indexTokenCountMap = streamOptions?.indexTokenCountMap ?? {};\n }\n\n this.Graph.maxContextTokens = streamOptions?.maxContextTokens;\n this.Graph.tokenCounter = tokenCounter;\n\n config.run_id = this.id;\n config.configurable = Object.assign(config.configurable ?? {}, { run_id: this.id, provider: this.provider });\n\n const stream = this.graphRunnable.streamEvents(inputs, config);\n\n for await (const event of stream) {\n const { data, name, metadata, ...info } = event;\n\n let eventName: t.EventName = info.event;\n if (hasTools && manualToolStreamProviders.has(provider) && eventName === GraphEvents.CHAT_MODEL_STREAM) {\n /* Skipping CHAT_MODEL_STREAM event due to double-call edge case */\n continue;\n }\n\n if (eventName && eventName === GraphEvents.ON_CUSTOM_EVENT) {\n eventName = name;\n }\n\n const handler = this.handlerRegistry.getHandler(eventName);\n if (handler) {\n handler.handle(eventName, data, metadata, this.Graph);\n }\n }\n\n if (this.returnContent) {\n return this.Graph.getContentParts();\n }\n }\n\n private createSystemCallback<K extends keyof ClientCallbacks>(\n clientCallbacks: ClientCallbacks,\n key: K\n ): SystemCallbacks[K] {\n return ((...args: unknown[]) => {\n const clientCallback = clientCallbacks[key];\n if (clientCallback && this.Graph) {\n (clientCallback as (...args: unknown[]) => void)(this.Graph, ...args);\n }\n }) as SystemCallbacks[K];\n }\n\n getCallbacks(clientCallbacks: ClientCallbacks): SystemCallbacks {\n return {\n [Callback.TOOL_ERROR]: this.createSystemCallback(clientCallbacks, Callback.TOOL_ERROR),\n [Callback.TOOL_START]: this.createSystemCallback(clientCallbacks, Callback.TOOL_START),\n [Callback.TOOL_END]: this.createSystemCallback(clientCallbacks, Callback.TOOL_END),\n };\n }\n\n async generateTitle({\n inputText,\n contentParts,\n titlePrompt,\n clientOptions,\n chainOptions,\n skipLanguage,\n } : {\n inputText: string;\n contentParts: (t.MessageContentComplex | undefined)[];\n titlePrompt?: string;\n skipLanguage?: boolean;\n clientOptions?: t.ClientOptions;\n chainOptions?: Partial<RunnableConfig> | undefined;\n }): Promise<{ language: string; title: string }> {\n const convoTemplate = PromptTemplate.fromTemplate('User: {input}\\nAI: {output}');\n const response = contentParts.map((part) => {\n if (part?.type === 'text') return part.text;\n return '';\n }).join('\\n');\n const convo = (await convoTemplate.invoke({ input: inputText, output: response })).value;\n const model = this.Graph?.getNewModel({\n clientOptions,\n omitOriginalOptions: ['streaming', 'stream', 'thinking', 'maxTokens', 'maxOutputTokens', 'additionalModelRequestFields'],\n });\n if (!model) {\n return { language: '', title: '' };\n }\n if (isOpenAILike(this.provider) && (model instanceof ChatOpenAI || model instanceof AzureChatOpenAI)) {\n model.temperature = (clientOptions as t.OpenAIClientOptions | undefined)?.temperature as number;\n model.topP = (clientOptions as t.OpenAIClientOptions | undefined)?.topP as number;\n model.frequencyPenalty = (clientOptions as t.OpenAIClientOptions | undefined)?.frequencyPenalty as number;\n model.presencePenalty = (clientOptions as t.OpenAIClientOptions | undefined)?.presencePenalty as number;\n model.n = (clientOptions as t.OpenAIClientOptions | undefined)?.n as number;\n }\n const chain = await createTitleRunnable(model, titlePrompt);\n return await chain.invoke({ convo, inputText, skipLanguage }, chainOptions) as { language: string; title: string };\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"run.mjs","sources":["../../src/run.ts"],"sourcesContent":["// src/run.ts\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport { PromptTemplate } from '@langchain/core/prompts';\nimport { AzureChatOpenAI, ChatOpenAI } from '@langchain/openai';\nimport { SystemMessage } from '@langchain/core/messages';\nimport type { BaseMessage, MessageContentComplex } from '@langchain/core/messages';\nimport type { ClientCallbacks, SystemCallbacks } from '@/graphs/Graph';\nimport type { RunnableConfig } from '@langchain/core/runnables';\nimport type * as t from '@/types';\nimport { GraphEvents, Providers, Callback } from '@/common';\nimport { manualToolStreamProviders } from '@/llm/providers';\nimport { shiftIndexTokenCountMap } from '@/messages/format';\nimport { createTitleRunnable } from '@/utils/title';\nimport { createTokenCounter } from '@/utils/tokens';\nimport { StandardGraph } from '@/graphs/Graph';\nimport { HandlerRegistry } from '@/events';\nimport { isOpenAILike } from '@/utils/llm';\n\nexport class Run<T extends t.BaseGraphState> {\n graphRunnable?: t.CompiledWorkflow<T, Partial<T>, string>;\n // private collab!: CollabGraph;\n // private taskManager!: TaskManager;\n private handlerRegistry: HandlerRegistry;\n id: string;\n Graph: StandardGraph | undefined;\n provider: Providers | undefined;\n returnContent: boolean = false;\n\n private constructor(config: Partial<t.RunConfig>) {\n const runId = config.runId ?? '';\n if (!runId) {\n throw new Error('Run ID not provided');\n }\n\n this.id = runId;\n\n const handlerRegistry = new HandlerRegistry();\n\n if (config.customHandlers) {\n for (const [eventType, handler] of Object.entries(config.customHandlers)) {\n handlerRegistry.register(eventType, handler);\n }\n }\n\n this.handlerRegistry = handlerRegistry;\n\n if (!config.graphConfig) {\n throw new Error('Graph config not provided');\n }\n\n if (config.graphConfig.type === 'standard' || !config.graphConfig.type) {\n this.provider = config.graphConfig.llmConfig.provider;\n this.graphRunnable = this.createStandardGraph(config.graphConfig) as unknown as t.CompiledWorkflow<T, Partial<T>, string>;\n if (this.Graph) {\n this.Graph.handlerRegistry = handlerRegistry;\n }\n }\n\n this.returnContent = config.returnContent ?? false;\n }\n\n private createStandardGraph(config: t.StandardGraphConfig): t.CompiledWorkflow<t.IState, Partial<t.IState>, string> {\n const { llmConfig, tools = [], ...graphInput } = config;\n const { provider, ...clientOptions } = llmConfig;\n\n const standardGraph = new StandardGraph({\n tools,\n provider,\n clientOptions,\n ...graphInput,\n runId: this.id,\n });\n this.Graph = standardGraph;\n return standardGraph.createWorkflow();\n }\n\n static async create<T extends t.BaseGraphState>(config: t.RunConfig): Promise<Run<T>> {\n return new Run<T>(config);\n }\n\n getRunMessages(): BaseMessage[] | undefined {\n if (!this.Graph) {\n throw new Error('Graph not initialized. Make sure to use Run.create() to instantiate the Run.');\n }\n return this.Graph.getRunMessages();\n }\n\n async processStream(\n inputs: t.IState,\n config: Partial<RunnableConfig> & { version: 'v1' | 'v2'; run_id?: string },\n streamOptions?: t.EventStreamOptions,\n ): Promise<MessageContentComplex[] | undefined> {\n if (!this.graphRunnable) {\n throw new Error('Run not initialized. Make sure to use Run.create() to instantiate the Run.');\n }\n if (!this.Graph) {\n throw new Error('Graph not initialized. Make sure to use Run.create() to instantiate the Run.');\n }\n\n this.Graph.resetValues(streamOptions?.keepContent);\n const provider = this.Graph.provider;\n const hasTools = this.Graph.tools ? this.Graph.tools.length > 0 : false;\n if (streamOptions?.callbacks) {\n /* TODO: conflicts with callback manager */\n const callbacks = config.callbacks as t.ProvidedCallbacks ?? [];\n config.callbacks = callbacks.concat(this.getCallbacks(streamOptions.callbacks));\n }\n\n if (!this.id) {\n throw new Error('Run ID not provided');\n }\n\n const tokenCounter = streamOptions?.tokenCounter ?? (streamOptions?.indexTokenCountMap ? await createTokenCounter() : undefined);\n const toolTokens = tokenCounter ? (this.Graph.tools?.reduce((acc, tool) => {\n if (!tool.schema) {\n return acc;\n }\n\n const jsonSchema = zodToJsonSchema(tool.schema.describe(tool.description ?? ''), tool.name);\n return acc + tokenCounter(new SystemMessage(JSON.stringify(jsonSchema)));\n }, 0) ?? 0) : 0;\n let instructionTokens = toolTokens;\n if (this.Graph.systemMessage && tokenCounter) {\n instructionTokens += tokenCounter(this.Graph.systemMessage);\n }\n if (instructionTokens > 0) {\n this.Graph.indexTokenCountMap = shiftIndexTokenCountMap(streamOptions?.indexTokenCountMap ?? {}, instructionTokens);\n } else {\n this.Graph.indexTokenCountMap = streamOptions?.indexTokenCountMap ?? {};\n }\n\n this.Graph.maxContextTokens = streamOptions?.maxContextTokens;\n this.Graph.tokenCounter = tokenCounter;\n\n config.run_id = this.id;\n config.configurable = Object.assign(config.configurable ?? {}, { run_id: this.id, provider: this.provider });\n\n const stream = this.graphRunnable.streamEvents(inputs, config);\n\n for await (const event of stream) {\n const { data, name, metadata, ...info } = event;\n\n let eventName: t.EventName = info.event;\n if (hasTools && manualToolStreamProviders.has(provider) && eventName === GraphEvents.CHAT_MODEL_STREAM) {\n /* Skipping CHAT_MODEL_STREAM event due to double-call edge case */\n continue;\n }\n\n if (eventName && eventName === GraphEvents.ON_CUSTOM_EVENT) {\n eventName = name;\n }\n\n const handler = this.handlerRegistry.getHandler(eventName);\n if (handler) {\n handler.handle(eventName, data, metadata, this.Graph);\n }\n }\n\n if (this.returnContent) {\n return this.Graph.getContentParts();\n }\n }\n\n private createSystemCallback<K extends keyof ClientCallbacks>(\n clientCallbacks: ClientCallbacks,\n key: K\n ): SystemCallbacks[K] {\n return ((...args: unknown[]) => {\n const clientCallback = clientCallbacks[key];\n if (clientCallback && this.Graph) {\n (clientCallback as (...args: unknown[]) => void)(this.Graph, ...args);\n }\n }) as SystemCallbacks[K];\n }\n\n getCallbacks(clientCallbacks: ClientCallbacks): SystemCallbacks {\n return {\n [Callback.TOOL_ERROR]: this.createSystemCallback(clientCallbacks, Callback.TOOL_ERROR),\n [Callback.TOOL_START]: this.createSystemCallback(clientCallbacks, Callback.TOOL_START),\n [Callback.TOOL_END]: this.createSystemCallback(clientCallbacks, Callback.TOOL_END),\n };\n }\n\n async generateTitle({\n inputText,\n contentParts,\n titlePrompt,\n clientOptions,\n chainOptions,\n skipLanguage,\n } : {\n inputText: string;\n contentParts: (t.MessageContentComplex | undefined)[];\n titlePrompt?: string;\n skipLanguage?: boolean;\n clientOptions?: t.ClientOptions;\n chainOptions?: Partial<RunnableConfig> | undefined;\n }): Promise<{ language: string; title: string }> {\n const convoTemplate = PromptTemplate.fromTemplate('User: {input}\\nAI: {output}');\n const response = contentParts.map((part) => {\n if (part?.type === 'text') return part.text;\n return '';\n }).join('\\n');\n const convo = (await convoTemplate.invoke({ input: inputText, output: response })).value;\n const model = this.Graph?.getNewModel({\n clientOptions,\n omitOriginalOptions: ['streaming', 'stream', 'thinking', 'maxTokens', 'maxOutputTokens', 'additionalModelRequestFields'],\n });\n if (!model) {\n return { language: '', title: '' };\n }\n if (isOpenAILike(this.provider) && (model instanceof ChatOpenAI || model instanceof AzureChatOpenAI)) {\n model.temperature = (clientOptions as t.OpenAIClientOptions | undefined)?.temperature as number;\n model.topP = (clientOptions as t.OpenAIClientOptions | undefined)?.topP as number;\n model.frequencyPenalty = (clientOptions as t.OpenAIClientOptions | undefined)?.frequencyPenalty as number;\n model.presencePenalty = (clientOptions as t.OpenAIClientOptions | undefined)?.presencePenalty as number;\n model.n = (clientOptions as t.OpenAIClientOptions | undefined)?.n as number;\n }\n const chain = await createTitleRunnable(model, titlePrompt);\n return await chain.invoke({ convo, inputText, skipLanguage }, chainOptions) as { language: string; title: string };\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/esm/stream.mjs
CHANGED
|
@@ -49,7 +49,7 @@ const handleToolCalls = (toolCalls, metadata, graph) => {
|
|
|
49
49
|
prevStepId = graph.getStepIdByKey(stepKey, graph.contentData.length - 1);
|
|
50
50
|
prevRunStep = graph.getRunStep(prevStepId);
|
|
51
51
|
}
|
|
52
|
-
catch
|
|
52
|
+
catch {
|
|
53
53
|
// no previous step
|
|
54
54
|
}
|
|
55
55
|
const dispatchToolCallIds = (lastMessageStepId) => {
|
|
@@ -144,7 +144,6 @@ class ChatModelStreamHandler {
|
|
|
144
144
|
const stepId = graph.getStepIdByKey(stepKey);
|
|
145
145
|
const runStep = graph.getRunStep(stepId);
|
|
146
146
|
if (!runStep) {
|
|
147
|
-
// eslint-disable-next-line no-console
|
|
148
147
|
console.warn(`\n
|
|
149
148
|
==============================================================
|
|
150
149
|
|
|
@@ -196,7 +195,7 @@ hasToolCallChunks: ${hasToolCallChunks}
|
|
|
196
195
|
graph.dispatchReasoningDelta(stepId, {
|
|
197
196
|
content: content.map((c) => ({
|
|
198
197
|
type: ContentTypes.THINK,
|
|
199
|
-
think: c.thinking ?? c.reasoningText
|
|
198
|
+
think: c.thinking ?? c.reasoningText.text ?? '',
|
|
200
199
|
}))
|
|
201
200
|
});
|
|
202
201
|
}
|
|
@@ -208,7 +207,7 @@ hasToolCallChunks: ${hasToolCallChunks}
|
|
|
208
207
|
prevStepId = graph.getStepIdByKey(stepKey, graph.contentData.length - 1);
|
|
209
208
|
prevRunStep = graph.getRunStep(prevStepId);
|
|
210
209
|
}
|
|
211
|
-
catch
|
|
210
|
+
catch {
|
|
212
211
|
/** Edge Case: If no previous step exists, create a new message creation step */
|
|
213
212
|
const message_id = getMessageId(stepKey, graph, true) ?? '';
|
|
214
213
|
prevStepId = graph.dispatchRunStep(stepKey, {
|