@langchain/core 0.2.0-rc.0 → 0.2.1

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 (134) hide show
  1. package/dist/callbacks/base.cjs +9 -1
  2. package/dist/callbacks/base.d.ts +3 -0
  3. package/dist/callbacks/base.js +9 -1
  4. package/dist/callbacks/manager.cjs +51 -0
  5. package/dist/callbacks/manager.js +51 -0
  6. package/dist/callbacks/tests/callbacks.test.d.ts +1 -0
  7. package/dist/callbacks/tests/callbacks.test.js +492 -0
  8. package/dist/callbacks/tests/manager.int.test.d.ts +1 -0
  9. package/dist/callbacks/tests/manager.int.test.js +29 -0
  10. package/dist/callbacks/tests/run_collector.test.d.ts +1 -0
  11. package/dist/callbacks/tests/run_collector.test.js +58 -0
  12. package/dist/chat_history.cjs +13 -0
  13. package/dist/chat_history.d.ts +9 -0
  14. package/dist/chat_history.js +13 -0
  15. package/dist/language_models/base.cjs +3 -0
  16. package/dist/language_models/base.js +3 -0
  17. package/dist/language_models/chat_models.cjs +21 -3
  18. package/dist/language_models/chat_models.d.ts +11 -2
  19. package/dist/language_models/chat_models.js +21 -3
  20. package/dist/language_models/tests/chat_models.test.d.ts +1 -0
  21. package/dist/language_models/tests/chat_models.test.js +154 -0
  22. package/dist/language_models/tests/count_tokens.test.d.ts +1 -0
  23. package/dist/language_models/tests/count_tokens.test.js +19 -0
  24. package/dist/language_models/tests/llms.test.d.ts +1 -0
  25. package/dist/language_models/tests/llms.test.js +39 -0
  26. package/dist/messages/tests/base_message.test.d.ts +1 -0
  27. package/dist/messages/tests/base_message.test.js +97 -0
  28. package/dist/output_parsers/openai_tools/tests/json_output_tools_parser.test.d.ts +1 -0
  29. package/dist/output_parsers/openai_tools/tests/json_output_tools_parser.test.js +81 -0
  30. package/dist/output_parsers/tests/json.test.d.ts +1 -0
  31. package/dist/output_parsers/tests/json.test.js +427 -0
  32. package/dist/output_parsers/tests/output_parser.test.d.ts +1 -0
  33. package/dist/output_parsers/tests/output_parser.test.js +78 -0
  34. package/dist/output_parsers/tests/string.test.d.ts +1 -0
  35. package/dist/output_parsers/tests/string.test.js +68 -0
  36. package/dist/output_parsers/tests/structured.test.d.ts +1 -0
  37. package/dist/output_parsers/tests/structured.test.js +166 -0
  38. package/dist/output_parsers/tests/xml.test.d.ts +1 -0
  39. package/dist/output_parsers/tests/xml.test.js +81 -0
  40. package/dist/prompts/tests/chat.mustache.test.d.ts +1 -0
  41. package/dist/prompts/tests/chat.mustache.test.js +61 -0
  42. package/dist/prompts/tests/chat.test.d.ts +1 -0
  43. package/dist/prompts/tests/chat.test.js +507 -0
  44. package/dist/prompts/tests/few_shot.test.d.ts +1 -0
  45. package/dist/prompts/tests/few_shot.test.js +224 -0
  46. package/dist/prompts/tests/pipeline.test.d.ts +1 -0
  47. package/dist/prompts/tests/pipeline.test.js +101 -0
  48. package/dist/prompts/tests/prompt.mustache.test.d.ts +1 -0
  49. package/dist/prompts/tests/prompt.mustache.test.js +85 -0
  50. package/dist/prompts/tests/prompt.test.d.ts +1 -0
  51. package/dist/prompts/tests/prompt.test.js +78 -0
  52. package/dist/prompts/tests/structured.test.d.ts +1 -0
  53. package/dist/prompts/tests/structured.test.js +37 -0
  54. package/dist/prompts/tests/template.test.d.ts +1 -0
  55. package/dist/prompts/tests/template.test.js +24 -0
  56. package/dist/runnables/base.cjs +174 -19
  57. package/dist/runnables/base.d.ts +47 -28
  58. package/dist/runnables/base.js +174 -19
  59. package/dist/runnables/history.cjs +87 -32
  60. package/dist/runnables/history.d.ts +1 -1
  61. package/dist/runnables/history.js +87 -32
  62. package/dist/runnables/iter.cjs +46 -0
  63. package/dist/runnables/iter.d.ts +5 -0
  64. package/dist/runnables/iter.js +39 -0
  65. package/dist/runnables/passthrough.cjs +1 -0
  66. package/dist/runnables/passthrough.d.ts +1 -1
  67. package/dist/runnables/passthrough.js +1 -0
  68. package/dist/runnables/remote.cjs +60 -48
  69. package/dist/runnables/remote.d.ts +8 -4
  70. package/dist/runnables/remote.js +61 -49
  71. package/dist/runnables/tests/runnable.test.d.ts +1 -0
  72. package/dist/runnables/tests/runnable.test.js +491 -0
  73. package/dist/runnables/tests/runnable_binding.test.d.ts +1 -0
  74. package/dist/runnables/tests/runnable_binding.test.js +46 -0
  75. package/dist/runnables/tests/runnable_branch.test.d.ts +1 -0
  76. package/dist/runnables/tests/runnable_branch.test.js +116 -0
  77. package/dist/runnables/tests/runnable_graph.test.d.ts +1 -0
  78. package/dist/runnables/tests/runnable_graph.test.js +84 -0
  79. package/dist/runnables/tests/runnable_history.test.d.ts +1 -0
  80. package/dist/runnables/tests/runnable_history.test.js +177 -0
  81. package/dist/runnables/tests/runnable_interface.test.d.ts +1 -0
  82. package/dist/runnables/tests/runnable_interface.test.js +209 -0
  83. package/dist/runnables/tests/runnable_map.test.d.ts +1 -0
  84. package/dist/runnables/tests/runnable_map.test.js +238 -0
  85. package/dist/runnables/tests/runnable_passthrough.test.d.ts +1 -0
  86. package/dist/runnables/tests/runnable_passthrough.test.js +96 -0
  87. package/dist/runnables/tests/runnable_remote.int.test.d.ts +1 -0
  88. package/dist/runnables/tests/runnable_remote.int.test.js +138 -0
  89. package/dist/runnables/tests/runnable_remote.test.d.ts +1 -0
  90. package/dist/runnables/tests/runnable_remote.test.js +200 -0
  91. package/dist/runnables/tests/runnable_retry.test.d.ts +1 -0
  92. package/dist/runnables/tests/runnable_retry.test.js +125 -0
  93. package/dist/runnables/tests/runnable_stream_events.test.d.ts +1 -0
  94. package/dist/runnables/tests/runnable_stream_events.test.js +1013 -0
  95. package/dist/runnables/tests/runnable_stream_events_v2.test.d.ts +1 -0
  96. package/dist/runnables/tests/runnable_stream_events_v2.test.js +973 -0
  97. package/dist/runnables/tests/runnable_stream_log.test.d.ts +1 -0
  98. package/dist/runnables/tests/runnable_stream_log.test.js +282 -0
  99. package/dist/runnables/tests/runnable_tracing.int.test.d.ts +1 -0
  100. package/dist/runnables/tests/runnable_tracing.int.test.js +37 -0
  101. package/dist/runnables/tests/runnable_with_fallbacks.test.d.ts +1 -0
  102. package/dist/runnables/tests/runnable_with_fallbacks.test.js +36 -0
  103. package/dist/runnables/utils.d.ts +1 -1
  104. package/dist/singletons/index.cjs +1 -1
  105. package/dist/singletons/index.d.ts +2 -2
  106. package/dist/singletons/index.js +1 -1
  107. package/dist/singletons/tests/async_local_storage.test.d.ts +1 -0
  108. package/dist/singletons/tests/async_local_storage.test.js +120 -0
  109. package/dist/structured_query/tests/utils.test.d.ts +1 -0
  110. package/dist/structured_query/tests/utils.test.js +47 -0
  111. package/dist/tracers/event_stream.cjs +493 -0
  112. package/dist/tracers/event_stream.d.ts +137 -0
  113. package/dist/tracers/event_stream.js +489 -0
  114. package/dist/tracers/log_stream.d.ts +2 -77
  115. package/dist/tracers/tests/langchain_tracer.int.test.d.ts +1 -0
  116. package/dist/tracers/tests/langchain_tracer.int.test.js +74 -0
  117. package/dist/tracers/tests/tracer.test.d.ts +1 -0
  118. package/dist/tracers/tests/tracer.test.js +378 -0
  119. package/dist/utils/stream.cjs +27 -11
  120. package/dist/utils/stream.d.ts +6 -1
  121. package/dist/utils/stream.js +27 -11
  122. package/dist/utils/testing/tests/chatfake.test.d.ts +1 -0
  123. package/dist/utils/testing/tests/chatfake.test.js +112 -0
  124. package/dist/utils/tests/async_caller.test.d.ts +1 -0
  125. package/dist/utils/tests/async_caller.test.js +27 -0
  126. package/dist/utils/tests/enviroment.test.d.ts +1 -0
  127. package/dist/utils/tests/enviroment.test.js +6 -0
  128. package/dist/utils/tests/function_calling.test.d.ts +1 -0
  129. package/dist/utils/tests/function_calling.test.js +107 -0
  130. package/dist/utils/tests/math_utils.test.d.ts +1 -0
  131. package/dist/utils/tests/math_utils.test.js +139 -0
  132. package/dist/utils/tests/polyfill_stream.test.d.ts +1 -0
  133. package/dist/utils/tests/polyfill_stream.test.js +15 -0
  134. package/package.json +7 -7
@@ -1,7 +1,9 @@
1
1
  import { z } from "zod";
2
2
  import pRetry from "p-retry";
3
+ import { v4 as uuidv4 } from "uuid";
3
4
  import { CallbackManager, } from "../callbacks/manager.js";
4
5
  import { LogStreamCallbackHandler, RunLog, RunLogPatch, } from "../tracers/log_stream.js";
6
+ import { EventStreamCallbackHandler, } from "../tracers/event_stream.js";
5
7
  import { Serializable } from "../load/serializable.js";
6
8
  import { IterableReadableStream, concat, atee, pipeGeneratorWithSetup, AsyncGeneratorWithSetup, } from "../utils/stream.js";
7
9
  import { DEFAULT_RECURSION_LIMIT, ensureConfig, getCallbackManagerForConfig, mergeConfigs, patchConfig, } from "./config.js";
@@ -11,6 +13,7 @@ import { _RootEventFilter, isRunnableInterface } from "./utils.js";
11
13
  import { AsyncLocalStorageProviderSingleton } from "../singletons/index.js";
12
14
  import { Graph } from "./graph.js";
13
15
  import { convertToHttpEventStream } from "./wrappers.js";
16
+ import { consumeAsyncIterableInContext, consumeIteratorInContext, isAsyncIterable, isIterator, } from "./iter.js";
14
17
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
18
  export function _coerceToDict(value, defaultKey) {
16
19
  return value &&
@@ -160,7 +163,11 @@ export class Runnable extends Serializable {
160
163
  async stream(input, options) {
161
164
  // Buffer the first streamed chunk to allow for initial errors
162
165
  // to surface immediately.
163
- const wrappedGenerator = new AsyncGeneratorWithSetup(this._streamIterator(input, ensureConfig(options)));
166
+ const config = ensureConfig(options);
167
+ const wrappedGenerator = new AsyncGeneratorWithSetup({
168
+ generator: this._streamIterator(input, config),
169
+ config,
170
+ });
164
171
  await wrappedGenerator.setup;
165
172
  return IterableReadableStream.fromAsyncGenerator(wrappedGenerator);
166
173
  }
@@ -273,11 +280,16 @@ export class Runnable extends Serializable {
273
280
  const pipe = await pipeGeneratorWithSetup(transformer.bind(this), wrapInputForTracing(), async () => callbackManager_?.handleChainStart(this.toJSON(), { input: "" }, config.runId, config.runType, undefined, undefined, config.runName ?? this.getName()), config);
274
281
  delete config.runId;
275
282
  runManager = pipe.setup;
283
+ const isStreamEventsHandler = (handler) => handler.name === "event_stream_tracer";
284
+ const streamEventsHandler = runManager?.handlers.find(isStreamEventsHandler);
285
+ let iterator = pipe.output;
286
+ if (streamEventsHandler !== undefined && runManager !== undefined) {
287
+ iterator = streamEventsHandler.tapOutputIterable(runManager.runId, iterator);
288
+ }
276
289
  const isLogStreamHandler = (handler) => handler.name === "log_stream_tracer";
277
290
  const streamLogHandler = runManager?.handlers.find(isLogStreamHandler);
278
- let iterator = pipe.output;
279
291
  if (streamLogHandler !== undefined && runManager !== undefined) {
280
- iterator = await streamLogHandler.tapOutputIterable(runManager.runId, pipe.output);
292
+ iterator = streamLogHandler.tapOutputIterable(runManager.runId, iterator);
281
293
  }
282
294
  for await (const chunk of iterator) {
283
295
  yield chunk;
@@ -442,19 +454,93 @@ export class Runnable extends Serializable {
442
454
  await runnableStreamConsumePromise;
443
455
  }
444
456
  }
445
- async *streamEvents(input, options, streamOptions) {
457
+ streamEvents(input, options, streamOptions) {
458
+ let stream;
459
+ if (options.version === "v1") {
460
+ stream = this._streamEventsV1(input, options, streamOptions);
461
+ }
462
+ else if (options.version === "v2") {
463
+ stream = this._streamEventsV2(input, options, streamOptions);
464
+ }
465
+ else {
466
+ throw new Error(`Only versions "v1" and "v2" of the schema are currently supported.`);
467
+ }
446
468
  if (options.encoding === "text/event-stream") {
447
- const stream = await this._streamEvents(input, options, streamOptions);
448
- yield* convertToHttpEventStream(stream);
469
+ return convertToHttpEventStream(stream);
449
470
  }
450
471
  else {
451
- yield* this._streamEvents(input, options, streamOptions);
472
+ return IterableReadableStream.fromAsyncGenerator(stream);
452
473
  }
453
474
  }
454
- async *_streamEvents(input, options, streamOptions) {
455
- if (options.version !== "v1") {
456
- throw new Error(`Only version "v1" of the events schema is currently supported.`);
475
+ async *_streamEventsV2(input, options, streamOptions) {
476
+ const eventStreamer = new EventStreamCallbackHandler({
477
+ ...streamOptions,
478
+ autoClose: false,
479
+ });
480
+ const config = ensureConfig(options);
481
+ const runId = config.runId ?? uuidv4();
482
+ config.runId = runId;
483
+ const callbacks = config.callbacks;
484
+ if (callbacks === undefined) {
485
+ config.callbacks = [eventStreamer];
486
+ }
487
+ else if (Array.isArray(callbacks)) {
488
+ config.callbacks = callbacks.concat(eventStreamer);
457
489
  }
490
+ else {
491
+ const copiedCallbacks = callbacks.copy();
492
+ copiedCallbacks.inheritableHandlers.push(eventStreamer);
493
+ // eslint-disable-next-line no-param-reassign
494
+ config.callbacks = copiedCallbacks;
495
+ }
496
+ // Call the runnable in streaming mode,
497
+ // add each chunk to the output stream
498
+ const outerThis = this;
499
+ async function consumeRunnableStream() {
500
+ try {
501
+ const runnableStream = await outerThis.stream(input, config);
502
+ const tappedStream = eventStreamer.tapOutputIterable(runId, runnableStream);
503
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
504
+ for await (const _ of tappedStream) {
505
+ // Just iterate so that the callback handler picks up events
506
+ }
507
+ }
508
+ finally {
509
+ await eventStreamer.writer.close();
510
+ }
511
+ }
512
+ const runnableStreamConsumePromise = consumeRunnableStream();
513
+ let firstEventSent = false;
514
+ let firstEventRunId;
515
+ try {
516
+ for await (const event of eventStreamer) {
517
+ // This is a work-around an issue where the inputs into the
518
+ // chain are not available until the entire input is consumed.
519
+ // As a temporary solution, we'll modify the input to be the input
520
+ // that was passed into the chain.
521
+ if (!firstEventSent) {
522
+ event.data.input = input;
523
+ firstEventSent = true;
524
+ firstEventRunId = event.run_id;
525
+ yield event;
526
+ continue;
527
+ }
528
+ if (event.run_id === firstEventRunId && event.event.endsWith("_end")) {
529
+ // If it's the end event corresponding to the root runnable
530
+ // we dont include the input in the event since it's guaranteed
531
+ // to be included in the first event.
532
+ if (event.data?.input) {
533
+ delete event.data.input;
534
+ }
535
+ }
536
+ yield event;
537
+ }
538
+ }
539
+ finally {
540
+ await runnableStreamConsumePromise;
541
+ }
542
+ }
543
+ async *_streamEventsV1(input, options, streamOptions) {
458
544
  let runLog;
459
545
  let hasEncounteredStartEvent = false;
460
546
  const config = ensureConfig(options);
@@ -731,11 +817,16 @@ export class RunnableBinding extends Runnable {
731
817
  generator, options) {
732
818
  yield* this.bound.transform(generator, await this._mergeConfig(ensureConfig(options), this.kwargs));
733
819
  }
734
- async *streamEvents(input, options, streamOptions) {
735
- yield* this.bound.streamEvents(input, {
736
- ...(await this._mergeConfig(ensureConfig(options), this.kwargs)),
737
- version: options.version,
738
- }, streamOptions);
820
+ streamEvents(input, options, streamOptions) {
821
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
822
+ const outerThis = this;
823
+ const generator = async function* () {
824
+ yield* outerThis.bound.streamEvents(input, {
825
+ ...(await outerThis._mergeConfig(ensureConfig(options), outerThis.kwargs)),
826
+ version: options.version,
827
+ }, streamOptions);
828
+ };
829
+ return IterableReadableStream.fromAsyncGenerator(generator());
739
830
  }
740
831
  static isRunnableBinding(
741
832
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1279,7 +1370,11 @@ export class RunnableMap extends Runnable {
1279
1370
  async function* generator() {
1280
1371
  yield input;
1281
1372
  }
1282
- const wrappedGenerator = new AsyncGeneratorWithSetup(this.transform(generator(), options));
1373
+ const config = ensureConfig(options);
1374
+ const wrappedGenerator = new AsyncGeneratorWithSetup({
1375
+ generator: this.transform(generator(), config),
1376
+ config,
1377
+ });
1283
1378
  await wrappedGenerator.setup;
1284
1379
  return IterableReadableStream.fromAsyncGenerator(wrappedGenerator);
1285
1380
  }
@@ -1333,6 +1428,44 @@ export class RunnableLambda extends Runnable {
1333
1428
  recursionLimit: (childConfig.recursionLimit ?? DEFAULT_RECURSION_LIMIT) - 1,
1334
1429
  });
1335
1430
  }
1431
+ else if (isAsyncIterable(output)) {
1432
+ let finalOutput;
1433
+ for await (const chunk of consumeAsyncIterableInContext(childConfig, output)) {
1434
+ if (finalOutput === undefined) {
1435
+ finalOutput = chunk;
1436
+ }
1437
+ else {
1438
+ // Make a best effort to gather, for any type that supports concat.
1439
+ try {
1440
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1441
+ finalOutput = concat(finalOutput, chunk);
1442
+ }
1443
+ catch (e) {
1444
+ finalOutput = chunk;
1445
+ }
1446
+ }
1447
+ }
1448
+ output = finalOutput;
1449
+ }
1450
+ else if (isIterator(output)) {
1451
+ let finalOutput;
1452
+ for (const chunk of consumeIteratorInContext(childConfig, output)) {
1453
+ if (finalOutput === undefined) {
1454
+ finalOutput = chunk;
1455
+ }
1456
+ else {
1457
+ // Make a best effort to gather, for any type that supports concat.
1458
+ try {
1459
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1460
+ finalOutput = concat(finalOutput, chunk);
1461
+ }
1462
+ catch (e) {
1463
+ finalOutput = chunk;
1464
+ }
1465
+ }
1466
+ }
1467
+ output = finalOutput;
1468
+ }
1336
1469
  resolve(output);
1337
1470
  }
1338
1471
  catch (e) {
@@ -1387,6 +1520,16 @@ export class RunnableLambda extends Runnable {
1387
1520
  yield chunk;
1388
1521
  }
1389
1522
  }
1523
+ else if (isAsyncIterable(output)) {
1524
+ for await (const chunk of consumeAsyncIterableInContext(config, output)) {
1525
+ yield chunk;
1526
+ }
1527
+ }
1528
+ else if (isIterator(output)) {
1529
+ for (const chunk of consumeIteratorInContext(config, output)) {
1530
+ yield chunk;
1531
+ }
1532
+ }
1390
1533
  else {
1391
1534
  yield output;
1392
1535
  }
@@ -1398,7 +1541,11 @@ export class RunnableLambda extends Runnable {
1398
1541
  async function* generator() {
1399
1542
  yield input;
1400
1543
  }
1401
- const wrappedGenerator = new AsyncGeneratorWithSetup(this.transform(generator(), options));
1544
+ const config = ensureConfig(options);
1545
+ const wrappedGenerator = new AsyncGeneratorWithSetup({
1546
+ generator: this.transform(generator(), config),
1547
+ config,
1548
+ });
1402
1549
  await wrappedGenerator.setup;
1403
1550
  return IterableReadableStream.fromAsyncGenerator(wrappedGenerator);
1404
1551
  }
@@ -1598,7 +1745,11 @@ export class RunnableAssign extends Runnable {
1598
1745
  async function* generator() {
1599
1746
  yield input;
1600
1747
  }
1601
- const wrappedGenerator = new AsyncGeneratorWithSetup(this.transform(generator(), options));
1748
+ const config = ensureConfig(options);
1749
+ const wrappedGenerator = new AsyncGeneratorWithSetup({
1750
+ generator: this.transform(generator(), config),
1751
+ config,
1752
+ });
1602
1753
  await wrappedGenerator.setup;
1603
1754
  return IterableReadableStream.fromAsyncGenerator(wrappedGenerator);
1604
1755
  }
@@ -1665,7 +1816,11 @@ export class RunnablePick extends Runnable {
1665
1816
  async function* generator() {
1666
1817
  yield input;
1667
1818
  }
1668
- const wrappedGenerator = new AsyncGeneratorWithSetup(this.transform(generator(), options));
1819
+ const config = ensureConfig(options);
1820
+ const wrappedGenerator = new AsyncGeneratorWithSetup({
1821
+ generator: this.transform(generator(), config),
1822
+ config,
1823
+ });
1669
1824
  await wrappedGenerator.setup;
1670
1825
  return IterableReadableStream.fromAsyncGenerator(wrappedGenerator);
1671
1826
  }
@@ -126,68 +126,123 @@ class RunnableWithMessageHistory extends base_js_1.RunnableBinding {
126
126
  this.outputMessagesKey = fields.outputMessagesKey;
127
127
  this.historyMessagesKey = fields.historyMessagesKey;
128
128
  }
129
- _getInputMessages(inputValue) {
130
- if (typeof inputValue === "string") {
131
- return [new index_js_1.HumanMessage(inputValue)];
129
+ _getInputMessages(
130
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
131
+ inputValue) {
132
+ let parsedInputValue;
133
+ if (typeof inputValue === "object" &&
134
+ !Array.isArray(inputValue) &&
135
+ !(0, index_js_1.isBaseMessage)(inputValue)) {
136
+ let key;
137
+ if (this.inputMessagesKey) {
138
+ key = this.inputMessagesKey;
139
+ }
140
+ else if (Object.keys(inputValue).length === 1) {
141
+ key = Object.keys(inputValue)[0];
142
+ }
143
+ else {
144
+ key = "input";
145
+ }
146
+ if (Array.isArray(inputValue[key]) && Array.isArray(inputValue[key][0])) {
147
+ parsedInputValue = inputValue[key][0];
148
+ }
149
+ else {
150
+ parsedInputValue = inputValue[key];
151
+ }
152
+ }
153
+ else {
154
+ parsedInputValue = inputValue;
155
+ }
156
+ if (typeof parsedInputValue === "string") {
157
+ return [new index_js_1.HumanMessage(parsedInputValue)];
132
158
  }
133
- else if (Array.isArray(inputValue)) {
134
- return inputValue;
159
+ else if (Array.isArray(parsedInputValue)) {
160
+ return parsedInputValue;
161
+ }
162
+ else if ((0, index_js_1.isBaseMessage)(parsedInputValue)) {
163
+ return [parsedInputValue];
135
164
  }
136
165
  else {
137
- return [inputValue];
166
+ throw new Error(`Expected a string, BaseMessage, or array of BaseMessages.\nGot ${JSON.stringify(parsedInputValue, null, 2)}`);
138
167
  }
139
168
  }
140
169
  _getOutputMessages(
141
170
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
142
171
  outputValue) {
143
- let newOutputValue = outputValue;
172
+ let parsedOutputValue;
144
173
  if (!Array.isArray(outputValue) &&
145
174
  !(0, index_js_1.isBaseMessage)(outputValue) &&
146
175
  typeof outputValue !== "string") {
147
- newOutputValue = outputValue[this.outputMessagesKey ?? "output"];
176
+ let key;
177
+ if (this.outputMessagesKey !== undefined) {
178
+ key = this.outputMessagesKey;
179
+ }
180
+ else if (Object.keys(outputValue).length === 1) {
181
+ key = Object.keys(outputValue)[0];
182
+ }
183
+ else {
184
+ key = "output";
185
+ }
186
+ // If you are wrapping a chat model directly
187
+ // The output is actually this weird generations object
188
+ if (outputValue.generations !== undefined) {
189
+ parsedOutputValue = outputValue.generations[0][0].message;
190
+ }
191
+ else {
192
+ parsedOutputValue = outputValue[key];
193
+ }
194
+ }
195
+ else {
196
+ parsedOutputValue = outputValue;
148
197
  }
149
- if (typeof newOutputValue === "string") {
150
- return [new index_js_1.AIMessage(newOutputValue)];
198
+ if (typeof parsedOutputValue === "string") {
199
+ return [new index_js_1.AIMessage(parsedOutputValue)];
151
200
  }
152
- else if (Array.isArray(newOutputValue)) {
153
- return newOutputValue;
201
+ else if (Array.isArray(parsedOutputValue)) {
202
+ return parsedOutputValue;
154
203
  }
155
- else if ((0, index_js_1.isBaseMessage)(newOutputValue)) {
156
- return [newOutputValue];
204
+ else if ((0, index_js_1.isBaseMessage)(parsedOutputValue)) {
205
+ return [parsedOutputValue];
206
+ }
207
+ else {
208
+ throw new Error(`Expected a string, BaseMessage, or array of BaseMessages. Received: ${JSON.stringify(parsedOutputValue, null, 2)}`);
157
209
  }
158
- throw new Error(`Expected a string, BaseMessage, or array of BaseMessages. Received: ${JSON.stringify(newOutputValue, null, 2)}`);
159
210
  }
160
211
  async _enterHistory(
161
212
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
162
213
  input, kwargs) {
163
214
  const history = kwargs?.config?.configurable?.messageHistory;
164
- if (this.historyMessagesKey) {
165
- return history.getMessages();
166
- }
167
- const inputVal = input ||
168
- (this.inputMessagesKey ? input[this.inputMessagesKey] : undefined);
169
- const historyMessages = history ? await history.getMessages() : [];
170
- const returnType = [
171
- ...historyMessages,
172
- ...this._getInputMessages(inputVal),
173
- ];
174
- return returnType;
215
+ const messages = await history.getMessages();
216
+ if (this.historyMessagesKey === undefined) {
217
+ return messages.concat(this._getInputMessages(input));
218
+ }
219
+ return messages;
175
220
  }
176
221
  async _exitHistory(run, config) {
177
222
  const history = config.configurable?.messageHistory;
178
223
  // Get input messages
179
- const { inputs } = run;
180
- const inputValue = inputs[this.inputMessagesKey ?? "input"];
181
- const inputMessages = this._getInputMessages(inputValue);
224
+ let inputs;
225
+ // Chat model inputs are nested arrays
226
+ if (Array.isArray(run.inputs) && Array.isArray(run.inputs[0])) {
227
+ inputs = run.inputs[0];
228
+ }
229
+ else {
230
+ inputs = run.inputs;
231
+ }
232
+ let inputMessages = this._getInputMessages(inputs);
233
+ // If historic messages were prepended to the input messages, remove them to
234
+ // avoid adding duplicate messages to history.
235
+ if (this.historyMessagesKey === undefined) {
236
+ const existingMessages = await history.getMessages();
237
+ inputMessages = inputMessages.slice(existingMessages.length);
238
+ }
182
239
  // Get output messages
183
240
  const outputValue = run.outputs;
184
241
  if (!outputValue) {
185
242
  throw new Error(`Output values from 'Run' undefined. Run: ${JSON.stringify(run, null, 2)}`);
186
243
  }
187
244
  const outputMessages = this._getOutputMessages(outputValue);
188
- for await (const message of [...inputMessages, ...outputMessages]) {
189
- await history.addMessage(message);
190
- }
245
+ await history.addMessages([...inputMessages, ...outputMessages]);
191
246
  }
192
247
  async _mergeConfig(...configs) {
193
248
  const config = await super._mergeConfig(...configs);
@@ -83,7 +83,7 @@ export declare class RunnableWithMessageHistory<RunInput, RunOutput> extends Run
83
83
  historyMessagesKey?: string;
84
84
  getMessageHistory: GetSessionHistoryCallable;
85
85
  constructor(fields: RunnableWithMessageHistoryInputs<RunInput, RunOutput>);
86
- _getInputMessages(inputValue: string | BaseMessage | Array<BaseMessage>): Array<BaseMessage>;
86
+ _getInputMessages(inputValue: string | BaseMessage | Array<BaseMessage> | Record<string, any>): Array<BaseMessage>;
87
87
  _getOutputMessages(outputValue: string | BaseMessage | Array<BaseMessage> | Record<string, any>): Array<BaseMessage>;
88
88
  _enterHistory(input: any, kwargs?: {
89
89
  config?: RunnableConfig;
@@ -123,68 +123,123 @@ export class RunnableWithMessageHistory extends RunnableBinding {
123
123
  this.outputMessagesKey = fields.outputMessagesKey;
124
124
  this.historyMessagesKey = fields.historyMessagesKey;
125
125
  }
126
- _getInputMessages(inputValue) {
127
- if (typeof inputValue === "string") {
128
- return [new HumanMessage(inputValue)];
126
+ _getInputMessages(
127
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
128
+ inputValue) {
129
+ let parsedInputValue;
130
+ if (typeof inputValue === "object" &&
131
+ !Array.isArray(inputValue) &&
132
+ !isBaseMessage(inputValue)) {
133
+ let key;
134
+ if (this.inputMessagesKey) {
135
+ key = this.inputMessagesKey;
136
+ }
137
+ else if (Object.keys(inputValue).length === 1) {
138
+ key = Object.keys(inputValue)[0];
139
+ }
140
+ else {
141
+ key = "input";
142
+ }
143
+ if (Array.isArray(inputValue[key]) && Array.isArray(inputValue[key][0])) {
144
+ parsedInputValue = inputValue[key][0];
145
+ }
146
+ else {
147
+ parsedInputValue = inputValue[key];
148
+ }
149
+ }
150
+ else {
151
+ parsedInputValue = inputValue;
152
+ }
153
+ if (typeof parsedInputValue === "string") {
154
+ return [new HumanMessage(parsedInputValue)];
129
155
  }
130
- else if (Array.isArray(inputValue)) {
131
- return inputValue;
156
+ else if (Array.isArray(parsedInputValue)) {
157
+ return parsedInputValue;
158
+ }
159
+ else if (isBaseMessage(parsedInputValue)) {
160
+ return [parsedInputValue];
132
161
  }
133
162
  else {
134
- return [inputValue];
163
+ throw new Error(`Expected a string, BaseMessage, or array of BaseMessages.\nGot ${JSON.stringify(parsedInputValue, null, 2)}`);
135
164
  }
136
165
  }
137
166
  _getOutputMessages(
138
167
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
139
168
  outputValue) {
140
- let newOutputValue = outputValue;
169
+ let parsedOutputValue;
141
170
  if (!Array.isArray(outputValue) &&
142
171
  !isBaseMessage(outputValue) &&
143
172
  typeof outputValue !== "string") {
144
- newOutputValue = outputValue[this.outputMessagesKey ?? "output"];
173
+ let key;
174
+ if (this.outputMessagesKey !== undefined) {
175
+ key = this.outputMessagesKey;
176
+ }
177
+ else if (Object.keys(outputValue).length === 1) {
178
+ key = Object.keys(outputValue)[0];
179
+ }
180
+ else {
181
+ key = "output";
182
+ }
183
+ // If you are wrapping a chat model directly
184
+ // The output is actually this weird generations object
185
+ if (outputValue.generations !== undefined) {
186
+ parsedOutputValue = outputValue.generations[0][0].message;
187
+ }
188
+ else {
189
+ parsedOutputValue = outputValue[key];
190
+ }
191
+ }
192
+ else {
193
+ parsedOutputValue = outputValue;
145
194
  }
146
- if (typeof newOutputValue === "string") {
147
- return [new AIMessage(newOutputValue)];
195
+ if (typeof parsedOutputValue === "string") {
196
+ return [new AIMessage(parsedOutputValue)];
148
197
  }
149
- else if (Array.isArray(newOutputValue)) {
150
- return newOutputValue;
198
+ else if (Array.isArray(parsedOutputValue)) {
199
+ return parsedOutputValue;
151
200
  }
152
- else if (isBaseMessage(newOutputValue)) {
153
- return [newOutputValue];
201
+ else if (isBaseMessage(parsedOutputValue)) {
202
+ return [parsedOutputValue];
203
+ }
204
+ else {
205
+ throw new Error(`Expected a string, BaseMessage, or array of BaseMessages. Received: ${JSON.stringify(parsedOutputValue, null, 2)}`);
154
206
  }
155
- throw new Error(`Expected a string, BaseMessage, or array of BaseMessages. Received: ${JSON.stringify(newOutputValue, null, 2)}`);
156
207
  }
157
208
  async _enterHistory(
158
209
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
159
210
  input, kwargs) {
160
211
  const history = kwargs?.config?.configurable?.messageHistory;
161
- if (this.historyMessagesKey) {
162
- return history.getMessages();
163
- }
164
- const inputVal = input ||
165
- (this.inputMessagesKey ? input[this.inputMessagesKey] : undefined);
166
- const historyMessages = history ? await history.getMessages() : [];
167
- const returnType = [
168
- ...historyMessages,
169
- ...this._getInputMessages(inputVal),
170
- ];
171
- return returnType;
212
+ const messages = await history.getMessages();
213
+ if (this.historyMessagesKey === undefined) {
214
+ return messages.concat(this._getInputMessages(input));
215
+ }
216
+ return messages;
172
217
  }
173
218
  async _exitHistory(run, config) {
174
219
  const history = config.configurable?.messageHistory;
175
220
  // Get input messages
176
- const { inputs } = run;
177
- const inputValue = inputs[this.inputMessagesKey ?? "input"];
178
- const inputMessages = this._getInputMessages(inputValue);
221
+ let inputs;
222
+ // Chat model inputs are nested arrays
223
+ if (Array.isArray(run.inputs) && Array.isArray(run.inputs[0])) {
224
+ inputs = run.inputs[0];
225
+ }
226
+ else {
227
+ inputs = run.inputs;
228
+ }
229
+ let inputMessages = this._getInputMessages(inputs);
230
+ // If historic messages were prepended to the input messages, remove them to
231
+ // avoid adding duplicate messages to history.
232
+ if (this.historyMessagesKey === undefined) {
233
+ const existingMessages = await history.getMessages();
234
+ inputMessages = inputMessages.slice(existingMessages.length);
235
+ }
179
236
  // Get output messages
180
237
  const outputValue = run.outputs;
181
238
  if (!outputValue) {
182
239
  throw new Error(`Output values from 'Run' undefined. Run: ${JSON.stringify(run, null, 2)}`);
183
240
  }
184
241
  const outputMessages = this._getOutputMessages(outputValue);
185
- for await (const message of [...inputMessages, ...outputMessages]) {
186
- await history.addMessage(message);
187
- }
242
+ await history.addMessages([...inputMessages, ...outputMessages]);
188
243
  }
189
244
  async _mergeConfig(...configs) {
190
245
  const config = await super._mergeConfig(...configs);
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.consumeAsyncIterableInContext = exports.consumeIteratorInContext = exports.isAsyncIterable = exports.isIterator = void 0;
4
+ const index_js_1 = require("../singletons/index.cjs");
5
+ function isIterator(thing) {
6
+ return (typeof thing === "object" &&
7
+ thing !== null &&
8
+ typeof thing[Symbol.iterator] === "function" &&
9
+ // avoid detecting array/set as iterator
10
+ typeof thing.next === "function");
11
+ }
12
+ exports.isIterator = isIterator;
13
+ function isAsyncIterable(thing) {
14
+ return (typeof thing === "object" &&
15
+ thing !== null &&
16
+ typeof thing[Symbol.asyncIterator] ===
17
+ "function");
18
+ }
19
+ exports.isAsyncIterable = isAsyncIterable;
20
+ function* consumeIteratorInContext(context, iter) {
21
+ const storage = index_js_1.AsyncLocalStorageProviderSingleton.getInstance();
22
+ while (true) {
23
+ const { value, done } = storage.run(context, iter.next.bind(iter));
24
+ if (done) {
25
+ break;
26
+ }
27
+ else {
28
+ yield value;
29
+ }
30
+ }
31
+ }
32
+ exports.consumeIteratorInContext = consumeIteratorInContext;
33
+ async function* consumeAsyncIterableInContext(context, iter) {
34
+ const storage = index_js_1.AsyncLocalStorageProviderSingleton.getInstance();
35
+ const iterator = iter[Symbol.asyncIterator]();
36
+ while (true) {
37
+ const { value, done } = await storage.run(context, iterator.next.bind(iter));
38
+ if (done) {
39
+ break;
40
+ }
41
+ else {
42
+ yield value;
43
+ }
44
+ }
45
+ }
46
+ exports.consumeAsyncIterableInContext = consumeAsyncIterableInContext;
@@ -0,0 +1,5 @@
1
+ import { RunnableConfig } from "./config.js";
2
+ export declare function isIterator(thing: unknown): thing is IterableIterator<unknown>;
3
+ export declare function isAsyncIterable(thing: unknown): thing is AsyncIterable<unknown>;
4
+ export declare function consumeIteratorInContext<T>(context: Partial<RunnableConfig> | undefined, iter: IterableIterator<T>): IterableIterator<T>;
5
+ export declare function consumeAsyncIterableInContext<T>(context: Partial<RunnableConfig> | undefined, iter: AsyncIterable<T>): AsyncIterableIterator<T>;