From 0560c29c67221989c87824edf2aef8ab89e7ceaa Mon Sep 17 00:00:00 2001 From: bracesproul Date: Thu, 5 Dec 2024 11:24:12 -0800 Subject: [PATCH 1/5] fix(langchain-core): Pick runnable config keys in asynclocalstorage --- langchain-core/src/runnables/base.ts | 5 +++-- langchain-core/src/runnables/iter.ts | 5 +++-- langchain-core/src/tools/index.ts | 5 +++-- langchain-core/src/utils/stream.ts | 23 +++++++++++++++++++++-- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/langchain-core/src/runnables/base.ts b/langchain-core/src/runnables/base.ts index 1cab402513ec..68d4dfae2a91 100644 --- a/langchain-core/src/runnables/base.ts +++ b/langchain-core/src/runnables/base.ts @@ -29,6 +29,7 @@ import { atee, pipeGeneratorWithSetup, AsyncGeneratorWithSetup, + pickRunnableConfigKeys, } from "../utils/stream.js"; import { raceWithSignal } from "../utils/signal.js"; import { @@ -2529,7 +2530,7 @@ export class RunnableLambda< recursionLimit: (config?.recursionLimit ?? DEFAULT_RECURSION_LIMIT) - 1, }); void AsyncLocalStorageProviderSingleton.runWithConfig( - childConfig, + pickRunnableConfigKeys(childConfig), async () => { try { let output = await this.func(input, { @@ -2627,7 +2628,7 @@ export class RunnableLambda< const output = await new Promise( (resolve, reject) => { void AsyncLocalStorageProviderSingleton.runWithConfig( - childConfig, + pickRunnableConfigKeys(childConfig), async () => { try { const res = await this.func(finalChunk as RunInput, { diff --git a/langchain-core/src/runnables/iter.ts b/langchain-core/src/runnables/iter.ts index 52b7a61db06a..f915697cc7ce 100644 --- a/langchain-core/src/runnables/iter.ts +++ b/langchain-core/src/runnables/iter.ts @@ -1,4 +1,5 @@ import { AsyncLocalStorageProviderSingleton } from "../singletons/index.js"; +import { pickRunnableConfigKeys } from "../utils/stream.js"; import { RunnableConfig } from "./config.js"; export function isIterableIterator( @@ -36,7 +37,7 @@ export function* consumeIteratorInContext( ): IterableIterator { while (true) { const { value, done } = AsyncLocalStorageProviderSingleton.runWithConfig( - context, + pickRunnableConfigKeys(context), iter.next.bind(iter), true ); @@ -56,7 +57,7 @@ export async function* consumeAsyncIterableInContext( while (true) { const { value, done } = await AsyncLocalStorageProviderSingleton.runWithConfig( - context, + pickRunnableConfigKeys(context), iterator.next.bind(iter), true ); diff --git a/langchain-core/src/tools/index.ts b/langchain-core/src/tools/index.ts index 348e85103904..833b50dba213 100644 --- a/langchain-core/src/tools/index.ts +++ b/langchain-core/src/tools/index.ts @@ -20,6 +20,7 @@ import { MessageContent } from "../messages/base.js"; import { AsyncLocalStorageProviderSingleton } from "../singletons/index.js"; import { _isToolCall, ToolInputParsingException } from "./utils.js"; import { isZodSchema } from "../utils/types/is_zod_schema.js"; +import { pickRunnableConfigKeys } from "../utils/stream.js"; export { ToolInputParsingException }; @@ -594,7 +595,7 @@ export function tool< callbacks: runManager?.getChild(), }); void AsyncLocalStorageProviderSingleton.runWithConfig( - childConfig, + pickRunnableConfigKeys(childConfig), async () => { try { // TS doesn't restrict the type here based on the guard above @@ -625,7 +626,7 @@ export function tool< callbacks: runManager?.getChild(), }); void AsyncLocalStorageProviderSingleton.runWithConfig( - childConfig, + pickRunnableConfigKeys(childConfig), async () => { try { // TS doesn't restrict the type here based on the guard above diff --git a/langchain-core/src/utils/stream.ts b/langchain-core/src/utils/stream.ts index aa9db0604637..8cca6cf3bd6a 100644 --- a/langchain-core/src/utils/stream.ts +++ b/langchain-core/src/utils/stream.ts @@ -1,3 +1,4 @@ +import { RunnableConfig } from "../../runnables.js"; import { AsyncLocalStorageProviderSingleton } from "../singletons/index.js"; import { raceWithSignal } from "./signal.js"; @@ -180,6 +181,24 @@ export function concat< } } +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function pickRunnableConfigKeys>( + config?: CallOptions +): RunnableConfig | undefined { + return config + ? { + configurable: config.configurable, + recursionLimit: config.recursionLimit, + callbacks: config.callbacks, + tags: config.tags, + metadata: config.metadata, + maxConcurrency: config.maxConcurrency, + timeout: config.timeout, + signal: config.signal, + } + : undefined; +} + export class AsyncGeneratorWithSetup< S = unknown, T = unknown, @@ -215,7 +234,7 @@ export class AsyncGeneratorWithSetup< // to each generator is available. this.setup = new Promise((resolve, reject) => { void AsyncLocalStorageProviderSingleton.runWithConfig( - params.config, + pickRunnableConfigKeys(params.config as RunnableConfig), async () => { this.firstResult = params.generator.next(); if (params.startSetup) { @@ -238,7 +257,7 @@ export class AsyncGeneratorWithSetup< } return AsyncLocalStorageProviderSingleton.runWithConfig( - this.config, + pickRunnableConfigKeys(this.config as RunnableConfig), this.signal ? async () => { return raceWithSignal(this.generator.next(...args), this.signal); From d532c22893882ed5f31bb1714dd6d051814fb6a9 Mon Sep 17 00:00:00 2001 From: bracesproul Date: Thu, 5 Dec 2024 12:51:31 -0800 Subject: [PATCH 2/5] reorg bc circular dep --- langchain-core/src/runnables/base.ts | 2 +- langchain-core/src/runnables/iter.ts | 3 +-- langchain-core/src/runnables/types.ts | 20 ++++++++++++++- langchain-core/src/tools/index.ts | 2 +- langchain-core/src/types/stream.ts | 5 ++++ langchain-core/src/utils/stream.ts | 37 ++++++++------------------- 6 files changed, 38 insertions(+), 31 deletions(-) create mode 100644 langchain-core/src/types/stream.ts diff --git a/langchain-core/src/runnables/base.ts b/langchain-core/src/runnables/base.ts index 68d4dfae2a91..4a8c9dd65d09 100644 --- a/langchain-core/src/runnables/base.ts +++ b/langchain-core/src/runnables/base.ts @@ -29,7 +29,6 @@ import { atee, pipeGeneratorWithSetup, AsyncGeneratorWithSetup, - pickRunnableConfigKeys, } from "../utils/stream.js"; import { raceWithSignal } from "../utils/signal.js"; import { @@ -56,6 +55,7 @@ import { } from "./iter.js"; import { _isToolCall, ToolInputParsingException } from "../tools/utils.js"; import { ToolCall } from "../messages/tool.js"; +import { pickRunnableConfigKeys } from "./types.js"; export { type RunnableInterface, RunnableBatchOptions }; diff --git a/langchain-core/src/runnables/iter.ts b/langchain-core/src/runnables/iter.ts index f915697cc7ce..2571cd490372 100644 --- a/langchain-core/src/runnables/iter.ts +++ b/langchain-core/src/runnables/iter.ts @@ -1,6 +1,5 @@ import { AsyncLocalStorageProviderSingleton } from "../singletons/index.js"; -import { pickRunnableConfigKeys } from "../utils/stream.js"; -import { RunnableConfig } from "./config.js"; +import { pickRunnableConfigKeys, type RunnableConfig } from "./types.js"; export function isIterableIterator( thing: unknown diff --git a/langchain-core/src/runnables/types.ts b/langchain-core/src/runnables/types.ts index f40d80ee3831..3d699c990135 100644 --- a/langchain-core/src/runnables/types.ts +++ b/langchain-core/src/runnables/types.ts @@ -1,7 +1,7 @@ import type { z } from "zod"; -import type { IterableReadableStreamInterface } from "../utils/stream.js"; import type { SerializableInterface } from "../load/serializable.js"; import type { BaseCallbackConfig } from "../callbacks/manager.js"; +import type { IterableReadableStreamInterface } from "../types/stream.js"; export type RunnableBatchOptions = { /** @deprecated Pass in via the standard runnable config object instead */ @@ -108,3 +108,21 @@ export interface RunnableConfig< */ signal?: AbortSignal; } + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function pickRunnableConfigKeys>( + config?: CallOptions +): RunnableConfig | undefined { + return config + ? { + configurable: config.configurable, + recursionLimit: config.recursionLimit, + callbacks: config.callbacks, + tags: config.tags, + metadata: config.metadata, + maxConcurrency: config.maxConcurrency, + timeout: config.timeout, + signal: config.signal, + } + : undefined; +} diff --git a/langchain-core/src/tools/index.ts b/langchain-core/src/tools/index.ts index 833b50dba213..7e311fb1dc24 100644 --- a/langchain-core/src/tools/index.ts +++ b/langchain-core/src/tools/index.ts @@ -20,7 +20,7 @@ import { MessageContent } from "../messages/base.js"; import { AsyncLocalStorageProviderSingleton } from "../singletons/index.js"; import { _isToolCall, ToolInputParsingException } from "./utils.js"; import { isZodSchema } from "../utils/types/is_zod_schema.js"; -import { pickRunnableConfigKeys } from "../utils/stream.js"; +import { pickRunnableConfigKeys } from "../runnables/types.js"; export { ToolInputParsingException }; diff --git a/langchain-core/src/types/stream.ts b/langchain-core/src/types/stream.ts new file mode 100644 index 000000000000..ae03b69b78bb --- /dev/null +++ b/langchain-core/src/types/stream.ts @@ -0,0 +1,5 @@ +// Make this a type to override ReadableStream's async iterator type in case +// the popular web-streams-polyfill is imported - the supplied types +// in that case don't quite match. +export type IterableReadableStreamInterface = ReadableStream & + AsyncIterable; diff --git a/langchain-core/src/utils/stream.ts b/langchain-core/src/utils/stream.ts index 8cca6cf3bd6a..123a6b64ca8e 100644 --- a/langchain-core/src/utils/stream.ts +++ b/langchain-core/src/utils/stream.ts @@ -1,12 +1,11 @@ -import { RunnableConfig } from "../../runnables.js"; +import { pickRunnableConfigKeys } from "../runnables/types.js"; import { AsyncLocalStorageProviderSingleton } from "../singletons/index.js"; +import { IterableReadableStreamInterface } from "../types/stream.js"; import { raceWithSignal } from "./signal.js"; -// Make this a type to override ReadableStream's async iterator type in case -// the popular web-streams-polyfill is imported - the supplied types -// in that case don't quite match. -export type IterableReadableStreamInterface = ReadableStream & - AsyncIterable; +// Re-exported for backwards compatibility +// Do NOT import this type from this file inside the project. Instead, always import from `types/stream.js` +export { IterableReadableStreamInterface }; /* * Support async iterator syntax for ReadableStreams in all environments. @@ -181,24 +180,6 @@ export function concat< } } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function pickRunnableConfigKeys>( - config?: CallOptions -): RunnableConfig | undefined { - return config - ? { - configurable: config.configurable, - recursionLimit: config.recursionLimit, - callbacks: config.callbacks, - tags: config.tags, - metadata: config.metadata, - maxConcurrency: config.maxConcurrency, - timeout: config.timeout, - signal: config.signal, - } - : undefined; -} - export class AsyncGeneratorWithSetup< S = unknown, T = unknown, @@ -234,7 +215,9 @@ export class AsyncGeneratorWithSetup< // to each generator is available. this.setup = new Promise((resolve, reject) => { void AsyncLocalStorageProviderSingleton.runWithConfig( - pickRunnableConfigKeys(params.config as RunnableConfig), + pickRunnableConfigKeys( + params.config as Record | undefined + ), async () => { this.firstResult = params.generator.next(); if (params.startSetup) { @@ -257,7 +240,9 @@ export class AsyncGeneratorWithSetup< } return AsyncLocalStorageProviderSingleton.runWithConfig( - pickRunnableConfigKeys(this.config as RunnableConfig), + pickRunnableConfigKeys( + this.config as Record | undefined + ), this.signal ? async () => { return raceWithSignal(this.generator.next(...args), this.signal); From bca8815f764697e377e1018690daedc49111cbd7 Mon Sep 17 00:00:00 2001 From: bracesproul Date: Thu, 5 Dec 2024 13:04:13 -0800 Subject: [PATCH 3/5] crt --- langchain-core/src/runnables/base.ts | 5 ++--- langchain-core/src/runnables/config.ts | 18 ++++++++++++++++++ langchain-core/src/runnables/iter.ts | 3 ++- langchain-core/src/runnables/types.ts | 18 ------------------ langchain-core/src/tools/index.ts | 2 +- langchain-core/src/utils/stream.ts | 2 +- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/langchain-core/src/runnables/base.ts b/langchain-core/src/runnables/base.ts index 4a8c9dd65d09..5c545455ea14 100644 --- a/langchain-core/src/runnables/base.ts +++ b/langchain-core/src/runnables/base.ts @@ -6,7 +6,7 @@ import { type TraceableFunction, isTraceableFunction, } from "langsmith/singletons/traceable"; -import type { RunnableInterface, RunnableBatchOptions } from "./types.js"; +import type { RunnableInterface, RunnableBatchOptions, RunnableConfig } from "./types.js"; import { CallbackManagerForChainRun } from "../callbacks/manager.js"; import { LogStreamCallbackHandler, @@ -33,11 +33,11 @@ import { import { raceWithSignal } from "../utils/signal.js"; import { DEFAULT_RECURSION_LIMIT, - RunnableConfig, ensureConfig, getCallbackManagerForConfig, mergeConfigs, patchConfig, + pickRunnableConfigKeys, } from "./config.js"; import { AsyncCaller } from "../utils/async_caller.js"; import { Run } from "../tracers/base.js"; @@ -55,7 +55,6 @@ import { } from "./iter.js"; import { _isToolCall, ToolInputParsingException } from "../tools/utils.js"; import { ToolCall } from "../messages/tool.js"; -import { pickRunnableConfigKeys } from "./types.js"; export { type RunnableInterface, RunnableBatchOptions }; diff --git a/langchain-core/src/runnables/config.ts b/langchain-core/src/runnables/config.ts index 8fa9a244ee3d..aae7164b5721 100644 --- a/langchain-core/src/runnables/config.ts +++ b/langchain-core/src/runnables/config.ts @@ -233,3 +233,21 @@ export function patchConfig( } return newConfig; } + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function pickRunnableConfigKeys>( + config?: CallOptions +): Partial | undefined { + return config + ? { + configurable: config.configurable, + recursionLimit: config.recursionLimit, + callbacks: config.callbacks, + tags: config.tags, + metadata: config.metadata, + maxConcurrency: config.maxConcurrency, + timeout: config.timeout, + signal: config.signal, + } + : undefined; +} diff --git a/langchain-core/src/runnables/iter.ts b/langchain-core/src/runnables/iter.ts index 2571cd490372..ae6b9a47aa78 100644 --- a/langchain-core/src/runnables/iter.ts +++ b/langchain-core/src/runnables/iter.ts @@ -1,5 +1,6 @@ +import type { RunnableConfig } from "../../dist/runnables/types.js"; import { AsyncLocalStorageProviderSingleton } from "../singletons/index.js"; -import { pickRunnableConfigKeys, type RunnableConfig } from "./types.js"; +import { pickRunnableConfigKeys } from "./config.js"; export function isIterableIterator( thing: unknown diff --git a/langchain-core/src/runnables/types.ts b/langchain-core/src/runnables/types.ts index 3d699c990135..f06e94fa1254 100644 --- a/langchain-core/src/runnables/types.ts +++ b/langchain-core/src/runnables/types.ts @@ -108,21 +108,3 @@ export interface RunnableConfig< */ signal?: AbortSignal; } - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function pickRunnableConfigKeys>( - config?: CallOptions -): RunnableConfig | undefined { - return config - ? { - configurable: config.configurable, - recursionLimit: config.recursionLimit, - callbacks: config.callbacks, - tags: config.tags, - metadata: config.metadata, - maxConcurrency: config.maxConcurrency, - timeout: config.timeout, - signal: config.signal, - } - : undefined; -} diff --git a/langchain-core/src/tools/index.ts b/langchain-core/src/tools/index.ts index 7e311fb1dc24..8ce02d28c935 100644 --- a/langchain-core/src/tools/index.ts +++ b/langchain-core/src/tools/index.ts @@ -12,6 +12,7 @@ import { import { ensureConfig, patchConfig, + pickRunnableConfigKeys, type RunnableConfig, } from "../runnables/config.js"; import type { RunnableFunc, RunnableInterface } from "../runnables/base.js"; @@ -20,7 +21,6 @@ import { MessageContent } from "../messages/base.js"; import { AsyncLocalStorageProviderSingleton } from "../singletons/index.js"; import { _isToolCall, ToolInputParsingException } from "./utils.js"; import { isZodSchema } from "../utils/types/is_zod_schema.js"; -import { pickRunnableConfigKeys } from "../runnables/types.js"; export { ToolInputParsingException }; diff --git a/langchain-core/src/utils/stream.ts b/langchain-core/src/utils/stream.ts index 123a6b64ca8e..b2c7ba21bb27 100644 --- a/langchain-core/src/utils/stream.ts +++ b/langchain-core/src/utils/stream.ts @@ -1,4 +1,4 @@ -import { pickRunnableConfigKeys } from "../runnables/types.js"; +import { pickRunnableConfigKeys } from "../runnables/config.js"; import { AsyncLocalStorageProviderSingleton } from "../singletons/index.js"; import { IterableReadableStreamInterface } from "../types/stream.js"; import { raceWithSignal } from "./signal.js"; From be17fabca6193f3f60a5b8758da5e0d1c9814f57 Mon Sep 17 00:00:00 2001 From: bracesproul Date: Thu, 5 Dec 2024 13:05:28 -0800 Subject: [PATCH 4/5] chore: lint files --- langchain-core/src/runnables/base.ts | 6 +++++- langchain-core/src/runnables/index.ts | 1 + langchain-core/src/runnables/iter.ts | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/langchain-core/src/runnables/base.ts b/langchain-core/src/runnables/base.ts index 5c545455ea14..d2ba10b6f6bd 100644 --- a/langchain-core/src/runnables/base.ts +++ b/langchain-core/src/runnables/base.ts @@ -6,7 +6,11 @@ import { type TraceableFunction, isTraceableFunction, } from "langsmith/singletons/traceable"; -import type { RunnableInterface, RunnableBatchOptions, RunnableConfig } from "./types.js"; +import type { + RunnableInterface, + RunnableBatchOptions, + RunnableConfig, +} from "./types.js"; import { CallbackManagerForChainRun } from "../callbacks/manager.js"; import { LogStreamCallbackHandler, diff --git a/langchain-core/src/runnables/index.ts b/langchain-core/src/runnables/index.ts index 2a34d91c8164..7d78b1c5f75a 100644 --- a/langchain-core/src/runnables/index.ts +++ b/langchain-core/src/runnables/index.ts @@ -29,6 +29,7 @@ export { patchConfig, ensureConfig, mergeConfigs, + pickRunnableConfigKeys, } from "./config.js"; export { RunnablePassthrough } from "./passthrough.js"; export { type RouterInput, RouterRunnable } from "./router.js"; diff --git a/langchain-core/src/runnables/iter.ts b/langchain-core/src/runnables/iter.ts index ae6b9a47aa78..4d7ead6efa60 100644 --- a/langchain-core/src/runnables/iter.ts +++ b/langchain-core/src/runnables/iter.ts @@ -1,4 +1,4 @@ -import type { RunnableConfig } from "../../dist/runnables/types.js"; +import type { RunnableConfig } from "../runnables/types.js"; import { AsyncLocalStorageProviderSingleton } from "../singletons/index.js"; import { pickRunnableConfigKeys } from "./config.js"; From dadb7e62ff81a1e2c1f177d73e550e46d1b7caa1 Mon Sep 17 00:00:00 2001 From: bracesproul Date: Thu, 5 Dec 2024 13:19:42 -0800 Subject: [PATCH 5/5] fix tests --- langchain-core/src/utils/stream.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/langchain-core/src/utils/stream.ts b/langchain-core/src/utils/stream.ts index b2c7ba21bb27..cd3e592806be 100644 --- a/langchain-core/src/utils/stream.ts +++ b/langchain-core/src/utils/stream.ts @@ -1,11 +1,11 @@ import { pickRunnableConfigKeys } from "../runnables/config.js"; import { AsyncLocalStorageProviderSingleton } from "../singletons/index.js"; -import { IterableReadableStreamInterface } from "../types/stream.js"; +import type { IterableReadableStreamInterface } from "../types/stream.js"; import { raceWithSignal } from "./signal.js"; // Re-exported for backwards compatibility // Do NOT import this type from this file inside the project. Instead, always import from `types/stream.js` -export { IterableReadableStreamInterface }; +export type { IterableReadableStreamInterface }; /* * Support async iterator syntax for ReadableStreams in all environments.