@langchain/core 0.2.21 → 0.2.22-rc.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.
|
@@ -229,6 +229,19 @@ function serialize(input) {
|
|
|
229
229
|
}
|
|
230
230
|
return input;
|
|
231
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* Client for interacting with LangChain runnables
|
|
234
|
+
* that are hosted as LangServe endpoints.
|
|
235
|
+
*
|
|
236
|
+
* Allows you to interact with hosted runnables using the standard
|
|
237
|
+
* `.invoke()`, `.stream()`, `.streamEvents()`, etc. methods that
|
|
238
|
+
* other runnables support.
|
|
239
|
+
*
|
|
240
|
+
* @param url - The base URL of the LangServe endpoint.
|
|
241
|
+
* @param options - Optional configuration for the remote runnable, including timeout and headers.
|
|
242
|
+
* @param fetch - Optional custom fetch implementation.
|
|
243
|
+
* @param fetchRequestOptions - Optional additional options for fetch requests.
|
|
244
|
+
*/
|
|
232
245
|
class RemoteRunnable extends base_js_1.Runnable {
|
|
233
246
|
constructor(fields) {
|
|
234
247
|
super(fields);
|
|
@@ -244,25 +257,43 @@ class RemoteRunnable extends base_js_1.Runnable {
|
|
|
244
257
|
writable: true,
|
|
245
258
|
value: void 0
|
|
246
259
|
});
|
|
260
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
261
|
+
Object.defineProperty(this, "fetchImplementation", {
|
|
262
|
+
enumerable: true,
|
|
263
|
+
configurable: true,
|
|
264
|
+
writable: true,
|
|
265
|
+
value: fetch
|
|
266
|
+
});
|
|
267
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
268
|
+
Object.defineProperty(this, "fetchRequestOptions", {
|
|
269
|
+
enumerable: true,
|
|
270
|
+
configurable: true,
|
|
271
|
+
writable: true,
|
|
272
|
+
value: void 0
|
|
273
|
+
});
|
|
247
274
|
Object.defineProperty(this, "lc_namespace", {
|
|
248
275
|
enumerable: true,
|
|
249
276
|
configurable: true,
|
|
250
277
|
writable: true,
|
|
251
278
|
value: ["langchain", "schema", "runnable", "remote"]
|
|
252
279
|
});
|
|
253
|
-
const { url, options } = fields;
|
|
280
|
+
const { url, options, fetch: fetchImplementation, fetchRequestOptions, } = fields;
|
|
254
281
|
this.url = url.replace(/\/$/, ""); // remove trailing slash
|
|
255
282
|
this.options = options;
|
|
283
|
+
this.fetchImplementation = fetchImplementation ?? this.fetchImplementation;
|
|
284
|
+
this.fetchRequestOptions = fetchRequestOptions;
|
|
256
285
|
}
|
|
257
286
|
async post(path, body, signal) {
|
|
258
|
-
return
|
|
287
|
+
return this.fetchImplementation(`${this.url}${path}`, {
|
|
259
288
|
method: "POST",
|
|
260
289
|
body: JSON.stringify(serialize(body)),
|
|
290
|
+
signal: signal ?? AbortSignal.timeout(this.options?.timeout ?? 60000),
|
|
291
|
+
...this.fetchRequestOptions,
|
|
261
292
|
headers: {
|
|
262
293
|
"Content-Type": "application/json",
|
|
294
|
+
...this.fetchRequestOptions?.headers,
|
|
263
295
|
...this.options?.headers,
|
|
264
296
|
},
|
|
265
|
-
signal: signal ?? AbortSignal.timeout(this.options?.timeout ?? 60000),
|
|
266
297
|
});
|
|
267
298
|
}
|
|
268
299
|
async _invoke(input, options, _) {
|
|
@@ -7,13 +7,30 @@ type RemoteRunnableOptions = {
|
|
|
7
7
|
timeout?: number;
|
|
8
8
|
headers?: Record<string, unknown>;
|
|
9
9
|
};
|
|
10
|
+
/**
|
|
11
|
+
* Client for interacting with LangChain runnables
|
|
12
|
+
* that are hosted as LangServe endpoints.
|
|
13
|
+
*
|
|
14
|
+
* Allows you to interact with hosted runnables using the standard
|
|
15
|
+
* `.invoke()`, `.stream()`, `.streamEvents()`, etc. methods that
|
|
16
|
+
* other runnables support.
|
|
17
|
+
*
|
|
18
|
+
* @param url - The base URL of the LangServe endpoint.
|
|
19
|
+
* @param options - Optional configuration for the remote runnable, including timeout and headers.
|
|
20
|
+
* @param fetch - Optional custom fetch implementation.
|
|
21
|
+
* @param fetchRequestOptions - Optional additional options for fetch requests.
|
|
22
|
+
*/
|
|
10
23
|
export declare class RemoteRunnable<RunInput, RunOutput, CallOptions extends RunnableConfig> extends Runnable<RunInput, RunOutput, CallOptions> {
|
|
11
24
|
private url;
|
|
12
25
|
private options?;
|
|
26
|
+
fetchImplementation: (...args: any[]) => any;
|
|
27
|
+
fetchRequestOptions?: Record<string, any>;
|
|
13
28
|
lc_namespace: string[];
|
|
14
29
|
constructor(fields: {
|
|
15
30
|
url: string;
|
|
16
31
|
options?: RemoteRunnableOptions;
|
|
32
|
+
fetch?: (...args: any[]) => any;
|
|
33
|
+
fetchRequestOptions?: Record<string, any>;
|
|
17
34
|
});
|
|
18
35
|
private post;
|
|
19
36
|
_invoke(input: RunInput, options?: Partial<CallOptions>, _?: CallbackManagerForChainRun): Promise<RunOutput>;
|
package/dist/runnables/remote.js
CHANGED
|
@@ -226,6 +226,19 @@ function serialize(input) {
|
|
|
226
226
|
}
|
|
227
227
|
return input;
|
|
228
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Client for interacting with LangChain runnables
|
|
231
|
+
* that are hosted as LangServe endpoints.
|
|
232
|
+
*
|
|
233
|
+
* Allows you to interact with hosted runnables using the standard
|
|
234
|
+
* `.invoke()`, `.stream()`, `.streamEvents()`, etc. methods that
|
|
235
|
+
* other runnables support.
|
|
236
|
+
*
|
|
237
|
+
* @param url - The base URL of the LangServe endpoint.
|
|
238
|
+
* @param options - Optional configuration for the remote runnable, including timeout and headers.
|
|
239
|
+
* @param fetch - Optional custom fetch implementation.
|
|
240
|
+
* @param fetchRequestOptions - Optional additional options for fetch requests.
|
|
241
|
+
*/
|
|
229
242
|
export class RemoteRunnable extends Runnable {
|
|
230
243
|
constructor(fields) {
|
|
231
244
|
super(fields);
|
|
@@ -241,25 +254,43 @@ export class RemoteRunnable extends Runnable {
|
|
|
241
254
|
writable: true,
|
|
242
255
|
value: void 0
|
|
243
256
|
});
|
|
257
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
258
|
+
Object.defineProperty(this, "fetchImplementation", {
|
|
259
|
+
enumerable: true,
|
|
260
|
+
configurable: true,
|
|
261
|
+
writable: true,
|
|
262
|
+
value: fetch
|
|
263
|
+
});
|
|
264
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
265
|
+
Object.defineProperty(this, "fetchRequestOptions", {
|
|
266
|
+
enumerable: true,
|
|
267
|
+
configurable: true,
|
|
268
|
+
writable: true,
|
|
269
|
+
value: void 0
|
|
270
|
+
});
|
|
244
271
|
Object.defineProperty(this, "lc_namespace", {
|
|
245
272
|
enumerable: true,
|
|
246
273
|
configurable: true,
|
|
247
274
|
writable: true,
|
|
248
275
|
value: ["langchain", "schema", "runnable", "remote"]
|
|
249
276
|
});
|
|
250
|
-
const { url, options } = fields;
|
|
277
|
+
const { url, options, fetch: fetchImplementation, fetchRequestOptions, } = fields;
|
|
251
278
|
this.url = url.replace(/\/$/, ""); // remove trailing slash
|
|
252
279
|
this.options = options;
|
|
280
|
+
this.fetchImplementation = fetchImplementation ?? this.fetchImplementation;
|
|
281
|
+
this.fetchRequestOptions = fetchRequestOptions;
|
|
253
282
|
}
|
|
254
283
|
async post(path, body, signal) {
|
|
255
|
-
return
|
|
284
|
+
return this.fetchImplementation(`${this.url}${path}`, {
|
|
256
285
|
method: "POST",
|
|
257
286
|
body: JSON.stringify(serialize(body)),
|
|
287
|
+
signal: signal ?? AbortSignal.timeout(this.options?.timeout ?? 60000),
|
|
288
|
+
...this.fetchRequestOptions,
|
|
258
289
|
headers: {
|
|
259
290
|
"Content-Type": "application/json",
|
|
291
|
+
...this.fetchRequestOptions?.headers,
|
|
260
292
|
...this.options?.headers,
|
|
261
293
|
},
|
|
262
|
-
signal: signal ?? AbortSignal.timeout(this.options?.timeout ?? 60000),
|
|
263
294
|
});
|
|
264
295
|
}
|
|
265
296
|
async _invoke(input, options, _) {
|
|
@@ -15,21 +15,43 @@ exports.EventStreamContentType = "text/event-stream";
|
|
|
15
15
|
* @param onChunk A function that will be called on each new byte chunk in the stream.
|
|
16
16
|
* @returns {Promise<void>} A promise that will be resolved when the stream closes.
|
|
17
17
|
*/
|
|
18
|
-
async function getBytes(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
async function getBytes(
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
stream, onChunk) {
|
|
21
|
+
// eslint-disable-next-line no-instanceof/no-instanceof
|
|
22
|
+
if (stream instanceof ReadableStream) {
|
|
23
|
+
const reader = stream.getReader();
|
|
24
|
+
// CHANGED: Introduced a "flush" mechanism to process potential pending messages when the stream ends.
|
|
25
|
+
// This change is essential to ensure that we capture every last piece of information from streams,
|
|
26
|
+
// such as those from Azure OpenAI, which may not terminate with a blank line. Without this
|
|
27
|
+
// mechanism, we risk ignoring a possibly significant last message.
|
|
28
|
+
// See https://github.com/langchain-ai/langchainjs/issues/1299 for details.
|
|
29
|
+
// eslint-disable-next-line no-constant-condition
|
|
30
|
+
while (true) {
|
|
31
|
+
const result = await reader.read();
|
|
32
|
+
if (result.done) {
|
|
33
|
+
onChunk(new Uint8Array(), true);
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
onChunk(result.value);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
try {
|
|
41
|
+
// Handle Node.js Readable streams with async iteration
|
|
42
|
+
for await (const chunk of stream) {
|
|
43
|
+
onChunk(new Uint8Array(chunk));
|
|
44
|
+
}
|
|
29
45
|
onChunk(new Uint8Array(), true);
|
|
30
|
-
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
throw new Error([
|
|
50
|
+
"Parsing event source stream failed.",
|
|
51
|
+
"Ensure your implementation of fetch returns a web or Node readable stream.",
|
|
52
|
+
`Error: ${e.message}`,
|
|
53
|
+
].join("\n"));
|
|
31
54
|
}
|
|
32
|
-
onChunk(result.value);
|
|
33
55
|
}
|
|
34
56
|
}
|
|
35
57
|
exports.getBytes = getBytes;
|
|
@@ -20,7 +20,7 @@ export interface EventSourceMessage {
|
|
|
20
20
|
* @param onChunk A function that will be called on each new byte chunk in the stream.
|
|
21
21
|
* @returns {Promise<void>} A promise that will be resolved when the stream closes.
|
|
22
22
|
*/
|
|
23
|
-
export declare function getBytes(stream: ReadableStream<Uint8Array>, onChunk: (arr: Uint8Array, flush?: boolean) => void): Promise<void>;
|
|
23
|
+
export declare function getBytes(stream: ReadableStream<Uint8Array> | AsyncIterable<any>, onChunk: (arr: Uint8Array, flush?: boolean) => void): Promise<void>;
|
|
24
24
|
/**
|
|
25
25
|
* Parses arbitary byte chunks into EventSource line buffers.
|
|
26
26
|
* Each line should be of the format "field: value" and ends with \r, \n, or \r\n.
|
|
@@ -12,21 +12,43 @@ export const EventStreamContentType = "text/event-stream";
|
|
|
12
12
|
* @param onChunk A function that will be called on each new byte chunk in the stream.
|
|
13
13
|
* @returns {Promise<void>} A promise that will be resolved when the stream closes.
|
|
14
14
|
*/
|
|
15
|
-
export async function getBytes(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
export async function getBytes(
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
stream, onChunk) {
|
|
18
|
+
// eslint-disable-next-line no-instanceof/no-instanceof
|
|
19
|
+
if (stream instanceof ReadableStream) {
|
|
20
|
+
const reader = stream.getReader();
|
|
21
|
+
// CHANGED: Introduced a "flush" mechanism to process potential pending messages when the stream ends.
|
|
22
|
+
// This change is essential to ensure that we capture every last piece of information from streams,
|
|
23
|
+
// such as those from Azure OpenAI, which may not terminate with a blank line. Without this
|
|
24
|
+
// mechanism, we risk ignoring a possibly significant last message.
|
|
25
|
+
// See https://github.com/langchain-ai/langchainjs/issues/1299 for details.
|
|
26
|
+
// eslint-disable-next-line no-constant-condition
|
|
27
|
+
while (true) {
|
|
28
|
+
const result = await reader.read();
|
|
29
|
+
if (result.done) {
|
|
30
|
+
onChunk(new Uint8Array(), true);
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
onChunk(result.value);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
try {
|
|
38
|
+
// Handle Node.js Readable streams with async iteration
|
|
39
|
+
for await (const chunk of stream) {
|
|
40
|
+
onChunk(new Uint8Array(chunk));
|
|
41
|
+
}
|
|
26
42
|
onChunk(new Uint8Array(), true);
|
|
27
|
-
|
|
43
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
throw new Error([
|
|
47
|
+
"Parsing event source stream failed.",
|
|
48
|
+
"Ensure your implementation of fetch returns a web or Node readable stream.",
|
|
49
|
+
`Error: ${e.message}`,
|
|
50
|
+
].join("\n"));
|
|
28
51
|
}
|
|
29
|
-
onChunk(result.value);
|
|
30
52
|
}
|
|
31
53
|
}
|
|
32
54
|
/**
|