@langchain/core
Version:
Core LangChain.js abstractions and schemas
98 lines (97 loc) • 3.62 kB
JavaScript
const require_base = require("../runnables/base.cjs");
const require_config = require("../runnables/config.cjs");
const require_types = require("./types.cjs");
// src/decisions/base.ts
function assertAnswered(questions, response) {
for (const [id, question] of Object.entries(questions)) {
const answer = Object.hasOwn(response.answers, id) ? response.answers[id] : void 0;
if (answer === void 0) throw new Error(`Decision model returned no answer for question "${id}".`);
if (answer.type !== question.type) throw new Error(`Decision model returned a ${answer.type} answer for ${question.type} question "${id}".`);
if (answer.type === "choice" && question.type === "choice" && !Object.hasOwn(question.criteria, answer.choice)) throw new Error(`Decision model returned a choice for question "${id}" that is not one of its labels.`);
}
}
/**
* Answer typed questions about text, messages, or structured state.
*
* A decision model evaluates shared state against one or more questions and
* returns typed answers: a probability for a `Noul`, a selected label for a
* `Choice`, an expected level for a `Score`, and a location for a `Box`.
* Answers keep their probability distributions and confidence so applications
* can choose their own thresholds.
*
* Subclasses implement `_classify` to call a provider. This class validates
* questions and handles callbacks, tracing metadata, and token-usage
* reporting.
*
* @example
* ```ts
* import {
* BaseDecisionModel,
* parseClassifierResponse,
* } from "@langchain/core/decisions";
*
* class MyDecisionModel extends BaseDecisionModel {
* lc_namespace = ["my_provider", "decisions"];
*
* get _provider() {
* return "my_provider";
* }
*
* async _classify(
* state: State,
* questions: Record<string, Question>,
* config?: Partial<RunnableConfig>
* ) {
* const body = await myClient.classify(
* { model: this.model, state, questions },
* { signal: config?.signal }
* );
* return parseClassifierResponse(body);
* }
* }
* ```
*/
var BaseDecisionModel = class extends require_base.Runnable {
/** Provider model name used to answer questions. */
model;
constructor(fields) {
super(fields);
this.model = fields.model;
}
/**
* Classify one request.
*
* The run is traced as an LLM run with `ls_provider` and `ls_model_name`
* metadata, and its output carries `usage_metadata` when the provider reports
* usage.
*
* @param input State and questions to evaluate.
* @param options Callbacks, tags, metadata, and other runnable config.
* @returns Answers keyed by answer ID and typed from `questions`, with
* request metadata.
* @throws Error if a question is invalid, `questions` is empty, or the
* provider leaves a question unanswered or answers it with the wrong type
* or an unknown `Choice` label.
*/
async invoke(input, options) {
const config = require_config.ensureConfig(options);
return await this._callWithConfig(async (request, runConfig, runManager) => {
const { runType: _runType, ...childConfig } = runConfig ?? {};
const questions = require_types.parseQuestions(request.questions);
const answered = await this._classify(request.state, questions, require_config.patchConfig(childConfig, { callbacks: runManager?.getChild() }));
assertAnswered(questions, answered);
return answered;
}, input, {
...config,
runType: "llm",
metadata: {
...config.metadata,
ls_provider: this._provider,
ls_model_name: this.model,
ls_model_type: "chat"
}
});
}
};
exports.BaseDecisionModel = BaseDecisionModel;
//# sourceMappingURL=base.cjs.map