192 lines
7.3 KiB
Swift
192 lines
7.3 KiB
Swift
// PR 8 (+ PR 14 advanced/experimental expansion) — GET /admin/api/models
|
|
// response + per-model settings shape, plus the patch body for
|
|
// PUT /admin/api/models/{id}/settings.
|
|
//
|
|
// All fields the HTML admin modal renders are now exposed here so the
|
|
// Swift Advanced tab can reach feature parity. Experimental flags
|
|
// (TurboQuant KV, IndexCache, SpecPrefill, DFlash, native MTP) decode
|
|
// alongside compatibility readouts (`dflash_compatible`,
|
|
// `mtp_compatible`, etc.) sourced from the server so the UI can disable
|
|
// switches the runtime won't accept.
|
|
|
|
import Foundation
|
|
|
|
struct ListModelsResponse: Codable, Sendable {
|
|
let models: [ModelDTO]
|
|
}
|
|
|
|
struct ModelDTO: Codable, Equatable, Sendable, Identifiable {
|
|
let id: String
|
|
let displayName: String?
|
|
let modelPath: String?
|
|
let loaded: Bool
|
|
let isLoading: Bool
|
|
let estimatedSize: Int64
|
|
let estimatedSizeFormatted: String?
|
|
let pinned: Bool?
|
|
let isDefault: Bool?
|
|
let isFavorite: Bool?
|
|
let engineType: String?
|
|
let modelType: String?
|
|
/// Lower-level config-derived model class (e.g. `deepseek_v32`,
|
|
/// `glm_moe_dsa`). Used to gate the IndexCache row to DSA models.
|
|
let configModelType: String?
|
|
/// Server-side default for `enable_thinking` derived from the model
|
|
/// (chat template, config). UI shows it as the inherited value when
|
|
/// `enable_thinking` is unset and offers a one-click reset to it.
|
|
let thinkingDefault: Bool?
|
|
/// True when the model is structurally compatible with DFlash (block
|
|
/// diffusion speculative decoding). The toggle stays disabled when false.
|
|
let dflashCompatible: Bool?
|
|
/// Human-readable explanation when `dflashCompatible` is false. Surfaced
|
|
/// as a tooltip on the disabled DFlash toggle.
|
|
let dflashCompatibilityReason: String?
|
|
/// True when the global paged-SSD cache directory is configured. The
|
|
/// DFlash SSD-cache sub-toggle stays disabled when false.
|
|
let dflashSsdCacheAvailable: Bool?
|
|
/// True when the model is structurally compatible with native MTP.
|
|
let mtpCompatible: Bool?
|
|
let mtpCompatibilityReason: String?
|
|
let settings: ModelSettingsDTO?
|
|
}
|
|
|
|
struct ModelSettingsDTO: Codable, Equatable, Sendable {
|
|
let modelAlias: String?
|
|
let modelTypeOverride: String?
|
|
let maxContextWindow: Int?
|
|
let maxTokens: Int?
|
|
let temperature: Double?
|
|
let topP: Double?
|
|
let topK: Int?
|
|
let minP: Double?
|
|
let presencePenalty: Double?
|
|
let repetitionPenalty: Double?
|
|
let forceSampling: Bool?
|
|
let maxToolResultTokens: Int?
|
|
let enableThinking: Bool?
|
|
let thinkingBudgetEnabled: Bool?
|
|
let thinkingBudgetTokens: Int?
|
|
let reasoningParser: String?
|
|
let ttlSeconds: Int?
|
|
let isPinned: Bool?
|
|
let isDefault: Bool?
|
|
let isFavorite: Bool?
|
|
let displayName: String?
|
|
let activeProfileName: String?
|
|
// Security
|
|
let trustRemoteCode: Bool?
|
|
// Chat-template kwargs (free-form dict + a sibling list of keys the
|
|
// user wants to *force* — those go to `forced_ct_kwargs` server-side
|
|
// and override the request's `chat_template_kwargs`).
|
|
let chatTemplateKwargs: [String: AnyCodable]?
|
|
let forcedCtKwargs: [String]?
|
|
// Experimental: TurboQuant KV cache
|
|
let turboquantKvEnabled: Bool?
|
|
let turboquantKvBits: Double?
|
|
// Experimental: IndexCache (DSA models only)
|
|
let indexCacheFreq: Int?
|
|
// Experimental: SpecPrefill
|
|
let specprefillEnabled: Bool?
|
|
let specprefillDraftModel: String?
|
|
let specprefillKeepPct: Double?
|
|
let specprefillThreshold: Int?
|
|
// Experimental: DFlash (block diffusion speculative decoding)
|
|
let dflashEnabled: Bool?
|
|
let dflashDraftModel: String?
|
|
let dflashDraftQuantEnabled: Bool?
|
|
let dflashDraftQuantWeightBits: Int?
|
|
let dflashDraftQuantActivationBits: Int?
|
|
let dflashDraftQuantGroupSize: Int?
|
|
let dflashMaxCtx: Int?
|
|
let dflashInMemoryCache: Bool?
|
|
let dflashInMemoryCacheMaxEntries: Int?
|
|
/// Stored in bytes server-side; the editor row exposes a GiB-scaled
|
|
/// view via `DflashByteSize.gibToBytes` / `bytesToGib`.
|
|
let dflashInMemoryCacheMaxBytes: Int64?
|
|
let dflashSsdCache: Bool?
|
|
let dflashSsdCacheMaxBytes: Int64?
|
|
let dflashDraftWindowSize: Int?
|
|
let dflashDraftSinkSize: Int?
|
|
let dflashVerifyMode: String?
|
|
// Experimental: native MTP (mlx-lm PR 990 / PR 15 monkey-patch)
|
|
let mtpEnabled: Bool?
|
|
// Experimental: VLM MTP (mlx-vlm assistant-drafter speculative decoding)
|
|
let vlmMtpEnabled: Bool?
|
|
let vlmMtpDraftModel: String?
|
|
let vlmMtpDraftBlockSize: Int?
|
|
}
|
|
|
|
/// Patch body for PUT /admin/api/models/{id}/settings. Flat snake-cased
|
|
/// keys (Encoder converts via `.convertToSnakeCase`). `nil` fields are
|
|
/// omitted by `encodeIfPresent` so the server merges instead of resetting.
|
|
struct ModelSettingsPatch: Encodable, Equatable, Sendable {
|
|
var modelAlias: String? = nil
|
|
var modelTypeOverride: String? = nil
|
|
var maxContextWindow: Int? = nil
|
|
var maxTokens: Int? = nil
|
|
var temperature: Double? = nil
|
|
var topP: Double? = nil
|
|
var topK: Int? = nil
|
|
var minP: Double? = nil
|
|
var presencePenalty: Double? = nil
|
|
var repetitionPenalty: Double? = nil
|
|
var ttlSeconds: Int? = nil
|
|
var enableThinking: Bool? = nil
|
|
var thinkingBudgetEnabled: Bool? = nil
|
|
var thinkingBudgetTokens: Int? = nil
|
|
var maxToolResultTokens: Int? = nil
|
|
var forceSampling: Bool? = nil
|
|
var isPinned: Bool? = nil
|
|
var isFavorite: Bool? = nil
|
|
// Security
|
|
var trustRemoteCode: Bool? = nil
|
|
var reasoningParser: String? = nil
|
|
// Chat-template kwargs
|
|
var chatTemplateKwargs: [String: AnyCodable]? = nil
|
|
var forcedCtKwargs: [String]? = nil
|
|
// Experimental: TurboQuant KV
|
|
var turboquantKvEnabled: Bool? = nil
|
|
var turboquantKvBits: Double? = nil
|
|
// Experimental: IndexCache
|
|
var indexCacheFreq: Int? = nil
|
|
// Experimental: SpecPrefill
|
|
var specprefillEnabled: Bool? = nil
|
|
var specprefillDraftModel: String? = nil
|
|
var specprefillKeepPct: Double? = nil
|
|
var specprefillThreshold: Int? = nil
|
|
// Experimental: DFlash
|
|
var dflashEnabled: Bool? = nil
|
|
var dflashDraftModel: String? = nil
|
|
var dflashDraftQuantEnabled: Bool? = nil
|
|
var dflashDraftQuantWeightBits: Int? = nil
|
|
var dflashDraftQuantActivationBits: Int? = nil
|
|
var dflashDraftQuantGroupSize: Int? = nil
|
|
var dflashMaxCtx: Int? = nil
|
|
var dflashInMemoryCache: Bool? = nil
|
|
var dflashInMemoryCacheMaxEntries: Int? = nil
|
|
var dflashInMemoryCacheMaxBytes: Int64? = nil
|
|
var dflashSsdCache: Bool? = nil
|
|
var dflashSsdCacheMaxBytes: Int64? = nil
|
|
var dflashDraftWindowSize: Int? = nil
|
|
var dflashDraftSinkSize: Int? = nil
|
|
var dflashVerifyMode: String? = nil
|
|
// Experimental: native MTP
|
|
var mtpEnabled: Bool? = nil
|
|
// Experimental: VLM MTP
|
|
var vlmMtpEnabled: Bool? = nil
|
|
var vlmMtpDraftModel: String? = nil
|
|
var vlmMtpDraftBlockSize: Int? = nil
|
|
}
|
|
|
|
/// Generic acknowledgment shape returned by non-streaming admin endpoints
|
|
/// that just need to signal completion (model load/unload, settings patch,
|
|
/// task cancel/remove, stats clear, sub-key CRUD, etc.). Server responses
|
|
/// vary in which subset of `status`/`message`/`success` they populate, so
|
|
/// all three are optional and callers typically only check that the call
|
|
/// did not throw.
|
|
struct SimpleStatusResponse: Codable, Sendable {
|
|
let status: String?
|
|
let message: String?
|
|
let success: Bool?
|
|
}
|