KI-gestützte Planungsunterstützung (4.5.9) + Kompetenzkatalog-Import (8.1.2)
KI-Unterstützung: neuer Einstellungen-Tab (Anmeldung, Guthaben) und Button im Planungs-Tab, der Einheiten+Stunden als JSON an ein neues PHP-Backend (ai-backend/) sendet und die Antwort als prüfbare Vorschlagsliste zurückbringt. Provider-Aufruf, Guthabenverwaltung und Abrechnung nach echten Token-Kosten laufen serverseitig, der Desktop-Client sieht nie einen LLM-API-Key. Zentral abgesichert: eine von der KI zurückgegebene Stunden-Id, die zu keiner echten Lesson der Einheit passt, wird nie als Update übernommen, sondern immer als neue Stunde behandelt. Kompetenzkatalog-Import (8.1.2): JSON-Export/Import für Kompetenzkataloge.
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/ProviderInterface.php';
|
||||
|
||||
/** Ruft die Anthropic Messages API direkt per curl auf — bewusst ohne SDK-Abhängigkeit. */
|
||||
class AnthropicProvider implements ProviderInterface
|
||||
{
|
||||
public function __construct(private string $apiKey, private string $model) {}
|
||||
|
||||
public function sendMessage(string $systemPrompt, string $userContent, int $maxTokens): array
|
||||
{
|
||||
$ch = curl_init('https://api.anthropic.com/v1/messages');
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_HTTPHEADER => [
|
||||
'content-type: application/json',
|
||||
'x-api-key: ' . $this->apiKey,
|
||||
'anthropic-version: 2023-06-01',
|
||||
],
|
||||
CURLOPT_POSTFIELDS => json_encode([
|
||||
'model' => $this->model,
|
||||
'max_tokens' => $maxTokens,
|
||||
'system' => $systemPrompt,
|
||||
'messages' => [['role' => 'user', 'content' => $userContent]],
|
||||
]),
|
||||
CURLOPT_TIMEOUT => 90,
|
||||
]);
|
||||
$raw = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$curlError = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($raw === false) {
|
||||
throw new RuntimeException("Anthropic-Anfrage fehlgeschlagen: $curlError");
|
||||
}
|
||||
if ($httpCode >= 400) {
|
||||
throw new RuntimeException("Anthropic-API-Fehler (HTTP $httpCode): " . substr((string) $raw, 0, 500));
|
||||
}
|
||||
|
||||
$data = json_decode((string) $raw, true);
|
||||
if (!is_array($data)) {
|
||||
throw new RuntimeException('Anthropic-Antwort konnte nicht als JSON gelesen werden.');
|
||||
}
|
||||
if (($data['stop_reason'] ?? null) === 'refusal') {
|
||||
throw new RuntimeException('Die KI hat die Anfrage abgelehnt.');
|
||||
}
|
||||
|
||||
$text = '';
|
||||
foreach (($data['content'] ?? []) as $block) {
|
||||
if (($block['type'] ?? null) === 'text') {
|
||||
$text .= $block['text'];
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'content' => $text,
|
||||
'inputTokens' => (int) ($data['usage']['input_tokens'] ?? 0),
|
||||
'outputTokens' => (int) ($data['usage']['output_tokens'] ?? 0),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user