(float) $value, $embedding)).']'; $chunkDistances = ArticleChunk::query() ->selectRaw('article_id, MIN(embedding <=> ?::vector) as distance', [$vector]) ->whereNotNull('embedding') ->when((bool) ($filters['published_only'] ?? false), function ($query) { $query->whereHas('article', function ($articleQuery) { $articleQuery ->where('status', 'published') ->where('is_ai_draft', false); }); }) ->when($embeddingContext !== [], function ($query) use ($embeddingContext) { $query ->where('embedding_provider_instance_id', $embeddingContext['provider_instance_id'] ?? null) ->where('embedding_model', $embeddingContext['embedding_model'] ?? null); }) ->groupBy('article_id') ->orderByRaw('MIN(embedding <=> ?::vector)', [$vector]) ->limit($limit) ->get(); if ($chunkDistances->isEmpty()) { return []; } $distanceByArticleId = $chunkDistances->pluck('distance', 'article_id'); $articleIds = $chunkDistances->pluck('article_id')->all(); $articles = Article::query() ->whereIn('id', $articleIds) ->get() ->sortBy(fn (Article $a) => (float) ($distanceByArticleId[$a->id] ?? 1)) ->values(); return $articles ->map(fn (Article $article) => ArticleCandidateDTO::fromArticle($article, (float) ($distanceByArticleId[$article->id] ?? 1))) ->all(); } }