feat(knowledge): add Qdrant backend with SQLite fallback

- Add QdrantKnowledgeSearch class for hybrid dense+sparse vector search
- Query RECON's 2.8M vector database via TEI embeddings + Qdrant
- Uses RRF (Reciprocal Rank Fusion) for hybrid search merging
- Extended KnowledgeConfig with Qdrant/TEI settings
- Auto backend tries Qdrant first, falls back to SQLite FTS5
- Graceful degradation if RECON infrastructure unreachable

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
K7ZVX 2026-05-06 15:54:43 +00:00
commit b11874f016
3 changed files with 255 additions and 14 deletions

View file

@ -284,20 +284,41 @@ class MeshAI:
)
logger.info(f"Alert engine initialized (critical: {mi.critical_nodes}, channel: {mi.alert_channel})")
# Knowledge base (optional - gracefully degrade if deps missing)
# Knowledge base (optional - Qdrant with SQLite fallback)
kb_cfg = self.config.knowledge
if kb_cfg.enabled and kb_cfg.db_path:
try:
from .knowledge import KnowledgeSearch
self.knowledge = KnowledgeSearch(
db_path=kb_cfg.db_path,
top_k=kb_cfg.top_k,
)
except ImportError as e:
logger.warning(f"Knowledge base disabled - missing dependencies: {e}")
self.knowledge = None
else:
self.knowledge = None
self.knowledge = None
if kb_cfg.enabled:
# Try Qdrant first if configured
if kb_cfg.backend in ("qdrant", "auto") and kb_cfg.qdrant_host:
try:
from .knowledge import QdrantKnowledgeSearch
qdrant = QdrantKnowledgeSearch(
qdrant_host=kb_cfg.qdrant_host,
qdrant_port=kb_cfg.qdrant_port,
collection=kb_cfg.qdrant_collection,
tei_host=kb_cfg.tei_host,
tei_port=kb_cfg.tei_port,
sparse_host=kb_cfg.sparse_host,
sparse_port=kb_cfg.sparse_port,
use_sparse=kb_cfg.use_sparse,
top_k=kb_cfg.top_k,
)
if qdrant.available:
self.knowledge = qdrant
logger.info("Using Qdrant knowledge backend (RECON hybrid)")
except Exception as e:
logger.warning(f"Qdrant knowledge unavailable: {e}")
# Fall back to SQLite if Qdrant failed or not configured
if not self.knowledge and kb_cfg.backend in ("sqlite", "auto") and kb_cfg.db_path:
try:
from .knowledge import KnowledgeSearch
self.knowledge = KnowledgeSearch(
db_path=kb_cfg.db_path,
top_k=kb_cfg.top_k,
)
except ImportError as e:
logger.warning(f"SQLite knowledge disabled - missing dependencies: {e}")
# Command dispatcher (needs mesh_reporter for health commands)
self.dispatcher = create_dispatcher(