@langchain/core 0.2.7 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/caches.cjs +2 -2
  2. package/dist/caches.d.ts +1 -1
  3. package/dist/caches.js +1 -1
  4. package/dist/callbacks/base.d.ts +1 -1
  5. package/dist/callbacks/manager.cjs +2 -2
  6. package/dist/callbacks/manager.d.ts +1 -1
  7. package/dist/callbacks/manager.js +1 -1
  8. package/dist/language_models/base.cjs +23 -3
  9. package/dist/language_models/base.d.ts +7 -1
  10. package/dist/language_models/base.js +20 -1
  11. package/dist/language_models/chat_models.cjs +81 -0
  12. package/dist/language_models/chat_models.d.ts +10 -4
  13. package/dist/language_models/chat_models.js +81 -0
  14. package/dist/messages/ai.cjs +2 -1
  15. package/dist/messages/ai.js +2 -1
  16. package/dist/messages/base.cjs +11 -0
  17. package/dist/messages/base.d.ts +11 -0
  18. package/dist/messages/base.js +11 -0
  19. package/dist/messages/chat.cjs +1 -0
  20. package/dist/messages/chat.js +1 -0
  21. package/dist/messages/function.cjs +1 -0
  22. package/dist/messages/function.js +1 -0
  23. package/dist/messages/human.cjs +1 -0
  24. package/dist/messages/human.js +1 -0
  25. package/dist/messages/index.cjs +1 -0
  26. package/dist/messages/index.d.ts +1 -0
  27. package/dist/messages/index.js +1 -0
  28. package/dist/messages/system.cjs +1 -0
  29. package/dist/messages/system.js +1 -0
  30. package/dist/messages/tests/base_message.test.js +16 -0
  31. package/dist/messages/tests/message_utils.test.d.ts +1 -0
  32. package/dist/messages/tests/message_utils.test.js +382 -0
  33. package/dist/messages/tool.cjs +1 -0
  34. package/dist/messages/tool.js +1 -0
  35. package/dist/messages/transformers.cjs +421 -0
  36. package/dist/messages/transformers.d.ts +465 -0
  37. package/dist/messages/transformers.js +414 -0
  38. package/dist/messages/utils.cjs +17 -4
  39. package/dist/messages/utils.d.ts +3 -3
  40. package/dist/messages/utils.js +17 -4
  41. package/dist/outputs.d.ts +1 -1
  42. package/dist/prompt_values.cjs +5 -4
  43. package/dist/prompt_values.d.ts +2 -1
  44. package/dist/prompt_values.js +2 -1
  45. package/dist/prompts/template.cjs +1 -1
  46. package/dist/prompts/template.js +1 -1
  47. package/dist/tracers/base.d.ts +1 -1
  48. package/dist/tracers/log_stream.cjs +2 -2
  49. package/dist/tracers/log_stream.js +1 -1
  50. package/dist/tracers/tracer_langchain_v1.cjs +2 -2
  51. package/dist/tracers/tracer_langchain_v1.js +1 -1
  52. package/package.json +1 -1
@@ -0,0 +1,421 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultTextSplitter = exports.trimMessages = exports.mergeMessageRuns = exports.filterMessages = void 0;
4
+ const base_js_1 = require("../runnables/base.cjs");
5
+ const ai_js_1 = require("./ai.cjs");
6
+ const chat_js_1 = require("./chat.cjs");
7
+ const function_js_1 = require("./function.cjs");
8
+ const human_js_1 = require("./human.cjs");
9
+ const system_js_1 = require("./system.cjs");
10
+ const tool_js_1 = require("./tool.cjs");
11
+ const utils_js_1 = require("./utils.cjs");
12
+ const _isMessageType = (msg, types) => {
13
+ const typesAsStrings = [
14
+ ...new Set(types?.map((t) => {
15
+ if (typeof t === "string") {
16
+ return t;
17
+ }
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ const instantiatedMsgClass = new t({});
20
+ if (!("_getType" in instantiatedMsgClass) ||
21
+ typeof instantiatedMsgClass._getType !== "function") {
22
+ throw new Error("Invalid type provided.");
23
+ }
24
+ return instantiatedMsgClass._getType();
25
+ })),
26
+ ];
27
+ const msgType = msg._getType();
28
+ return typesAsStrings.some((t) => t === msgType);
29
+ };
30
+ function filterMessages(messagesOrOptions, options) {
31
+ if (Array.isArray(messagesOrOptions)) {
32
+ return _filterMessages(messagesOrOptions, options);
33
+ }
34
+ return base_js_1.RunnableLambda.from((input) => {
35
+ return _filterMessages(input, messagesOrOptions);
36
+ });
37
+ }
38
+ exports.filterMessages = filterMessages;
39
+ function _filterMessages(messages, options = {}) {
40
+ const { includeNames, excludeNames, includeTypes, excludeTypes, includeIds, excludeIds, } = options;
41
+ const filtered = [];
42
+ for (const msg of messages) {
43
+ if (excludeNames && msg.name && excludeNames.includes(msg.name)) {
44
+ continue;
45
+ }
46
+ else if (excludeTypes && _isMessageType(msg, excludeTypes)) {
47
+ continue;
48
+ }
49
+ else if (excludeIds && msg.id && excludeIds.includes(msg.id)) {
50
+ continue;
51
+ }
52
+ // default to inclusion when no inclusion criteria given.
53
+ if (!(includeTypes || includeIds || includeNames)) {
54
+ filtered.push(msg);
55
+ }
56
+ else if (includeNames &&
57
+ msg.name &&
58
+ includeNames.some((iName) => iName === msg.name)) {
59
+ filtered.push(msg);
60
+ }
61
+ else if (includeTypes && _isMessageType(msg, includeTypes)) {
62
+ filtered.push(msg);
63
+ }
64
+ else if (includeIds && msg.id && includeIds.some((id) => id === msg.id)) {
65
+ filtered.push(msg);
66
+ }
67
+ }
68
+ return filtered;
69
+ }
70
+ function mergeMessageRuns(messages) {
71
+ if (Array.isArray(messages)) {
72
+ return _mergeMessageRuns(messages);
73
+ }
74
+ return base_js_1.RunnableLambda.from(_mergeMessageRuns);
75
+ }
76
+ exports.mergeMessageRuns = mergeMessageRuns;
77
+ function _mergeMessageRuns(messages) {
78
+ if (!messages.length) {
79
+ return [];
80
+ }
81
+ const merged = [];
82
+ for (const msg of messages) {
83
+ const curr = msg; // Create a shallow copy of the message
84
+ const last = merged.pop();
85
+ if (!last) {
86
+ merged.push(curr);
87
+ }
88
+ else if (curr._getType() === "tool" ||
89
+ !(curr._getType() === last._getType())) {
90
+ merged.push(last, curr);
91
+ }
92
+ else {
93
+ const lastChunk = (0, utils_js_1.convertToChunk)(last);
94
+ const currChunk = (0, utils_js_1.convertToChunk)(curr);
95
+ const mergedChunks = lastChunk.concat(currChunk);
96
+ if (typeof lastChunk.content === "string" &&
97
+ typeof currChunk.content === "string") {
98
+ mergedChunks.content = `${lastChunk.content}\n${currChunk.content}`;
99
+ }
100
+ merged.push(_chunkToMsg(mergedChunks));
101
+ }
102
+ }
103
+ return merged;
104
+ }
105
+ function trimMessages(messagesOrOptions, options) {
106
+ if (Array.isArray(messagesOrOptions)) {
107
+ const messages = messagesOrOptions;
108
+ if (!options) {
109
+ throw new Error("Options parameter is required when providing messages.");
110
+ }
111
+ return _trimMessagesHelper(messages, options);
112
+ }
113
+ else {
114
+ const trimmerOptions = messagesOrOptions;
115
+ return base_js_1.RunnableLambda.from((input) => _trimMessagesHelper(input, trimmerOptions));
116
+ }
117
+ }
118
+ exports.trimMessages = trimMessages;
119
+ async function _trimMessagesHelper(messages, options) {
120
+ const { maxTokens, tokenCounter, strategy = "last", allowPartial = false, endOn, startOn, includeSystem = false, textSplitter, } = options;
121
+ if (startOn && strategy === "first") {
122
+ throw new Error("`startOn` should only be specified if `strategy` is 'last'.");
123
+ }
124
+ if (includeSystem && strategy === "first") {
125
+ throw new Error("`includeSystem` should only be specified if `strategy` is 'last'.");
126
+ }
127
+ let listTokenCounter;
128
+ if ("getNumTokens" in tokenCounter) {
129
+ listTokenCounter = async (msgs) => {
130
+ const tokenCounts = await Promise.all(msgs.map((msg) => tokenCounter.getNumTokens(msg.content)));
131
+ return tokenCounts.reduce((sum, count) => sum + count, 0);
132
+ };
133
+ }
134
+ else {
135
+ listTokenCounter = async (msgs) => tokenCounter(msgs);
136
+ }
137
+ let textSplitterFunc = defaultTextSplitter;
138
+ if (textSplitter) {
139
+ if ("splitText" in textSplitter) {
140
+ textSplitterFunc = textSplitter.splitText;
141
+ }
142
+ else {
143
+ textSplitterFunc = async (text) => textSplitter(text);
144
+ }
145
+ }
146
+ if (strategy === "first") {
147
+ return _firstMaxTokens(messages, {
148
+ maxTokens,
149
+ tokenCounter: listTokenCounter,
150
+ textSplitter: textSplitterFunc,
151
+ partialStrategy: allowPartial ? "first" : undefined,
152
+ endOn,
153
+ });
154
+ }
155
+ else if (strategy === "last") {
156
+ return _lastMaxTokens(messages, {
157
+ maxTokens,
158
+ tokenCounter: listTokenCounter,
159
+ textSplitter: textSplitterFunc,
160
+ allowPartial,
161
+ includeSystem,
162
+ startOn,
163
+ endOn,
164
+ });
165
+ }
166
+ else {
167
+ throw new Error(`Unrecognized strategy: '${strategy}'. Must be one of 'first' or 'last'.`);
168
+ }
169
+ }
170
+ async function _firstMaxTokens(messages, options) {
171
+ const { maxTokens, tokenCounter, textSplitter, partialStrategy, endOn } = options;
172
+ let messagesCopy = [...messages];
173
+ let idx = 0;
174
+ for (let i = 0; i < messagesCopy.length; i += 1) {
175
+ const remainingMessages = i > 0 ? messagesCopy.slice(0, -i) : messagesCopy;
176
+ if ((await tokenCounter(remainingMessages)) <= maxTokens) {
177
+ idx = messagesCopy.length - i;
178
+ break;
179
+ }
180
+ }
181
+ if (idx < messagesCopy.length - 1 && partialStrategy) {
182
+ let includedPartial = false;
183
+ if (Array.isArray(messagesCopy[idx].content)) {
184
+ const excluded = messagesCopy[idx];
185
+ if (typeof excluded.content === "string") {
186
+ throw new Error("Expected content to be an array.");
187
+ }
188
+ const numBlock = excluded.content.length;
189
+ const reversedContent = partialStrategy === "last"
190
+ ? [...excluded.content].reverse()
191
+ : excluded.content;
192
+ for (let i = 1; i <= numBlock; i += 1) {
193
+ const partialContent = partialStrategy === "first"
194
+ ? reversedContent.slice(0, i)
195
+ : reversedContent.slice(-i);
196
+ const fields = Object.fromEntries(Object.entries(excluded).filter(([k]) => k !== "type" && !k.startsWith("lc_")));
197
+ const updatedMessage = _switchTypeToMessage(excluded._getType(), {
198
+ ...fields,
199
+ content: partialContent,
200
+ });
201
+ const slicedMessages = [...messagesCopy.slice(0, idx), updatedMessage];
202
+ if ((await tokenCounter(slicedMessages)) <= maxTokens) {
203
+ messagesCopy = slicedMessages;
204
+ idx += 1;
205
+ includedPartial = true;
206
+ }
207
+ else {
208
+ break;
209
+ }
210
+ }
211
+ if (includedPartial && partialStrategy === "last") {
212
+ excluded.content = [...reversedContent].reverse();
213
+ }
214
+ }
215
+ if (!includedPartial) {
216
+ const excluded = messagesCopy[idx];
217
+ let text;
218
+ if (Array.isArray(excluded.content) &&
219
+ excluded.content.some((block) => typeof block === "string" || block.type === "text")) {
220
+ const textBlock = excluded.content.find((block) => block.type === "text" && block.text);
221
+ text = textBlock?.text;
222
+ }
223
+ else if (typeof excluded.content === "string") {
224
+ text = excluded.content;
225
+ }
226
+ if (text) {
227
+ const splitTexts = await textSplitter(text);
228
+ const numSplits = splitTexts.length;
229
+ if (partialStrategy === "last") {
230
+ splitTexts.reverse();
231
+ }
232
+ for (let _ = 0; _ < numSplits - 1; _ += 1) {
233
+ splitTexts.pop();
234
+ excluded.content = splitTexts.join("");
235
+ if ((await tokenCounter([...messagesCopy.slice(0, idx), excluded])) <=
236
+ maxTokens) {
237
+ if (partialStrategy === "last") {
238
+ excluded.content = [...splitTexts].reverse().join("");
239
+ }
240
+ messagesCopy = [...messagesCopy.slice(0, idx), excluded];
241
+ idx += 1;
242
+ break;
243
+ }
244
+ }
245
+ }
246
+ }
247
+ }
248
+ if (endOn) {
249
+ const endOnArr = Array.isArray(endOn) ? endOn : [endOn];
250
+ while (idx > 0 && !_isMessageType(messagesCopy[idx - 1], endOnArr)) {
251
+ idx -= 1;
252
+ }
253
+ }
254
+ return messagesCopy.slice(0, idx);
255
+ }
256
+ async function _lastMaxTokens(messages, options) {
257
+ const { allowPartial = false, includeSystem = false, endOn, startOn, ...rest } = options;
258
+ if (endOn) {
259
+ const endOnArr = Array.isArray(endOn) ? endOn : [endOn];
260
+ while (messages &&
261
+ !_isMessageType(messages[messages.length - 1], endOnArr)) {
262
+ messages.pop();
263
+ }
264
+ }
265
+ const swappedSystem = includeSystem && messages[0]._getType() === "system";
266
+ let reversed_ = swappedSystem
267
+ ? messages.slice(0, 1).concat(messages.slice(1).reverse())
268
+ : messages.reverse();
269
+ reversed_ = await _firstMaxTokens(reversed_, {
270
+ ...rest,
271
+ partialStrategy: allowPartial ? "last" : undefined,
272
+ endOn: startOn,
273
+ });
274
+ if (swappedSystem) {
275
+ return [reversed_[0], ...reversed_.slice(1).reverse()];
276
+ }
277
+ else {
278
+ return reversed_.reverse();
279
+ }
280
+ }
281
+ const _MSG_CHUNK_MAP = {
282
+ human: {
283
+ message: human_js_1.HumanMessage,
284
+ messageChunk: human_js_1.HumanMessageChunk,
285
+ },
286
+ ai: {
287
+ message: ai_js_1.AIMessage,
288
+ messageChunk: ai_js_1.AIMessageChunk,
289
+ },
290
+ system: {
291
+ message: system_js_1.SystemMessage,
292
+ messageChunk: system_js_1.SystemMessageChunk,
293
+ },
294
+ tool: {
295
+ message: tool_js_1.ToolMessage,
296
+ messageChunk: tool_js_1.ToolMessageChunk,
297
+ },
298
+ function: {
299
+ message: function_js_1.FunctionMessage,
300
+ messageChunk: function_js_1.FunctionMessageChunk,
301
+ },
302
+ generic: {
303
+ message: chat_js_1.ChatMessage,
304
+ messageChunk: chat_js_1.ChatMessageChunk,
305
+ },
306
+ };
307
+ function _switchTypeToMessage(messageType, fields, returnChunk) {
308
+ let chunk;
309
+ let msg;
310
+ switch (messageType) {
311
+ case "human":
312
+ if (returnChunk) {
313
+ chunk = new human_js_1.HumanMessageChunk(fields);
314
+ }
315
+ else {
316
+ msg = new human_js_1.HumanMessage(fields);
317
+ }
318
+ break;
319
+ case "ai":
320
+ if (returnChunk) {
321
+ let aiChunkFields = {
322
+ ...fields,
323
+ };
324
+ if ("tool_calls" in aiChunkFields) {
325
+ aiChunkFields = {
326
+ ...aiChunkFields,
327
+ tool_call_chunks: aiChunkFields.tool_calls?.map((tc) => ({
328
+ ...tc,
329
+ index: undefined,
330
+ args: JSON.stringify(tc.args),
331
+ })),
332
+ };
333
+ }
334
+ chunk = new ai_js_1.AIMessageChunk(aiChunkFields);
335
+ }
336
+ else {
337
+ msg = new ai_js_1.AIMessage(fields);
338
+ }
339
+ break;
340
+ case "system":
341
+ if (returnChunk) {
342
+ chunk = new system_js_1.SystemMessageChunk(fields);
343
+ }
344
+ else {
345
+ msg = new system_js_1.SystemMessage(fields);
346
+ }
347
+ break;
348
+ case "tool":
349
+ if ("tool_call_id" in fields) {
350
+ if (returnChunk) {
351
+ chunk = new tool_js_1.ToolMessageChunk(fields);
352
+ }
353
+ else {
354
+ msg = new tool_js_1.ToolMessage(fields);
355
+ }
356
+ }
357
+ else {
358
+ throw new Error("Can not convert ToolMessage to ToolMessageChunk if 'tool_call_id' field is not defined.");
359
+ }
360
+ break;
361
+ case "function":
362
+ if (returnChunk) {
363
+ chunk = new function_js_1.FunctionMessageChunk(fields);
364
+ }
365
+ else {
366
+ if (!fields.name) {
367
+ throw new Error("FunctionMessage must have a 'name' field");
368
+ }
369
+ msg = new function_js_1.FunctionMessage(fields);
370
+ }
371
+ break;
372
+ case "generic":
373
+ if ("role" in fields) {
374
+ if (returnChunk) {
375
+ chunk = new chat_js_1.ChatMessageChunk(fields);
376
+ }
377
+ else {
378
+ msg = new chat_js_1.ChatMessage(fields);
379
+ }
380
+ }
381
+ else {
382
+ throw new Error("Can not convert ChatMessage to ChatMessageChunk if 'role' field is not defined.");
383
+ }
384
+ break;
385
+ default:
386
+ throw new Error(`Unrecognized message type ${messageType}`);
387
+ }
388
+ if (returnChunk && chunk) {
389
+ return chunk;
390
+ }
391
+ if (msg) {
392
+ return msg;
393
+ }
394
+ throw new Error(`Unrecognized message type ${messageType}`);
395
+ }
396
+ function _chunkToMsg(chunk) {
397
+ const chunkType = chunk._getType();
398
+ let msg;
399
+ const fields = Object.fromEntries(Object.entries(chunk).filter(([k]) => !["type", "tool_call_chunks"].includes(k) && !k.startsWith("lc_")));
400
+ if (chunkType in _MSG_CHUNK_MAP) {
401
+ msg = _switchTypeToMessage(chunkType, fields);
402
+ }
403
+ if (!msg) {
404
+ throw new Error(`Unrecognized message chunk class ${chunkType}. Supported classes are ${Object.keys(_MSG_CHUNK_MAP)}`);
405
+ }
406
+ return msg;
407
+ }
408
+ /**
409
+ * The default text splitter function that splits text by newlines.
410
+ *
411
+ * @param {string} text
412
+ * @returns A promise that resolves to an array of strings split by newlines.
413
+ */
414
+ function defaultTextSplitter(text) {
415
+ const splits = text.split("\n");
416
+ return Promise.resolve([
417
+ ...splits.slice(0, -1).map((s) => `${s}\n`),
418
+ splits[splits.length - 1],
419
+ ]);
420
+ }
421
+ exports.defaultTextSplitter = defaultTextSplitter;