{"version":3,"file":"base.cjs","names":["Runnable","ensureConfig","parseQuestions","patchConfig"],"sources":["../../src/decisions/base.ts"],"sourcesContent":["import type { CallbackManagerForChainRun } from \"../callbacks/manager.js\";\nimport { Runnable } from \"../runnables/base.js\";\nimport {\n  ensureConfig,\n  patchConfig,\n  type RunnableConfig,\n} from \"../runnables/config.js\";\nimport {\n  parseQuestions,\n  type ClassifierRequest,\n  type ClassifierResponse,\n  type Question,\n  type State,\n} from \"./types.js\";\n\n// Throws unless every question has an answer of its type, so the response\n// matches its typed answers. Names question IDs only, never answer values.\nfunction assertAnswered(\n  questions: Record<string, Question>,\n  response: ClassifierResponse\n): void {\n  for (const [id, question] of Object.entries(questions)) {\n    const answer = Object.hasOwn(response.answers, id)\n      ? response.answers[id]\n      : undefined;\n    if (answer === undefined) {\n      throw new Error(\n        `Decision model returned no answer for question \"${id}\".`\n      );\n    }\n    if (answer.type !== question.type) {\n      throw new Error(\n        `Decision model returned a ${answer.type} answer for ${question.type} question \"${id}\".`\n      );\n    }\n    if (\n      answer.type === \"choice\" &&\n      question.type === \"choice\" &&\n      !Object.hasOwn(question.criteria, answer.choice)\n    ) {\n      throw new Error(\n        `Decision model returned a choice for question \"${id}\" that is not one of its labels.`\n      );\n    }\n  }\n}\n\n/** Fields shared by every decision model. */\nexport interface BaseDecisionModelFields {\n  /** Provider model name used to answer questions. */\n  model: string;\n}\n\n/**\n * Answer typed questions about text, messages, or structured state.\n *\n * A decision model evaluates shared state against one or more questions and\n * returns typed answers: a probability for a `Noul`, a selected label for a\n * `Choice`, an expected level for a `Score`, and a location for a `Box`.\n * Answers keep their probability distributions and confidence so applications\n * can choose their own thresholds.\n *\n * Subclasses implement `_classify` to call a provider. This class validates\n * questions and handles callbacks, tracing metadata, and token-usage\n * reporting.\n *\n * @example\n * ```ts\n * import {\n *   BaseDecisionModel,\n *   parseClassifierResponse,\n * } from \"@langchain/core/decisions\";\n *\n * class MyDecisionModel extends BaseDecisionModel {\n *   lc_namespace = [\"my_provider\", \"decisions\"];\n *\n *   get _provider() {\n *     return \"my_provider\";\n *   }\n *\n *   async _classify(\n *     state: State,\n *     questions: Record<string, Question>,\n *     config?: Partial<RunnableConfig>\n *   ) {\n *     const body = await myClient.classify(\n *       { model: this.model, state, questions },\n *       { signal: config?.signal }\n *     );\n *     return parseClassifierResponse(body);\n *   }\n * }\n * ```\n */\nexport abstract class BaseDecisionModel extends Runnable<\n  ClassifierRequest,\n  ClassifierResponse\n> {\n  /** Provider model name used to answer questions. */\n  readonly model: string;\n\n  constructor(fields: BaseDecisionModelFields) {\n    super(fields);\n    this.model = fields.model;\n  }\n\n  /** Provider name reported to LangSmith as `ls_provider`. */\n  abstract get _provider(): string;\n\n  /**\n   * Answer one request.\n   *\n   * @param state State to evaluate.\n   * @param questions Validated questions keyed by answer ID.\n   * @param config Runnable config, including the abort `signal`.\n   * @returns Typed answers keyed by answer ID, with request metadata.\n   */\n  abstract _classify(\n    state: State,\n    questions: Record<string, Question>,\n    config?: Partial<RunnableConfig>\n  ): Promise<ClassifierResponse>;\n\n  /**\n   * Classify one request.\n   *\n   * The run is traced as an LLM run with `ls_provider` and `ls_model_name`\n   * metadata, and its output carries `usage_metadata` when the provider reports\n   * usage.\n   *\n   * @param input State and questions to evaluate.\n   * @param options Callbacks, tags, metadata, and other runnable config.\n   * @returns Answers keyed by answer ID and typed from `questions`, with\n   *   request metadata.\n   * @throws Error if a question is invalid, `questions` is empty, or the\n   *   provider leaves a question unanswered or answers it with the wrong type\n   *   or an unknown `Choice` label.\n   */\n  async invoke<const Q extends Record<string, Question>>(\n    input: ClassifierRequest<Q>,\n    options?: Partial<RunnableConfig>\n  ): Promise<ClassifierResponse<Q>> {\n    const config = ensureConfig(options);\n    const response = await this._callWithConfig(\n      async (\n        request: ClassifierRequest,\n        runConfig?: Partial<RunnableConfig & { runType: string }>,\n        runManager?: CallbackManagerForChainRun\n      ) => {\n        const { runType: _runType, ...childConfig } = runConfig ?? {};\n        const questions = parseQuestions(request.questions);\n        const answered = await this._classify(\n          request.state,\n          questions,\n          patchConfig(childConfig, { callbacks: runManager?.getChild() })\n        );\n        assertAnswered(questions, answered);\n        return answered;\n      },\n      input,\n      {\n        ...config,\n        runType: \"llm\",\n        metadata: {\n          ...config.metadata,\n          ls_provider: this._provider,\n          ls_model_name: this.model,\n          ls_model_type: \"chat\",\n        },\n      }\n    );\n    return response as ClassifierResponse<Q>;\n  }\n}\n"],"mappings":";;;;AAiBA,SAAS,eACP,WACA,UACM;CACN,KAAK,MAAM,CAAC,IAAI,aAAa,OAAO,QAAQ,SAAS,GAAG;EACtD,MAAM,SAAS,OAAO,OAAO,SAAS,SAAS,EAAE,IAC7C,SAAS,QAAQ,MACjB,KAAA;EACJ,IAAI,WAAW,KAAA,GACb,MAAM,IAAI,MACR,mDAAmD,GAAG,GACxD;EAEF,IAAI,OAAO,SAAS,SAAS,MAC3B,MAAM,IAAI,MACR,6BAA6B,OAAO,KAAK,cAAc,SAAS,KAAK,aAAa,GAAG,GACvF;EAEF,IACE,OAAO,SAAS,YAChB,SAAS,SAAS,YAClB,CAAC,OAAO,OAAO,SAAS,UAAU,OAAO,MAAM,GAE/C,MAAM,IAAI,MACR,kDAAkD,GAAG,iCACvD;CAEJ;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,IAAsB,oBAAtB,cAAgDA,aAAAA,SAG9C;;CAEA;CAEA,YAAY,QAAiC;EAC3C,MAAM,MAAM;EACZ,KAAK,QAAQ,OAAO;CACtB;;;;;;;;;;;;;;;;CAkCA,MAAM,OACJ,OACA,SACgC;EAChC,MAAM,SAASC,eAAAA,aAAa,OAAO;EA6BnC,OAAO,MA5BgB,KAAK,gBAC1B,OACE,SACA,WACA,eACG;GACH,MAAM,EAAE,SAAS,UAAU,GAAG,gBAAgB,aAAa,CAAC;GAC5D,MAAM,YAAYC,cAAAA,eAAe,QAAQ,SAAS;GAClD,MAAM,WAAW,MAAM,KAAK,UAC1B,QAAQ,OACR,WACAC,eAAAA,YAAY,aAAa,EAAE,WAAW,YAAY,SAAS,EAAE,CAAC,CAChE;GACA,eAAe,WAAW,QAAQ;GAClC,OAAO;EACT,GACA,OACA;GACE,GAAG;GACH,SAAS;GACT,UAAU;IACR,GAAG,OAAO;IACV,aAAa,KAAK;IAClB,eAAe,KAAK;IACpB,eAAe;GACjB;EACF,CACF;CAEF;AACF"}