Protokoll #3717
| ID | 3717 |
|---|---|
| Zeitstempel | 2025-12-22 08:25:56.987122 |
| Client | root |
| IP | Warning: Undefined array key "request_ip" in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 13 Deprecated: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 13 |
| Modell | claude-sonnet-4-20250514 |
| Status | completed |
| Tokens | 2,795 (Input: 0, Output: 0) |
| Dauer | 104 ms |
| Request-Zeit | Warning: Undefined array key "request_timestamp" in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 18 |
| Response-Zeit | - |
Warning: Undefined array key "error_message" in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 22
Request
{
"event": "PreToolUse",
"tool_name": "Edit",
"tool_input": {
"file_path": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/AI\/QdrantService.php",
"old_string": "final readonly class QdrantService",
"new_string": "final class QdrantService"
}
}
Response
{
"tool_response": {
"filePath": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/AI\/QdrantService.php",
"oldString": "final readonly class QdrantService",
"newString": "final class QdrantService",
"originalFile": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Infrastructure\\AI;\n\nuse Infrastructure\\Config\\CredentialService;\nuse RuntimeException;\n\n\/**\n * Service for interacting with Qdrant vector database API.\n *\n * Provides methods to:\n * - Search for similar vectors in collections\n * - Check collection existence and availability\n * - Retrieve collection metadata and information\n * - Perform health checks on the Qdrant service\n *\n * This service uses cURL for HTTP requests without external dependencies.\n * All methods include proper timeout handling and exception management.\n *\n * @package Infrastructure\\AI\n * @author System Generated\n * @version 1.0.0\n *\/\nfinal readonly class QdrantService\n{\n \/**\n * Default timeout for HTTP requests in seconds.\n *\/\n private const int DEFAULT_TIMEOUT = 30;\n\n \/**\n * Health check timeout in seconds.\n *\/\n private const int HEALTH_CHECK_TIMEOUT = 5;\n\n \/**\n * Constructs a new QdrantService instance.\n *\n * @param string $host The Qdrant API host URL (default: http:\/\/localhost:6333)\n *\/\n public function __construct(\n private string $host = 'http:\/\/localhost:6333'\n ) {\n }\n\n \/**\n * Searches for similar vectors in a Qdrant collection.\n *\n * Performs a vector similarity search using the provided embedding vector.\n * Returns the most similar points from the collection based on cosine distance.\n *\n * @param array<int, float> $vector The query embedding vector\n * @param string $collection The collection name to search in (default: documents)\n * @param int $limit Maximum number of results to return (default: 5)\n *\n * @return array<int, array{id: int|string, score: float, payload: array<string, mixed>}> Array of search results with scores and payloads\n *\n * @throws RuntimeException If the API request fails or returns invalid data\n *\n * @example\n * $service = new QdrantService();\n * $vector = [0.123, -0.456, 0.789, ...]; \/\/ 1024-dimensional vector\n * $results = $service->search($vector, 'documents', 5);\n * \/\/ Returns: [\n * \/\/ ['id' => 1, 'score' => 0.89, 'payload' => ['content' => '...', 'title' => '...']],\n * \/\/ ['id' => 2, 'score' => 0.76, 'payload' => ['content' => '...', 'title' => '...']]\n * \/\/ ]\n *\/\n public function search(array $vector, string $collection = 'documents', int $limit = 5): array\n {\n $url = sprintf('%s\/collections\/%s\/points\/search', $this->host, urlencode($collection));\n\n $payload = [\n 'vector' => array_values($vector),\n 'limit' => $limit,\n 'with_payload' => true,\n ];\n\n $response = $this->makeRequest($url, $payload, self::DEFAULT_TIMEOUT);\n\n if (!isset($response['result']) || !is_array($response['result'])) {\n throw new RuntimeException('Invalid search response from Qdrant API');\n }\n\n return array_map(\n static function (mixed $item): array {\n if (!is_array($item)) {\n throw new RuntimeException('Invalid search result item format');\n }\n\n return [\n 'id' => $item['id'] ?? throw new RuntimeException('Missing id in search result'),\n 'score' => (float) ($item['score'] ?? throw new RuntimeException('Missing score in search result')),\n 'payload' => is_array($item['payload'] ?? null) ? $item['payload'] : [],\n ];\n },\n $response['result']\n );\n }\n\n \/**\n * Checks if a collection exists in Qdrant.\n *\n * Verifies the existence of a specific collection by attempting to retrieve\n * its information. This is useful before performing searches or operations.\n *\n * @param string $collection The collection name to check\n *\n * @return bool True if the collection exists, false otherwise\n *\n * @example\n * $service = new QdrantService();\n * if ($service->collectionExists('documents')) {\n * echo \"Collection exists\";\n * } else {\n * echo \"Collection not found\";\n * }\n *\/\n public function collectionExists(string $collection): bool\n {\n $url = sprintf('%s\/collections\/%s', $this->host, urlencode($collection));\n\n try {\n $ch = curl_init($url);\n\n if ($ch === false) {\n return false;\n }\n\n curl_setopt_array($ch, [\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_TIMEOUT => self::HEALTH_CHECK_TIMEOUT,\n CURLOPT_CONNECTTIMEOUT => self::HEALTH_CHECK_TIMEOUT,\n CURLOPT_HTTPHEADER => ['Content-Type: application\/json'],\n CURLOPT_CUSTOMREQUEST => 'GET',\n ]);\n\n $result = curl_exec($ch);\n $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n\n curl_close($ch);\n\n return $result !== false && $httpCode === 200;\n } catch (\\Throwable) {\n return false;\n }\n }\n\n \/**\n * Lists all available collections in Qdrant.\n *\n * Retrieves a list of all collection names from the Qdrant database.\n * Returns an empty array if Qdrant is not available or on error.\n *\n * @return array<int, string> Array of collection names\n *\n * @example\n * $service = new QdrantService();\n * $collections = $service->listCollections();\n * \/\/ Returns: ['documents', 'mail', 'entities']\n *\/\n public function listCollections(): array\n {\n $url = $this->host . '\/collections';\n\n try {\n $ch = curl_init($url);\n\n if ($ch === false) {\n return [];\n }\n\n curl_setopt_array($ch, [\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_TIMEOUT => self::HEALTH_CHECK_TIMEOUT,\n CURLOPT_CONNECTTIMEOUT => self::HEALTH_CHECK_TIMEOUT,\n CURLOPT_HTTPHEADER => ['Content-Type: application\/json'],\n CURLOPT_CUSTOMREQUEST => 'GET',\n ]);\n\n $result = curl_exec($ch);\n $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n\n curl_close($ch);\n\n if ($result === false || $httpCode !== 200) {\n return [];\n }\n\n $decoded = json_decode((string) $result, true);\n\n if (!is_array($decoded) || !isset($decoded['result']['collections'])) {\n return [];\n }\n\n $collections = [];\n foreach ($decoded['result']['collections'] as $collection) {\n if (is_array($collection) && isset($collection['name'])) {\n $collections[] = (string) $collection['name'];\n }\n }\n\n sort($collections);\n\n return $collections;\n } catch (\\Throwable) {\n return [];\n }\n }\n\n \/**\n * Checks if the Qdrant API is available and responding.\n *\n * Performs a health check by querying the Qdrant root endpoint.\n * This is a quick operation with a short timeout.\n *\n * @return bool True if the API is available, false otherwise\n *\n * @example\n * $service = new QdrantService();\n * if ($service->isAvailable()) {\n * echo \"Qdrant is running\";\n * } else {\n * echo \"Qdrant is not available\";\n * }\n *\/\n public function isAvailable(): bool\n {\n $url = $this->host . '\/';\n\n try {\n $ch = curl_init($url);\n\n if ($ch === false) {\n return false;\n }\n\n curl_setopt_array($ch, [\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_TIMEOUT => self::HEALTH_CHECK_TIMEOUT,\n CURLOPT_CONNECTTIMEOUT => self::HEALTH_CHECK_TIMEOUT,\n CURLOPT_HTTPHEADER => ['Content-Type: application\/json'],\n ]);\n\n $result = curl_exec($ch);\n $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n\n curl_close($ch);\n\n return $result !== false && $httpCode === 200;\n } catch (\\Throwable) {\n return false;\n }\n }\n\n \/**\n * Retrieves metadata and information about a collection.\n *\n * Fetches detailed information about a specific collection including\n * vector size, distance metric, number of points, and other metadata.\n *\n * @param string $collection The collection name to query\n *\n * @return array<string, mixed>|null The collection information array, or null if collection does not exist\n *\n * @throws RuntimeException If the API request fails (excluding 404)\n *\n * @example\n * $service = new QdrantService();\n * $info = $service->getCollectionInfo('documents');\n * \/\/ Returns: [\n * \/\/ 'status' => 'green',\n * \/\/ 'vectors_count' => 1234,\n * \/\/ 'points_count' => 1234,\n * \/\/ 'config' => ['params' => ['vectors' => ['size' => 1024, 'distance' => 'Cosine']]]\n * \/\/ ]\n *\/\n public function getCollectionInfo(string $collection): ?array\n {\n $url = sprintf('%s\/collections\/%s', $this->host, urlencode($collection));\n\n try {\n $ch = curl_init($url);\n\n if ($ch === false) {\n throw new RuntimeException('Failed to initialize cURL');\n }\n\n curl_setopt_array($ch, [\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_TIMEOUT => self::DEFAULT_TIMEOUT,\n CURLOPT_CONNECTTIMEOUT => 10,\n CURLOPT_HTTPHEADER => ['Content-Type: application\/json'],\n CURLOPT_CUSTOMREQUEST => 'GET',\n ]);\n\n $result = curl_exec($ch);\n $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n $curlError = curl_error($ch);\n\n curl_close($ch);\n\n if ($result === false) {\n throw new RuntimeException(\n spr... [TRUNCATED-0a5559e3e2d9bf0c]",
"structuredPatch": [
{
"oldStart": 23,
"oldLines": 7,
"newStart": 23,
"newLines": 7,
"lines": [
" * @author System Generated",
" * @version 1.0.0",
" *\/",
"-final readonly class QdrantService",
"+final class QdrantService",
" {",
" \/**",
" * Default timeout for HTTP requests in seconds."
]
}
],
"userModified": false,
"replaceAll": false
}
}