phase7: cheapestModel prefers non-reasoning models for utility calls (+ regression test)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Showing 2 changed files with +18 and −3
modified
Sources/ZyquoCloud/Services/ModelCatalog.swift
+5 −3
@@ -36,10 +36,12 @@ final class ModelCatalog: ObservableObject { | ||
| 36 | 36 | } |
| 37 | 37 | |
| 38 | 38 | /// Cheapest non-legacy chat model for a provider (used for key tests and |
| 39 | − /// auto-title generation). | |
| 39 | + /// auto-title generation). Non-reasoning models are preferred — reasoning | |
| 40 | + /// models burn their token budget thinking, useless for tiny utility calls. | |
| 40 | 41 | func cheapestModel(for provider: ProviderID) -> AIModel? { |
| 41 | − models(for: provider) | |
| 42 | − .filter { !$0.isLegacy } | |
| 42 | + let candidates = models(for: provider).filter { !$0.isLegacy } | |
| 43 | + let plain = candidates.filter { !$0.capabilities.reasoning } | |
| 44 | + return (plain.isEmpty ? candidates : plain) | |
| 43 | 45 | .min { ($0.pricing?.outputPerMTok ?? .infinity) < ($1.pricing?.outputPerMTok ?? .infinity) } |
| 44 | 46 | } |
| 45 | 47 | |
modified
Tests/ZyquoCloudTests/ModelTests.swift
+13 −0
@@ -77,6 +77,19 @@ import Testing | ||
| 77 | 77 | #expect(message == "model not found") |
| 78 | 78 | } |
| 79 | 79 | |
| 80 | + @Test @MainActor func cheapestModelPrefersNonReasoning() { | |
| 81 | + let catalog = ModelCatalog() | |
| 82 | + for provider in ProviderID.builtIn { | |
| 83 | + guard let cheapest = catalog.cheapestModel(for: provider) else { continue } | |
| 84 | + let plainExists = catalog.models(for: provider) | |
| 85 | + .contains { !$0.isLegacy && !$0.capabilities.reasoning } | |
| 86 | + if plainExists { | |
| 87 | + #expect(!cheapest.capabilities.reasoning, | |
| 88 | + "\(provider): utility calls must not use a reasoning model") | |
| 89 | + } | |
| 90 | + } | |
| 91 | + } | |
| 92 | + | |
| 80 | 93 | @Test func everyBuiltInProviderHasBaseURLAndFormat() { |
| 81 | 94 | for provider in ProviderID.builtIn { |
| 82 | 95 | #expect(provider.defaultBaseURL != nil, "\(provider) missing base URL") |
| 83 | 96 | |