Feat: "Auto"-Button beim Kontext setzen - setzt den setup-bewussten Optimalwert
Beim manuellen ctx-Eintrag (Modellkarte »Ctx«) gab es nur ein leeres Eingabefeld.
Jetzt:
- Backend: GET /api/models/{id}/ctx/auto liefert den setup-bewussten Optimal-ctx fuer
ein bestehendes Modell (Rolle/Params/Quant + aktuelles Setup) inkl. Budget-Herleitung.
budget.py: params_of_model() + setup_aware_ctx_for_model() (DRY mit footprint_gb).
- Dialog (CustomDialog/useDialog): optionaler Auto-Button im Prompt, der den Wert eintraegt.
- Cockpit: »Ctx« holt den Optimalwert, zeigt ihn + Budget (GTT/reserviert/frei) in der
Meldung und bietet »Auto (Nk)« zum direkten Uebernehmen.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+67
-67
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -7,7 +7,7 @@
|
||||
<link rel="manifest" href="/manifest.webmanifest" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<title>Mission Control 2.0</title>
|
||||
<script type="module" crossorigin src="/assets/index-DGRyEXwM.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-eaeyLEVq.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CqYu-pXY.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -6,11 +6,13 @@ export interface CustomDialogProps {
|
||||
title: string
|
||||
message: string
|
||||
defaultValue?: string
|
||||
autoValue?: string
|
||||
autoLabel?: string
|
||||
onConfirm: (val?: string) => void
|
||||
onCancel?: () => void
|
||||
}
|
||||
|
||||
export function CustomDialog({ type, title, message, defaultValue, onConfirm, onCancel }: CustomDialogProps) {
|
||||
export function CustomDialog({ type, title, message, defaultValue, autoValue, autoLabel, onConfirm, onCancel }: CustomDialogProps) {
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
return (
|
||||
<div className="fixed inset-0 z-[99] bg-black/60 backdrop-blur-sm flex items-center justify-center p-4">
|
||||
@@ -27,18 +29,30 @@ export function CustomDialog({ type, title, message, defaultValue, onConfirm, on
|
||||
<p className="text-xs text-muted-foreground leading-relaxed">{message}</p>
|
||||
|
||||
{type === "prompt" && (
|
||||
<input
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
defaultValue={defaultValue}
|
||||
className="w-full h-9 px-3 text-xs bg-background/40 border border-border/60 rounded-lg outline-none focus:border-primary transition-colors text-foreground"
|
||||
autoFocus
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
onConfirm(inputRef.current?.value)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div className="flex gap-2">
|
||||
<input
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
defaultValue={defaultValue}
|
||||
className="flex-1 h-9 px-3 text-xs bg-background/40 border border-border/60 rounded-lg outline-none focus:border-primary transition-colors text-foreground"
|
||||
autoFocus
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
onConfirm(inputRef.current?.value)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{autoValue !== undefined && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => { if (inputRef.current) inputRef.current.value = autoValue }}
|
||||
title="Setup-bewussten Optimalwert eintragen"
|
||||
className="h-9 px-3 shrink-0 text-xs font-semibold text-primary border border-primary/50 bg-primary/10 hover:bg-primary/20 rounded-lg transition-colors cursor-pointer"
|
||||
>
|
||||
{autoLabel || "Auto"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex justify-end gap-3 pt-2">
|
||||
|
||||
@@ -15,6 +15,8 @@ interface DialogState {
|
||||
title: string
|
||||
message: string
|
||||
defaultValue?: string
|
||||
autoValue?: string
|
||||
autoLabel?: string
|
||||
onConfirm: (val?: string) => void
|
||||
onCancel?: () => void
|
||||
}
|
||||
@@ -41,9 +43,11 @@ export function useDialog() {
|
||||
|
||||
const showPrompt = useCallback(
|
||||
(title: string, message: string, defaultValue: string,
|
||||
onConfirm: (val?: string) => void, onCancel?: () => void) => {
|
||||
onConfirm: (val?: string) => void, onCancel?: () => void,
|
||||
opts?: { autoValue?: string; autoLabel?: string }) => {
|
||||
setDialog({
|
||||
type: "prompt", title, message, defaultValue,
|
||||
autoValue: opts?.autoValue, autoLabel: opts?.autoLabel,
|
||||
onConfirm: (val) => { setDialog(null); onConfirm(val) },
|
||||
onCancel: () => { setDialog(null); onCancel?.() },
|
||||
})
|
||||
|
||||
@@ -132,22 +132,36 @@ export function Cockpit() {
|
||||
}
|
||||
|
||||
async function handleSetCtx(name: string, cur: number | null) {
|
||||
// Setup-bewussten Optimalwert holen (Rolle/Params/Quant + aktuelles Setup).
|
||||
let auto: { ctx: number; gtt_gb: number; reserved_gb: number; budget_gb: number; mode: string } | null = null
|
||||
try {
|
||||
auto = await api(`/api/models/${encodeURIComponent(name)}/ctx/auto`)
|
||||
} catch { /* Auto optional — Prompt funktioniert auch ohne */ }
|
||||
|
||||
const hint = auto
|
||||
? `Optimal für dein Setup: ${(auto.ctx / 1024).toFixed(0)}k (${auto.ctx}) — ` +
|
||||
`GTT ${auto.gtt_gb} GB − reserviert ${auto.reserved_gb} GB (${auto.mode}) → ${auto.budget_gb} GB frei. ` +
|
||||
`»Auto« trägt diesen Wert ein.`
|
||||
: "Gib die gewünschte Kontextlänge in Tokens an:"
|
||||
|
||||
showPrompt(
|
||||
"Kontextlänge anpassen",
|
||||
"Gib die gewünschte Kontextlänge in Tokens an:",
|
||||
hint,
|
||||
String(cur || 32768),
|
||||
async (v) => {
|
||||
if (!v) return
|
||||
try {
|
||||
await api(`/api/models/${encodeURIComponent(name)}/ctx`, {
|
||||
method: "POST",
|
||||
method: "POST",
|
||||
body: JSON.stringify({ ctx: parseInt(v, 10) }),
|
||||
})
|
||||
reload()
|
||||
} catch (e: any) {
|
||||
showAlert("Fehler", `Fehler beim Setzen des Kontexts: ${e.message || e}`)
|
||||
}
|
||||
}
|
||||
},
|
||||
undefined,
|
||||
auto ? { autoValue: String(auto.ctx), autoLabel: `Auto (${(auto.ctx / 1024).toFixed(0)}k)` } : undefined,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user