apiKey = getenv('VOYAGE_API_KEY') ?: ($_SERVER['VOYAGE_API_KEY'] ?? '') ?: ($_ENV['VOYAGE_API_KEY'] ?? '') ?: (class_exists('Env') ? Env::get('VOYAGE_API_KEY', '') : ''); $this->model = getenv('VOYAGE_MODEL') ?: ($_SERVER['VOYAGE_MODEL'] ?? null) ?: ($_ENV['VOYAGE_MODEL'] ?? null) ?: 'voyage-3-lite'; if (empty($this->apiKey)) { throw new RuntimeException('VOYAGE_API_KEY non configurata'); } } /** * @return float[] Vettore embedding 1024-dim */ public function embed(string $text): array { $ch = curl_init('https://api.voyageai.com/v1/embeddings'); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Authorization: Bearer ' . $this->apiKey, ], CURLOPT_POSTFIELDS => json_encode([ 'input' => [$text], 'model' => $this->model, 'input_type' => 'document', 'output_dimension' => 512, ]), CURLOPT_TIMEOUT => 30, ]); $raw = curl_exec($ch); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($status !== 200 || !$raw) { throw new RuntimeException("Voyage embed failed (HTTP $status): " . substr((string)$raw, 0, 200)); } $data = json_decode($raw, true); $vec = $data['data'][0]['embedding'] ?? null; if (!is_array($vec)) { throw new RuntimeException('Voyage response without embedding: ' . substr($raw, 0, 200)); } return $vec; } }