ChunkSearchService.php
- Pfad:
src/Infrastructure/Docs/ChunkSearchService.php - Namespace: Infrastructure\Docs
- Zeilen: 79 | Größe: 2,471 Bytes
- Geändert: 2025-12-25 13:00:11 | Gescannt: 2025-12-31 10:22:15
Code Hygiene Score: 100
- Dependencies: 100 (25%)
- LOC: 100 (20%)
- Methods: 100 (20%)
- Secrets: 100 (15%)
- Classes: 100 (10%)
- Magic Numbers: 100 (10%)
Keine Issues gefunden.
Dependencies 4
- constructor Infrastructure\AI\QdrantClient
- constructor Infrastructure\AI\OllamaService
- use Infrastructure\AI\OllamaService
- use Infrastructure\AI\QdrantClient
Klassen 1
-
ChunkSearchServiceclass Zeile 12
Funktionen 4
-
__construct()public Zeile 16 -
search()public Zeile 28 -
searchByTaxonomy()public Zeile 55 -
getStats()public Zeile 74
Verwendet von 5
- DocsController.php constructor
- DocsController.php use
- DocumentationChatUseCase.php constructor
- DocumentationChatUseCase.php use
- InfrastructureServiceProvider.php use
Code
<?php
declare(strict_types=1);
namespace Infrastructure\Docs;
// @responsibility: Semantische Suche in Dokumentations-Chunks via Qdrant
use Infrastructure\AI\OllamaService;
use Infrastructure\AI\QdrantClient;
final class ChunkSearchService
{
private const string COLLECTION = 'dokumentation_chunks';
public function __construct(
private QdrantClient $qdrant,
private OllamaService $ollama
) {
}
/**
* Searches for similar chunks using semantic search.
*
* @param array<string, mixed>|null $filter Optional filter for taxonomy/entities
* @return array<array{id: int, doc_id: int, path: string, title: string, content: string, score: float, taxonomy: array<string>, entities: array<mixed>}>
*/
public function search(string $query, int $limit = 5, ?array $filter = null): array
{
$embedding = $this->ollama->getEmbedding($query);
$results = $this->qdrant->search(self::COLLECTION, $embedding, $limit, $filter);
return array_map(static function (array $item): array {
$payload = $item['payload'] ?? [];
return [
'id' => (int) ($payload['chunk_id'] ?? 0),
'doc_id' => (int) ($payload['doc_id'] ?? 0),
'path' => (string) ($payload['path'] ?? ''),
'title' => (string) ($payload['title'] ?? ''),
'content' => (string) ($payload['content_preview'] ?? ''),
'score' => (float) ($item['score'] ?? 0),
'taxonomy' => is_array($payload['taxonomy'] ?? null) ? $payload['taxonomy'] : [],
'entities' => is_array($payload['entities'] ?? null) ? $payload['entities'] : [],
];
}, $results);
}
/**
* Searches with taxonomy filter.
*
* @return array<array<string, mixed>>
*/
public function searchByTaxonomy(string $query, string $category, int $limit = 5): array
{
$filter = [
'must' => [
[
'key' => 'taxonomy_category',
'match' => ['value' => $category],
],
],
];
return $this->search($query, $limit, $filter);
}
/**
* Gets collection statistics.
*
* @return array{points_count: int, status: string}|null
*/
public function getStats(): ?array
{
return $this->qdrant->getCollectionStats(self::COLLECTION);
}
}