*/ public static function phrasesFromText(string $text, int $limit = 50): array { $lines = preg_split('/\R/u', $text) ?: []; $phrases = []; $seen = []; foreach ($lines as $line) { $phrase = self::cleanPhrase($line); if ($phrase === '') { continue; } $hash = self::hashPhrase($phrase); if (isset($seen[$hash])) { continue; } $seen[$hash] = true; $phrases[] = $phrase; if (count($phrases) >= $limit) { break; } } return $phrases; } public static function cleanPhrase(string $phrase): string { return Str::of($phrase)->squish()->value(); } public static function hashPhrase(string $phrase): string { return hash('sha256', Str::of($phrase)->squish()->lower()->value()); } /** * @param array $vector * @return array */ public static function normalize(array $vector): array { $magnitude = sqrt(array_sum(array_map( fn (int|float $value): float => (float) $value * (float) $value, $vector ))); if ($magnitude == 0.0) { return array_map(fn (): float => 0.0, $vector); } return array_map(fn (int|float $value): float => (float) $value / $magnitude, $vector); } /** * @param array $first * @param array $second */ public static function cosineSimilarity(array $first, array $second): float { if (count($first) !== count($second)) { throw new InvalidArgumentException('Vectors must have the same number of dimensions.'); } $dotProduct = 0.0; $firstMagnitude = 0.0; $secondMagnitude = 0.0; foreach ($first as $index => $firstValue) { $secondValue = $second[$index]; $dotProduct += (float) $firstValue * (float) $secondValue; $firstMagnitude += (float) $firstValue * (float) $firstValue; $secondMagnitude += (float) $secondValue * (float) $secondValue; } if ($firstMagnitude == 0.0 || $secondMagnitude == 0.0) { return 0.0; } return max(-1.0, min(1.0, $dotProduct / (sqrt($firstMagnitude) * sqrt($secondMagnitude)))); } /** * @param array $vector * @return array */ public static function rounded(array $vector, int $precision = 6): array { return array_map(fn (int|float $value): float => round((float) $value, $precision), $vector); } /** * @param array $vector * @return array */ public static function preview(array $vector, int $limit = 12): array { return array_slice(self::rounded($vector), 0, $limit); } }