SendChatMessageUseCase.php

Code Hygiene Score: 100

Keine Issues gefunden.

Dependencies 9

Klassen 1

Funktionen 2

Verwendet von 3

Versionen 27

Code

<?php

declare(strict_types=1);

namespace UseCases\Chat;

// @responsibility: Orchestriert Chat-Nachrichten mit AI-Service

use Domain\Repository\ChatMessageRepositoryInterface;
use Domain\Repository\ChatSessionRepositoryInterface;
use Infrastructure\AI\ChatService;
use Infrastructure\AI\ContentQualityValidator;

class SendChatMessageUseCase
{
    public function __construct(
        private ChatService $chatService,
        private ChatSessionRepositoryInterface $sessionRepo,
        private ChatMessageRepositoryInterface $messageRepo,
        private ChatPromptLoader $promptLoader,
        private ContentQualityValidator $qualityValidator
    ) {
    }

    /**
     * Execute the use case
     *
     * @param string $sessionUuid Session UUID
     * @param string $message User message text
     * @param string $model AI model identifier
     * @param array<string> $collections Qdrant collections to search
     * @param int $contextLimit Number of context chunks
     * @param int $authorProfileId Author profile ID (0 = none)
     * @param int $systemPromptId System prompt config ID
     * @param float $temperature AI temperature setting
     * @param int $maxTokens Max tokens for response
     * @param int $structureId Output structure ID (0 = frei)
     * @param bool $qualityCheck Run quality validation on response
     * @return ChatResponse
     */
    public function execute(
        string $sessionUuid,
        string $message,
        string $model,
        array $collections = ['documents'],
        int $contextLimit = 5,
        int $authorProfileId = 0,
        int $systemPromptId = 1,
        float $temperature = 0.7,
        int $maxTokens = 4096,
        int $structureId = 0,
        bool $qualityCheck = false
    ): ChatResponse {
        // 1. Validate session
        $session = $this->sessionRepo->findByUuid($sessionUuid);
        if ($session === null) {
            return ChatResponse::error('Session nicht gefunden.');
        }
        $sessionId = $session->getId() ?? 0;

        // 2. Validate message
        $message = trim($message);
        if ($message === '') {
            return ChatResponse::error('Bitte gib eine Frage ein.');
        }

        // 3. Save user message
        $this->messageRepo->save(
            sessionId: $sessionId,
            role: 'user',
            content: $message,
            model: $model
        );

        // 4. Auto-set title from first message
        if ($session->getTitle() === null) {
            $title = mb_substr($message, 0, 50) . (mb_strlen($message) > 50 ? '...' : '');
            $this->sessionRepo->updateTitle($sessionId, $title);
        }

        // 5. Get prompts via ChatPromptLoader
        $stylePrompt = $this->promptLoader->getStylePrompt($authorProfileId);
        $systemPrompt = $this->promptLoader->getSystemPrompt($systemPromptId);
        $structurePrompt = $this->promptLoader->getStructurePrompt($structureId);
        if ($structurePrompt !== null) {
            $systemPrompt = ($systemPrompt ?? '') . "\n\n" . $structurePrompt;
        }

        // 7. Track timing and get AI response
        $startTime = microtime(true);

        try {
            $result = $this->chatService->chat(
                question: $message,
                model: $model,
                collections: $collections,
                limit: $contextLimit,
                stylePrompt: $stylePrompt,
                customSystemPrompt: $systemPrompt,
                temperature: $temperature,
                maxTokens: $maxTokens
            );
        } catch (\Exception $e) {
            return ChatResponse::error('Chat-Service Fehler: ' . $e->getMessage());
        }

        $endTime = microtime(true);

        // 8. Prepare sources as JSON strings for storage
        /** @var array<int, non-empty-string> $sourcesForStorage */
        $sourcesForStorage = array_map(
            static fn (array $source): string => json_encode($source, JSON_THROW_ON_ERROR),
            $result['sources']
        );

        // 9. Save assistant message with tracking
        $collectionsJson = json_encode($collections);
        $this->messageRepo->save(
            sessionId: $sessionId,
            role: 'assistant',
            content: $result['answer'],
            model: $model,
            tokensInput: $result['usage']['input_tokens'] ?? null,
            tokensOutput: $result['usage']['output_tokens'] ?? null,
            sources: $sourcesForStorage,
            startMicrotime: $startTime,
            endMicrotime: $endTime,
            authorProfileId: $authorProfileId > 0 ? $authorProfileId : null,
            systemPromptId: $systemPromptId > 0 ? $systemPromptId : null,
            collectionsJson: $collectionsJson,
            contextLimit: $contextLimit
        );

        // 10. Create response
        $response = ChatResponse::fromServiceResponse($result, $endTime - $startTime);
        // 11. Run quality validation if enabled
        if ($qualityCheck) {
            $structureName = $this->promptLoader->getStructureName($structureId);
            $validation = $this->qualityValidator->validate(
                question: $message,
                answer: $result['answer'],
                sources: $result['sources'],
                structureName: $structureName
            );
            $response = $response->withQualityValidation($validation);
        }

        // 12. Return response
        return $response;
    }
}
← Übersicht Graph