@langchain/core 0.2.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 (113) hide show
  1. package/dist/callbacks/tests/callbacks.test.d.ts +1 -0
  2. package/dist/callbacks/tests/callbacks.test.js +492 -0
  3. package/dist/callbacks/tests/manager.int.test.d.ts +1 -0
  4. package/dist/callbacks/tests/manager.int.test.js +29 -0
  5. package/dist/callbacks/tests/run_collector.test.d.ts +1 -0
  6. package/dist/callbacks/tests/run_collector.test.js +58 -0
  7. package/dist/chat_history.cjs +13 -0
  8. package/dist/chat_history.d.ts +9 -0
  9. package/dist/chat_history.js +13 -0
  10. package/dist/language_models/chat_models.d.ts +2 -2
  11. package/dist/language_models/tests/chat_models.test.d.ts +1 -0
  12. package/dist/language_models/tests/chat_models.test.js +154 -0
  13. package/dist/language_models/tests/count_tokens.test.d.ts +1 -0
  14. package/dist/language_models/tests/count_tokens.test.js +19 -0
  15. package/dist/language_models/tests/llms.test.d.ts +1 -0
  16. package/dist/language_models/tests/llms.test.js +39 -0
  17. package/dist/messages/tests/base_message.test.d.ts +1 -0
  18. package/dist/messages/tests/base_message.test.js +97 -0
  19. package/dist/output_parsers/openai_tools/tests/json_output_tools_parser.test.d.ts +1 -0
  20. package/dist/output_parsers/openai_tools/tests/json_output_tools_parser.test.js +81 -0
  21. package/dist/output_parsers/tests/json.test.d.ts +1 -0
  22. package/dist/output_parsers/tests/json.test.js +427 -0
  23. package/dist/output_parsers/tests/output_parser.test.d.ts +1 -0
  24. package/dist/output_parsers/tests/output_parser.test.js +78 -0
  25. package/dist/output_parsers/tests/string.test.d.ts +1 -0
  26. package/dist/output_parsers/tests/string.test.js +68 -0
  27. package/dist/output_parsers/tests/structured.test.d.ts +1 -0
  28. package/dist/output_parsers/tests/structured.test.js +166 -0
  29. package/dist/output_parsers/tests/xml.test.d.ts +1 -0
  30. package/dist/output_parsers/tests/xml.test.js +81 -0
  31. package/dist/prompts/tests/chat.mustache.test.d.ts +1 -0
  32. package/dist/prompts/tests/chat.mustache.test.js +61 -0
  33. package/dist/prompts/tests/chat.test.d.ts +1 -0
  34. package/dist/prompts/tests/chat.test.js +507 -0
  35. package/dist/prompts/tests/few_shot.test.d.ts +1 -0
  36. package/dist/prompts/tests/few_shot.test.js +224 -0
  37. package/dist/prompts/tests/pipeline.test.d.ts +1 -0
  38. package/dist/prompts/tests/pipeline.test.js +101 -0
  39. package/dist/prompts/tests/prompt.mustache.test.d.ts +1 -0
  40. package/dist/prompts/tests/prompt.mustache.test.js +85 -0
  41. package/dist/prompts/tests/prompt.test.d.ts +1 -0
  42. package/dist/prompts/tests/prompt.test.js +78 -0
  43. package/dist/prompts/tests/structured.test.d.ts +1 -0
  44. package/dist/prompts/tests/structured.test.js +37 -0
  45. package/dist/prompts/tests/template.test.d.ts +1 -0
  46. package/dist/prompts/tests/template.test.js +24 -0
  47. package/dist/runnables/base.cjs +87 -6
  48. package/dist/runnables/base.d.ts +45 -26
  49. package/dist/runnables/base.js +87 -6
  50. package/dist/runnables/history.cjs +87 -32
  51. package/dist/runnables/history.d.ts +1 -1
  52. package/dist/runnables/history.js +87 -32
  53. package/dist/runnables/remote.cjs +2 -2
  54. package/dist/runnables/remote.d.ts +3 -3
  55. package/dist/runnables/remote.js +2 -2
  56. package/dist/runnables/tests/runnable.test.d.ts +1 -0
  57. package/dist/runnables/tests/runnable.test.js +491 -0
  58. package/dist/runnables/tests/runnable_binding.test.d.ts +1 -0
  59. package/dist/runnables/tests/runnable_binding.test.js +46 -0
  60. package/dist/runnables/tests/runnable_branch.test.d.ts +1 -0
  61. package/dist/runnables/tests/runnable_branch.test.js +116 -0
  62. package/dist/runnables/tests/runnable_graph.test.d.ts +1 -0
  63. package/dist/runnables/tests/runnable_graph.test.js +84 -0
  64. package/dist/runnables/tests/runnable_history.test.d.ts +1 -0
  65. package/dist/runnables/tests/runnable_history.test.js +177 -0
  66. package/dist/runnables/tests/runnable_interface.test.d.ts +1 -0
  67. package/dist/runnables/tests/runnable_interface.test.js +209 -0
  68. package/dist/runnables/tests/runnable_map.test.d.ts +1 -0
  69. package/dist/runnables/tests/runnable_map.test.js +238 -0
  70. package/dist/runnables/tests/runnable_passthrough.test.d.ts +1 -0
  71. package/dist/runnables/tests/runnable_passthrough.test.js +96 -0
  72. package/dist/runnables/tests/runnable_remote.int.test.d.ts +1 -0
  73. package/dist/runnables/tests/runnable_remote.int.test.js +138 -0
  74. package/dist/runnables/tests/runnable_remote.test.d.ts +1 -0
  75. package/dist/runnables/tests/runnable_remote.test.js +200 -0
  76. package/dist/runnables/tests/runnable_retry.test.d.ts +1 -0
  77. package/dist/runnables/tests/runnable_retry.test.js +125 -0
  78. package/dist/runnables/tests/runnable_stream_events.test.d.ts +1 -0
  79. package/dist/runnables/tests/runnable_stream_events.test.js +1013 -0
  80. package/dist/runnables/tests/runnable_stream_events_v2.test.d.ts +1 -0
  81. package/dist/runnables/tests/runnable_stream_events_v2.test.js +973 -0
  82. package/dist/runnables/tests/runnable_stream_log.test.d.ts +1 -0
  83. package/dist/runnables/tests/runnable_stream_log.test.js +282 -0
  84. package/dist/runnables/tests/runnable_tracing.int.test.d.ts +1 -0
  85. package/dist/runnables/tests/runnable_tracing.int.test.js +37 -0
  86. package/dist/runnables/tests/runnable_with_fallbacks.test.d.ts +1 -0
  87. package/dist/runnables/tests/runnable_with_fallbacks.test.js +36 -0
  88. package/dist/runnables/utils.d.ts +1 -1
  89. package/dist/singletons/tests/async_local_storage.test.d.ts +1 -0
  90. package/dist/singletons/tests/async_local_storage.test.js +120 -0
  91. package/dist/structured_query/tests/utils.test.d.ts +1 -0
  92. package/dist/structured_query/tests/utils.test.js +47 -0
  93. package/dist/tracers/event_stream.cjs +493 -0
  94. package/dist/tracers/event_stream.d.ts +137 -0
  95. package/dist/tracers/event_stream.js +489 -0
  96. package/dist/tracers/log_stream.d.ts +2 -77
  97. package/dist/tracers/tests/langchain_tracer.int.test.d.ts +1 -0
  98. package/dist/tracers/tests/langchain_tracer.int.test.js +74 -0
  99. package/dist/tracers/tests/tracer.test.d.ts +1 -0
  100. package/dist/tracers/tests/tracer.test.js +378 -0
  101. package/dist/utils/testing/tests/chatfake.test.d.ts +1 -0
  102. package/dist/utils/testing/tests/chatfake.test.js +112 -0
  103. package/dist/utils/tests/async_caller.test.d.ts +1 -0
  104. package/dist/utils/tests/async_caller.test.js +27 -0
  105. package/dist/utils/tests/enviroment.test.d.ts +1 -0
  106. package/dist/utils/tests/enviroment.test.js +6 -0
  107. package/dist/utils/tests/function_calling.test.d.ts +1 -0
  108. package/dist/utils/tests/function_calling.test.js +107 -0
  109. package/dist/utils/tests/math_utils.test.d.ts +1 -0
  110. package/dist/utils/tests/math_utils.test.js +139 -0
  111. package/dist/utils/tests/polyfill_stream.test.d.ts +1 -0
  112. package/dist/utils/tests/polyfill_stream.test.js +15 -0
  113. package/package.json +6 -6
@@ -0,0 +1,973 @@
1
+ /* eslint-disable no-promise-executor-return */
2
+ /* eslint-disable no-process-env */
3
+ /* eslint-disable @typescript-eslint/no-explicit-any */
4
+ import { test } from "@jest/globals";
5
+ import { z } from "zod";
6
+ import { RunnableLambda, RunnableMap, RunnablePassthrough, RunnablePick, } from "../index.js";
7
+ import { ChatPromptTemplate } from "../../prompts/chat.js";
8
+ import { FakeListChatModel, FakeRetriever, FakeStreamingLLM, } from "../../utils/testing/index.js";
9
+ import { AIMessageChunk, HumanMessage, SystemMessage, } from "../../messages/index.js";
10
+ import { DynamicStructuredTool, DynamicTool } from "../../tools.js";
11
+ import { Document } from "../../documents/document.js";
12
+ function reverse(s) {
13
+ // Reverse a string.
14
+ return s.split("").reverse().join("");
15
+ }
16
+ const originalCallbackValue = process.env.LANGCHAIN_CALLBACKS_BACKGROUND;
17
+ afterEach(() => {
18
+ process.env.LANGCHAIN_CALLBACKS_BACKGROUND = originalCallbackValue;
19
+ });
20
+ test("Runnable streamEvents method", async () => {
21
+ const chain = RunnableLambda.from(reverse).withConfig({
22
+ runName: "reverse",
23
+ });
24
+ const events = [];
25
+ const eventStream = await chain.streamEvents("hello", { version: "v2" });
26
+ for await (const event of eventStream) {
27
+ events.push(event);
28
+ }
29
+ expect(events).toEqual([
30
+ {
31
+ data: { input: "hello" },
32
+ event: "on_chain_start",
33
+ metadata: {},
34
+ name: "reverse",
35
+ run_id: expect.any(String),
36
+ tags: [],
37
+ },
38
+ {
39
+ data: { chunk: "olleh" },
40
+ event: "on_chain_stream",
41
+ metadata: {},
42
+ name: "reverse",
43
+ run_id: expect.any(String),
44
+ tags: [],
45
+ },
46
+ {
47
+ data: { output: "olleh" },
48
+ event: "on_chain_end",
49
+ metadata: {},
50
+ name: "reverse",
51
+ run_id: expect.any(String),
52
+ tags: [],
53
+ },
54
+ ]);
55
+ });
56
+ test("Runnable streamEvents method with three runnables", async () => {
57
+ const r = RunnableLambda.from(reverse);
58
+ const chain = r
59
+ .withConfig({ runName: "1" })
60
+ .pipe(r.withConfig({ runName: "2" }))
61
+ .pipe(r.withConfig({ runName: "3" }));
62
+ const events = [];
63
+ const eventStream = await chain.streamEvents("hello", { version: "v2" });
64
+ for await (const event of eventStream) {
65
+ events.push(event);
66
+ }
67
+ expect(events).toEqual([
68
+ {
69
+ data: { input: "hello" },
70
+ event: "on_chain_start",
71
+ metadata: {},
72
+ name: "RunnableSequence",
73
+ run_id: expect.any(String),
74
+ tags: [],
75
+ },
76
+ {
77
+ data: {},
78
+ event: "on_chain_start",
79
+ metadata: {},
80
+ name: "1",
81
+ run_id: expect.any(String),
82
+ tags: ["seq:step:1"],
83
+ },
84
+ {
85
+ data: { chunk: "olleh" },
86
+ event: "on_chain_stream",
87
+ metadata: {},
88
+ name: "1",
89
+ run_id: expect.any(String),
90
+ tags: ["seq:step:1"],
91
+ },
92
+ {
93
+ data: {},
94
+ event: "on_chain_start",
95
+ metadata: {},
96
+ name: "2",
97
+ run_id: expect.any(String),
98
+ tags: ["seq:step:2"],
99
+ },
100
+ {
101
+ data: { input: "hello", output: "olleh" },
102
+ event: "on_chain_end",
103
+ metadata: {},
104
+ name: "1",
105
+ run_id: expect.any(String),
106
+ tags: ["seq:step:1"],
107
+ },
108
+ {
109
+ data: { chunk: "hello" },
110
+ event: "on_chain_stream",
111
+ metadata: {},
112
+ name: "2",
113
+ run_id: expect.any(String),
114
+ tags: ["seq:step:2"],
115
+ },
116
+ {
117
+ data: {},
118
+ event: "on_chain_start",
119
+ metadata: {},
120
+ name: "3",
121
+ run_id: expect.any(String),
122
+ tags: ["seq:step:3"],
123
+ },
124
+ {
125
+ data: { input: "olleh", output: "hello" },
126
+ event: "on_chain_end",
127
+ metadata: {},
128
+ name: "2",
129
+ run_id: expect.any(String),
130
+ tags: ["seq:step:2"],
131
+ },
132
+ {
133
+ data: { chunk: "olleh" },
134
+ event: "on_chain_stream",
135
+ metadata: {},
136
+ name: "3",
137
+ run_id: expect.any(String),
138
+ tags: ["seq:step:3"],
139
+ },
140
+ {
141
+ data: { chunk: "olleh" },
142
+ event: "on_chain_stream",
143
+ metadata: {},
144
+ name: "RunnableSequence",
145
+ run_id: expect.any(String),
146
+ tags: [],
147
+ },
148
+ {
149
+ data: { input: "hello", output: "olleh" },
150
+ event: "on_chain_end",
151
+ metadata: {},
152
+ name: "3",
153
+ run_id: expect.any(String),
154
+ tags: ["seq:step:3"],
155
+ },
156
+ {
157
+ data: { output: "olleh" },
158
+ event: "on_chain_end",
159
+ metadata: {},
160
+ name: "RunnableSequence",
161
+ run_id: expect.any(String),
162
+ tags: [],
163
+ },
164
+ ]);
165
+ });
166
+ test("Runnable streamEvents method with three runnables with backgrounded callbacks set to true", async () => {
167
+ process.env.LANGCHAIN_CALLBACKS_BACKGROUND = "true";
168
+ const r = RunnableLambda.from(reverse);
169
+ const chain = r
170
+ .withConfig({ runName: "1" })
171
+ .pipe(r.withConfig({ runName: "2" }))
172
+ .pipe(r.withConfig({ runName: "3" }));
173
+ const events = [];
174
+ const eventStream = await chain.streamEvents("hello", { version: "v2" });
175
+ for await (const event of eventStream) {
176
+ events.push(event);
177
+ }
178
+ expect(events).toEqual([
179
+ {
180
+ data: { input: "hello" },
181
+ event: "on_chain_start",
182
+ metadata: {},
183
+ name: "RunnableSequence",
184
+ run_id: expect.any(String),
185
+ tags: [],
186
+ },
187
+ {
188
+ data: {},
189
+ event: "on_chain_start",
190
+ metadata: {},
191
+ name: "1",
192
+ run_id: expect.any(String),
193
+ tags: ["seq:step:1"],
194
+ },
195
+ {
196
+ data: { chunk: "olleh" },
197
+ event: "on_chain_stream",
198
+ metadata: {},
199
+ name: "1",
200
+ run_id: expect.any(String),
201
+ tags: ["seq:step:1"],
202
+ },
203
+ {
204
+ data: {},
205
+ event: "on_chain_start",
206
+ metadata: {},
207
+ name: "2",
208
+ run_id: expect.any(String),
209
+ tags: ["seq:step:2"],
210
+ },
211
+ {
212
+ data: { input: "hello", output: "olleh" },
213
+ event: "on_chain_end",
214
+ metadata: {},
215
+ name: "1",
216
+ run_id: expect.any(String),
217
+ tags: ["seq:step:1"],
218
+ },
219
+ {
220
+ data: { chunk: "hello" },
221
+ event: "on_chain_stream",
222
+ metadata: {},
223
+ name: "2",
224
+ run_id: expect.any(String),
225
+ tags: ["seq:step:2"],
226
+ },
227
+ {
228
+ data: {},
229
+ event: "on_chain_start",
230
+ metadata: {},
231
+ name: "3",
232
+ run_id: expect.any(String),
233
+ tags: ["seq:step:3"],
234
+ },
235
+ {
236
+ data: { input: "olleh", output: "hello" },
237
+ event: "on_chain_end",
238
+ metadata: {},
239
+ name: "2",
240
+ run_id: expect.any(String),
241
+ tags: ["seq:step:2"],
242
+ },
243
+ {
244
+ data: { chunk: "olleh" },
245
+ event: "on_chain_stream",
246
+ metadata: {},
247
+ name: "3",
248
+ run_id: expect.any(String),
249
+ tags: ["seq:step:3"],
250
+ },
251
+ {
252
+ data: { chunk: "olleh" },
253
+ event: "on_chain_stream",
254
+ metadata: {},
255
+ name: "RunnableSequence",
256
+ run_id: expect.any(String),
257
+ tags: [],
258
+ },
259
+ {
260
+ data: { input: "hello", output: "olleh" },
261
+ event: "on_chain_end",
262
+ metadata: {},
263
+ name: "3",
264
+ run_id: expect.any(String),
265
+ tags: ["seq:step:3"],
266
+ },
267
+ {
268
+ data: { output: "olleh" },
269
+ event: "on_chain_end",
270
+ metadata: {},
271
+ name: "RunnableSequence",
272
+ run_id: expect.any(String),
273
+ tags: [],
274
+ },
275
+ ]);
276
+ });
277
+ test("Runnable streamEvents method with three runnables with filtering", async () => {
278
+ const r = RunnableLambda.from(reverse);
279
+ const chain = r
280
+ .withConfig({ runName: "1" })
281
+ .pipe(r.withConfig({ runName: "2", tags: ["my_tag"] }))
282
+ .pipe(r.withConfig({ runName: "3", tags: ["my_tag"] }));
283
+ const events = [];
284
+ const eventStream = await chain.streamEvents("hello", { version: "v2" }, {
285
+ includeNames: ["1"],
286
+ });
287
+ for await (const event of eventStream) {
288
+ events.push(event);
289
+ }
290
+ expect(events).toEqual([
291
+ {
292
+ data: { input: "hello" },
293
+ event: "on_chain_start",
294
+ metadata: {},
295
+ name: "1",
296
+ run_id: expect.any(String),
297
+ tags: ["seq:step:1"],
298
+ },
299
+ {
300
+ data: { chunk: "olleh" },
301
+ event: "on_chain_stream",
302
+ metadata: {},
303
+ name: "1",
304
+ run_id: expect.any(String),
305
+ tags: ["seq:step:1"],
306
+ },
307
+ {
308
+ data: { output: "olleh" },
309
+ event: "on_chain_end",
310
+ metadata: {},
311
+ name: "1",
312
+ run_id: expect.any(String),
313
+ tags: ["seq:step:1"],
314
+ },
315
+ ]);
316
+ const events2 = [];
317
+ const eventStream2 = await chain.streamEvents("hello", { version: "v2" }, {
318
+ excludeNames: ["2"],
319
+ includeTags: ["my_tag"],
320
+ });
321
+ for await (const event of eventStream2) {
322
+ events2.push(event);
323
+ }
324
+ expect(events2).toEqual([
325
+ {
326
+ data: {
327
+ input: "hello",
328
+ },
329
+ event: "on_chain_start",
330
+ metadata: {},
331
+ name: "3",
332
+ run_id: expect.any(String),
333
+ tags: expect.arrayContaining(["seq:step:3", "my_tag"]),
334
+ },
335
+ {
336
+ data: { chunk: "olleh" },
337
+ event: "on_chain_stream",
338
+ metadata: {},
339
+ name: "3",
340
+ run_id: expect.any(String),
341
+ tags: expect.arrayContaining(["seq:step:3", "my_tag"]),
342
+ },
343
+ {
344
+ data: { output: "olleh" },
345
+ event: "on_chain_end",
346
+ metadata: {},
347
+ name: "3",
348
+ run_id: expect.any(String),
349
+ tags: expect.arrayContaining(["seq:step:3", "my_tag"]),
350
+ },
351
+ ]);
352
+ });
353
+ test("Runnable streamEvents method with a runnable map", async () => {
354
+ const r = RunnableLambda.from(reverse);
355
+ const chain = RunnableMap.from({
356
+ reversed: r,
357
+ original: new RunnablePassthrough(),
358
+ }).pipe(new RunnablePick("reversed"));
359
+ const events = [];
360
+ const eventStream = await chain.streamEvents("hello", { version: "v2" });
361
+ for await (const event of eventStream) {
362
+ events.push(event);
363
+ }
364
+ expect(events).toEqual([
365
+ {
366
+ run_id: expect.any(String),
367
+ event: "on_chain_start",
368
+ name: "RunnableSequence",
369
+ tags: [],
370
+ metadata: {},
371
+ data: { input: "hello" },
372
+ },
373
+ {
374
+ event: "on_chain_start",
375
+ name: "RunnableMap",
376
+ run_id: expect.any(String),
377
+ tags: ["seq:step:1"],
378
+ metadata: {},
379
+ data: {},
380
+ },
381
+ {
382
+ event: "on_chain_start",
383
+ name: "RunnableLambda",
384
+ run_id: expect.any(String),
385
+ tags: ["map:key:reversed"],
386
+ metadata: {},
387
+ data: {},
388
+ },
389
+ {
390
+ event: "on_chain_start",
391
+ name: "RunnablePassthrough",
392
+ run_id: expect.any(String),
393
+ tags: ["map:key:original"],
394
+ metadata: {},
395
+ data: {},
396
+ },
397
+ {
398
+ event: "on_chain_stream",
399
+ name: "RunnablePassthrough",
400
+ run_id: expect.any(String),
401
+ tags: ["map:key:original"],
402
+ metadata: {},
403
+ data: { chunk: "hello" },
404
+ },
405
+ {
406
+ event: "on_chain_stream",
407
+ name: "RunnableLambda",
408
+ run_id: expect.any(String),
409
+ tags: ["map:key:reversed"],
410
+ metadata: {},
411
+ data: { chunk: "olleh" },
412
+ },
413
+ {
414
+ event: "on_chain_stream",
415
+ name: "RunnableMap",
416
+ run_id: expect.any(String),
417
+ tags: ["seq:step:1"],
418
+ metadata: {},
419
+ data: {
420
+ chunk: {
421
+ original: "hello",
422
+ },
423
+ },
424
+ },
425
+ {
426
+ event: "on_chain_start",
427
+ name: "RunnablePick",
428
+ run_id: expect.any(String),
429
+ tags: ["seq:step:2"],
430
+ metadata: {},
431
+ data: {},
432
+ },
433
+ {
434
+ event: "on_chain_stream",
435
+ name: "RunnableMap",
436
+ run_id: expect.any(String),
437
+ tags: ["seq:step:1"],
438
+ metadata: {},
439
+ data: {
440
+ chunk: {
441
+ reversed: "olleh",
442
+ },
443
+ },
444
+ },
445
+ {
446
+ event: "on_chain_end",
447
+ name: "RunnablePassthrough",
448
+ run_id: expect.any(String),
449
+ tags: ["map:key:original"],
450
+ metadata: {},
451
+ data: { input: "hello", output: "hello" },
452
+ },
453
+ {
454
+ event: "on_chain_stream",
455
+ name: "RunnablePick",
456
+ run_id: expect.any(String),
457
+ tags: ["seq:step:2"],
458
+ metadata: {},
459
+ data: { chunk: "olleh" },
460
+ },
461
+ {
462
+ event: "on_chain_stream",
463
+ run_id: expect.any(String),
464
+ tags: [],
465
+ metadata: {},
466
+ name: "RunnableSequence",
467
+ data: { chunk: "olleh" },
468
+ },
469
+ {
470
+ event: "on_chain_end",
471
+ name: "RunnableLambda",
472
+ run_id: expect.any(String),
473
+ tags: ["map:key:reversed"],
474
+ metadata: {},
475
+ data: { input: "hello", output: "olleh" },
476
+ },
477
+ {
478
+ event: "on_chain_end",
479
+ name: "RunnableMap",
480
+ run_id: expect.any(String),
481
+ tags: ["seq:step:1"],
482
+ metadata: {},
483
+ data: {
484
+ input: "hello",
485
+ output: {
486
+ original: "hello",
487
+ reversed: "olleh",
488
+ },
489
+ },
490
+ },
491
+ {
492
+ event: "on_chain_end",
493
+ name: "RunnablePick",
494
+ run_id: expect.any(String),
495
+ tags: ["seq:step:2"],
496
+ metadata: {},
497
+ data: {
498
+ input: {
499
+ original: "hello",
500
+ reversed: "olleh",
501
+ },
502
+ output: "olleh",
503
+ },
504
+ },
505
+ {
506
+ event: "on_chain_end",
507
+ name: "RunnableSequence",
508
+ run_id: expect.any(String),
509
+ tags: [],
510
+ metadata: {},
511
+ data: { output: "olleh" },
512
+ },
513
+ ]);
514
+ });
515
+ test("Runnable streamEvents method with llm", async () => {
516
+ const model = new FakeStreamingLLM({
517
+ responses: ["hey!"],
518
+ }).withConfig({
519
+ metadata: { a: "b" },
520
+ tags: ["my_model"],
521
+ runName: "my_model",
522
+ });
523
+ const events = [];
524
+ const eventStream = await model.streamEvents("hello", { version: "v2" });
525
+ for await (const event of eventStream) {
526
+ events.push(event);
527
+ }
528
+ expect(events).toEqual([
529
+ {
530
+ event: "on_llm_start",
531
+ name: "my_model",
532
+ run_id: expect.any(String),
533
+ tags: expect.arrayContaining(["my_model"]),
534
+ metadata: {
535
+ a: "b",
536
+ },
537
+ data: {
538
+ input: "hello",
539
+ },
540
+ },
541
+ {
542
+ event: "on_llm_stream",
543
+ run_id: expect.any(String),
544
+ tags: expect.arrayContaining(["my_model"]),
545
+ metadata: {
546
+ a: "b",
547
+ },
548
+ name: "my_model",
549
+ data: { chunk: "h" },
550
+ },
551
+ {
552
+ event: "on_llm_stream",
553
+ run_id: expect.any(String),
554
+ tags: expect.arrayContaining(["my_model"]),
555
+ metadata: {
556
+ a: "b",
557
+ },
558
+ name: "my_model",
559
+ data: { chunk: "e" },
560
+ },
561
+ {
562
+ event: "on_llm_stream",
563
+ run_id: expect.any(String),
564
+ tags: expect.arrayContaining(["my_model"]),
565
+ metadata: {
566
+ a: "b",
567
+ },
568
+ name: "my_model",
569
+ data: { chunk: "y" },
570
+ },
571
+ {
572
+ event: "on_llm_stream",
573
+ run_id: expect.any(String),
574
+ tags: expect.arrayContaining(["my_model"]),
575
+ metadata: {
576
+ a: "b",
577
+ },
578
+ name: "my_model",
579
+ data: { chunk: "!" },
580
+ },
581
+ {
582
+ event: "on_llm_end",
583
+ name: "my_model",
584
+ run_id: expect.any(String),
585
+ tags: expect.arrayContaining(["my_model"]),
586
+ metadata: {
587
+ a: "b",
588
+ },
589
+ data: {
590
+ output: {
591
+ generations: [
592
+ [
593
+ {
594
+ generationInfo: {},
595
+ text: "hey!",
596
+ },
597
+ ],
598
+ ],
599
+ llmOutput: {},
600
+ },
601
+ },
602
+ },
603
+ ]);
604
+ });
605
+ test("Runnable streamEvents method with chat model chain", async () => {
606
+ const template = ChatPromptTemplate.fromMessages([
607
+ ["system", "You are Godzilla"],
608
+ ["human", "{question}"],
609
+ ]).withConfig({
610
+ runName: "my_template",
611
+ tags: ["my_template"],
612
+ });
613
+ const model = new FakeListChatModel({
614
+ responses: ["ROAR"],
615
+ }).withConfig({
616
+ metadata: { a: "b" },
617
+ tags: ["my_model"],
618
+ runName: "my_model",
619
+ });
620
+ const chain = template.pipe(model).withConfig({
621
+ metadata: { foo: "bar" },
622
+ tags: ["my_chain"],
623
+ runName: "my_chain",
624
+ });
625
+ const events = [];
626
+ const eventStream = await chain.streamEvents({ question: "hello" }, { version: "v2" });
627
+ for await (const event of eventStream) {
628
+ events.push(event);
629
+ }
630
+ expect(events).toEqual([
631
+ {
632
+ run_id: expect.any(String),
633
+ event: "on_chain_start",
634
+ name: "my_chain",
635
+ tags: ["my_chain"],
636
+ metadata: {
637
+ foo: "bar",
638
+ },
639
+ data: {
640
+ input: {
641
+ question: "hello",
642
+ },
643
+ },
644
+ },
645
+ {
646
+ data: { input: { question: "hello" } },
647
+ event: "on_prompt_start",
648
+ metadata: { foo: "bar" },
649
+ name: "my_template",
650
+ run_id: expect.any(String),
651
+ tags: expect.arrayContaining(["my_chain", "seq:step:1", "my_template"]),
652
+ },
653
+ {
654
+ event: "on_prompt_end",
655
+ name: "my_template",
656
+ run_id: expect.any(String),
657
+ tags: expect.arrayContaining(["seq:step:1", "my_template", "my_chain"]),
658
+ metadata: {
659
+ foo: "bar",
660
+ },
661
+ data: {
662
+ input: {
663
+ question: "hello",
664
+ },
665
+ output: await template.invoke({ question: "hello" }),
666
+ },
667
+ },
668
+ {
669
+ event: "on_chat_model_start",
670
+ name: "my_model",
671
+ run_id: expect.any(String),
672
+ tags: expect.arrayContaining(["seq:step:2", "my_model", "my_chain"]),
673
+ metadata: {
674
+ foo: "bar",
675
+ a: "b",
676
+ ls_model_type: "chat",
677
+ ls_stop: undefined,
678
+ },
679
+ data: {
680
+ input: {
681
+ messages: [
682
+ [new SystemMessage("You are Godzilla"), new HumanMessage("hello")],
683
+ ],
684
+ },
685
+ },
686
+ },
687
+ {
688
+ event: "on_chat_model_stream",
689
+ run_id: expect.any(String),
690
+ tags: expect.arrayContaining(["my_chain", "my_model", "seq:step:2"]),
691
+ metadata: {
692
+ a: "b",
693
+ foo: "bar",
694
+ ls_model_type: "chat",
695
+ ls_stop: undefined,
696
+ },
697
+ name: "my_model",
698
+ data: { chunk: new AIMessageChunk("R") },
699
+ },
700
+ {
701
+ event: "on_chain_stream",
702
+ run_id: expect.any(String),
703
+ tags: ["my_chain"],
704
+ metadata: {
705
+ foo: "bar",
706
+ },
707
+ name: "my_chain",
708
+ data: { chunk: new AIMessageChunk("R") },
709
+ },
710
+ {
711
+ event: "on_chat_model_stream",
712
+ run_id: expect.any(String),
713
+ tags: expect.arrayContaining(["my_chain", "my_model", "seq:step:2"]),
714
+ metadata: {
715
+ a: "b",
716
+ foo: "bar",
717
+ ls_model_type: "chat",
718
+ ls_stop: undefined,
719
+ },
720
+ name: "my_model",
721
+ data: { chunk: new AIMessageChunk("O") },
722
+ },
723
+ {
724
+ event: "on_chain_stream",
725
+ run_id: expect.any(String),
726
+ tags: ["my_chain"],
727
+ metadata: {
728
+ foo: "bar",
729
+ },
730
+ name: "my_chain",
731
+ data: { chunk: new AIMessageChunk("O") },
732
+ },
733
+ {
734
+ event: "on_chat_model_stream",
735
+ run_id: expect.any(String),
736
+ tags: expect.arrayContaining(["my_chain", "my_model", "seq:step:2"]),
737
+ metadata: {
738
+ a: "b",
739
+ foo: "bar",
740
+ ls_model_type: "chat",
741
+ ls_stop: undefined,
742
+ },
743
+ name: "my_model",
744
+ data: { chunk: new AIMessageChunk("A") },
745
+ },
746
+ {
747
+ event: "on_chain_stream",
748
+ run_id: expect.any(String),
749
+ tags: ["my_chain"],
750
+ metadata: {
751
+ foo: "bar",
752
+ },
753
+ name: "my_chain",
754
+ data: { chunk: new AIMessageChunk("A") },
755
+ },
756
+ {
757
+ event: "on_chat_model_stream",
758
+ run_id: expect.any(String),
759
+ tags: expect.arrayContaining(["my_chain", "my_model", "seq:step:2"]),
760
+ metadata: {
761
+ a: "b",
762
+ foo: "bar",
763
+ ls_model_type: "chat",
764
+ ls_stop: undefined,
765
+ },
766
+ name: "my_model",
767
+ data: { chunk: new AIMessageChunk("R") },
768
+ },
769
+ {
770
+ event: "on_chain_stream",
771
+ run_id: expect.any(String),
772
+ tags: ["my_chain"],
773
+ metadata: {
774
+ foo: "bar",
775
+ },
776
+ name: "my_chain",
777
+ data: { chunk: new AIMessageChunk("R") },
778
+ },
779
+ {
780
+ event: "on_chat_model_end",
781
+ name: "my_model",
782
+ run_id: expect.any(String),
783
+ tags: expect.arrayContaining(["seq:step:2", "my_model", "my_chain"]),
784
+ metadata: {
785
+ foo: "bar",
786
+ a: "b",
787
+ ls_model_type: "chat",
788
+ ls_stop: undefined,
789
+ },
790
+ data: {
791
+ input: {
792
+ messages: [
793
+ [new SystemMessage("You are Godzilla"), new HumanMessage("hello")],
794
+ ],
795
+ },
796
+ output: new AIMessageChunk("ROAR"),
797
+ },
798
+ },
799
+ {
800
+ event: "on_chain_end",
801
+ name: "my_chain",
802
+ run_id: expect.any(String),
803
+ tags: ["my_chain"],
804
+ metadata: {
805
+ foo: "bar",
806
+ },
807
+ data: {
808
+ output: new AIMessageChunk("ROAR"),
809
+ },
810
+ },
811
+ ]);
812
+ });
813
+ test("Runnable streamEvents method with simple tools", async () => {
814
+ const tool = new DynamicTool({
815
+ func: async () => "hello",
816
+ name: "parameterless",
817
+ description: "A tool that does nothing",
818
+ });
819
+ const events = [];
820
+ const eventStream = await tool.streamEvents({}, { version: "v2" });
821
+ for await (const event of eventStream) {
822
+ events.push(event);
823
+ }
824
+ expect(events).toEqual([
825
+ {
826
+ data: { input: {} },
827
+ event: "on_tool_start",
828
+ metadata: {},
829
+ name: "parameterless",
830
+ run_id: expect.any(String),
831
+ tags: [],
832
+ },
833
+ {
834
+ data: { output: "hello" },
835
+ event: "on_tool_end",
836
+ metadata: {},
837
+ name: "parameterless",
838
+ run_id: expect.any(String),
839
+ tags: [],
840
+ },
841
+ ]);
842
+ const toolWithParams = new DynamicStructuredTool({
843
+ func: async (params) => JSON.stringify({ x: params.x, y: params.y }),
844
+ schema: z.object({
845
+ x: z.number(),
846
+ y: z.string(),
847
+ }),
848
+ name: "with_parameters",
849
+ description: "A tool that does nothing",
850
+ });
851
+ const events2 = [];
852
+ const eventStream2 = await toolWithParams.streamEvents({ x: 1, y: "2" }, { version: "v2" });
853
+ for await (const event of eventStream2) {
854
+ events2.push(event);
855
+ }
856
+ expect(events2).toEqual([
857
+ {
858
+ data: { input: { x: 1, y: "2" } },
859
+ event: "on_tool_start",
860
+ metadata: {},
861
+ name: "with_parameters",
862
+ run_id: expect.any(String),
863
+ tags: [],
864
+ },
865
+ {
866
+ data: { output: JSON.stringify({ x: 1, y: "2" }) },
867
+ event: "on_tool_end",
868
+ metadata: {},
869
+ name: "with_parameters",
870
+ run_id: expect.any(String),
871
+ tags: [],
872
+ },
873
+ ]);
874
+ });
875
+ test("Runnable streamEvents method with a retriever", async () => {
876
+ const retriever = new FakeRetriever({
877
+ output: [
878
+ new Document({ pageContent: "hello world!", metadata: { foo: "bar" } }),
879
+ new Document({
880
+ pageContent: "goodbye world!",
881
+ metadata: { food: "spare" },
882
+ }),
883
+ ],
884
+ });
885
+ const events = [];
886
+ const eventStream = await retriever.streamEvents("hello", {
887
+ version: "v2",
888
+ });
889
+ for await (const event of eventStream) {
890
+ events.push(event);
891
+ }
892
+ expect(events).toEqual([
893
+ {
894
+ data: {
895
+ input: "hello",
896
+ },
897
+ event: "on_retriever_start",
898
+ metadata: {},
899
+ name: "FakeRetriever",
900
+ run_id: expect.any(String),
901
+ tags: [],
902
+ },
903
+ {
904
+ data: {
905
+ output: [
906
+ new Document({
907
+ pageContent: "hello world!",
908
+ metadata: { foo: "bar" },
909
+ }),
910
+ new Document({
911
+ pageContent: "goodbye world!",
912
+ metadata: { food: "spare" },
913
+ }),
914
+ ],
915
+ },
916
+ event: "on_retriever_end",
917
+ metadata: {},
918
+ name: "FakeRetriever",
919
+ run_id: expect.any(String),
920
+ tags: [],
921
+ },
922
+ ]);
923
+ });
924
+ test("Runnable streamEvents method with text/event-stream encoding", async () => {
925
+ const chain = RunnableLambda.from(reverse).withConfig({
926
+ runName: "reverse",
927
+ });
928
+ const events = [];
929
+ const eventStream = await chain.streamEvents("hello", {
930
+ version: "v2",
931
+ encoding: "text/event-stream",
932
+ runId: "1234",
933
+ });
934
+ for await (const event of eventStream) {
935
+ events.push(event);
936
+ }
937
+ const decoder = new TextDecoder();
938
+ expect(events.length).toEqual(4);
939
+ const dataEvents = events
940
+ .slice(0, 3)
941
+ .map((event) => decoder.decode(event).split("event: data\ndata: ")[1]);
942
+ const expectedPayloads = [
943
+ {
944
+ data: { input: "hello" },
945
+ event: "on_chain_start",
946
+ metadata: {},
947
+ name: "reverse",
948
+ run_id: "1234",
949
+ tags: [],
950
+ },
951
+ {
952
+ data: { chunk: "olleh" },
953
+ event: "on_chain_stream",
954
+ metadata: {},
955
+ name: "reverse",
956
+ run_id: "1234",
957
+ tags: [],
958
+ },
959
+ {
960
+ data: { output: "olleh" },
961
+ event: "on_chain_end",
962
+ metadata: {},
963
+ name: "reverse",
964
+ run_id: "1234",
965
+ tags: [],
966
+ },
967
+ ];
968
+ for (let i = 0; i < dataEvents.length; i += 1) {
969
+ expect(dataEvents[i].endsWith("\n\n")).toBe(true);
970
+ expect(JSON.parse(dataEvents[i].replace("\n\n", ""))).toEqual(expectedPayloads[i]);
971
+ }
972
+ expect(decoder.decode(events[3])).toEqual("event: end\n\n");
973
+ });