UNPKG

@langchain/core

Version:
208 lines (207 loc) 8.07 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RunnableBranch = void 0; const base_js_1 = require("./base.cjs"); const config_js_1 = require("./config.cjs"); const stream_js_1 = require("../utils/stream.cjs"); /** * Class that represents a runnable branch. The RunnableBranch is * initialized with an array of branches and a default branch. When invoked, * it evaluates the condition of each branch in order and executes the * corresponding branch if the condition is true. If none of the conditions * are true, it executes the default branch. * @example * ```typescript * const branch = RunnableBranch.from([ * [ * (x: { topic: string; question: string }) => * x.topic.toLowerCase().includes("anthropic"), * anthropicChain, * ], * [ * (x: { topic: string; question: string }) => * x.topic.toLowerCase().includes("langchain"), * langChainChain, * ], * generalChain, * ]); * * const fullChain = RunnableSequence.from([ * { * topic: classificationChain, * question: (input: { question: string }) => input.question, * }, * branch, * ]); * * const result = await fullChain.invoke({ * question: "how do I use LangChain?", * }); * ``` */ // eslint-disable-next-line @typescript-eslint/no-explicit-any class RunnableBranch extends base_js_1.Runnable { static lc_name() { return "RunnableBranch"; } constructor(fields) { super(fields); Object.defineProperty(this, "lc_namespace", { enumerable: true, configurable: true, writable: true, value: ["langchain_core", "runnables"] }); Object.defineProperty(this, "lc_serializable", { enumerable: true, configurable: true, writable: true, value: true }); Object.defineProperty(this, "default", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "branches", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.branches = fields.branches; this.default = fields.default; } /** * Convenience method for instantiating a RunnableBranch from * RunnableLikes (objects, functions, or Runnables). * * Each item in the input except for the last one should be a * tuple with two items. The first is a "condition" RunnableLike that * returns "true" if the second RunnableLike in the tuple should run. * * The final item in the input should be a RunnableLike that acts as a * default branch if no other branches match. * * @example * ```ts * import { RunnableBranch } from "@langchain/core/runnables"; * * const branch = RunnableBranch.from([ * [(x: number) => x > 0, (x: number) => x + 1], * [(x: number) => x < 0, (x: number) => x - 1], * (x: number) => x * ]); * ``` * @param branches An array where the every item except the last is a tuple of [condition, runnable] * pairs. The last item is a default runnable which is invoked if no other condition matches. * @returns A new RunnableBranch. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any static from(branches) { if (branches.length < 1) { throw new Error("RunnableBranch requires at least one branch"); } const branchLikes = branches.slice(0, -1); const coercedBranches = branchLikes.map(([condition, runnable]) => [ (0, base_js_1._coerceToRunnable)(condition), (0, base_js_1._coerceToRunnable)(runnable), ]); const defaultBranch = (0, base_js_1._coerceToRunnable)(branches[branches.length - 1]); return new this({ branches: coercedBranches, default: defaultBranch, }); } async _invoke(input, config, runManager) { let result; for (let i = 0; i < this.branches.length; i += 1) { const [condition, branchRunnable] = this.branches[i]; const conditionValue = await condition.invoke(input, (0, config_js_1.patchConfig)(config, { callbacks: runManager?.getChild(`condition:${i + 1}`), })); if (conditionValue) { result = await branchRunnable.invoke(input, (0, config_js_1.patchConfig)(config, { callbacks: runManager?.getChild(`branch:${i + 1}`), })); break; } } if (!result) { result = await this.default.invoke(input, (0, config_js_1.patchConfig)(config, { callbacks: runManager?.getChild("branch:default"), })); } return result; } async invoke(input, config = {}) { return this._callWithConfig(this._invoke, input, config); } async *_streamIterator(input, config) { const callbackManager_ = await (0, config_js_1.getCallbackManagerForConfig)(config); const runManager = await callbackManager_?.handleChainStart(this.toJSON(), (0, base_js_1._coerceToDict)(input, "input"), config?.runId, undefined, undefined, undefined, config?.runName); let finalOutput; let finalOutputSupported = true; let stream; try { for (let i = 0; i < this.branches.length; i += 1) { const [condition, branchRunnable] = this.branches[i]; const conditionValue = await condition.invoke(input, (0, config_js_1.patchConfig)(config, { callbacks: runManager?.getChild(`condition:${i + 1}`), })); if (conditionValue) { stream = await branchRunnable.stream(input, (0, config_js_1.patchConfig)(config, { callbacks: runManager?.getChild(`branch:${i + 1}`), })); for await (const chunk of stream) { yield chunk; if (finalOutputSupported) { if (finalOutput === undefined) { finalOutput = chunk; } else { try { finalOutput = (0, stream_js_1.concat)(finalOutput, chunk); } catch (e) { finalOutput = undefined; finalOutputSupported = false; } } } } break; } } if (stream === undefined) { stream = await this.default.stream(input, (0, config_js_1.patchConfig)(config, { callbacks: runManager?.getChild("branch:default"), })); for await (const chunk of stream) { yield chunk; if (finalOutputSupported) { if (finalOutput === undefined) { finalOutput = chunk; } else { try { finalOutput = (0, stream_js_1.concat)(finalOutput, chunk); } catch (e) { finalOutput = undefined; finalOutputSupported = false; } } } } } } catch (e) { await runManager?.handleChainError(e); throw e; } await runManager?.handleChainEnd(finalOutput ?? {}); } } exports.RunnableBranch = RunnableBranch;