Preference Signal
Overview
preference infers response-style preferences from examples and classifier
settings. Define preference rules under routing.signals.preferences.
This family is learned: it uses the preference-classification path under global.model_catalog.modules.classifier.preference.
Rules with authored examples use embedding similarity by default. Rules with
only descriptions use the default decision deployment. An explicit
embedding_model also selects embedding similarity. A configured external
preference-role backend keeps its own path unless you explicitly choose another
mode.
Key Advantages
- Personalizes routing without hard-coding user state into decisions.
- Keeps preference detection separate from route outcomes.
- Supports example-driven style detection such as terse vs detailed answers.
- Reuses one preference policy across multiple decisions.
What Problem Does It Solve?
Users often want different response styles even when they ask about the same topic. If those preferences are only handled downstream, routing cannot choose the most suitable model or plugin stack.
preference solves that by exposing inferred style preferences as named routing inputs.
When to Use
Use preference when:
- some users prefer terse answers while others want high detail
- route behavior should adapt to stable style preferences
- you want preference detection to stay reusable across several decisions
- user style signals should influence model choice, plugin choice, or both
Configuration
routing:
signals:
preferences:
- name: terse_answers
description: Users who prefer short, direct responses.
examples:
- keep it concise
- bullet points only
- answer in one paragraph
threshold: 0.7
The examples describe the style you want to recognize; they are compared by
meaning rather than matched as literal keywords. Their threshold applies to
the embedding similarity score, not a decision-model probability.
To use this comparison explicitly, including when your rules contain only
descriptions, set use_contrastive: true:
global:
model_catalog:
modules:
classifier:
preference:
use_contrastive: true
prototype_scoring:
enabled: true
cluster_similarity_threshold: 0.9
max_prototypes: 8
best_weight: 0.75
top_m: 2
margin_threshold: 0.05
In contrastive mode, the router embeds each preference rule's descriptions and examples, compresses them into representative prototypes when prototype_scoring is enabled, and compares the incoming request against those prototypes. margin_threshold lets you reject ambiguous winners instead of forcing a weak preference match.
An explicit use_contrastive: false disables this embedding comparison and uses
the external preference backend when configured, or otherwise the default
decision deployment. Prototype settings alone do not select contrastive mode.
To select a native decision task explicitly, bind preference with
contract: decision.v1 under routing.model_bindings or
global.model_catalog.bindings. That binding takes precedence over examples
and use_contrastive, and its rule thresholds apply to native choice
probabilities. Keep cosine thresholds and prototype margins with the embedding
path; check your examples again when switching to native judgments.
Dependencies and Limitations
Preference rules use the shared embedding/classifier path and infer style only
from the available request context. They should not be treated as durable user
consent or identity. See a complete example:
config/fragments/signal/preference/power-user.yaml.