neural-sync/backend/app/models.py

103 lines
3.9 KiB
Python

from sqlalchemy import Column, Integer, String, Boolean, Float, ForeignKey, Text, DateTime, JSON
from sqlalchemy.orm import relationship
import uuid
from datetime import datetime
from .database import Base
# Compatibility layer for SQLite and PostgreSQL without pgvector
try:
from sqlalchemy.dialects.postgresql import UUID, ARRAY
import os
if "sqlite" in os.getenv("DATABASE_URL", ""):
raise ImportError("Using SQLite")
# Try to import pgvector, if fails use JSON
try:
from pgvector.sqlalchemy import Vector
except ImportError:
# No pgvector, use JSON instead
Vector = JSON
except ImportError:
from sqlalchemy.types import TypeDecorator, CHAR
import json
class UUID(TypeDecorator):
impl = CHAR(36)
def __init__(self, as_uuid=True):
super().__init__()
def process_bind_param(self, value, dialect):
if value is None: return None
return str(value)
def process_result_value(self, value, dialect):
if value is None: return None
return uuid.UUID(value)
class Vector(TypeDecorator):
impl = Text
def __init__(self, dim=None):
super().__init__()
def process_bind_param(self, value, dialect):
if value is None: return None
return json.dumps(value)
def process_result_value(self, value, dialect):
if value is None: return None
return json.loads(value)
ARRAY = JSON
class ContextNode(Base):
__tablename__ = "context_nodes"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
content = Column(Text, nullable=False)
embedding = Column(Vector(768))
version = Column(Integer, default=1)
status = Column(String(20), default='active')
created_by = Column(UUID(as_uuid=True), nullable=True) # Placeholder for user link
# New fields for AI Insights
ai_insights = Column(JSON, nullable=True) # Stores 'moat', 'tech_specs', etc.
class Experiment(Base):
__tablename__ = "experiments"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
title = Column(String(255))
hypothesis = Column(Text)
status = Column(String(50), default='draft')
owner_id = Column(UUID(as_uuid=True), nullable=True) # Placeholder
linked_context_nodes = Column(JSON, nullable=True) # Changed from ARRAY to JSON for compatibility
target_metric = Column(String(50))
current_score = Column(Float, nullable=True)
class Signal(Base):
__tablename__ = "signals"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
source = Column(String(50))
content = Column(Text)
impact_score = Column(Float)
priority = Column(String(20), default='low') # critical, high, medium, low
processed = Column(Boolean, default=False)
# Store strategic analysis result
strategic_analysis = Column(Text, nullable=True) # JSON string
tasks_generated = Column(Text, nullable=True) # JSON string
created_at = Column(DateTime, default=datetime.utcnow)
class SignalFeedback(Base):
"""User feedback on AI strategic analysis of signals"""
__tablename__ = "signal_feedbacks"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
signal_id = Column(UUID(as_uuid=True), ForeignKey('signals.id'), nullable=False)
# User's correction of the AI's judgment
was_strategic = Column(Boolean, nullable=False) # User's actual judgment
reason = Column(Text, nullable=True) # Why they agree/disagree
# Reference to original AI prediction for analysis
ai_predicted_strategic = Column(Boolean, nullable=False)
ai_confidence = Column(Float, nullable=True)
# Optional: user info for tracking
user_id = Column(String(100), nullable=True) # Simple identifier (email, name, etc.)
created_at = Column(DateTime, default=datetime.utcnow)
# Relationship to signal
signal = relationship("Signal", backref="feedbacks")