Decision models: typed probabilistic answers about text, messages, or state.
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, and optionally _aclassify, to call a provider.
This class handles callbacks, tracing metadata, and
token-usage reporting.
from langchain_core.decisions import BaseDecisionModel, ClassifierResponse
class MyDecisionModel(BaseDecisionModel):
model: str = "my-model"
@property
def _provider(self) -> str:
return "my_provider"
def _classify(self, state, questions):
body = my_client.classify(state=state, questions=questions)
return ClassifierResponse.model_validate(body)Locate what the instructions describe in an image in the state.
The answer gives the edges of a box as fractions of the image height and width.
Location of what a Box question describes.
Edges of a box as fractions of the image height and width, from 0 to 1.
Select one label from a fixed set of alternatives.
Use Choice for categorical decisions with no inherent ordering, such as routing a
support request, detecting a document type, or selecting an intent. The answer
includes the selected label, a probability for every supplied label, and a
confidence value.
from langchain_core.decisions import Choice
response = classifier.invoke(
{
"state": "Stripe fails whenever I connect my account.",
"questions": {
"department": Choice(
instructions="Which team should handle this request?",
criteria={
"billing": "Payment, invoice, or subscription issues.",
"technical": "Product bugs or integration failures.",
"sales": "Pricing or purchasing questions.",
},
)
},
}
)
department = response.choices["department"]
if department.confidence >= 0.7:
route_to(department.choice)
else:
route_to_human_triage()Selected Choice label with its probability distribution and confidence.
Complete input for one decision model invocation.
Keeping the state and questions in the Runnable input ensures both values participate in composition, batching, and tracing.
Typed answers and metadata returned from one classification request.
Access every answer through answers, or use nouls, choices, scores, and
boxes for views filtered by answer type. Each mapping preserves the question IDs
supplied to ClassifierRequest.questions.
Ask a binary question and receive the probability that its answer is yes.
Use Noul when the probability itself is useful to application code, such as
deciding whether a message reports a bug or requests a refund. A value near 1
indicates strong support for yes, a value near 0 indicates strong support for no,
and a value near 0.5 indicates uncertainty. Noul answers do not include a separate
confidence value.
from langchain_core.decisions import Noul
response = classifier.invoke(
{
"state": "Production is down. Please help immediately.",
"questions": {
"urgent": Noul(
instructions="Does this message require an urgent response?"
)
},
}
)
urgency = response.nouls["urgent"].noul
if urgency >= 0.8:
page_on_call_engineer()Probability that a Noul question's answer is yes.
Optional descriptions for the two outcomes of a Noul question.
Criteria clarify what should count as yes and no when the instruction alone leaves room for interpretation. Both values accept any JSON-compatible content, so callers can provide a short description or structured examples.
Evaluate state against an ordered rubric.
Use Score when the answer lies on a spectrum whose levels can be described, such
as severity, urgency, or customer frustration. Criteria are numbered from zero in
their supplied order. The returned score is an expected value and may fall between
integer levels; the full probability distribution remains available for custom
decision logic.
from langchain_core.decisions import Score
response = classifier.invoke(
{
"state": "This has failed three times. Fix it now.",
"questions": {
"frustration": Score(
instructions="How frustrated does the customer appear?",
criteria=[
"Calm and neutral.",
"Concerned but civil.",
"Very angry or using strong language.",
],
)
},
}
)
frustration = response.scores["frustration"]
print(frustration.score) # May be fractional, for example 1.35.
print(frustration.legend) # The original zero-based rubric.
print(frustration.probabilities) # Probability for each rubric level.Expected Score value with its rubric, distribution, and confidence.
Text, a JSON object, or a JSON array used in question instructions.
As in State, LangChain standard media blocks may appear anywhere in instructions and
criteria. Providers send them as media, or raise an error if their API does not accept
that media in questions.
Root state accepted by decision models.
State is a string, JSON object, or JSON array. LangChain BaseMessage objects and
message sequences can appear at the root or at any depth inside objects and arrays.
LangChain standard media blocks (for example {"type": "image", "base64": ..., "mime_type": ...}) may appear anywhere in the state. Each provider documents which
media it supports and how it sends state its API cannot accept natively.