QdrantSearchResultDTO.php

Code Hygiene Score: 100

Keine Issues gefunden.

Dependencies 1

Klassen 1

Funktionen 6

Versionen 3

Code

<?php

declare(strict_types=1);

namespace Domain\DTO;

// @responsibility: DTO für Qdrant-Suchergebnisse

use Domain\Constants;

final readonly class QdrantSearchResultDTO
{
    /**
     * @param array<string, mixed> $metadata
     */
    public function __construct(
        public string $id,
        public float $score,
        public string $content,
        public string $documentTitle,
        public string $collection,
        public int $chunkIndex,
        public array $metadata = [],
    ) {
    }

    /**
     * Create from Qdrant API response.
     *
     * @param array<string, mixed> $point
     */
    public static function fromQdrantPoint(array $point): self
    {
        $payload = is_array($point['payload'] ?? null) ? $point['payload'] : [];

        $id = isset($point['id']) ? (string) $point['id'] : '';
        $score = isset($point['score']) ? (float) $point['score'] : 0.0;

        $content = '';
        if (isset($payload['content'])) {
            $content = (string) $payload['content'];
        } elseif (isset($payload['content_preview'])) {
            $content = (string) $payload['content_preview'];
        }

        $documentTitle = 'Unbekannt';
        if (isset($payload['document_title'])) {
            $documentTitle = (string) $payload['document_title'];
        } elseif (isset($payload['title'])) {
            $documentTitle = (string) $payload['title'];
        }

        $collection = isset($payload['collection']) ? (string) $payload['collection'] : 'documents';
        $chunkIndex = isset($payload['chunk_index']) ? (int) $payload['chunk_index'] : 0;

        return new self(
            id: $id,
            score: $score,
            content: $content,
            documentTitle: $documentTitle,
            collection: $collection,
            chunkIndex: $chunkIndex,
            metadata: self::extractMetadata($payload),
        );
    }

    /**
     * Extract additional metadata from payload.
     *
     * @param array<string, mixed> $payload
     * @return array<string, mixed>
     */
    private static function extractMetadata(array $payload): array
    {
        $excludeKeys = ['content', 'content_preview', 'document_title', 'title', 'collection', 'chunk_index'];

        return array_filter(
            $payload,
            fn (string $key): bool => !in_array($key, $excludeKeys, true),
            ARRAY_FILTER_USE_KEY
        );
    }

    /**
     * Check if result is highly relevant (score > threshold).
     */
    public function isHighlyRelevant(float $threshold = 0.8): bool
    {
        return $this->score >= $threshold;
    }

    /**
     * Get content preview.
     */
    public function contentPreview(int $length = 200): string
    {
        if (mb_strlen($this->content) <= $length) {
            return $this->content;
        }

        return mb_substr($this->content, 0, $length) . '...';
    }

    /**
     * Get score as percentage.
     */
    public function scorePercentage(): int
    {
        return (int) round($this->score * Constants::PERCENT_FULL);
    }
}
← Übersicht Graph