@langchain/core 0.2.18 → 0.2.19

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 (128) hide show
  1. package/dist/callbacks/manager.cjs +94 -19
  2. package/dist/callbacks/manager.d.ts +3 -1
  3. package/dist/callbacks/manager.js +94 -19
  4. package/dist/messages/base.cjs +16 -1
  5. package/dist/messages/base.d.ts +9 -0
  6. package/dist/messages/base.js +14 -0
  7. package/dist/messages/tool.cjs +23 -0
  8. package/dist/messages/tool.d.ts +15 -0
  9. package/dist/messages/tool.js +24 -1
  10. package/dist/messages/utils.cjs +1 -1
  11. package/dist/messages/utils.js +1 -1
  12. package/dist/output_parsers/string.cjs +1 -0
  13. package/dist/output_parsers/string.js +1 -0
  14. package/dist/runnables/base.cjs +1 -3
  15. package/dist/runnables/base.js +1 -3
  16. package/dist/runnables/remote.cjs +3 -1
  17. package/dist/runnables/remote.js +3 -1
  18. package/dist/tools/index.cjs +15 -6
  19. package/dist/tools/index.d.ts +21 -12
  20. package/dist/tools/index.js +15 -6
  21. package/dist/utils/testing/index.cjs +161 -3
  22. package/dist/utils/testing/index.d.ts +94 -3
  23. package/dist/utils/testing/index.js +160 -3
  24. package/package.json +4 -3
  25. package/dist/caches/tests/in_memory_cache.test.d.ts +0 -1
  26. package/dist/caches/tests/in_memory_cache.test.js +0 -33
  27. package/dist/callbacks/tests/callbacks.test.d.ts +0 -1
  28. package/dist/callbacks/tests/callbacks.test.js +0 -495
  29. package/dist/callbacks/tests/manager.int.test.d.ts +0 -1
  30. package/dist/callbacks/tests/manager.int.test.js +0 -29
  31. package/dist/callbacks/tests/run_collector.test.d.ts +0 -1
  32. package/dist/callbacks/tests/run_collector.test.js +0 -58
  33. package/dist/language_models/tests/chat_models.test.d.ts +0 -1
  34. package/dist/language_models/tests/chat_models.test.js +0 -204
  35. package/dist/language_models/tests/count_tokens.test.d.ts +0 -1
  36. package/dist/language_models/tests/count_tokens.test.js +0 -19
  37. package/dist/language_models/tests/llms.test.d.ts +0 -1
  38. package/dist/language_models/tests/llms.test.js +0 -52
  39. package/dist/messages/tests/base_message.test.d.ts +0 -1
  40. package/dist/messages/tests/base_message.test.js +0 -245
  41. package/dist/messages/tests/message_utils.test.d.ts +0 -1
  42. package/dist/messages/tests/message_utils.test.js +0 -434
  43. package/dist/output_parsers/openai_tools/tests/json_output_tools_parser.test.d.ts +0 -1
  44. package/dist/output_parsers/openai_tools/tests/json_output_tools_parser.test.js +0 -81
  45. package/dist/output_parsers/tests/json.test.d.ts +0 -1
  46. package/dist/output_parsers/tests/json.test.js +0 -427
  47. package/dist/output_parsers/tests/output_parser.test.d.ts +0 -1
  48. package/dist/output_parsers/tests/output_parser.test.js +0 -78
  49. package/dist/output_parsers/tests/string.test.d.ts +0 -1
  50. package/dist/output_parsers/tests/string.test.js +0 -68
  51. package/dist/output_parsers/tests/structured.test.d.ts +0 -1
  52. package/dist/output_parsers/tests/structured.test.js +0 -166
  53. package/dist/output_parsers/tests/xml.test.d.ts +0 -1
  54. package/dist/output_parsers/tests/xml.test.js +0 -81
  55. package/dist/prompts/tests/chat.mustache.test.d.ts +0 -1
  56. package/dist/prompts/tests/chat.mustache.test.js +0 -129
  57. package/dist/prompts/tests/chat.test.d.ts +0 -1
  58. package/dist/prompts/tests/chat.test.js +0 -557
  59. package/dist/prompts/tests/few_shot.test.d.ts +0 -1
  60. package/dist/prompts/tests/few_shot.test.js +0 -224
  61. package/dist/prompts/tests/pipeline.test.d.ts +0 -1
  62. package/dist/prompts/tests/pipeline.test.js +0 -101
  63. package/dist/prompts/tests/prompt.mustache.test.d.ts +0 -1
  64. package/dist/prompts/tests/prompt.mustache.test.js +0 -105
  65. package/dist/prompts/tests/prompt.test.d.ts +0 -1
  66. package/dist/prompts/tests/prompt.test.js +0 -78
  67. package/dist/prompts/tests/structured.test.d.ts +0 -1
  68. package/dist/prompts/tests/structured.test.js +0 -37
  69. package/dist/prompts/tests/template.test.d.ts +0 -1
  70. package/dist/prompts/tests/template.test.js +0 -24
  71. package/dist/runnables/tests/runnable.test.d.ts +0 -1
  72. package/dist/runnables/tests/runnable.test.js +0 -491
  73. package/dist/runnables/tests/runnable_binding.test.d.ts +0 -1
  74. package/dist/runnables/tests/runnable_binding.test.js +0 -46
  75. package/dist/runnables/tests/runnable_branch.test.d.ts +0 -1
  76. package/dist/runnables/tests/runnable_branch.test.js +0 -116
  77. package/dist/runnables/tests/runnable_graph.test.d.ts +0 -1
  78. package/dist/runnables/tests/runnable_graph.test.js +0 -100
  79. package/dist/runnables/tests/runnable_history.test.d.ts +0 -1
  80. package/dist/runnables/tests/runnable_history.test.js +0 -177
  81. package/dist/runnables/tests/runnable_interface.test.d.ts +0 -1
  82. package/dist/runnables/tests/runnable_interface.test.js +0 -209
  83. package/dist/runnables/tests/runnable_map.test.d.ts +0 -1
  84. package/dist/runnables/tests/runnable_map.test.js +0 -238
  85. package/dist/runnables/tests/runnable_passthrough.test.d.ts +0 -1
  86. package/dist/runnables/tests/runnable_passthrough.test.js +0 -96
  87. package/dist/runnables/tests/runnable_remote.int.test.d.ts +0 -1
  88. package/dist/runnables/tests/runnable_remote.int.test.js +0 -138
  89. package/dist/runnables/tests/runnable_remote.test.d.ts +0 -1
  90. package/dist/runnables/tests/runnable_remote.test.js +0 -200
  91. package/dist/runnables/tests/runnable_retry.test.d.ts +0 -1
  92. package/dist/runnables/tests/runnable_retry.test.js +0 -125
  93. package/dist/runnables/tests/runnable_stream_events.test.d.ts +0 -1
  94. package/dist/runnables/tests/runnable_stream_events.test.js +0 -1013
  95. package/dist/runnables/tests/runnable_stream_events_v2.test.d.ts +0 -1
  96. package/dist/runnables/tests/runnable_stream_events_v2.test.js +0 -2022
  97. package/dist/runnables/tests/runnable_stream_log.test.d.ts +0 -1
  98. package/dist/runnables/tests/runnable_stream_log.test.js +0 -71
  99. package/dist/runnables/tests/runnable_tools.test.d.ts +0 -1
  100. package/dist/runnables/tests/runnable_tools.test.js +0 -149
  101. package/dist/runnables/tests/runnable_tracing.int.test.d.ts +0 -1
  102. package/dist/runnables/tests/runnable_tracing.int.test.js +0 -37
  103. package/dist/runnables/tests/runnable_with_fallbacks.test.d.ts +0 -1
  104. package/dist/runnables/tests/runnable_with_fallbacks.test.js +0 -36
  105. package/dist/singletons/tests/async_local_storage.test.d.ts +0 -1
  106. package/dist/singletons/tests/async_local_storage.test.js +0 -153
  107. package/dist/structured_query/tests/utils.test.d.ts +0 -1
  108. package/dist/structured_query/tests/utils.test.js +0 -47
  109. package/dist/tools/tests/tools.test.d.ts +0 -1
  110. package/dist/tools/tests/tools.test.js +0 -85
  111. package/dist/tracers/tests/langchain_tracer.int.test.d.ts +0 -1
  112. package/dist/tracers/tests/langchain_tracer.int.test.js +0 -74
  113. package/dist/tracers/tests/langsmith_interop.test.d.ts +0 -1
  114. package/dist/tracers/tests/langsmith_interop.test.js +0 -551
  115. package/dist/tracers/tests/tracer.test.d.ts +0 -1
  116. package/dist/tracers/tests/tracer.test.js +0 -378
  117. package/dist/utils/testing/tests/chatfake.test.d.ts +0 -1
  118. package/dist/utils/testing/tests/chatfake.test.js +0 -112
  119. package/dist/utils/tests/async_caller.test.d.ts +0 -1
  120. package/dist/utils/tests/async_caller.test.js +0 -27
  121. package/dist/utils/tests/enviroment.test.d.ts +0 -1
  122. package/dist/utils/tests/enviroment.test.js +0 -6
  123. package/dist/utils/tests/function_calling.test.d.ts +0 -1
  124. package/dist/utils/tests/function_calling.test.js +0 -107
  125. package/dist/utils/tests/math_utils.test.d.ts +0 -1
  126. package/dist/utils/tests/math_utils.test.js +0 -139
  127. package/dist/utils/tests/polyfill_stream.test.d.ts +0 -1
  128. package/dist/utils/tests/polyfill_stream.test.js +0 -15
@@ -1,238 +0,0 @@
1
- /* eslint-disable no-promise-executor-return */
2
- /* eslint-disable @typescript-eslint/no-explicit-any */
3
- import { StringOutputParser } from "../../output_parsers/string.js";
4
- import { ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate, } from "../../prompts/chat.js";
5
- import { concat } from "../../utils/stream.js";
6
- import { FakeLLM, FakeChatModel, FakeRetriever, FakeStreamingLLM, } from "../../utils/testing/index.js";
7
- import { RunnableSequence, RunnableMap } from "../base.js";
8
- import { RunnablePassthrough } from "../passthrough.js";
9
- test("Create a runnable sequence with a runnable map", async () => {
10
- const promptTemplate = ChatPromptTemplate.fromMessages([
11
- SystemMessagePromptTemplate.fromTemplate(`You are a nice assistant.`),
12
- HumanMessagePromptTemplate.fromTemplate(`Context:\n{documents}\n\nQuestion:\n{question}`),
13
- ]);
14
- const llm = new FakeChatModel({});
15
- const inputs = {
16
- question: (input) => input,
17
- documents: RunnableSequence.from([
18
- new FakeRetriever(),
19
- (docs) => JSON.stringify(docs),
20
- ]),
21
- extraField: new FakeLLM({}),
22
- };
23
- const runnable = new RunnableMap({ steps: inputs })
24
- .pipe(promptTemplate)
25
- .pipe(llm);
26
- const result = await runnable.invoke("Do you know the Muffin Man?");
27
- console.log(result);
28
- expect(result.content).toEqual(`You are a nice assistant.\nContext:\n[{"pageContent":"foo","metadata":{}},{"pageContent":"bar","metadata":{}}]\n\nQuestion:\nDo you know the Muffin Man?`);
29
- });
30
- test("Test map inference in a sequence", async () => {
31
- const prompt = ChatPromptTemplate.fromTemplate("context: {context}, question: {question}");
32
- const chain = RunnableSequence.from([
33
- {
34
- question: new RunnablePassthrough(),
35
- context: async () => "SOME STUFF",
36
- },
37
- prompt,
38
- new FakeLLM({}),
39
- new StringOutputParser(),
40
- ]);
41
- const response = await chain.invoke("Just passing through.");
42
- console.log(response);
43
- expect(response).toBe(`Human: context: SOME STUFF, question: Just passing through.`);
44
- });
45
- test("Should not allow mismatched inputs", async () => {
46
- const prompt = ChatPromptTemplate.fromTemplate("context: {context}, question: {question}");
47
- const badChain = RunnableSequence.from([
48
- {
49
- // @ts-expect-error TS compiler should flag mismatched input types
50
- question: new FakeLLM({}),
51
- context: async (input) => input,
52
- },
53
- prompt,
54
- new FakeLLM({}),
55
- new StringOutputParser(),
56
- ]);
57
- console.log(badChain);
58
- });
59
- test("Should not allow improper inputs into a map in a sequence", async () => {
60
- const prompt = ChatPromptTemplate.fromTemplate("context: {context}, question: {question}");
61
- const map = RunnableMap.from({
62
- question: new FakeLLM({}),
63
- context: async (_input) => 9,
64
- });
65
- // @ts-expect-error TS compiler should flag mismatched output types
66
- const runnable = prompt.pipe(map);
67
- console.log(runnable);
68
- });
69
- test("Should not allow improper outputs from a map into the next item in a sequence", async () => {
70
- const map = RunnableMap.from({
71
- question: new FakeLLM({}),
72
- context: async (_input) => 9,
73
- });
74
- // @ts-expect-error TS compiler should flag mismatched output types
75
- const runnable = map.pipe(new FakeLLM({}));
76
- console.log(runnable);
77
- });
78
- test("Should stream chunks from each step as they are produced", async () => {
79
- const prompt = ChatPromptTemplate.fromMessages([
80
- ["system", "You are a nice assistant."],
81
- "{question}",
82
- ]);
83
- const chat = new FakeChatModel({});
84
- const llm = new FakeStreamingLLM({ sleep: 0 });
85
- const chain = RunnableSequence.from([
86
- prompt,
87
- RunnableMap.from({
88
- passthrough: new RunnablePassthrough(),
89
- chat,
90
- llm,
91
- }),
92
- ]);
93
- const stream = await chain.stream({ question: "What is your name?" });
94
- const chunks = [];
95
- for await (const chunk of stream) {
96
- chunks.push(chunk);
97
- }
98
- expect(chunks.length).toBeGreaterThan(3);
99
- expect(chunks.reduce(concat)).toEqual(await chain.invoke({ question: "What is your name?" }));
100
- const chainWithSelect = chain.pipe((output) => output.llm);
101
- expect(await chainWithSelect.invoke({ question: "What is your name?" }))
102
- .toEqual(`System: You are a nice assistant.
103
- Human: What is your name?`);
104
- });
105
- test("Should stream chunks through runnable passthrough and assign", async () => {
106
- const llm = new FakeStreamingLLM({ sleep: 0 });
107
- const chain = RunnableSequence.from([
108
- llm,
109
- RunnableMap.from({
110
- llm: new RunnablePassthrough(),
111
- }),
112
- ]);
113
- const stream = await chain.stream("What is your name?");
114
- const chunks = [];
115
- for await (const chunk of stream) {
116
- chunks.push(chunk);
117
- }
118
- expect(chunks).toEqual([
119
- { llm: "W" },
120
- { llm: "h" },
121
- { llm: "a" },
122
- { llm: "t" },
123
- { llm: " " },
124
- { llm: "i" },
125
- { llm: "s" },
126
- { llm: " " },
127
- { llm: "y" },
128
- { llm: "o" },
129
- { llm: "u" },
130
- { llm: "r" },
131
- { llm: " " },
132
- { llm: "n" },
133
- { llm: "a" },
134
- { llm: "m" },
135
- { llm: "e" },
136
- { llm: "?" },
137
- ]);
138
- expect(chunks.reduce(concat)).toEqual(await chain.invoke("What is your name?"));
139
- const chainWithAssign = chain.pipe(RunnablePassthrough.assign({
140
- chat: RunnableSequence.from([(input) => input.llm, llm]),
141
- }));
142
- const stream2 = await chainWithAssign.stream("What is your name?");
143
- const chunks2 = [];
144
- for await (const chunk of stream2) {
145
- chunks2.push(chunk);
146
- }
147
- expect(chunks2).toEqual([
148
- { llm: "W" },
149
- { llm: "h" },
150
- { llm: "a" },
151
- { llm: "t" },
152
- { llm: " " },
153
- { llm: "i" },
154
- { llm: "s" },
155
- { llm: " " },
156
- { llm: "y" },
157
- { llm: "o" },
158
- { llm: "u" },
159
- { llm: "r" },
160
- { llm: " " },
161
- { llm: "n" },
162
- { llm: "a" },
163
- { llm: "m" },
164
- { llm: "e" },
165
- { llm: "?" },
166
- { chat: "W" },
167
- { chat: "h" },
168
- { chat: "a" },
169
- { chat: "t" },
170
- { chat: " " },
171
- { chat: "i" },
172
- { chat: "s" },
173
- { chat: " " },
174
- { chat: "y" },
175
- { chat: "o" },
176
- { chat: "u" },
177
- { chat: "r" },
178
- { chat: " " },
179
- { chat: "n" },
180
- { chat: "a" },
181
- { chat: "m" },
182
- { chat: "e" },
183
- { chat: "?" },
184
- ]);
185
- expect(chunks2.reduce(concat)).toEqual(await chainWithAssign.invoke("What is your name?"));
186
- const chainWithPick = chainWithAssign.pick("llm");
187
- const chunks3 = [];
188
- for await (const chunk of await chainWithPick.stream("What is your name?")) {
189
- chunks3.push(chunk);
190
- }
191
- expect(chunks3).toEqual([
192
- "W",
193
- "h",
194
- "a",
195
- "t",
196
- " ",
197
- "i",
198
- "s",
199
- " ",
200
- "y",
201
- "o",
202
- "u",
203
- "r",
204
- " ",
205
- "n",
206
- "a",
207
- "m",
208
- "e",
209
- "?",
210
- ]);
211
- expect(chunks3.reduce(concat)).toEqual(await chainWithPick.invoke("What is your name?"));
212
- const chainWithPickMulti = chainWithAssign.pick(["llm"]);
213
- const chunks4 = [];
214
- for await (const chunk of await chainWithPickMulti.stream("What is your name?")) {
215
- chunks4.push(chunk);
216
- }
217
- expect(chunks4).toEqual([
218
- { llm: "W" },
219
- { llm: "h" },
220
- { llm: "a" },
221
- { llm: "t" },
222
- { llm: " " },
223
- { llm: "i" },
224
- { llm: "s" },
225
- { llm: " " },
226
- { llm: "y" },
227
- { llm: "o" },
228
- { llm: "u" },
229
- { llm: "r" },
230
- { llm: " " },
231
- { llm: "n" },
232
- { llm: "a" },
233
- { llm: "m" },
234
- { llm: "e" },
235
- { llm: "?" },
236
- ]);
237
- expect(chunks4.reduce(concat)).toEqual(await chainWithPickMulti.invoke("What is your name?"));
238
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,96 +0,0 @@
1
- import { PromptTemplate } from "../../prompts/prompt.js";
2
- import { FakeChatModel } from "../../utils/testing/index.js";
3
- import { RunnablePassthrough } from "../passthrough.js";
4
- import { JsonOutputParser } from "../../output_parsers/json.js";
5
- import { RunnableSequence } from "../base.js";
6
- test("RunnablePassthrough can call .assign and pass prev result through", async () => {
7
- const promptTemplate = PromptTemplate.fromTemplate("{input}");
8
- const llm = new FakeChatModel({});
9
- const parser = new JsonOutputParser();
10
- const text = `\`\`\`
11
- {"outputValue": "testing"}
12
- \`\`\``;
13
- const chain = promptTemplate.pipe(llm).pipe(parser);
14
- const chainWithAssign = chain.pipe(RunnablePassthrough.assign({
15
- outputValue: (i) => i.outputValue,
16
- }));
17
- const result = await chainWithAssign.invoke({ input: text });
18
- console.log(result);
19
- expect(result).toEqual({ outputValue: "testing" });
20
- });
21
- test("RunnablePassthrough can call .assign as the first step with proper typing", async () => {
22
- const promptTemplate = PromptTemplate.fromTemplate("{input}");
23
- const llm = new FakeChatModel({});
24
- const parser = new JsonOutputParser();
25
- const text = `\`\`\`
26
- {"outputValue": "testing2"}
27
- \`\`\``;
28
- const chain = RunnableSequence.from([
29
- RunnablePassthrough.assign({
30
- input: (input) => input.otherProp,
31
- }),
32
- promptTemplate,
33
- llm,
34
- parser,
35
- ]);
36
- const result = await chain.invoke({ otherProp: text });
37
- console.log(result);
38
- expect(result).toEqual({ outputValue: "testing2" });
39
- });
40
- test("RunnablePassthrough can invoke a function without modifying passthrough value", async () => {
41
- let wasCalled = false;
42
- const addOne = (input) => {
43
- wasCalled = true;
44
- return input + 1;
45
- };
46
- const passthrough = new RunnablePassthrough({
47
- func: addOne,
48
- });
49
- const result = await passthrough.invoke(1);
50
- expect(result).toEqual(1);
51
- expect(wasCalled).toEqual(true);
52
- });
53
- test("RunnablePassthrough can transform a function as constructor args", async () => {
54
- let wasCalled = false;
55
- const addOne = (input) => {
56
- wasCalled = true;
57
- return input + 1;
58
- };
59
- const passthrough = new RunnablePassthrough({
60
- func: addOne,
61
- });
62
- async function* generateNumbers() {
63
- yield 1;
64
- }
65
- const transformedGenerator = passthrough.transform(generateNumbers(), {});
66
- const results = [];
67
- for await (const value of transformedGenerator) {
68
- results.push(value);
69
- }
70
- expect(results).toEqual([1]);
71
- expect(wasCalled).toEqual(true);
72
- });
73
- test("RunnablePassthrough can invoke a function and pass through config", async () => {
74
- let wasCalled = false;
75
- let addOneResult = 0;
76
- const addOne = (input, config) => {
77
- wasCalled = true;
78
- if (!config?.configurable?.number ??
79
- Number.isNaN(config?.configurable?.number)) {
80
- throw new Error("configurable.number is NaN");
81
- }
82
- console.log(config.configurable.number);
83
- addOneResult = input + config.configurable.number;
84
- };
85
- const passthrough = new RunnablePassthrough({
86
- func: addOne,
87
- });
88
- const result = await passthrough.invoke(1, {
89
- configurable: {
90
- number: 1,
91
- },
92
- });
93
- expect(result).toEqual(1);
94
- expect(addOneResult).toEqual(2);
95
- expect(wasCalled).toEqual(true);
96
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,138 +0,0 @@
1
- import { HumanMessage } from "../../messages/index.js";
2
- import { applyPatch } from "../../utils/json_patch.js";
3
- import { RemoteRunnable } from "../remote.js";
4
- test("invoke hosted langserve", async () => {
5
- const remote = new RemoteRunnable({
6
- url: `https://chat-langchain-backend.langchain.dev/chat`,
7
- });
8
- const result = await remote.invoke({
9
- question: "What is a document loader?",
10
- });
11
- console.log(result);
12
- });
13
- test("invoke hosted langserve error handling", async () => {
14
- const remote = new RemoteRunnable({
15
- url: `https://chat-langchain-backend.langchain.dev/nonexistent`,
16
- });
17
- await expect(async () => {
18
- await remote.invoke({
19
- question: "What is a document loader?",
20
- });
21
- }).rejects.toThrowError();
22
- });
23
- test("stream hosted langserve", async () => {
24
- const remote = new RemoteRunnable({
25
- url: `https://chat-langchain-backend.langchain.dev/chat`,
26
- });
27
- const result = await remote.stream({
28
- question: "What is a document loader?",
29
- });
30
- let totalByteSize = 0;
31
- for await (const chunk of result) {
32
- console.log(chunk);
33
- const jsonString = JSON.stringify(chunk);
34
- const byteSize = Buffer.byteLength(jsonString, "utf-8");
35
- totalByteSize += byteSize;
36
- }
37
- console.log("totalByteSize", totalByteSize);
38
- });
39
- test("stream error handling hosted langserve", async () => {
40
- const remote = new RemoteRunnable({
41
- url: `https://chat-langchain-backend.langchain.dev/nonexistent`,
42
- });
43
- await expect(async () => {
44
- const result = await remote.stream({
45
- question: "What is a document loader?",
46
- });
47
- for await (const chunk of result) {
48
- console.log(chunk);
49
- }
50
- }).rejects.toThrowError();
51
- });
52
- test("streamLog hosted langserve", async () => {
53
- const remote = new RemoteRunnable({
54
- url: `https://chat-langchain-backend.langchain.dev/chat`,
55
- });
56
- const result = await remote.streamLog({
57
- question: "What is a document loader?",
58
- });
59
- let totalByteSize = 0;
60
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
- let aggregate = {};
62
- for await (const chunk of result) {
63
- const jsonString = JSON.stringify(chunk);
64
- aggregate = applyPatch(aggregate, chunk.ops).newDocument;
65
- const byteSize = Buffer.byteLength(jsonString, "utf-8");
66
- totalByteSize += byteSize;
67
- }
68
- console.log("aggregate", aggregate);
69
- console.log("totalByteSize", totalByteSize);
70
- });
71
- test("streamLog error handling hosted langserve", async () => {
72
- const remote = new RemoteRunnable({
73
- url: `https://chat-langchain-backend.langchain.dev/nonexistent`,
74
- });
75
- const result = await remote.streamLog({
76
- question: "What is a document loader?",
77
- });
78
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
79
- await expect(async () => {
80
- for await (const chunk of result) {
81
- console.log(chunk);
82
- }
83
- }).rejects.toThrowError();
84
- });
85
- test("streamLog hosted langserve with concat syntax", async () => {
86
- const remote = new RemoteRunnable({
87
- url: `https://chat-langchain-backend.langchain.dev/chat`,
88
- });
89
- const result = await remote.streamLog({
90
- question: "What is a document loader?",
91
- });
92
- let totalByteSize = 0;
93
- let state;
94
- for await (const chunk of result) {
95
- if (!state) {
96
- state = chunk;
97
- }
98
- else {
99
- state = state.concat(chunk);
100
- }
101
- const jsonString = JSON.stringify(chunk);
102
- const byteSize = Buffer.byteLength(jsonString, "utf-8");
103
- totalByteSize += byteSize;
104
- }
105
- console.log("final state", state);
106
- console.log("totalByteSize", totalByteSize);
107
- });
108
- test.skip("stream events hosted langserve with concat syntax", async () => {
109
- const remote = new RemoteRunnable({
110
- url: `https://privateurl.com/pirate-speak/`,
111
- });
112
- const result = await remote.streamEvents({
113
- input: "What is a document loader?",
114
- chat_history: [new HumanMessage("What is a document loader?")],
115
- }, { version: "v1" });
116
- let totalByteSize = 0;
117
- const state = [];
118
- for await (const chunk of result) {
119
- console.log(chunk);
120
- state.push(chunk);
121
- const jsonString = JSON.stringify(chunk);
122
- const byteSize = Buffer.byteLength(jsonString, "utf-8");
123
- totalByteSize += byteSize;
124
- }
125
- // console.log("final state", state);
126
- console.log("totalByteSize", totalByteSize);
127
- });
128
- test.skip("streamLog with raw messages", async () => {
129
- const chain = new RemoteRunnable({
130
- url: "https://aimor-deployment-bf1e4ebc87365334b3b8a6b175fb4151-ffoprvkqsa-uc.a.run.app/",
131
- });
132
- const events = chain.streamLog([new HumanMessage("I'd like some advice!")], {
133
- configurable: { thread_id: "THREAD_ID", user_id: "USER_ID" },
134
- });
135
- for await (const logEvent of events) {
136
- console.log(logEvent);
137
- }
138
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,200 +0,0 @@
1
- /* eslint-disable no-promise-executor-return */
2
- /* eslint-disable @typescript-eslint/no-explicit-any */
3
- import { jest, test } from "@jest/globals";
4
- import { AIMessage, HumanMessage, SystemMessage, } from "../../messages/index.js";
5
- import { RemoteRunnable } from "../remote.js";
6
- import { ChatPromptValue } from "../../prompt_values.js";
7
- import { PromptTemplate } from "../../prompts/prompt.js";
8
- const BASE_URL = "http://my-langserve-endpoint";
9
- function respToStream(resp) {
10
- const chunks = resp.split("\n");
11
- return new ReadableStream({
12
- start(controller) {
13
- for (const chunk of chunks) {
14
- controller.enqueue(Buffer.from(`${chunk}\n`));
15
- }
16
- controller.close();
17
- },
18
- });
19
- }
20
- const aResp = `event: data
21
- data: ["a", "b", "c", "d"]
22
-
23
- event: end`;
24
- const bResp = `event: data
25
- data: {"content": "", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
26
-
27
- event: data
28
- data: {"content": "\\"", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
29
-
30
- event: data
31
- data: {"content": "object", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
32
-
33
- event: data
34
- data: {"content": "1", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
35
-
36
- event: data
37
- data: {"content": ",", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
38
-
39
- event: data
40
- data: {"content": " object", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
41
-
42
- event: data
43
- data: {"content": "2", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
44
-
45
- event: data
46
- data: {"content": ",", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
47
-
48
- event: data
49
- data: {"content": " object", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
50
-
51
- event: data
52
- data: {"content": "3", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
53
-
54
- event: data
55
- data: {"content": ",", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
56
-
57
- event: data
58
- data: {"content": " object", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
59
-
60
- event: data
61
- data: {"content": "4", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
62
-
63
- event: data
64
- data: {"content": ",", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
65
-
66
- event: data
67
- data: {"content": " object", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
68
-
69
- event: data
70
- data: {"content": "5", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
71
-
72
- event: data
73
- data: {"content": "\\"", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
74
-
75
- event: data
76
- data: {"content": "", "additional_kwargs": {}, "type": "AIMessageChunk", "example": false}
77
-
78
- event: end`;
79
- const strangeTypesResp = `event: data
80
- data: {"content": "what is a document loader", "additional_kwargs": {}, "type": "human", "example": false}
81
-
82
- event: data
83
- data: {"messages":[{"content":"You are an expert programmer and problem-solver, tasked with answering any question about Langchain.","type":"system","additional_kwargs":{}},{"content":"I am an AI","type":"ai","additional_kwargs":{}}]}
84
-
85
- event: end`;
86
- describe("RemoteRunnable", () => {
87
- beforeEach(() => {
88
- // mock langserve service
89
- const returnDataByEndpoint = {
90
- "/a/invoke": JSON.stringify({ output: ["a", "b", "c"] }),
91
- "/a/batch": JSON.stringify({
92
- output: [
93
- ["a", "b", "c"],
94
- ["d", "e", "f"],
95
- ],
96
- }),
97
- "/a/stream": respToStream(aResp),
98
- "/b/stream": respToStream(bResp),
99
- "/strange_types/stream": respToStream(strangeTypesResp),
100
- };
101
- const oldFetch = global.fetch;
102
- global.fetch = jest
103
- .fn()
104
- .mockImplementation(async (url, init) => {
105
- if (!url.startsWith(BASE_URL))
106
- return await oldFetch(url, init);
107
- const { pathname } = new URL(url);
108
- const resp = new Response(returnDataByEndpoint[pathname]);
109
- return resp;
110
- });
111
- });
112
- afterEach(() => {
113
- jest.clearAllMocks();
114
- });
115
- test("Invoke local langserve", async () => {
116
- // mock fetch, expect /invoke
117
- const remote = new RemoteRunnable({ url: `${BASE_URL}/a` });
118
- const result = await remote.invoke({ text: "string" });
119
- expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/a/invoke`, expect.objectContaining({
120
- body: '{"input":{"text":"string"},"config":{"tags":[],"metadata":{},"recursionLimit":25},"kwargs":{}}',
121
- }));
122
- expect(result).toEqual(["a", "b", "c"]);
123
- });
124
- test("Invoke local langserve passing a configurable object", async () => {
125
- // mock fetch, expect /invoke
126
- const remote = new RemoteRunnable({ url: `${BASE_URL}/a` });
127
- const result = await remote.invoke({ text: "string" }, {
128
- configurable: {
129
- destination: "destination",
130
- integration_id: "integration_id",
131
- user_id: "user_id",
132
- },
133
- });
134
- expect(fetch).toHaveBeenCalledWith(`${BASE_URL}/a/invoke`, expect.objectContaining({
135
- body: expect.any(String),
136
- }));
137
- expect(result).toEqual(["a", "b", "c"]);
138
- });
139
- test("Batch local langserve", async () => {
140
- const returnData = [
141
- ["a", "b", "c"],
142
- ["d", "e", "f"],
143
- ];
144
- const remote = new RemoteRunnable({ url: `${BASE_URL}/a` });
145
- const result = await remote.batch([{ text: "1" }, { text: "2" }]);
146
- expect(result).toEqual(returnData);
147
- });
148
- test("Stream local langserve", async () => {
149
- const remote = new RemoteRunnable({ url: `${BASE_URL}/a` });
150
- const stream = await remote.stream({ text: "What are the 5 best apples?" });
151
- let chunkCount = 0;
152
- for await (const chunk of stream) {
153
- expect(chunk).toEqual(["a", "b", "c", "d"]);
154
- chunkCount += 1;
155
- }
156
- expect(chunkCount).toBe(1);
157
- });
158
- test("Stream model output", async () => {
159
- const remote = new RemoteRunnable({ url: `${BASE_URL}/b` });
160
- const stream = await remote.stream({ text: "What are the 5 best apples?" });
161
- let chunkCount = 0;
162
- let accumulator = null;
163
- for await (const chunk of stream) {
164
- const innerChunk = chunk;
165
- accumulator = accumulator ? accumulator.concat(innerChunk) : innerChunk;
166
- chunkCount += 1;
167
- }
168
- expect(chunkCount).toBe(18);
169
- expect(accumulator?.content).toEqual('"object1, object2, object3, object4, object5"');
170
- });
171
- test("Stream legacy data type formats", async () => {
172
- const remote = new RemoteRunnable({ url: `${BASE_URL}/strange_types` });
173
- const stream = await remote.stream({ text: "What are the 5 best apples?" });
174
- const chunks = [];
175
- for await (const chunk of stream) {
176
- console.log(chunk);
177
- chunks.push(chunk);
178
- }
179
- expect(chunks[0]).toBeInstanceOf(HumanMessage);
180
- expect(chunks[1]).toBeInstanceOf(ChatPromptValue);
181
- expect(chunks[1].messages[0]).toBeInstanceOf(SystemMessage);
182
- expect(chunks[1].messages[1]).toBeInstanceOf(AIMessage);
183
- });
184
- test("Streaming in a chain with model output", async () => {
185
- const remote = new RemoteRunnable({ url: `${BASE_URL}/b` });
186
- const prompt = PromptTemplate.fromTemplate("");
187
- const chunks = await prompt
188
- .pipe(remote)
189
- .stream({ text: "What are the 5 best apples?" });
190
- let chunkCount = 0;
191
- let accumulator = null;
192
- for await (const chunk of chunks) {
193
- const innerChunk = chunk;
194
- accumulator = accumulator ? accumulator.concat(innerChunk) : innerChunk;
195
- chunkCount += 1;
196
- }
197
- expect(chunkCount).toBe(18);
198
- expect(accumulator?.content).toEqual('"object1, object2, object3, object4, object5"');
199
- });
200
- });
@@ -1 +0,0 @@
1
- export {};