Backup #1558

ID1558
Dateipfad/var/www/dev.campus.systemische-tools.de/src/Controller/ChatController.php
Version111
Typ modified
Größe8.4 KB
Hash23513e94f1256f63bce1ef6c161bab05aafb7ad6149847e7de0a7de7254b7b44
Datum2025-12-26 20:28:10
Geändert vonclaude-code-hook
GrundClaude Code Pre-Hook Backup vor Edit-Operation
Datei existiert Ja

Dateiinhalt

<?php

declare(strict_types=1);

namespace Controller;

// @responsibility: HTTP-Endpunkte für KI-Chat (Sessions, Nachrichten, Export)

use Domain\Factory\ChatSessionFactory;
use Domain\Service\ModelRegistryInterface;
use Framework\Controller;
use Infrastructure\Formatting\ChatMessageFormatter;
use UseCases\Chat\CreateChatSessionUseCaseInterface;
use UseCases\Chat\DeleteChatSessionUseCaseInterface;
use UseCases\Chat\ExportChatSessionUseCase;
use UseCases\Chat\GetChatSessionUseCaseInterface;
use UseCases\Chat\SendChatMessageUseCase;
use UseCases\Chat\UpdateChatSessionUseCaseInterface;

class ChatController extends Controller
{
    public function __construct(
        private CreateChatSessionUseCaseInterface $createSessionUseCase,
        private GetChatSessionUseCaseInterface $getSessionUseCase,
        private UpdateChatSessionUseCaseInterface $updateSessionUseCase,
        private DeleteChatSessionUseCaseInterface $deleteSessionUseCase,
        private SendChatMessageUseCase $messageUseCase,
        private ChatMessageFormatter $formatter,
        private ExportChatSessionUseCase $exportUseCase,
        private ModelRegistryInterface $modelRegistry
    ) {
    }

    public function index(): void
    {
        $uuid = $this->createSessionUseCase->createSession();
        header('Location: /chat/' . $uuid);
        exit;
    }

    public function show(string $uuid): void
    {
        $session = $this->getSessionUseCase->getSession($uuid);

        if ($session === null) {
            header('Location: /chat');
            exit;
        }

        // Convert entities to arrays for views
        $messages = $this->getSessionUseCase->getMessages($session->getId() ?? 0);
        $messagesArray = array_map(fn ($m) => $m->toArray(), $messages);

        $this->view('chat.index', [
            'title' => $session->getTitle() ?? 'KI-Chat',
            'session' => ChatSessionFactory::toArray($session),
            'messages' => $messagesArray,
            'sessions' => $this->getSessionUseCase->getAllSessionsWithStats(),
            'authorProfiles' => $this->getSessionUseCase->getAuthorProfiles(),
            'systemPrompts' => $this->getSessionUseCase->getSystemPrompts(),
            'outputStructures' => $this->getSessionUseCase->getOutputStructures(),
            'collections' => $this->getSessionUseCase->getAvailableCollections(),
            'models' => $this->modelRegistry->getChatModels(),
            'defaultModel' => $this->modelRegistry->getDefaultChatModel(),
        ]);
    }

    public function sessionList(): void
    {
        $this->view('chat.partials.session-list', [
            'sessions' => $this->getSessionUseCase->getAllSessionsWithStats(),
            'currentUuid' => $this->getString('current') ?: null,
        ]);
    }

    public function message(string $uuid): void
    {
        $session = $this->getSessionUseCase->getSession($uuid);

        if ($session === null) {
            $this->view('chat.partials.error', ['error' => 'Session nicht gefunden.']);

            return;
        }

        $sessionId = $session->getId() ?? 0;
        $question = trim($_POST['message'] ?? '');
        $requestedModel = $_POST['model'] ?? $session->getModel();
        $model = $this->modelRegistry->isValid($requestedModel)
            ? $requestedModel
            : $this->modelRegistry->getDefaultChatModel();
        $sessionCollections = $session->getCollections();
        $collections = $_POST['collections'] ?? $sessionCollections;
        $contextLimit = (int) ($_POST['context_limit'] ?? $session->getContextLimit());
        $authorProfileId = (int) ($_POST['author_profile_id'] ?? $session->getAuthorProfileId() ?? 0);
        $systemPromptId = (int) ($_POST['system_prompt_id'] ?? $session->getSystemPromptId() ?? 1);
        $structureId = (int) ($_POST['structure_id'] ?? 0);
        $temperature = (float) ($_POST['temperature'] ?? $session->getTemperature());
        $maxTokens = (int) ($_POST['max_tokens'] ?? $session->getMaxTokens());

        if ($this->updateSessionUseCase->settingsHaveChanged($session, $model, $collections, $contextLimit, $authorProfileId, $temperature, $maxTokens)) {
            $this->updateSessionUseCase->updateSettings($sessionId, $model, $collections, $contextLimit, $authorProfileId, $temperature, $maxTokens);
        }

        if ($question === '') {
            $this->view('chat.partials.error', ['error' => 'Bitte gib eine Frage ein.']);

            return;
        }

        if (!empty($collections)) {
            $compatibility = $this->updateSessionUseCase->validateCollectionCompatibility($collections);
            if (!$compatibility['valid']) {
                $this->view('chat.partials.error', [
                    'error' => 'Collection-Fehler: ' . $compatibility['error'],
                    'details' => 'Bitte wähle nur Collections mit gleichem Embedding-Modell.',
                ]);

                return;
            }
        }

        $qualityCheck = isset($_POST['quality_check']) && $_POST['quality_check'] === '1';

        $response = $this->messageUseCase->execute(
            sessionUuid: $uuid,
            message: $question,
            model: $model,
            collections: $collections,
            contextLimit: $contextLimit,
            authorProfileId: $authorProfileId,
            systemPromptId: $systemPromptId,
            temperature: $temperature,
            maxTokens: $maxTokens,
            structureId: $structureId,
            qualityCheck: $qualityCheck
        );

        if ($response->hasError()) {
            $this->view('chat.partials.error', ['error' => $response->getError()]);

            return;
        }

        $result = $response->toArray();
        $this->view('chat.partials.response', [
            'question' => $question,
            'result' => $result,
            'model' => $model,
            'formattedAnswer' => $this->formatter->formatAnswer($result['answer'] ?? ''),
        ]);
    }

    public function updateTitle(string $uuid): void
    {
        $session = $this->getSessionUseCase->getSession($uuid);

        if ($session === null) {
            $this->notFound('Session nicht gefunden');
        }

        $title = $this->updateSessionUseCase->updateTitle($session->getId() ?? 0, $_POST['title'] ?? '');
        $this->html(htmlspecialchars($title));
    }

    public function systemPrompt(string $uuid): void
    {
        $session = $this->getSessionUseCase->getSession($uuid);

        if ($session === null) {
            $this->notFound('Session nicht gefunden');
        }

        $result = $this->updateSessionUseCase->updateSystemPrompt($session->getId() ?? 0, $_POST['system_prompt'] ?? '');
        $this->view('chat.partials.success', ['message' => $result->message]);
    }

    public function getSystemPrompt(string $uuid): void
    {
        $session = $this->getSessionUseCase->getSession($uuid);

        if ($session === null) {
            $this->notFound('Session nicht gefunden');
        }

        $this->view('chat.partials.system-prompt-modal', [
            'session' => ChatSessionFactory::toArray($session),
            'currentPrompt' => $this->getSessionUseCase->getSystemPromptById($session->getSystemPromptId()),
            'defaultPrompt' => $this->getSessionUseCase->getDefaultSystemPrompt(),
        ]);
    }

    public function delete(string $uuid): void
    {
        $session = $this->getSessionUseCase->getSession($uuid);

        if ($session !== null) {
            $this->deleteSessionUseCase->deleteSession($session->getId() ?? 0);
        }

        $this->htmxRedirect('/chat');
    }

    public function deleteAll(): void
    {
        $this->deleteSessionUseCase->deleteAllSessions();
        $this->htmxRedirect('/chat');
    }

    public function export(string $uuid): void
    {
        $format = $this->getString('format') ?: 'markdown';
        $filename = $this->exportUseCase->generateFilename($uuid, $format);

        if ($format === 'json') {
            $data = $this->exportUseCase->exportAsJson($uuid);

            if ($data === null) {
                $this->notFound('Session nicht gefunden');
            }

            $content = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
            $this->download($content, $filename, 'application/json');
        } else {
            $content = $this->exportUseCase->exportAsMarkdown($uuid);

            if ($content === null) {
                $this->notFound('Session nicht gefunden');
            }

            $this->download($content, $filename, 'text/markdown');
        }
    }
}

Vollständig herunterladen

Aktionen

Herunterladen

Andere Versionen dieser Datei

ID Version Typ Größe Datum
2128 131 modified 17.2 KB 2025-12-29 15:04
2126 130 modified 15.7 KB 2025-12-29 15:00
2125 129 modified 15.6 KB 2025-12-29 15:00
2124 128 modified 15.6 KB 2025-12-29 15:00
2120 127 modified 15.5 KB 2025-12-29 09:18
2119 126 modified 15.3 KB 2025-12-29 09:17
2111 125 modified 15.3 KB 2025-12-29 08:49
2091 124 modified 13.5 KB 2025-12-29 00:15
2090 123 modified 14.3 KB 2025-12-29 00:14
2089 122 modified 16.9 KB 2025-12-29 00:14
2088 121 modified 17.8 KB 2025-12-29 00:13
2087 120 modified 14.2 KB 2025-12-29 00:13
1583 119 modified 14.1 KB 2025-12-26 21:07
1579 118 modified 13.9 KB 2025-12-26 20:56
1578 117 modified 13.8 KB 2025-12-26 20:55
1574 116 modified 13.6 KB 2025-12-26 20:40
1573 115 modified 13.5 KB 2025-12-26 20:39
1572 114 modified 13.5 KB 2025-12-26 20:39
1571 113 modified 13.2 KB 2025-12-26 20:39
1559 112 modified 8.6 KB 2025-12-26 20:28
1558 111 modified 8.4 KB 2025-12-26 20:28
1544 110 modified 8.3 KB 2025-12-26 20:05
1539 109 modified 9.6 KB 2025-12-26 20:04
1538 108 modified 10.1 KB 2025-12-26 20:04
1536 107 modified 8.8 KB 2025-12-26 19:45
1535 106 modified 8.3 KB 2025-12-26 19:45
1494 105 modified 8.3 KB 2025-12-25 17:31
1488 104 modified 8.3 KB 2025-12-25 17:04
1487 103 modified 8.2 KB 2025-12-25 17:04
1486 102 modified 8.2 KB 2025-12-25 17:04
1485 101 modified 8.2 KB 2025-12-25 17:04
1484 100 modified 8.2 KB 2025-12-25 17:04
1483 99 modified 8.2 KB 2025-12-25 17:04
1482 98 modified 8.2 KB 2025-12-25 17:03
1466 97 modified 8.2 KB 2025-12-25 17:02
1465 96 modified 8.2 KB 2025-12-25 17:01
1464 95 modified 8.1 KB 2025-12-25 17:01
1453 94 modified 8.1 KB 2025-12-25 17:00
1452 93 modified 8.1 KB 2025-12-25 17:00
1451 92 modified 8.1 KB 2025-12-25 17:00
1445 91 modified 7.7 KB 2025-12-25 17:00
1293 90 modified 7.6 KB 2025-12-25 13:27
1292 89 modified 7.6 KB 2025-12-25 13:27
1291 88 modified 7.9 KB 2025-12-25 13:27
1145 87 modified 7.9 KB 2025-12-25 09:45
1144 86 modified 7.8 KB 2025-12-25 09:45
1142 85 modified 7.7 KB 2025-12-25 09:45
1137 84 modified 7.7 KB 2025-12-25 09:42
1136 83 modified 7.7 KB 2025-12-25 09:42
1135 82 modified 7.6 KB 2025-12-25 09:42
685 81 modified 7.5 KB 2025-12-23 07:51
681 80 modified 7.5 KB 2025-12-23 07:44
632 79 modified 7.8 KB 2025-12-23 04:44
631 78 modified 7.8 KB 2025-12-23 04:44
630 77 modified 7.8 KB 2025-12-23 04:44
629 76 modified 7.6 KB 2025-12-23 04:44
619 75 modified 7.7 KB 2025-12-23 04:42
564 74 modified 7.6 KB 2025-12-23 03:35
551 73 modified 7.6 KB 2025-12-23 02:39
550 72 modified 7.5 KB 2025-12-23 02:39
546 71 modified 7.4 KB 2025-12-23 02:38
540 70 modified 6.4 KB 2025-12-22 22:30
539 69 modified 6.4 KB 2025-12-22 22:29
470 68 modified 22.7 KB 2025-12-22 10:36
321 67 modified 22.7 KB 2025-12-22 08:06
293 66 modified 22.7 KB 2025-12-22 08:03
283 65 modified 23.2 KB 2025-12-22 02:19
282 64 modified 23.3 KB 2025-12-22 02:19
281 63 modified 23.4 KB 2025-12-22 02:19
274 62 modified 24.1 KB 2025-12-22 02:14
273 61 modified 25.6 KB 2025-12-22 02:14
272 60 modified 27.0 KB 2025-12-22 02:14
271 59 modified 27.4 KB 2025-12-22 02:13
270 58 modified 29.0 KB 2025-12-22 02:13
269 57 modified 28.8 KB 2025-12-22 02:13
268 56 modified 28.7 KB 2025-12-22 02:12
257 55 modified 29.0 KB 2025-12-22 02:00
256 54 modified 32.1 KB 2025-12-22 01:59
255 53 modified 32.1 KB 2025-12-22 01:59
254 52 modified 32.1 KB 2025-12-22 01:59
253 51 modified 32.1 KB 2025-12-22 01:59
252 50 modified 32.2 KB 2025-12-22 01:59
251 49 modified 32.2 KB 2025-12-22 01:59
250 48 modified 32.2 KB 2025-12-22 01:59
217 47 modified 32.2 KB 2025-12-22 01:43
216 46 modified 32.3 KB 2025-12-22 01:43
215 45 modified 32.3 KB 2025-12-22 01:43
197 44 modified 32.4 KB 2025-12-21 14:39
196 43 modified 32.4 KB 2025-12-21 14:39
195 42 modified 32.5 KB 2025-12-21 14:39
183 41 modified 31.9 KB 2025-12-21 14:15
182 40 modified 31.4 KB 2025-12-21 14:15
181 39 modified 31.0 KB 2025-12-21 14:15
180 38 modified 30.6 KB 2025-12-21 14:15
169 37 modified 30.5 KB 2025-12-21 04:12
168 36 modified 30.6 KB 2025-12-21 04:12
167 35 modified 30.6 KB 2025-12-21 04:12
148 34 modified 30.6 KB 2025-12-21 02:30
147 33 modified 30.6 KB 2025-12-21 02:30
146 32 modified 29.4 KB 2025-12-21 02:30
145 31 modified 29.4 KB 2025-12-21 02:29
144 30 modified 29.4 KB 2025-12-21 02:29
143 29 modified 29.5 KB 2025-12-21 02:29
142 28 modified 29.3 KB 2025-12-21 02:16
132 27 modified 27.8 KB 2025-12-20 19:46
131 26 modified 27.7 KB 2025-12-20 19:46
130 25 modified 26.5 KB 2025-12-20 19:42
82 24 modified 26.4 KB 2025-12-20 19:13
81 23 modified 26.3 KB 2025-12-20 19:13
80 22 modified 26.3 KB 2025-12-20 19:13
79 21 modified 25.9 KB 2025-12-20 19:12
78 20 modified 25.9 KB 2025-12-20 19:12
77 19 modified 25.9 KB 2025-12-20 19:12
76 18 modified 25.9 KB 2025-12-20 19:10
75 17 modified 25.8 KB 2025-12-20 19:10
74 16 modified 25.7 KB 2025-12-20 19:10
68 15 modified 25.9 KB 2025-12-20 18:49
67 14 modified 25.4 KB 2025-12-20 18:49
66 13 modified 25.3 KB 2025-12-20 18:49
65 12 modified 25.0 KB 2025-12-20 18:49
60 11 modified 24.5 KB 2025-12-20 18:32
59 10 modified 24.4 KB 2025-12-20 18:31
58 9 modified 24.3 KB 2025-12-20 18:31
57 8 modified 24.3 KB 2025-12-20 18:31
56 7 modified 24.0 KB 2025-12-20 18:31
55 6 modified 23.8 KB 2025-12-20 18:31
40 5 modified 24.1 KB 2025-12-20 17:24
39 4 modified 24.9 KB 2025-12-20 17:24
9 3 modified 24.9 KB 2025-12-20 16:32
5 2 modified 24.8 KB 2025-12-20 16:08
4 1 modified 24.8 KB 2025-12-20 16:08

← Zurück zur Übersicht