## Agents Added - Alateya: R&D, biotech, innovations - Clan (Spirit): Community spirit agent - Eonarch: Consciousness evolution agent ## Changes - docker-compose.node1.yml: Added tokens for all 3 new agents - gateway-bot/http_api.py: Added configs and webhook endpoints - gateway-bot/clan_prompt.txt: New prompt file - gateway-bot/eonarch_prompt.txt: New prompt file ## Fixes - Fixed ROUTER_URL from :9102 to :8000 (internal container port) - All 9 Telegram agents now working ## Documentation - Created PROJECT-MASTER-INDEX.md - single entry point - Added various status documents and scripts Tokens configured: - Helion, NUTRA, Agromatrix (existing) - Alateya, Clan, Eonarch (new) - Druid, GreenFood, DAARWIZZ (configured)
222 lines
8.2 KiB
Python
222 lines
8.2 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Qdrant Vector Collections Setup for Helion Memory v3.0
|
||
|
||
Collections:
|
||
1. helion_memory_items - Long-term memory facts (preferences, decisions, lessons)
|
||
2. helion_artifacts - Documents, specs, whitepaper embeddings
|
||
3. helion_messages - Recent message embeddings for context retrieval
|
||
|
||
Run: python setup_qdrant_collections.py [--host HOST] [--port PORT]
|
||
"""
|
||
|
||
import argparse
|
||
import sys
|
||
from qdrant_client import QdrantClient
|
||
from qdrant_client.http import models as qmodels
|
||
|
||
# Cohere embed-multilingual-v3.0 produces 1024-dimensional vectors
|
||
EMBEDDING_DIMENSIONS = 1024
|
||
|
||
|
||
def setup_collections(host: str = "localhost", port: int = 6333):
|
||
"""Create and configure Qdrant collections for Helion Memory"""
|
||
|
||
print(f"🔌 Connecting to Qdrant at {host}:{port}...")
|
||
client = QdrantClient(host=host, port=port)
|
||
|
||
# Check connection
|
||
try:
|
||
collections = client.get_collections()
|
||
print(f"✅ Connected. Existing collections: {[c.name for c in collections.collections]}")
|
||
except Exception as e:
|
||
print(f"❌ Failed to connect: {e}")
|
||
sys.exit(1)
|
||
|
||
# =========================================================================
|
||
# Collection 1: helion_memory_items
|
||
# =========================================================================
|
||
|
||
collection_name = "helion_memory_items"
|
||
print(f"\n📦 Setting up collection: {collection_name}")
|
||
|
||
if not client.collection_exists(collection_name):
|
||
client.create_collection(
|
||
collection_name=collection_name,
|
||
vectors_config=qmodels.VectorParams(
|
||
size=EMBEDDING_DIMENSIONS,
|
||
distance=qmodels.Distance.COSINE
|
||
),
|
||
# Optimized for filtering by user and type
|
||
optimizers_config=qmodels.OptimizersConfigDiff(
|
||
indexing_threshold=10000
|
||
),
|
||
# On-disk storage for large collections
|
||
on_disk_payload=True
|
||
)
|
||
print(f" ✅ Created collection: {collection_name}")
|
||
else:
|
||
print(f" ℹ️ Collection already exists: {collection_name}")
|
||
|
||
# Create payload indexes for filtering
|
||
print(f" 📇 Creating payload indexes...")
|
||
|
||
indexes = [
|
||
("platform_user_id", qmodels.PayloadSchemaType.KEYWORD),
|
||
("type", qmodels.PayloadSchemaType.KEYWORD),
|
||
("category", qmodels.PayloadSchemaType.KEYWORD),
|
||
("visibility", qmodels.PayloadSchemaType.KEYWORD),
|
||
("scope_ref", qmodels.PayloadSchemaType.KEYWORD),
|
||
("confidence", qmodels.PayloadSchemaType.FLOAT),
|
||
("created_at", qmodels.PayloadSchemaType.DATETIME),
|
||
("expires_at", qmodels.PayloadSchemaType.DATETIME),
|
||
("archived", qmodels.PayloadSchemaType.BOOL),
|
||
]
|
||
|
||
for field_name, field_type in indexes:
|
||
try:
|
||
client.create_payload_index(
|
||
collection_name=collection_name,
|
||
field_name=field_name,
|
||
field_schema=field_type,
|
||
wait=False
|
||
)
|
||
print(f" ✅ Index: {field_name} ({field_type.value})")
|
||
except Exception as e:
|
||
if "already exists" in str(e).lower():
|
||
print(f" ℹ️ Index exists: {field_name}")
|
||
else:
|
||
print(f" ⚠️ Index {field_name}: {e}")
|
||
|
||
# =========================================================================
|
||
# Collection 2: helion_artifacts
|
||
# =========================================================================
|
||
|
||
collection_name = "helion_artifacts"
|
||
print(f"\n📦 Setting up collection: {collection_name}")
|
||
|
||
if not client.collection_exists(collection_name):
|
||
client.create_collection(
|
||
collection_name=collection_name,
|
||
vectors_config=qmodels.VectorParams(
|
||
size=EMBEDDING_DIMENSIONS,
|
||
distance=qmodels.Distance.COSINE
|
||
),
|
||
on_disk_payload=True
|
||
)
|
||
print(f" ✅ Created collection: {collection_name}")
|
||
else:
|
||
print(f" ℹ️ Collection already exists: {collection_name}")
|
||
|
||
# Artifact indexes
|
||
print(f" 📇 Creating payload indexes...")
|
||
|
||
artifact_indexes = [
|
||
("artifact_id", qmodels.PayloadSchemaType.KEYWORD),
|
||
("project_id", qmodels.PayloadSchemaType.KEYWORD),
|
||
("source", qmodels.PayloadSchemaType.KEYWORD),
|
||
("source_type", qmodels.PayloadSchemaType.KEYWORD), # whitepaper, spec, landing, faq
|
||
("language", qmodels.PayloadSchemaType.KEYWORD),
|
||
("version", qmodels.PayloadSchemaType.KEYWORD),
|
||
("chunk_index", qmodels.PayloadSchemaType.INTEGER),
|
||
("created_at", qmodels.PayloadSchemaType.DATETIME),
|
||
]
|
||
|
||
for field_name, field_type in artifact_indexes:
|
||
try:
|
||
client.create_payload_index(
|
||
collection_name=collection_name,
|
||
field_name=field_name,
|
||
field_schema=field_type,
|
||
wait=False
|
||
)
|
||
print(f" ✅ Index: {field_name} ({field_type.value})")
|
||
except Exception as e:
|
||
if "already exists" in str(e).lower():
|
||
print(f" ℹ️ Index exists: {field_name}")
|
||
else:
|
||
print(f" ⚠️ Index {field_name}: {e}")
|
||
|
||
# =========================================================================
|
||
# Collection 3: helion_messages (for recent context retrieval)
|
||
# =========================================================================
|
||
|
||
collection_name = "helion_messages"
|
||
print(f"\n📦 Setting up collection: {collection_name}")
|
||
|
||
if not client.collection_exists(collection_name):
|
||
client.create_collection(
|
||
collection_name=collection_name,
|
||
vectors_config=qmodels.VectorParams(
|
||
size=EMBEDDING_DIMENSIONS,
|
||
distance=qmodels.Distance.COSINE
|
||
),
|
||
# Faster retrieval for recent messages
|
||
optimizers_config=qmodels.OptimizersConfigDiff(
|
||
indexing_threshold=5000
|
||
),
|
||
on_disk_payload=True
|
||
)
|
||
print(f" ✅ Created collection: {collection_name}")
|
||
else:
|
||
print(f" ℹ️ Collection already exists: {collection_name}")
|
||
|
||
# Message indexes
|
||
print(f" 📇 Creating payload indexes...")
|
||
|
||
message_indexes = [
|
||
("conversation_id", qmodels.PayloadSchemaType.KEYWORD),
|
||
("platform_user_id", qmodels.PayloadSchemaType.KEYWORD),
|
||
("channel", qmodels.PayloadSchemaType.KEYWORD),
|
||
("chat_id", qmodels.PayloadSchemaType.KEYWORD),
|
||
("role", qmodels.PayloadSchemaType.KEYWORD), # user, assistant, system
|
||
("timestamp", qmodels.PayloadSchemaType.DATETIME),
|
||
]
|
||
|
||
for field_name, field_type in message_indexes:
|
||
try:
|
||
client.create_payload_index(
|
||
collection_name=collection_name,
|
||
field_name=field_name,
|
||
field_schema=field_type,
|
||
wait=False
|
||
)
|
||
print(f" ✅ Index: {field_name} ({field_type.value})")
|
||
except Exception as e:
|
||
if "already exists" in str(e).lower():
|
||
print(f" ℹ️ Index exists: {field_name}")
|
||
else:
|
||
print(f" ⚠️ Index {field_name}: {e}")
|
||
|
||
# =========================================================================
|
||
# Summary
|
||
# =========================================================================
|
||
|
||
print("\n" + "=" * 60)
|
||
print("📊 Qdrant Collections Summary")
|
||
print("=" * 60)
|
||
|
||
for coll in client.get_collections().collections:
|
||
info = client.get_collection(coll.name)
|
||
print(f"\n{coll.name}:")
|
||
print(f" Points: {info.points_count}")
|
||
print(f" Vectors: {info.vectors_count}")
|
||
print(f" Status: {info.status}")
|
||
|
||
print("\n✅ Qdrant setup complete!")
|
||
|
||
return True
|
||
|
||
|
||
def main():
|
||
parser = argparse.ArgumentParser(description="Setup Qdrant collections for Helion Memory")
|
||
parser.add_argument("--host", default="localhost", help="Qdrant host")
|
||
parser.add_argument("--port", type=int, default=6333, help="Qdrant port")
|
||
args = parser.parse_args()
|
||
|
||
setup_collections(args.host, args.port)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|