fix(s31): close 1 review MAJOR — bound the blend weight so the hybrid preserves structural order
This commit is contained in:
parent
b05747a3cd
commit
6618f67c3f
1 changed files with 30 additions and 3 deletions
|
|
@ -78,8 +78,29 @@ if TYPE_CHECKING: # verdicts imports agent_framework — keep it out of the run
|
|||
EMBED_DIM = 64
|
||||
|
||||
# Blend weight for HybridRanker: score = weight * cosine + (1 - weight) * structural.
|
||||
# 0.5 gives the two falsifiable signals equal say; the caller can override per construction.
|
||||
SEMANTIC_WEIGHT_DEFAULT = 0.5
|
||||
# The caller can override per construction.
|
||||
#
|
||||
# 0.25, and the reason is MEASURED, not aesthetic. The previous value (0.5) was justified as
|
||||
# "giving the two falsifiable signals equal say" — a claim about equivalence that the measurement
|
||||
# refutes. Over the 1770 pairs of a fully enumerated 60-feature family, the ``FakeEmbedder``
|
||||
# cosine is a near-constant: mean 0.7500, sd 0.0380, range [0.6123, 0.8614] => spread 0.2492. A
|
||||
# term with that little dynamic range is a TIE-BREAKER, not a co-equal signal, and weighting it as
|
||||
# though it were an equal partner does not make it one — it just lets 0.25 of a near-constant
|
||||
# outvote real structural distance.
|
||||
#
|
||||
# Worst-case bound: the semantic term can overturn a structural gap G only when
|
||||
# w * spread > (1 - w) * G, i.e. it is safe while ``w < G / (G + spread)``. With G = one
|
||||
# ``verdicts._W_MAGNITUDE`` step (0.15) and the measured spread, that ceiling is 0.3758 — so 0.5
|
||||
# sat ABOVE it and the ordering was genuinely overturnable; 0.25 sits below with margin. Stated as
|
||||
# a property rather than a fixture fit: w = 0.25 holds for any spread below 0.45, against 0.2492
|
||||
# observed. Measured, not assumed: 9 adverse triples at w = 0.5, zero at every weight from 0.45
|
||||
# down to 0.05 (see ``test_hybrid_preserves_structural_order_across_one_magnitude_step``).
|
||||
#
|
||||
# Lowering it costs nothing the seam is for: cosine still decides 100% of exact structural ties at
|
||||
# any w > 0, which is the role SC2 pins. Only the co-equal-signal role disappears, and it was
|
||||
# never defended. An injected REAL embedder has a different cosine distribution and therefore
|
||||
# needs its own weight justification — this number is derived from the shipped fake one.
|
||||
SEMANTIC_WEIGHT_DEFAULT = 0.25
|
||||
|
||||
# Mirrors ``verdicts._MAGNITUDE_BUCKETS``. DUPLICATED, not imported, on purpose: importing it
|
||||
# would pull ``verdicts`` (and therefore ``agent_framework``) into this module's runtime graph
|
||||
|
|
@ -121,7 +142,13 @@ def _canonical_feature_string(features: ProposalFeatures) -> str:
|
|||
Honesty limit, stated at the site: over a structural tie the cosine ordering is deterministic
|
||||
but semantically ARBITRARY, because the shipped ``FakeEmbedder`` is a sha256 projection with no
|
||||
semantics. Retrieval *quality* arrives only with an injected embedder — the seam is the
|
||||
deliverable, not better ranking."""
|
||||
deliverable, not better ranking.
|
||||
|
||||
And the limit is wider than "ties": an arbitrary term does not politely confine itself to
|
||||
exact ties. It also decides NEAR-ties, and ``SEMANTIC_WEIGHT_DEFAULT`` is the only thing that
|
||||
bounds how near — at weight w it can overturn any structural gap below ``w/(1-w)`` times the
|
||||
cosine spread. That is why the weight is derived from a measurement rather than chosen for
|
||||
symmetry, and why raising it is a correctness change, not a taste one."""
|
||||
return "|".join(
|
||||
(
|
||||
",".join(sorted(features.affected_codes)),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue