ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

semantic-router 的 Complexity 信号:用嵌入相似度学习驱动推理升级路由

semantic-router 的 Complexity 信号:用嵌入相似度学习驱动推理升级路由
  • 后端
  • API网关
  • 模型推理服务
  • AI Agent

【免费下载链接】semantic-router

An open, programmable decision layer for models and compute.

项目地址:https://gitcode.com/gh_mirrors/sem/semantic-router
点击查看免费下载

本文围绕 semantic-router 官方文档中的 Complexity 信号展开,介绍这一「学习型」信号如何通过难/易候选示例的嵌入相似度,估计请求需要更强推理还是更便宜的简易路径,并给出完整配置、边界判定原理、多模态扩展与源码级实现佐证。读完本文,你将掌握routing.signals.complexity的完整配置方法、threshold 与边界对的语义差异、决策规则中的引用方式,以及本地原型评分与远程评分后端两条执行路径的取舍。

一、为什么需要单独估计「复杂度」:领域不等于难度

在路由系统中,最常见的分类维度是主题(domain):把「法律咨询」路由到法律模型、「数学证明」路由到推理模型。但仅凭主题无法判断是否需要强推理——同一个领域内,两个问题的推理深度可能差异很大:

  • 「什么是牛顿第二定律」与「推导并证明动量守恒在变质量系统下的成立条件」同属物理领域,但前者一问即答,后者需要多步推理;
  • 「把这句话改得更简洁」与「分析这个 3000 行函数的根因」同属文本处理场景,成本与延迟差异巨大。

如果路由只依赖领域分类,简单请求会被过度升级(成本浪费),复杂请求会被留在廉价模型(质量受损)。semantic-router 的complexity信号正是为解决这一问题而生:它通过示例驱动的规则直接估计任务难度,而不依赖主题推断。这条设计把「推理升级」与「领域分类」彻底解耦,使同一套复杂度策略可以被多条决策复用,难/易示例随时间调参也相对简单——这是该信号族最核心的优势。

二、该信号的定位与适用场景

complexity属于学习型(learned)信号族:分类器用嵌入相似度将请求与难/易候选示例比较,而不是靠正则或关键字硬编码。它映射到config/fragments/signal/complexity/,在routing.signals.complexity中声明。

在以下场景优先使用complexity:

  • 部分提示需要更强推理或更长思维链,但无法靠主题识别;
  • 简单流量应留在更便宜模型,复杂提示应升级到更强模型;
  • 希望升级策略独立于领域,同一策略在多条决策间复用;
  • 多模态推理请求(如带截图、带图像的 CUA 请求)与简单提示需要不同处理。

仓库中一个典型的复杂度片段位于 config/fragments/signal/complexity/escalation.yaml,它定义了名为needs_reasoning的规则:把「多步推理、综合权衡、根因分析」类请求标记为 hard,把「简短回答、快速摘要、简单改写」类请求标记为 easy。

三、完整配置:规则结构逐字段拆解

官方文档给出的最小配置如下,它在routing.signals.complexity下声明一条规则:

routing: signals: complexity: - name: needs_reasoning threshold: 0.75 description: Escalate multi-step reasoning or synthesis-heavy prompts. hard: candidates: - solve this step by step - compare multiple tradeoffs - analyze the root cause easy: candidates: - answer briefly - quick summary - simple rewrite

对照源码中 ComplexityRule 结构体 与ComplexityCandidates(同文件 L479-L482),各字段含义如下:

字段类型必填说明
namestring是规则名,最终以rule:verdict(如needs_reasoning:hard)的形式供决策条件引用
thresholdfloat32二选一对称阈值简写。本地 margin 以 0 为中心的有符号值:hard 边界为+threshold,easy 边界为-threshold
hard_above/easy_belowfloat64二选一显式边界对:分数越高越难时使用(见「边界判定」一节)
hard_below/easy_abovefloat64二选一显式边界对:分数越低越难时使用
descriptionstring否规则说明,会注入决策任务路径的问题描述
hard.candidates[]string是困难示例库,启动时预计算嵌入
easy.candidates[]string是简单示例库,启动时预计算嵌入
hard.image_candidates/easy.image_candidates[]string否多模态图片候选(本地路径或>complexity_model: backend: protocol: http_classify contract: score.v1 # 或 label_distribution.v1 ...

complexity信号支持两种远程契约(classifier_backend_complexity.go):

  • score.v1:携带连续分数,运行时用每条规则声明的边界将其转换为判定;不报告置信度——决策引擎对依赖该规则的决策回退到结构化默认值,并把池标记为 unscored;
  • label_distribution.v1:直接携带判定标签,胜出标签即判定,其概率即置信度。

启动校验保证:protocol必须是http_classify(http_chat返回散文,无法解析分数或标签分布,直接被拒绝);score.v1下每条规则必须声明显式边界对;而hard_below/easy_above(低分更难)仅在配置了 score 后端时合法,因为本地 margin 按构造就是「hard 减 easy」,更高即更难——本地需要反向时应当交换 hard/easy 候选列表(classifier_backend_complexity.go)。

另外还有一条决策任务路径:当 complexity 信号绑定到DecisionTaskContract时,模型会以问答形式直接为请求打分(decision_complexity.go),规则的description被注入问题指令,hard/easy 候选分别注入 levels 的示例。该路径下显式边界读取原生 [0,1] 分数,legacy 对称阈值则映射为2*score - 1以匹配以 0 为中心的量纲(同文件 L84-L91)。

八、在决策规则中引用 complexity:完整实战示例

仓库 config/recipes/balance/config.yaml 中,complexity信号被广泛用于组合决策条件,例如:

  • 法律/合规场景升级:legal_risk:medium、legal_risk:hard类型的 complexity 条件与domain: law、keyword 条件 OR 组合,命中则路由到anthropic/claude-opus-4.6、openai/gpt5.4的高推理通道(config/recipes/balance/config.yaml);
  • 数学推理降级保护:math_task:medium类型的 complexity 条件配合投影条件,决定请求是否进入reasoning_deep决策(同文件 L335-L347);
  • 证据敏感的健康咨询升级:evidence_synthesis:hard触发verified_health通道(同文件 L676-L678);
  • 简易解释保留在廉价模型:evidence_synthesis:medium配合领域与投影条件,将中等复杂度的解释类请求留在qwen/qwen3.5-rocm(同文件 L877-L887)。

注意:决策规则中引用复杂度判定时,条件写法为:

conditions: - name: legal_risk:hard type: complexity

其中name是规则名:判定,type固定为complexity。这也是routing.signals.complexity中规则name必须唯一且稳定的原因——它直接成为跨决策复用的键。

九、调参实践与注意事项

  1. 用有代表性的难/易示例配置:候选示例决定学习边界,示例应贴近真实路由成本画像(哪些请求该贵、哪些该便宜),而非任意短语。
  2. 从低 threshold 起步:仓库自带片段 escalation.yaml 使用threshold: 0.10,相比文档示例的0.75更为宽松——threshold是到 0 的距离,值越大越保守(只有 margin 足够极端才升级),值越小越敏感。按流量观察 hard/easy 判定占比再逐步调整。
  3. medium 区间是缓冲带:介于边界之间的请求不会触发任何判定,避免接近边界的请求在两次路由间反复横跳。
  4. 显式边界对用于远程分数:一旦配置score.v1后端,立即改用hard_above/easy_below显式对,并确认量纲与阈值范围匹配。
  5. 多模态候选需第二个嵌入 provider:声明image_candidates前,确认多模态嵌入模型已初始化;图片候选会强制走多模态原型路径。
  6. 校验在启动时完成:重叠边界、半对边界(只声明一个方向)、threshold与显式对并存、非有限数值等错误都会在启动阶段被 ValidateComplexityRuleBoundaries 拦截,先跑一遍配置校验再上线。

十、源码路径速查

  • 信号片段与默认规则:config/fragments/signal/complexity/escalation.yaml
  • 规则结构定义:src/semantic-router/pkg/config/signal_config.go
  • 边界解析与校验:src/semantic-router/pkg/config/complexity_boundaries.go
  • 后端契约与启动校验:src/semantic-router/pkg/config/classifier_backend_complexity.go
  • 分类器核心实现:src/semantic-router/pkg/classification/complexity_classifier.go
  • 候选嵌入预加载:src/semantic-router/pkg/classification/complexity_candidate_embeddings.go
  • 信号评分与融合:src/semantic-router/pkg/classification/complexity_rule_scoring.go
  • 查询嵌入加载:src/semantic-router/pkg/classification/complexity_query_embeddings.go
  • 决策引擎引用示例:config/recipes/balance/config.yaml
  • 后端
  • API网关
  • 模型推理服务
  • AI Agent

【免费下载链接】semantic-router

An open, programmable decision layer for models and compute.

项目地址:https://gitcode.com/gh_mirrors/sem/semantic-router
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进