AI_Chatbot / models.py
embedingHF's picture
Upload folder using huggingface_hub
ae677bb verified
Raw
History Blame Contribute Delete
6.54 kB
import uuid
import builtins
from django.db import models
from pgvector.django import VectorField
from django.conf import settings
class GlobalQA(models.Model):
"""Global Q&A for greetings - works across ALL properties and agencies"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
question = models.TextField(unique=True)
answer = models.TextField()
question_embedding = VectorField(dimensions=384)
language = models.CharField(max_length=20, choices=[
('en', 'English'),
('ur', 'Roman Urdu'),
('both', 'Both')
], default='both')
is_active = models.BooleanField(default=True)
priority = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-priority', 'question']
indexes = [
models.Index(fields=['is_active', '-priority']),
models.Index(fields=['language', 'is_active']),
]
def __str__(self):
return f"{self.question[:50]}"
class MasterQuestion(models.Model):
"""Pre-defined questions created by admin that agencies must answer"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
question = models.TextField(unique=True)
is_active = models.BooleanField(default=True)
order = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['order']
indexes = [
models.Index(fields=['is_active', 'order']),
]
def __str__(self):
return self.question[:100]
class PropertyQA(models.Model):
"""Agency's answers to master questions for a specific property"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
agency = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='property_qa_answers'
)
property = models.ForeignKey(
'Property.Property',
on_delete=models.CASCADE,
related_name='ai_qa'
)
master_question = models.ForeignKey(
MasterQuestion,
on_delete=models.CASCADE,
null=True,
blank=True
)
answer = models.TextField()
# Embedding for similarity search
question_embedding = VectorField(dimensions=384)
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True) # FIX #5: Track updates
class Meta:
unique_together = ['property', 'master_question']
# FIX #2: Database indexes for performance
indexes = [
models.Index(fields=['property', 'is_active']),
models.Index(fields=['agency', 'is_active']),
models.Index(fields=['master_question', 'is_active']),
# Vector index will be added via migration
]
@builtins.property
def question_text(self):
return self.master_question.question if self.master_question else None
def __str__(self):
return f"{self.property.title}: {self.question_text[:50] if self.question_text else 'No question'}"
class AgencyAutoChatSetting(models.Model):
"""Auto-chat settings per agency"""
agency = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='auto_chat_setting'
)
is_enabled = models.BooleanField(default=False)
delay_seconds = models.IntegerField(default=30, help_text="Seconds to wait before AI replies")
confidence_threshold = models.FloatField(default=0.6, help_text="Minimum similarity score (0-1)")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
indexes = [
models.Index(fields=['is_enabled']),
]
def __str__(self):
return f"{self.agency.email}: {'ON' if self.is_enabled else 'OFF'}"
class PropertyAutoChatState(models.Model):
"""Track auto-chat state per property"""
property = models.OneToOneField(
'Property.Property',
on_delete=models.CASCADE,
related_name='auto_chat_state'
)
is_auto_chat_enabled = models.BooleanField(default=False)
last_auto_reply_at = models.DateTimeField(null=True, blank=True)
total_auto_replies = models.IntegerField(default=0)
last_agency_reply_at = models.DateTimeField(null=True, blank=True)
class Meta:
indexes = [
models.Index(fields=['is_auto_chat_enabled']),
models.Index(fields=['property', 'is_auto_chat_enabled']),
]
def __str__(self):
return f"{self.property.title}: Auto Chat {'ON' if self.is_auto_chat_enabled else 'OFF'}"
class PropertyCustomQA(models.Model):
"""
Custom Q&A for a specific property (max 5 per property)
Agency writes these when enabling auto-chat
"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
# Relationships
agency = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='property_custom_qa'
)
property = models.ForeignKey(
'Property.Property',
on_delete=models.CASCADE,
related_name='custom_qa'
)
# The actual Q&A
question = models.TextField()
answer = models.TextField()
# For AI similarity search
question_embedding = VectorField(dimensions=384)
# Metadata
order = models.IntegerField(default=0) # 1-5 for display order
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['order']
# Ensure max 5 per property
constraints = [
models.UniqueConstraint(
fields=['property', 'order'],
name='unique_order_per_property'
)
]
indexes = [
models.Index(fields=['property', 'is_active']),
models.Index(fields=['agency', 'is_active']),
]
def __str__(self):
return f"{self.property.title}: Q{self.order} - {self.question[:50]}"