$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 $point */ public static function fromQdrantPoint(array $point): self { $payload = $point['payload'] ?? []; return new self( id: (string) ($point['id'] ?? ''), score: (float) ($point['score'] ?? 0.0), content: (string) ($payload['content'] ?? $payload['content_preview'] ?? ''), documentTitle: (string) ($payload['document_title'] ?? $payload['title'] ?? 'Unbekannt'), collection: (string) ($payload['collection'] ?? 'documents'), chunkIndex: (int) ($payload['chunk_index'] ?? 0), metadata: self::extractMetadata($payload), ); } /** * Extract additional metadata from payload. * * @param array $payload * @return array */ 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 * 100); } }