Skip to content

fix: 隐藏模型不再进入自动探测与限流替补 (#103) - #106

Open
ghshhf wants to merge 2 commits into
LAGcomcom:masterfrom
ghshhf:fix/reasoning-effort-max
Open

ghshhf wants to merge 2 commits into
LAGcomcom:masterfrom
ghshhf:fix/reasoning-effort-max

Conversation

@ghshhf

@ghshhf ghshhf commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

问题

模型页取消勾选的模型(cfg.HiddenModels),只是从选择器和 GET /v1/models 里消失。lane 依然每轮探测它们,限流切换时也依然把它们当替补。

结果是:一个用户明确关掉的模型,持续收到真实上游请求、持续消耗免费额度。在按额度计的免费车道上,这不只是浪费,还是把用户主动省下的配额替用户花掉。

修复

  • Lane 新增 hidden map[string]bool 与 SetHidden([]string)
  • ProbeRound 取目标时改用过滤后的目录,隐藏模型不进入本轮探测;全部隐藏时本轮直接空转
  • nextCandidate 跳过隐藏 id,Candidates() 随之干净
  • 启动时从 cfg.HiddenModels 播种,可见性接口里热应用(不必重启)
  • 显式请求路径完全不变:Complete 仍走 BaseModelId(req.Model)。隐藏的语义是"不自动用它",不是"禁用"

一个必须说清的坑

第一版过滤函数是自锁的:它在 ProbeRound 持有写锁期间去拿读锁,而 sync.RWMutex 不可重入 —— 于是整轮探测死锁,所有等结论的调用方一起挂住。这里的实测表现很能说明问题:TestReprobeCoversCustomProviderModels 从 5s 变成 2 分 09 秒直至超时。

现在拆成 probeTargetsLocked()(供已持锁者调用)与 probeTargets()(自己拿读锁)两个,ProbeRound 走前者。

测试

internal/lane/hidden_test.go 钉死三件事:

  1. 隐藏模型不出现于探测目标,也不作为候选返回;
  2. 取消隐藏后能回来(不是单向门);
  3. 全部隐藏时 ProbeRound 仍会返回 —— 用 goroutine + 10s 超时兜住死锁回归。

go build ./... / go vet ./... 通过;go test ./... 全绿(internal/gateway 28.3s、internal/lane 34.9s)。

Closes #103

…#103)

Hidden models (user-unchecked on the 模型 page) stay servable when
requested explicitly but are now excluded from:
- ProbeRound (no more real upstream requests for hidden models)
- nextCandidate (hidden models won't become failover substitutes)
- Candidates() hint list

Lane.SetHidden() holds an independent hidden set, seeded from
cfg.HiddenModels at boot and hot-applied on visibility changes.
…Gcomcom#103)

probeTargets took the read lock while ProbeRound still held the write lock;
sync.RWMutex is not reentrant, so the round deadlocked and every caller that
waited for a verdict hung with it. The filtered copy is now built by
probeTargetsLocked, and probeTargets is only for callers that do not already
hold the lock.

Tests: hidden models stay out of both the probe round and the candidate
list, come back when unhidden, and a round with every model hidden still
returns.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

模型页取消勾选的模型,仍会被周期探测和限流切换真实访问

1 participant