UNPKG

@langchain/core

Version:
1 lines • 6.76 kB
{"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"}