PageSourceSearch

https://vllm-sr.ai/assets/js/eb41a1d5.56d5f33a.js

js vllm-sr.ai collected 2026-10-04 01:32:11 UTC 10,004 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunksemantic_router_docs=self.webpackChunksemantic_router_docs||[]).push([[15452],{78973(e,n,i){i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>d,default:()=>h,frontMatter:()=>r,metadata:()=>s,toc:()=>c});const s=JSON.parse('{"id":"tutorials/projection/mappings","title":"Mappings","description":"Overview","source":"@site/docs/tutorials/projection/mappings.md","sourceDirName":"tutorials/projection","slug":"/tutorials/projection/mappings","permalink":"/docs/tutorials/projection/mappings","draft":false,"unlisted":false,"editUrl":"https://github.com/vllm-project/semantic-router/edit/main/website/docs/tutorials/projection/mappings.md","tags":[],"version":"current","sidebarPosition":4,"frontMatter":{"sidebar_position":4},"sidebar":"tutorialSidebar","previous":{"title":"Scores","permalink":"/docs/tutorials/projection/scores"},"next":{"title":"Decisions","permalink":"/docs/tutorials/decision/overview"}}');var t=i(74848),o=i(28453);const r={sidebar_position:4},d="Mappings",l={},c=[{value:"Overview",id:"overview",level:2},{value:"What Problem Does It Solve?",id:"what-problem-does-it-solve",level:2},{value:"How Mappings Behave at Runtime",id:"how-mappings-behave-at-runtime",level:2},{value:"Configuration",id:"configuration",level:2},{value:"DSL",id:"dsl",level:2},{value:"Config Fields",id:"config-fields",level:2},{value:"Dashboard",id:"dashboard",level:2},{value:"When to Use",id:"when-to-use",level:2},{value:"When Not to Use",id:"when-not-to-use",level:2}];function a(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,o.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"mappings",children:"Mappings"})}),"\n",(0,t.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"routing.projections.mappings"})," turns a projection score into named routing bands that decisions can consume."]}),"\n",(0,t.jsx)(n.h2,{id:"what-problem-does-it-solve",children:"What Problem Does It Solve?"}),"\n",(0,t.jsx)(n.p,{children:'Scores are useful internal signals, but decision rules should not depend on everyone remembering that "0.82 means reasoning tier" or "0.35 means verification required."'}),"\n",(0,t.jsx)(n.p,{children:"Mappings solve that by turning numeric thresholds into reusable policy names."}),"\n",(0,t.jsxs)(n.p,{children:["This is also the point where a projection becomes decision-visible. Decisions\nreference ",(0,t.jsx)(n.code,{children:"mapping.outputs[*].name"}),", not score names or partition names."]}),"\n",(0,t.jsx)(n.h2,{id:"how-mappings-behave-at-runtime",children:"How Mappings Behave at Runtime"}),"\n",(0,t.jsx)(n.p,{children:"Two mapping methods are supported:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"threshold_bands"})," (default, also used when ",(0,t.jsx)(n.code,{children:"method"})," is unset) \u2014 emits the ",(0,t.jsx)(n.strong,{children:"first"})," matching output band."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"multi_emit"})," \u2014 emits ",(0,t.jsx)(n.strong,{children:"every"})," matching output band, so one mapping can set several orthogonal policy tags from the same score. Requires at least two outputs."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Each output declares one or more bounds using:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"lt"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"lte"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"gt"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"gte"})}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Important runtime details:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"outputs are checked in declared order"}),"\n",(0,t.jsxs)(n.li,{children:["with ",(0,t.jsx)(n.code,{children:"threshold_bands"}),", the first matching output wins"]}),"\n",(0,t.jsxs)(n.li,{children:["with ",(0,t.jsx)(n.code,{children:"multi_emit"}),", every matching output is emitted (in declared order)"]}),"\n",(0,t.jsx)(n.li,{children:"if no output matches, the mapping emits nothing"}),"\n",(0,t.jsxs)(n.li,{children:["optional ",(0,t.jsx)(n.code,{children:"calibration"})," computes a confidence for each emitted projection output"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["The supported calibration method today is ",(0,t.jsx)(n.code,{children:"sigmoid_distance"}),", which derives confidence from how far the score sits from the nearest threshold boun
1dary."]}),"\n",(0,t.jsx)(n.h2,{id:"configuration",children:"Configuration"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:"routing:\n  projections:\n    mappings:\n      - name: difficulty_band\n        source: difficulty_score\n        method: threshold_bands\n        calibration:\n          method: sigmoid_distance\n          slope: 10.0\n        outputs:\n          - name: balance_simple\n            lt: 0.18\n          - name: balance_medium\n            gte: 0.18\n            lt: 0.48\n          - name: balance_complex\n            gte: 0.48\n            lt: 0.82\n          - name: balance_reasoning\n            gte: 0.82\n\n  decisions:\n    - name: reasoning_deep\n      description: Use the reasoning model for the highest difficulty band.\n      priority: 250\n      rules:\n        operator: AND\n        conditions:\n          - type: domain\n            name: math\n          - type: projection\n            name: balance_reasoning\n      modelRefs:\n        - model: google/gemini-3.1-pro\n"})}),"\n",(0,t.jsx)(n.h2,{id:"dsl",children:"DSL"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-dsl",children:'PROJECTION mapping difficulty_band {\n  source: "difficulty_score"\n  method: "threshold_bands"\n  calibration: { method: "sigmoid_distance", slope: 10 }\n  outputs: [\n    { name: "balance_simple", lt: 0.18 },\n    { name: "balance_medium", gte: 0.18, lt: 0.48 },\n    { name: "balance_complex", gte: 0.48, lt: 0.82 },\n    { name: "balance_reasoning", gte: 0.82 }\n  ]\n}\n\nROUTE reasoning_deep {\n  PRIORITY 250\n  WHEN domain("math") AND projection("balance_reasoning")\n  MODEL "google/gemini-3.1-pro"\n}\n'})}),"\n",(0,t.jsx)(n.h2,{id:"config-fields",children:"Config Fields"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Field"}),(0,t.jsx)(n.th,{children:"Meaning"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"name"})}),(0,t.jsx)(n.td,{children:"mapping identifier"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"source"})}),(0,t.jsx)(n.td,{children:"score name to read from"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"method"})}),(0,t.jsxs)(n.td,{children:[(0,t.jsx)(n.code,{children:"threshold_bands"})," (default) or ",(0,t.jsx)(n.code,{children:"multi_emit"})]})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"calibration"})}),(0,t.jsx)(n.td,{children:"optional confidence model for the matched output"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"outputs[].name"})}),(0,t.jsx)(n.td,{children:"decision-visible projection name"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"outputs[].lt/lte/gt/gte"})}
1),(0,t.jsx)(n.td,{children:"threshold bounds for that output"})]})]})]}),"\n",(0,t.jsx)(n.h2,{id:"dashboard",children:"Dashboard"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"Config -> Projections"})," edits mappings in canonical config form"]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.code,{children:"Config -> Decisions"})," can reference mapping outputs with condition type ",(0,t.jsx)(n.code,{children:"projection"})]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"when-to-use",children:"When to Use"}),"\n",(0,t.jsx)(n.p,{children:"Use mappings when:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"several routes should share the same tier names"}),"\n",(0,t.jsxs)(n.li,{children:["you want readable decision rules such as ",(0,t.jsx)(n.code,{children:'projection("verification_required")'})]}),"\n",(0,t.jsx)(n.li,{children:"threshold policy should be centralized and auditable"}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"when-not-to-use",children:"When Not to Use"}),"\n",(0,t.jsx)(n.p,{children:"Do not use mappings when:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"the decision should reference a raw signal directly"}),"\n",(0,t.jsx)(n.li,{children:"the score is only diagnostic and not part of routing policy"}),"\n",(0,t.jsx)(n.li,{children:"you have not first defined the score that this mapping should read from"}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Mappings make no model or storage calls; they transform scores already computed\nfor the request. Thresholds still inherit the uncertainty and calibration of\ntheir input signals. See a complete end-to-end example in the\n",(0,t.jsx)(n.a,{href:"https://github.com/vllm-project/semantic-router/blob/main/config/recipes/balance/config.yaml",children:(0,t.jsx)(n.code,{children:"config/recipes/balance/config.yaml"})}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(a,{...e})}):a(e)}},28453(e,n,i){i.d(n,{R:()=>r,x:()=>d});var s=i(96540);const t={},o=s.createContext(t);function r(e){const n=s.useContext(o);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.