'no query']); exit; } // Get embedding from Ollama $ch = curl_init('http://127.0.0.1:11434/api/embed'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 8, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode(['model' => 'all-minilm', 'input' => substr($q, 0, 500)]) ]); $r = curl_exec($ch); curl_close($ch); $emb = json_decode($r, true)['embeddings'][0] ?? null; if (!$emb) { echo json_encode(['error' => 'embedding failed']); exit; } // Search Qdrant $ch = curl_init('http://127.0.0.1:6333/collections/obsidian_vault/points/query'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 5, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode(['query' => $emb, 'limit' => 5, 'with_payload' => true]) ]); $r = curl_exec($ch); curl_close($ch); $data = json_decode($r, true); $results = []; foreach ($data['result']['points'] ?? [] as $p) { $results[] = [ 'file' => $p['payload']['file'] ?? '?', 'score' => round($p['score'] ?? 0, 3), 'snippet' => substr($p['payload']['content'] ?? '', 0, 200) ]; } echo json_encode(['query' => $q, 'results' => $results, 'count' => count($results), 'engine' => 'qdrant+ollama']);