模型元数据(ModelSpec)与注册表(designs/provider-reliability.md §8;
Keelson Models/ModelSpec.cs、Models/ModelRegistry.cs)。
压缩(触发线 = 上下文窗口 × 百分比)、工具结果截断、thinking 预算上限、主备链
(chat-model.fallback/from-registry)都要问「这个模型的窗口 / 上限 / 能力 / 备选是什么」。
本 ns 只放结构与查询 API:不内置模型表(会过期,且是假想需求)、不按 spec 造 ChatModel
(造法由宿主给)。
"<provider>/<线上的模型 id>",按第一个斜杠拆("openrouter/anthropic/claude" →
["openrouter" "anthropic/claude"])。(def reg (spec/registry))
(spec/register! reg "anthropic/claude-sonnet-4"
{:context-limit 200000 :output-limit 64000 :fallbacks ["openai/gpt-4o"]})
(spec/context-limit reg "anthropic/claude-sonnet-4") ;=> 200000
(spec/fallback-chain reg "anthropic/claude-sonnet-4") ;=> ["openai/gpt-4o"]
模型元数据(ModelSpec)与注册表(designs/provider-reliability.md §8;
Keelson `Models/ModelSpec.cs`、`Models/ModelRegistry.cs`)。
压缩(触发线 = 上下文窗口 × 百分比)、工具结果截断、thinking 预算上限、主备链
(`chat-model.fallback/from-registry`)都要问「这个模型的窗口 / 上限 / 能力 / 备选是什么」。
本 ns **只放结构与查询 API**:不内置模型表(会过期,且是假想需求)、不按 spec 造 ChatModel
(造法由宿主给)。
- ref = `"<provider>/<线上的模型 id>"`,按**第一个**斜杠拆(`"openrouter/anthropic/claude"` →
`["openrouter" "anthropic/claude"]`)。
- 注册表是**实例**(atom),没有全局单例(design-principles §3)。
```clojure
(def reg (spec/registry))
(spec/register! reg "anthropic/claude-sonnet-4"
{:context-limit 200000 :output-limit 64000 :fallbacks ["openai/gpt-4o"]})
(spec/context-limit reg "anthropic/claude-sonnet-4") ;=> 200000
(spec/fallback-chain reg "anthropic/claude-sonnet-4") ;=> ["openai/gpt-4o"]
```(auto-compact-threshold spec)自动压缩触发线(token)= 可用窗口 × :auto-compact-percent / 100;缺任一 → nil。
自动压缩触发线(token)= 可用窗口 × :auto-compact-percent / 100;缺任一 → nil。
(context-limit reg ref)上下文窗口(token);没登记 / 没给 → nil。
上下文窗口(token);没登记 / 没给 → nil。
(fallback-chain reg ref)这条模型的备用链:按 :fallbacks 次序展开,各站自己的备选也接在后面(广度优先:先走完起点 自己列的那几家);去重、去掉起点、防环。没登记的 ref 留在链上——轮到它时才由造 ChatModel 的一方 报错,登记次序不该影响主模型的可用性。起点没登记 → []。
这条模型的备用链:按 :fallbacks 次序展开,各站自己的备选也接在后面(**广度优先**:先走完起点 自己列的那几家);去重、去掉起点、防环。没登记的 ref 留在链上——轮到它时才由造 ChatModel 的一方 报错,登记次序不该影响主模型的可用性。起点没登记 → []。
认得的元数据键(其余键原样收进 :options,选项表是开放的)。
认得的元数据键(其余键原样收进 :options,选项表是开放的)。
(model-spec ref)(model-spec ref opts)构造一条 ModelSpec(纯 map)。opts 认得的键见 known-keys,其余收进 :options。
返回 {:ref :provider :wire-id :label :context-limit :output-limit :thinking-levels :vision? :parallel-tools? :tool-output-limit :auto-compact-percent :usable-window-percent :metadata-guessed? :fallbacks [...] :options {...}}(没给的键不出现,:fallbacks 恒为向量)。
校验:ref 形状;:thinking-levels 须是字符串序列;fallbacks 去自身、去重、形状正确。
构造一条 ModelSpec(纯 map)。opts 认得的键见 `known-keys`,其余收进 `:options`。
返回 `{:ref :provider :wire-id :label :context-limit :output-limit :thinking-levels :vision?
:parallel-tools? :tool-output-limit :auto-compact-percent :usable-window-percent
:metadata-guessed? :fallbacks [...] :options {...}}`(没给的键不出现,:fallbacks 恒为向量)。
校验:ref 形状;`:thinking-levels` 须是字符串序列;fallbacks 去自身、去重、形状正确。(option spec k)(option spec k default)取一项开放选项(:options 里的);没有 → default。
取一项开放选项(:options 里的);没有 → default。
(output-limit reg ref)输出上限(token);没登记 / 没给 → nil。
输出上限(token);没登记 / 没给 → nil。
(ref-provider ref)ref 的 provider 段;拆不开 → nil。
ref 的 provider 段;拆不开 → nil。
(ref-wire-id ref)ref 的 wire-id 段;拆不开 → 原样(没有 provider 前缀的就是线上的名字)。
ref 的 wire-id 段;拆不开 → 原样(没有 provider 前缀的就是线上的名字)。
(register! reg spec-or-ref)(register! reg spec-or-ref opts)登记一条模型(同 ref 替换,位置不变)。接受 ModelSpec,或 ref + opts。返回登记的 spec。
登记一条模型(同 ref 替换,位置不变)。接受 ModelSpec,或 ref + opts。返回登记的 spec。
(registry)(registry specs)新建一张空注册表(atom,线程安全)。可选给一组初始条目:ModelSpec 或 [ref opts]。
新建一张空注册表(atom,线程安全)。可选给一组初始条目:ModelSpec 或 [ref opts]。
(set-fallbacks! reg ref fallbacks)给已登记的模型换备用链(主模型先登记、备选后填是常见配法)。没有这条 → 抛 :validation-error。
给已登记的模型换备用链(主模型先登记、备选后填是常见配法)。没有这条 → 抛 :validation-error。
(split-ref ref)按第一个斜杠拆成 [provider wire-id];没有斜杠 / 斜杠在头或尾 → nil。
按第一个斜杠拆成 [provider wire-id];没有斜杠 / 斜杠在头或尾 → nil。
给思考预算留出的回答余量:思考预算上限 = 输出上限 − 它(Keelson ThinkingAnswerHeadroom)。
给思考预算留出的回答余量:思考预算上限 = 输出上限 − 它(Keelson `ThinkingAnswerHeadroom`)。
(thinking-budget-cap spec)思考预算上限 = 输出上限 − 回答余量(4096);没有输出上限或不够余量 → nil。
思考预算上限 = 输出上限 − 回答余量(4096);没有输出上限或不够余量 → nil。
(usable-context spec)可用窗口 = 上下文窗口 × :usable-window-percent / 100(没给百分比 → 原窗口);没有窗口 → nil。
可用窗口 = 上下文窗口 × :usable-window-percent / 100(没给百分比 → 原窗口);没有窗口 → nil。
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |