This commit is contained in:
@@ -188,6 +188,19 @@ deaktiviert (`AllowOverride None`), oder es läuft nginx statt Apache (dort gilt
|
||||
grundsätzlich nicht) — dann hilft nur eine serverseitige Konfiguration durch den Hoster/Support
|
||||
(z.B. bei nginx ein `fastcgi_param HTTP_AUTHORIZATION $http_authorization;`).
|
||||
|
||||
## Fehlerbehebung: KI-Antwort endet mitten im JSON
|
||||
|
||||
Eine im Rettungsdialog am Ende abgeschnittene Modellantwort entsteht typischerweise nicht durch
|
||||
die Socketverbindung, sondern durch Anthropics `stop_reason: max_tokens`. Das Backend erkennt
|
||||
diesen Fall ausdrücklich und nennt das konfigurierte Limit in der Fehlermeldung. Der empfohlene
|
||||
Wert für `max_output_tokens` ist **16000**; abgerechnet werden trotzdem nur tatsächlich erzeugte
|
||||
Tokens.
|
||||
|
||||
Für echte Zeitüberschreitungen wartet der Anthropic-cURL-Aufruf höchstens 180 Sekunden und der
|
||||
Desktop-Client 210 Sekunden. Bricht eine Anfrage reproduzierbar früher ab, liegt davor noch ein
|
||||
Zeitlimit des Hosters (nginx/Apache/FastCGI/Reverse Proxy), das auf mindestens 180 Sekunden gesetzt
|
||||
werden muss.
|
||||
|
||||
## Was hiermit NICHT geprüft ist
|
||||
|
||||
- Ob Anthropic zuverlässig valides JSON im erwarteten Schema liefert (reine Prompt-Qualitätsfrage,
|
||||
|
||||
@@ -27,7 +27,10 @@ return [
|
||||
],
|
||||
|
||||
// Sicherheitsnetz gegen ausufernde Antworten (und damit Kosten) pro Anfrage.
|
||||
'max_output_tokens' => 8000,
|
||||
// 8.000 waren bei ausführlichen Einheitenplanungen nachweislich zu knapp und führten zu
|
||||
// mitten im JSON abgeschnittenen Antworten. Das ist eine Obergrenze, kein vorab berechneter
|
||||
// Festpreis: kürzere Antworten verbrauchen und kosten weiterhin nur ihre tatsächlichen Tokens.
|
||||
'max_output_tokens' => 16000,
|
||||
|
||||
// USD je 1 Million Token, getrennt nach Input/Output/Prompt-Cache. Vor dem produktiven Einsatz
|
||||
// gegen die aktuelle Anthropic-Preisseite gegenprüfen — Preise ändern sich.
|
||||
|
||||
@@ -161,6 +161,15 @@ $result = ai_backend_call_and_charge($pdo, $config, $user, $systemPrompt, $userC
|
||||
|
||||
// Erst NACH der Abrechnung validieren: die Token wurden real verbraucht, das wird auch dann
|
||||
// verrechnet, wenn die KI kein valides JSON geliefert hat (siehe Planungsdokument).
|
||||
if (($result['stopReason'] ?? null) === 'max_tokens') {
|
||||
ai_backend_fail(502,
|
||||
'Die KI-Antwort wurde am Ausgabelimit von ' . $config['max_output_tokens'] .
|
||||
' Tokens abgeschnitten. Bitte den Umfang der Anfrage verkleinern oder das Serverlimit erhöhen.', [
|
||||
'errorCode' => 'output_limit_reached',
|
||||
'rawResponse' => $result['content'],
|
||||
]);
|
||||
}
|
||||
|
||||
$parsed = ai_backend_decode_json_response($result['content']);
|
||||
if (!is_array($parsed) || !isset($parsed['lessons']) || !is_array($parsed['lessons'])) {
|
||||
// Die bezahlte Modellantwort nicht wegwerfen: Der Desktop-Client kann sie in einem
|
||||
|
||||
@@ -37,7 +37,11 @@ class AnthropicProvider implements ProviderInterface
|
||||
],
|
||||
'messages' => [['role' => 'user', 'content' => $userContent]],
|
||||
]),
|
||||
CURLOPT_TIMEOUT => 90,
|
||||
// Umfangreiche Einheitenplanungen können bei großen Antworten länger dauern. Der
|
||||
// Desktop-Client wartet etwas länger (210 s), damit immer dieser Server mit einer
|
||||
// verständlichen Fehlermeldung antworten kann, statt dass zuerst der Client abbricht.
|
||||
CURLOPT_CONNECTTIMEOUT => 15,
|
||||
CURLOPT_TIMEOUT => 180,
|
||||
]);
|
||||
$raw = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
@@ -68,6 +72,9 @@ class AnthropicProvider implements ProviderInterface
|
||||
|
||||
return [
|
||||
'content' => $text,
|
||||
// Insbesondere "max_tokens" darf nicht verloren gehen: Dann ist der Text zwar eine
|
||||
// technisch erfolgreiche API-Antwort, das JSON aber zwangsläufig am Ende abgeschnitten.
|
||||
'stopReason' => $data['stop_reason'] ?? null,
|
||||
'inputTokens' => (int) ($data['usage']['input_tokens'] ?? 0),
|
||||
'outputTokens' => (int) ($data['usage']['output_tokens'] ?? 0),
|
||||
'cacheCreationInputTokens' => (int) ($data['usage']['cache_creation_input_tokens'] ?? 0),
|
||||
|
||||
Reference in New Issue
Block a user