{"version":3,"file":"sequential_chain.cjs","names":["BaseChain","intersection","union","difference"],"sources":["../../src/chains/sequential_chain.ts"],"sourcesContent":["import { ChainValues } from \"@langchain/core/utils/types\";\nimport { CallbackManagerForChainRun } from \"@langchain/core/callbacks/manager\";\nimport { BaseChain, ChainInputs } from \"./base.js\";\nimport {\n  SerializedBaseChain,\n  SerializedSequentialChain,\n  SerializedSimpleSequentialChain,\n} from \"./serde.js\";\nimport { intersection, union, difference } from \"../util/set.js\";\n\nfunction formatSet(input: Set<string>) {\n  return Array.from(input)\n    .map((i) => `\"${i}\"`)\n    .join(\", \");\n}\n\n/**\n * Interface for the input parameters of the SequentialChain class.\n */\nexport interface SequentialChainInput extends ChainInputs {\n  /** Array of chains to run as a sequence. The chains are run in order they appear in the array. */\n  chains: BaseChain[];\n  /** Defines which variables should be passed as initial input to the first chain. */\n  inputVariables: string[];\n  /** Which variables should be returned as a result of executing the chain. If not specified, output of the last of the chains is used. */\n  outputVariables?: string[];\n  /** Whether or not to return all intermediate outputs and variables (excluding initial input variables). */\n  returnAll?: boolean;\n}\n\n/**\n * Chain where the outputs of one chain feed directly into next.\n * @example\n * ```typescript\n * const promptTemplate = new PromptTemplate({\n *   template: `You are a playwright. Given the title of play and the era it is set in, it is your job to write a synopsis for that title.\n * Title: {title}\n * Era: {era}\n * Playwright: This is a synopsis for the above play:`,\n *   inputVariables: [\"title\", \"era\"],\n * });\n\n * const reviewPromptTemplate = new PromptTemplate({\n *   template: `You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.\n *   \n *     Play Synopsis:\n *     {synopsis}\n *     Review from a New York Times play critic of the above play:`,\n *   inputVariables: [\"synopsis\"],\n * });\n\n * const overallChain = new SequentialChain({\n *   chains: [\n *     new LLMChain({\n *       llm: new ChatOpenAI({ model: \"gpt-4o-mini\", temperature: 0 }),\n *       prompt: promptTemplate,\n *       outputKey: \"synopsis\",\n *     }),\n *     new LLMChain({\n *       llm: new OpenAI({ model: \"gpt-4o-mini\", temperature: 0 }),\n *       prompt: reviewPromptTemplate,\n *       outputKey: \"review\",\n *     }),\n *   ],\n *   inputVariables: [\"era\", \"title\"],\n *   outputVariables: [\"synopsis\", \"review\"],\n *   verbose: true,\n * });\n\n * const chainExecutionResult = await overallChain.call({\n *   title: \"Tragedy at sunset on the beach\",\n *   era: \"Victorian England\",\n * });\n * console.log(chainExecutionResult);\n * ```\n */\nexport class SequentialChain extends BaseChain implements SequentialChainInput {\n  static lc_name() {\n    return \"SequentialChain\";\n  }\n\n  chains: BaseChain[];\n\n  inputVariables: string[];\n\n  outputVariables: string[];\n\n  returnAll?: boolean | undefined;\n\n  get inputKeys() {\n    return this.inputVariables;\n  }\n\n  get outputKeys(): string[] {\n    return this.outputVariables;\n  }\n\n  constructor(fields: SequentialChainInput) {\n    super(fields);\n    this.chains = fields.chains;\n    this.inputVariables = fields.inputVariables;\n    this.outputVariables = fields.outputVariables ?? [];\n    if (this.outputVariables.length > 0 && fields.returnAll) {\n      throw new Error(\n        \"Either specify variables to return using `outputVariables` or use `returnAll` param. Cannot apply both conditions at the same time.\"\n      );\n    }\n    this.returnAll = fields.returnAll ?? false;\n    this._validateChains();\n  }\n\n  /** @ignore */\n  _validateChains() {\n    if (this.chains.length === 0) {\n      throw new Error(\"Sequential chain must have at least one chain.\");\n    }\n\n    const memoryKeys = this.memory?.memoryKeys ?? [];\n    const inputKeysSet = new Set(this.inputKeys);\n    const memoryKeysSet = new Set(memoryKeys);\n    const keysIntersection = intersection(inputKeysSet, memoryKeysSet);\n    if (keysIntersection.size > 0) {\n      throw new Error(\n        `The following keys: ${formatSet(\n          keysIntersection\n        )} are overlapping between memory and input keys of the chain variables. This can lead to unexpected behaviour. Please use input and memory keys that don't overlap.`\n      );\n    }\n\n    const availableKeys = union(inputKeysSet, memoryKeysSet);\n    for (const chain of this.chains) {\n      let missingKeys = difference(new Set(chain.inputKeys), availableKeys);\n\n      if (chain.memory) {\n        missingKeys = difference(missingKeys, new Set(chain.memory.memoryKeys));\n      }\n\n      if (missingKeys.size > 0) {\n        throw new Error(\n          `Missing variables for chain \"${chain._chainType()}\": ${formatSet(\n            missingKeys\n          )}. Only got the following variables: ${formatSet(availableKeys)}.`\n        );\n      }\n      const outputKeysSet = new Set(chain.outputKeys);\n      const overlappingOutputKeys = intersection(availableKeys, outputKeysSet);\n      if (overlappingOutputKeys.size > 0) {\n        throw new Error(\n          `The following output variables for chain \"${chain._chainType()}\" are overlapping: ${formatSet(\n            overlappingOutputKeys\n          )}. This can lead to unexpected behaviour.`\n        );\n      }\n\n      for (const outputKey of outputKeysSet) {\n        availableKeys.add(outputKey);\n      }\n    }\n\n    if (this.outputVariables.length === 0) {\n      if (this.returnAll) {\n        const outputKeys = difference(availableKeys, inputKeysSet);\n        this.outputVariables = Array.from(outputKeys);\n      } else {\n        this.outputVariables = this.chains[this.chains.length - 1].outputKeys;\n      }\n    } else {\n      const missingKeys = difference(\n        new Set(this.outputVariables),\n        new Set(availableKeys)\n      );\n      if (missingKeys.size > 0) {\n        throw new Error(\n          `The following output variables were expected to be in the final chain output but were not found: ${formatSet(\n            missingKeys\n          )}.`\n        );\n      }\n    }\n  }\n\n  /** @ignore */\n  async _call(\n    values: ChainValues,\n    runManager?: CallbackManagerForChainRun\n  ): Promise<ChainValues> {\n    let input: ChainValues = {};\n    const allChainValues: ChainValues = values;\n    let i = 0;\n    for (const chain of this.chains) {\n      i += 1;\n      input = await chain.call(\n        allChainValues,\n        runManager?.getChild(`step_${i}`)\n      );\n      for (const key of Object.keys(input)) {\n        allChainValues[key] = input[key];\n      }\n    }\n    const output: ChainValues = {};\n    for (const key of this.outputVariables) {\n      output[key] = allChainValues[key];\n    }\n\n    return output;\n  }\n\n  _chainType() {\n    return \"sequential_chain\" as const;\n  }\n\n  static async deserialize(data: SerializedSequentialChain) {\n    const chains: BaseChain[] = [];\n    const inputVariables: string[] = data.input_variables;\n    const outputVariables: string[] = data.output_variables;\n    const serializedChains = data.chains;\n    for (const serializedChain of serializedChains) {\n      const deserializedChain = await BaseChain.deserialize(serializedChain);\n      chains.push(deserializedChain);\n    }\n    return new SequentialChain({ chains, inputVariables, outputVariables });\n  }\n\n  serialize(): SerializedSequentialChain {\n    const chains: SerializedBaseChain[] = [];\n    for (const chain of this.chains) {\n      chains.push(chain.serialize());\n    }\n    return {\n      _type: this._chainType(),\n      input_variables: this.inputVariables,\n      output_variables: this.outputVariables,\n      chains,\n    };\n  }\n}\n\n/**\n * Interface for the input parameters of the SimpleSequentialChain class.\n */\nexport interface SimpleSequentialChainInput extends ChainInputs {\n  /** Array of chains to run as a sequence. The chains are run in order they appear in the array. */\n  chains: Array<BaseChain>;\n  /** Whether or not to trim the intermediate outputs. */\n  trimOutputs?: boolean;\n}\n\n/**\n * Simple chain where a single string output of one chain is fed directly into the next.\n * @augments BaseChain\n * @augments SimpleSequentialChainInput\n *\n * @example\n * ```ts\n * import { SimpleSequentialChain, LLMChain } from \"@langchain/classic/chains\";\n * import { OpenAI } from \"langchain/llms/openai\";\n * import { PromptTemplate } from \"langchain/prompts\";\n *\n * // This is an LLMChain to write a synopsis given a title of a play.\n * const llm = new OpenAI({ temperature: 0 });\n * const template = `You are a playwright. Given the title of play, it is your job to write a synopsis for that title.\n *\n * Title: {title}\n * Playwright: This is a synopsis for the above play:`\n * const promptTemplate = new PromptTemplate({ template, inputVariables: [\"title\"] });\n * const synopsisChain = new LLMChain({ llm, prompt: promptTemplate });\n *\n *\n * // This is an LLMChain to write a review of a play given a synopsis.\n * const reviewLLM = new OpenAI({ temperature: 0 })\n * const reviewTemplate = `You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.\n *\n * Play Synopsis:\n * {synopsis}\n * Review from a New York Times play critic of the above play:`\n * const reviewPromptTemplate = new PromptTemplate({ template: reviewTemplate, inputVariables: [\"synopsis\"] });\n * const reviewChain = new LLMChain({ llm: reviewLLM, prompt: reviewPromptTemplate });\n *\n * const overallChain = new SimpleSequentialChain({chains: [synopsisChain, reviewChain], verbose:true})\n * const review = await overallChain.run(\"Tragedy at sunset on the beach\")\n * // the variable review contains resulting play review.\n * ```\n */\nexport class SimpleSequentialChain\n  extends BaseChain\n  implements SimpleSequentialChainInput\n{\n  static lc_name() {\n    return \"SimpleSequentialChain\";\n  }\n\n  chains: Array<BaseChain>;\n\n  inputKey = \"input\";\n\n  outputKey = \"output\";\n\n  trimOutputs: boolean;\n\n  get inputKeys() {\n    return [this.inputKey];\n  }\n\n  get outputKeys(): string[] {\n    return [this.outputKey];\n  }\n\n  constructor(fields: SimpleSequentialChainInput) {\n    super(fields);\n    this.chains = fields.chains;\n    this.trimOutputs = fields.trimOutputs ?? false;\n    this._validateChains();\n  }\n\n  /** @ignore */\n  _validateChains() {\n    for (const chain of this.chains) {\n      if (\n        chain.inputKeys.filter((k) => !chain.memory?.memoryKeys.includes(k))\n          .length !== 1\n      ) {\n        throw new Error(\n          `Chains used in SimpleSequentialChain should all have one input, got ${\n            chain.inputKeys.length\n          } for ${chain._chainType()}.`\n        );\n      }\n      if (chain.outputKeys.length !== 1) {\n        throw new Error(\n          `Chains used in SimpleSequentialChain should all have one output, got ${\n            chain.outputKeys.length\n          } for ${chain._chainType()}.`\n        );\n      }\n    }\n  }\n\n  /** @ignore */\n  async _call(\n    values: ChainValues,\n    runManager?: CallbackManagerForChainRun\n  ): Promise<ChainValues> {\n    let input: string = values[this.inputKey];\n    let i = 0;\n    for (const chain of this.chains) {\n      i += 1;\n      input = (\n        await chain.call(\n          { [chain.inputKeys[0]]: input, signal: values.signal },\n          runManager?.getChild(`step_${i}`)\n        )\n      )[chain.outputKeys[0]];\n      if (this.trimOutputs) {\n        input = input.trim();\n      }\n      await runManager?.handleText(input);\n    }\n    return { [this.outputKey]: input };\n  }\n\n  _chainType() {\n    return \"simple_sequential_chain\" as const;\n  }\n\n  static async deserialize(data: SerializedSimpleSequentialChain) {\n    const chains: Array<BaseChain> = [];\n    const serializedChains = data.chains;\n    for (const serializedChain of serializedChains) {\n      const deserializedChain = await BaseChain.deserialize(serializedChain);\n      chains.push(deserializedChain);\n    }\n    return new SimpleSequentialChain({ chains });\n  }\n\n  serialize(): SerializedSimpleSequentialChain {\n    const chains: Array<SerializedBaseChain> = [];\n    for (const chain of this.chains) {\n      chains.push(chain.serialize());\n    }\n    return {\n      _type: this._chainType(),\n      chains,\n    };\n  }\n}\n"],"mappings":"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"}