annator-atom / backend /scripts /initialize_lancedb.py
techprotrade's picture
Full stack ATOM backend + AIMONEYFLOW clients (port 7860) (part 5)
f84a02d verified
Raw
History Blame Contribute Delete
9.64 kB
#!/usr/bin/env python3
"""
LanceDB Initialization Script for ATOM Platform
This script initializes the LanceDB database with sample data to enable
search functionality in the ATOM platform.
Usage:
python initialize_lancedb.py
"""
from datetime import datetime, timezone
import json
import logging
import os
import sys
from typing import Any, Dict, List
import uuid
# Configure logging
logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
def initialize_lancedb():
"""Initialize LanceDB with sample data for search functionality"""
try:
# Import LanceDB
import lancedb
import numpy as np
import pandas as pd
import pyarrow as pa
except ImportError as e:
logger.error(f"LanceDB dependencies not available: {e}")
logger.info(
"Please install required packages: pip install lancedb pyarrow pandas numpy"
)
return False
# Get database path from environment or use default
db_path = os.environ.get("LANCEDB_URI", "/tmp/atom_lancedb")
logger.info(f"Initializing LanceDB at: {db_path}")
try:
# Connect to LanceDB
db = lancedb.connect(db_path)
logger.info("Connected to LanceDB")
# Define schema for document chunks
chunk_schema = pa.schema(
[
pa.field("chunk_id", pa.string()),
pa.field("doc_id", pa.string()),
pa.field("user_id", pa.string()),
pa.field("chunk_index", pa.int32()),
pa.field("chunk_text", pa.string()),
pa.field("metadata", pa.string()),
pa.field(
"vector_embedding", pa.list_(pa.float32(), 1536)
), # OpenAI embedding dimension
pa.field("created_at", pa.string()),
]
)
# Create or open the document_chunks table
table_name = "document_chunks"
if table_name in db.table_names():
logger.info(f"Table {table_name} already exists, opening...")
table = db.open_table(table_name)
else:
logger.info(f"Creating new table: {table_name}")
table = db.create_table(table_name, schema=chunk_schema)
# Generate sample data
sample_documents = [
{
"title": "Project Planning Meeting",
"content": "Discussed project timelines, resource allocation, and milestones for Q4 2024. Team agreed on aggressive but achievable deadlines.",
"tags": ["meeting", "planning", "project"],
},
{
"title": "Technical Architecture Review",
"content": "Reviewed the microservices architecture and API design patterns. Decided to use GraphQL for frontend communication.",
"tags": ["technical", "architecture", "api"],
},
{
"title": "Customer Feedback Analysis",
"content": "Analyzed customer feedback from Q3. Key themes: improved UI/UX, faster response times, better documentation.",
"tags": ["customer", "feedback", "analysis"],
},
{
"title": "Security Audit Report",
"content": "Completed security audit with penetration testing. Identified vulnerabilities in authentication system.",
"tags": ["security", "audit", "vulnerabilities"],
},
{
"title": "Team Standup Notes",
"content": "Daily standup: backend team working on authentication, frontend team implementing search UI, QA team testing workflows.",
"tags": ["standup", "team", "progress"],
},
]
# Generate embeddings for sample data
logger.info("Generating embeddings for sample data...")
try:
from note_utils import get_text_embedding_openai
embedding_function_available = True
except ImportError:
logger.warning("note_utils not available, using mock embeddings")
embedding_function_available = False
# Prepare data for insertion
data_to_insert = []
user_id = "default_user"
for doc_idx, doc in enumerate(sample_documents):
doc_id = str(uuid.uuid4())
# Split content into chunks (simplified - just use the whole content)
chunks = [
{
"text": doc["content"],
"metadata": {
"title": doc["title"],
"tags": doc["tags"],
"source": "sample_data",
},
}
]
for chunk_idx, chunk in enumerate(chunks):
# Generate embedding
if embedding_function_available:
embedding_result = get_text_embedding_openai(chunk["text"])
if embedding_result["status"] == "success":
embedding = embedding_result["data"]
else:
logger.warning(
f"Failed to generate embedding: {embedding_result.get('message')}"
)
# Use mock embedding
embedding = [0.01] * 1536
else:
# Use mock embedding
embedding = [0.01] * 1536
# Create chunk record
chunk_record = {
"chunk_id": str(uuid.uuid4()),
"doc_id": doc_id,
"user_id": user_id,
"chunk_index": chunk_idx,
"chunk_text": chunk["text"],
"metadata": json.dumps(chunk["metadata"]),
"vector_embedding": embedding,
"created_at": datetime.now(timezone.utc).isoformat(),
}
data_to_insert.append(chunk_record)
# Insert data into LanceDB
if data_to_insert:
logger.info(f"Inserting {len(data_to_insert)} document chunks...")
table.add(data_to_insert)
logger.info("Sample data inserted successfully!")
else:
logger.warning("No data to insert")
# Verify the data was inserted
count = table.count_rows()
logger.info(f"Table now contains {count} rows")
# Test search functionality
logger.info("Testing search functionality...")
# Generate embedding for test query
test_query = "project planning"
if embedding_function_available:
embedding_result = get_text_embedding_openai(test_query)
if embedding_result["status"] == "success":
query_embedding = embedding_result["data"]
# Perform search
results = table.search(query_embedding).limit(3).to_list()
logger.info(f"Search test returned {len(results)} results")
# Display results
for i, result in enumerate(results):
logger.info(
f"Result {i + 1}: {result.get('chunk_text', '')[:100]}..."
)
else:
logger.warning("Could not test search - embedding generation failed")
else:
logger.info("Search test skipped - mock embeddings in use")
logger.info("LanceDB initialization completed successfully!")
return True
except Exception as e:
logger.error(f"Failed to initialize LanceDB: {e}")
return False
def create_meeting_transcripts_table():
"""Create meeting_transcripts_embeddings table if needed"""
try:
import lancedb
import pyarrow as pa
db_path = os.environ.get("LANCEDB_URI", "/tmp/atom_lancedb")
db = lancedb.connect(db_path)
table_name = "meeting_transcripts_embeddings"
if table_name not in db.table_names():
logger.info(f"Creating table: {table_name}")
# Define schema for meeting transcripts
schema = pa.schema(
[
pa.field("transcript_id", pa.string()),
pa.field("user_id", pa.string()),
pa.field("meeting_title", pa.string()),
pa.field("content", pa.string()),
pa.field("timestamp", pa.string()),
pa.field("vector_embedding", pa.list_(pa.float32(), 1536)),
pa.field("metadata", pa.string()),
]
)
db.create_table(table_name, schema=schema)
logger.info(f"Table {table_name} created successfully")
else:
logger.info(f"Table {table_name} already exists")
return True
except Exception as e:
logger.error(f"Failed to create meeting transcripts table: {e}")
return False
def main():
"""Main execution function"""
logger.info("Starting LanceDB initialization...")
# Initialize main document chunks table
if not initialize_lancedb():
logger.error("LanceDB initialization failed")
sys.exit(1)
# Create meeting transcripts table (for compatibility)
create_meeting_transcripts_table()
logger.info("LanceDB setup completed!")
logger.info(
"You can now test search functionality at: http://localhost:5058/semantic_search_meetings"
)
if __name__ == "__main__":
main()