Prompt-Caching, Tool-Ergebnis-Kappung und Kostenerfassung
T1 — Prompt-Caching. Bisher wurde bei jedem Schritt eines Runs der komplette Prompt neu berechnet, inklusive Tool-Definitionen und System-Prompt, die sich nie aendern. Bei zehn Schritten und einem 15k-Praefix sind das 150.000 statt 15.000 Eingabe-Tokens. ChatMessage bekommt dafuer einen eigenen JsonConverter: Der Inhalt geht weiterhin als String raus, bei gesetztem CacheBreakpoint jedoch als Blockarray mit cache_control. Beim Lesen werden beide Formate akzeptiert, damit bestehende ChatContext.json weiter geladen werden koennen. PromptCache setzt zwei Breakpoints: einen auf den System-Prompt (deckt Tool-Definitionen und System-Prompt ab) und einen rollierenden auf die letzte Nachricht mit Inhalt. Vorherige Markierungen werden vorher entfernt, damit sie sich nicht ansammeln. Aktivierung ueber promptCaching: auto (Default, aktiv fuer Modelle mit Unterstuetzung), on oder off. Der wichtigste Test dazu prueft die Praefix-Stabilitaet: Der System-Prompt muss ueber alle Schritte zeichengleich serialisiert werden. Ein einziger Zeitstempel darin wuerde den Cache still verwerfen — die Kosten blieben unveraendert, ohne dass es irgendwo auffiele. T9 — Usage liest prompt_tokens_details.cached_tokens; die Zahl wird bis in AgentRunResult durchgereicht. Ohne sie liesse sich die Wirkung nicht belegen. T2 — Tool-Ergebnisse werden jetzt zentral in ExecuteToolCallAsync gekappt (maxToolResultChars, Default 16.000). Bisher konnte ein einzelner WebFetch mit dem 512-KB-Standardlimit rund 130.000 Tokens in EINER Antwort erzeugen; die Compaction griff erst danach, bezahlt war der Request laengst. T3 — Die Zusammenfassung beim Kompaktieren laeuft ueber ein konfigurierbares summaryModel (Default gemini-2.5-flash) statt ueber das teure Agentenmodell. B4 — AgentRunResult fuehrt Prompt- und Completion-Tokens getrennt; die Kostenanzeige schaetzte bisher 50/50, real liegt das Verhaeltnis eher bei 95:5. Die veraltete Preistabelle bleibt offen. Neue Einstellungen sind im PropertyGrid sichtbar und werden vom AgentEditor bei neuen Agenten mitgeschrieben. Alle 91 Tests gruen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
6bbe9f9a80
commit
69b5704add
@@ -3,6 +3,16 @@ using ClawdDotNet.Core.Config;
|
||||
|
||||
namespace ClawdDotNet.Models;
|
||||
|
||||
/// <summary>Bietet die drei gültigen Prompt-Caching-Werte als Auswahlliste an.</summary>
|
||||
public sealed class PromptCachingConverter : StringConverter
|
||||
{
|
||||
public override bool GetStandardValuesSupported(ITypeDescriptorContext? context) => true;
|
||||
public override bool GetStandardValuesExclusive(ITypeDescriptorContext? context) => true;
|
||||
|
||||
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext? context)
|
||||
=> new(new[] { "auto", "on", "off" });
|
||||
}
|
||||
|
||||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public sealed class AgentSettingsViewModel
|
||||
{
|
||||
@@ -106,6 +116,42 @@ public sealed class AgentSettingsViewModel
|
||||
set => _config.LoopGuard.CompactionThreshold = Math.Clamp(value, 50, 95) / 100.0;
|
||||
}
|
||||
|
||||
[Category("3 - Kontext-Management")]
|
||||
[DisplayName("Modell für Zusammenfassungen")]
|
||||
[Description("Modell, mit dem beim Kompaktieren zusammengefasst wird. Leer = Modell des Agenten. " +
|
||||
"Zusammenfassen ist anspruchslos — ein günstiges Modell spart hier deutlich, " +
|
||||
"da bis zu 30.000 Zeichen verarbeitet werden.")]
|
||||
public string SummaryModel
|
||||
{
|
||||
get => _config.LoopGuard.SummaryModel;
|
||||
set => _config.LoopGuard.SummaryModel = value ?? "";
|
||||
}
|
||||
|
||||
[Category("3 - Kontext-Management")]
|
||||
[DisplayName("Max. Zeichen pro Tool-Ergebnis")]
|
||||
[Description("Längere Tool-Ergebnisse werden gekürzt, bevor sie in den Kontext gelangen. " +
|
||||
"Ohne Grenze kann ein einzelner Abruf den Kontext sprengen — 512 KB entsprechen " +
|
||||
"etwa 130.000 Tokens in einer einzigen Antwort.")]
|
||||
public int MaxToolResultChars
|
||||
{
|
||||
get => _config.MaxToolResultChars;
|
||||
set => _config.MaxToolResultChars = Math.Max(1_000, value);
|
||||
}
|
||||
|
||||
// ──────────────── Kosten ────────────────
|
||||
|
||||
[Category("5 - Kosten")]
|
||||
[DisplayName("Prompt-Caching")]
|
||||
[Description("auto = für Modelle aktivieren, die es unterstützen; on = erzwingen; off = aus. " +
|
||||
"Spart erheblich, weil jeder Schritt eines Runs den kompletten Prompt erneut sendet — " +
|
||||
"System-Prompt und Tool-Definitionen also dutzendfach.")]
|
||||
[TypeConverter(typeof(PromptCachingConverter))]
|
||||
public string PromptCaching
|
||||
{
|
||||
get => _config.PromptCaching;
|
||||
set => _config.PromptCaching = string.IsNullOrWhiteSpace(value) ? "auto" : value;
|
||||
}
|
||||
|
||||
// ──────────────── Tools (Read-Only) ────────────────
|
||||
|
||||
[Category("4 - Tools")]
|
||||
|
||||
Reference in New Issue
Block a user