scripts/reset_qdrant.py aktualisiert
Some checks failed
Deploy mindnet to llm-node / deploy (push) Failing after 2s
Some checks failed
Deploy mindnet to llm-node / deploy (push) Failing after 2s
This commit is contained in:
parent
566fe813b9
commit
5a089b6262
|
|
@ -1,95 +1,156 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Name: scripts/reset_qdrant.py
|
||||
Version: v1.0.0 (2025-09-04)
|
||||
Name: scripts/reset_qdrant.py
|
||||
Version: v1.1.0 (2025-09-04)
|
||||
Kurzbeschreibung:
|
||||
Löscht entweder die gesamten mindnet-Collections (Wipe) und legt sie gemäß
|
||||
Projekt-Defaults neu an, oder löscht nur alle Punkte (Truncate), wobei die
|
||||
Collection-Konfiguration erhalten bleibt.
|
||||
Sicheres Zurücksetzen der Qdrant-Collections für EIN Projektpräfix. Das Skript
|
||||
ermittelt zunächst die tatsächlich betroffenen Collections und zeigt eine
|
||||
Übersicht an. Anschließend wird der User um Bestätigung gebeten (interaktive
|
||||
Abfrage), bevor eine der beiden Aktionen ausgeführt wird:
|
||||
|
||||
- wipe: Löscht die Collections komplett und legt sie gemäß Projekt-Defaults neu an
|
||||
- truncate: Löscht nur alle Points (Inhalte), behält die Collection-Settings
|
||||
|
||||
Aufruf (aus Projekt-Root, im venv):
|
||||
python3 -m scripts.reset_qdrant --mode wipe [--prefix PREFIX]
|
||||
python3 -m scripts.reset_qdrant --mode truncate [--prefix PREFIX]
|
||||
|
||||
python3 -m scripts.reset_qdrant --mode wipe [--prefix PREFIX] [--yes] [--dry-run]
|
||||
python3 -m scripts.reset_qdrant --mode truncate [--prefix PREFIX] [--yes] [--dry-run]
|
||||
|
||||
Parameter:
|
||||
--mode wipe | truncate
|
||||
--prefix Collection-Prefix (Default: env COLLECTION_PREFIX oder 'mindnet')
|
||||
|
||||
--mode wipe | truncate (Pflicht)
|
||||
--prefix Collection-Prefix (Default: env COLLECTION_PREFIX oder 'mindnet')
|
||||
--yes Keine Rückfrage, direkt ausführen (CI/CD geeignet)
|
||||
--dry-run Nur anzeigen, was passieren würde; nichts ändern
|
||||
|
||||
Umgebungsvariablen (optional):
|
||||
QDRANT_URL, QDRANT_API_KEY, COLLECTION_PREFIX, VECTOR_DIM (Default 384)
|
||||
QDRANT_URL, QDRANT_API_KEY, COLLECTION_PREFIX, VECTOR_DIM (Default 384)
|
||||
|
||||
Sicherheitsmerkmale:
|
||||
- Betrachtet ausschließlich Collections des angegebenen Präfixes.
|
||||
- Listet vor Ausführung die tatsächlich existierenden Ziel-Collections auf.
|
||||
- Fragt interaktiv nach Bestätigung (es sei denn --yes ist gesetzt).
|
||||
|
||||
Hinweise:
|
||||
- Wipe: Collections werden komplett gelöscht und via ensure_collections() neu
|
||||
erstellt (Notes/Chunks: 384d/COSINE; Edges: 1d/DOT).
|
||||
- Truncate: löscht nur Points (behält Settings/Indexing).
|
||||
|
||||
Exitcodes:
|
||||
0 = OK, 1 = abgebrochen/keine Aktion, 2 = Verbindungs-/Konfigurationsfehler
|
||||
|
||||
Changelog:
|
||||
v1.0.0: Initiale Version.
|
||||
v1.1.0: Interaktive Bestätigung, --yes/--dry-run hinzugefügt, Preview der betroffenen Collections.
|
||||
v1.0.0: Wipe/Truncate ohne Bestätigungsabfrage.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import argparse
|
||||
|
||||
import os
|
||||
import sys
|
||||
from typing import List
|
||||
|
||||
from qdrant_client import QdrantClient
|
||||
from qdrant_client.http import models as rest
|
||||
|
||||
|
||||
from app.core.qdrant import QdrantConfig, get_client, ensure_collections, collection_names
|
||||
|
||||
|
||||
def resolve_existing_collections(client: QdrantClient, prefix: str) -> List[str]:
|
||||
"""Ermittelt die *existierenden* Collections für das übergebene Präfix.
|
||||
Es werden NUR die projektdefinierten Collections betrachtet (notes/chunks/edges).
|
||||
"""
|
||||
notes, chunks, edges = collection_names(prefix)
|
||||
candidates = [notes, chunks, edges]
|
||||
existing = [c for c in candidates if client.collection_exists(c)]
|
||||
return existing
|
||||
|
||||
|
||||
def delete_all_points(client: QdrantClient, collections):
|
||||
match_all = rest.Filter(must=[])
|
||||
for col in collections:
|
||||
if client.collection_exists(col):
|
||||
client.delete_points(collection_name=col, points_selector=match_all, wait=True)
|
||||
def confirm_or_abort(action: str, collections: List[str], nonexisting: List[str], assume_yes: bool) -> bool:
|
||||
print("\n=== Reset-Vorschau ===")
|
||||
print(f"Aktion: {action}")
|
||||
if collections:
|
||||
print("Betroffen (existieren):")
|
||||
for c in collections:
|
||||
print(f" - {c}")
|
||||
else:
|
||||
print("Betroffen (existieren): — (keine)")
|
||||
|
||||
if nonexisting:
|
||||
print("Nicht vorhanden (werden bei wipe ggf. neu angelegt):")
|
||||
for c in nonexisting:
|
||||
print(f" - {c}")
|
||||
|
||||
if assume_yes:
|
||||
print("\n--yes gesetzt → führe ohne Rückfrage aus.")
|
||||
return True
|
||||
|
||||
try:
|
||||
ans = input("\nFortfahren? (yes/no): ").strip().lower()
|
||||
except EOFError:
|
||||
return False
|
||||
return ans in ("y", "yes")
|
||||
|
||||
|
||||
def delete_all_points(client: QdrantClient, collections: List[str]) -> None:
|
||||
match_all = rest.Filter(must=[])
|
||||
for col in collections:
|
||||
client.delete_points(collection_name=col, points_selector=match_all, wait=True)
|
||||
|
||||
|
||||
def wipe_collections(client: QdrantClient, collections):
|
||||
for col in collections:
|
||||
if client.collection_exists(col):
|
||||
client.delete_collection(col)
|
||||
|
||||
|
||||
def wipe_collections(client: QdrantClient, all_col_names: List[str], existing: List[str]) -> None:
|
||||
# Lösche nur Collections, die wirklich existieren; die anderen werden anschließend neu angelegt
|
||||
for col in existing:
|
||||
client.delete_collection(col)
|
||||
# ensure_collections legt alle benötigten Collections (notes/chunks/edges) neu an
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="Wipe oder truncate mindnet-Collections in Qdrant.")
|
||||
ap.add_argument("--mode", choices=["wipe", "truncate"], required=True,
|
||||
help="wipe = Collections löschen & neu anlegen; truncate = nur Inhalte löschen")
|
||||
ap.add_argument("--prefix", help="Collection-Prefix (Default: env COLLECTION_PREFIX oder 'mindnet')")
|
||||
args = ap.parse_args()
|
||||
ap = argparse.ArgumentParser(description="Wipe oder truncate mindnet-Collections in Qdrant (mit Bestätigung).")
|
||||
ap.add_argument("--mode", choices=["wipe", "truncate"], required=True,
|
||||
help="wipe = Collections löschen & neu anlegen; truncate = nur Inhalte löschen")
|
||||
ap.add_argument("--prefix", help="Collection-Prefix (Default: env COLLECTION_PREFIX oder 'mindnet')")
|
||||
ap.add_argument("--yes", action="store_true", help="Ohne Rückfrage ausführen (CI/CD)")
|
||||
ap.add_argument("--dry-run", action="store_true", help="Nur anzeigen, was passieren würde; nichts ändern")
|
||||
args = ap.parse_args()
|
||||
|
||||
# Qdrant-Konfiguration
|
||||
try:
|
||||
cfg = QdrantConfig.from_env()
|
||||
except Exception as e:
|
||||
print(f"Konfigurationsfehler: {e}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
cfg = QdrantConfig.from_env()
|
||||
if args.prefix:
|
||||
cfg.prefix = args.prefix
|
||||
if args.prefix:
|
||||
cfg.prefix = args.prefix
|
||||
|
||||
# Client
|
||||
try:
|
||||
client = get_client(cfg)
|
||||
except Exception as e:
|
||||
print(f"Verbindungsfehler zu Qdrant: {e}", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
client = get_client(cfg)
|
||||
notes, chunks, edges = collection_names(cfg.prefix)
|
||||
cols = [notes, chunks, edges]
|
||||
# Ziel-Collections: existierende & nicht existierende (per Namenskonvention)
|
||||
notes, chunks, edges = collection_names(cfg.prefix)
|
||||
all_col_names = [notes, chunks, edges]
|
||||
existing = resolve_existing_collections(client, cfg.prefix)
|
||||
nonexisting = [c for c in all_col_names if c not in existing]
|
||||
|
||||
# Preview & Bestätigung
|
||||
if not confirm_or_abort(args.mode, existing, nonexisting, args.yes):
|
||||
print("Abgebrochen – keine Änderungen vorgenommen.")
|
||||
sys.exit(1)
|
||||
|
||||
if args.mode == "wipe":
|
||||
wipe_collections(client, cols)
|
||||
ensure_collections(client, cfg.prefix, cfg.dim)
|
||||
print(f"Wiped & recreated: {cols}")
|
||||
else:
|
||||
delete_all_points(client, cols)
|
||||
print(f"Truncated (deleted all points in): {cols}")
|
||||
|
||||
if args.dry_run:
|
||||
print("Dry-Run – keine Änderungen vorgenommen.")
|
||||
sys.exit(0)
|
||||
|
||||
# Ausführen
|
||||
if args.mode == "wipe":
|
||||
wipe_collections(client, all_col_names, existing)
|
||||
ensure_collections(client, cfg.prefix, cfg.dim)
|
||||
print(f"Wiped & recreated (Prefix={cfg.prefix}): {all_col_names}")
|
||||
else:
|
||||
if not existing:
|
||||
print("Keine existierenden Collections zum Truncaten gefunden. Beende ohne Aktion.")
|
||||
sys.exit(0)
|
||||
delete_all_points(client, existing)
|
||||
print(f"Truncated (deleted all points in): {existing}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user