#!/usr/bin/env python3 """ Interroge la base vectorielle Qdrant avec une question en langage naturel. Usage: rag-query "ma question" [--top N] Retourne les passages de documentation les plus pertinents. """ import sys import json import os import urllib.request QDRANT_URL = os.environ.get("QDRANT_URL", "http://127.0.0.1:6333") EMBED_URL = os.environ.get("EMBED_URL", "http://192.168.10.20:1234/v1/embeddings") EMBED_MODEL = os.environ.get("EMBED_MODEL", "qwen3-8b") COLLECTION = os.environ.get("RAG_COLLECTION", "funk-docs") MIN_SCORE = 0.60 def _post(url, data): req = urllib.request.Request( url, data=json.dumps(data).encode(), headers={"Content-Type": "application/json"}, method="POST" ) with urllib.request.urlopen(req, timeout=60) as r: return json.loads(r.read()) def embed(text): result = _post(EMBED_URL, {"model": EMBED_MODEL, "input": text}) return result["data"][0]["embedding"] def search(question, top=5): vector = embed(question) result = _post(f"{QDRANT_URL}/collections/{COLLECTION}/points/search", { "vector": vector, "limit": top, "with_payload": True, "score_threshold": MIN_SCORE, }) return result["result"] if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: rag-query \"question\" [--top N]", file=sys.stderr) sys.exit(1) question = sys.argv[1] top = 5 if "--top" in sys.argv: idx = sys.argv.index("--top") try: top = int(sys.argv[idx + 1]) except (IndexError, ValueError): pass try: results = search(question, top) except Exception as e: print(f"ERREUR: {e}", file=sys.stderr) sys.exit(1) if not results: print(f"Aucun résultat pertinent pour : {question}") sys.exit(0) print(f"=== Contexte RAG — {len(results)} résultat(s) pour : {question} ===\n") for i, r in enumerate(results, 1): p = r["payload"] score = r["score"] print(f"--- [{i}] {p['file']} § {p['section']} (score: {score:.3f}) ---") print(p["text"][:700]) print()